Mini fuloong, yeeloong are all Loongson2F based systems. Loongson2F have builtin DDR2 and PCIX controller. The PCIX controller have a similar programming interface with FPGA northbridge used in Loongson2E. --- arch/mips/Kconfig | 9 +- arch/mips/Makefile | 19 + arch/mips/include/asm/mach-lemote/dma-coherence.h | 11 + arch/mips/include/asm/mips-boards/bonito64.h | 2 +- arch/mips/lemote/lm2f/Kconfig | 70 + arch/mips/lemote/lm2f/common/Makefile | 9 + arch/mips/lemote/lm2f/common/cs5536.h | 578 ++++++ arch/mips/lemote/lm2f/common/cs5536_pci.h | 181 ++ arch/mips/lemote/lm2f/common/cs5536_vsm.c | 2294 +++++++++++++++++++++ arch/mips/lemote/lm2f/common/mem.c | 23 + arch/mips/lemote/lm2f/common/mfgpt.c | 222 ++ arch/mips/lemote/lm2f/common/mipsdha.c | 164 ++ arch/mips/lemote/lm2f/common/pci.c | 89 + arch/mips/lemote/lm2f/common/pcireg.h | 485 +++++ arch/mips/lemote/lm2f/common/plat.c | 82 + arch/mips/lemote/lm2f/fuloong/Makefile | 7 + arch/mips/lemote/lm2f/fuloong/bonito-irq.c | 105 + arch/mips/lemote/lm2f/fuloong/dbg_io.c | 182 ++ arch/mips/lemote/lm2f/fuloong/irq.c | 234 +++ arch/mips/lemote/lm2f/fuloong/prom.c | 106 + arch/mips/lemote/lm2f/fuloong/reset.c | 87 + arch/mips/lemote/lm2f/fuloong/setup.c | 132 ++ arch/mips/lemote/lm2f/yeeloong/Makefile | 7 + arch/mips/lemote/lm2f/yeeloong/bonito-irq.c | 104 + arch/mips/lemote/lm2f/yeeloong/dbg_io.c | 170 ++ arch/mips/lemote/lm2f/yeeloong/irq.c | 234 +++ arch/mips/lemote/lm2f/yeeloong/prom.c | 157 ++ arch/mips/lemote/lm2f/yeeloong/reset.c | 80 + arch/mips/lemote/lm2f/yeeloong/setup.c | 134 ++ arch/mips/pci/Makefile | 2 + arch/mips/pci/fixup-fl2f.c | 256 +++ arch/mips/pci/fixup-yl2f.c | 245 +++ arch/mips/pci/ops-lm2f.c | 205 ++ 33 files changed, 6683 insertions(+), 2 deletions(-) create mode 100644 arch/mips/lemote/lm2f/Kconfig create mode 100644 arch/mips/lemote/lm2f/common/Makefile create mode 100644 arch/mips/lemote/lm2f/common/cs5536.h create mode 100644 arch/mips/lemote/lm2f/common/cs5536_pci.h create mode 100644 arch/mips/lemote/lm2f/common/cs5536_vsm.c create mode 100644 arch/mips/lemote/lm2f/common/mem.c create mode 100644 arch/mips/lemote/lm2f/common/mfgpt.c create mode 100644 arch/mips/lemote/lm2f/common/mipsdha.c create mode 100644 arch/mips/lemote/lm2f/common/pci.c create mode 100644 arch/mips/lemote/lm2f/common/pcireg.h create mode 100644 arch/mips/lemote/lm2f/common/plat.c create mode 100644 arch/mips/lemote/lm2f/fuloong/Makefile create mode 100644 arch/mips/lemote/lm2f/fuloong/bonito-irq.c create mode 100644 arch/mips/lemote/lm2f/fuloong/dbg_io.c create mode 100644 arch/mips/lemote/lm2f/fuloong/irq.c create mode 100644 arch/mips/lemote/lm2f/fuloong/prom.c create mode 100644 arch/mips/lemote/lm2f/fuloong/reset.c create mode 100644 arch/mips/lemote/lm2f/fuloong/setup.c create mode 100644 arch/mips/lemote/lm2f/yeeloong/Makefile create mode 100644 arch/mips/lemote/lm2f/yeeloong/bonito-irq.c create mode 100644 arch/mips/lemote/lm2f/yeeloong/dbg_io.c create mode 100644 arch/mips/lemote/lm2f/yeeloong/irq.c create mode 100644 arch/mips/lemote/lm2f/yeeloong/prom.c create mode 100644 arch/mips/lemote/lm2f/yeeloong/reset.c create mode 100644 arch/mips/lemote/lm2f/yeeloong/setup.c create mode 100644 arch/mips/pci/fixup-fl2f.c create mode 100644 arch/mips/pci/fixup-yl2f.c create mode 100644 arch/mips/pci/ops-lm2f.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 206cb79..182df7c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -182,6 +182,13 @@ config LEMOTE_FULONG Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and an FPGA northbridge +config MACH_LM2F + bool "Lemote Loongson2F based machines" + help + Loongson2F have built-in DDR2 and PCIX controller. The PCIX controller + have a similar programming interface with FPGA northbridge used in + Loongson2E. + config MIPS_MALTA bool "MIPS Malta board" select ARCH_MAY_HAVE_PC_FDC @@ -649,6 +656,7 @@ source "arch/mips/sibyte/Kconfig" source "arch/mips/txx9/Kconfig" source "arch/mips/vr41xx/Kconfig" source "arch/mips/cavium-octeon/Kconfig" +source "arch/mips/lemote/lm2f/Kconfig" endmenu @@ -1401,7 +1409,6 @@ config 32BIT config 64BIT bool "64-bit kernel" depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL - select HAVE_SYSCALL_WRAPPERS help Select this option if you want to build a 64-bit kernel. diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 22dab2e..6ccfb3d 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -311,6 +311,25 @@ load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000 cflags-$(CONFIG_LEMOTE_FULONG) += -I$(srctree)/arch/mips/include/asm/mach-lemote # +# common lemote loongson2f stuffs +# +core-$(CONFIG_MACH_LM2F) +=arch/mips/lemote/lm2f/common/ + +# +# lemote loongson2f fuloong mini-PC board +# +core-$(CONFIG_LEMOTE_FULOONG2F) +=arch/mips/lemote/lm2f/fuloong/ +load-$(CONFIG_LEMOTE_FULOONG2F) +=0xffffffff80200000 +cflags-$(CONFIG_LEMOTE_FULOONG2F) += -I$(srctree)/arch/mips/include/asm/mach-lemote + +# +# lemote loongson2f yeeloong mini laptop +# +core-$(CONFIG_LEMOTE_YEELOONG2F) +=arch/mips/lemote/lm2f/yeeloong/ +load-$(CONFIG_LEMOTE_YEELOONG2F) +=0xffffffff80200000 +cflags-$(CONFIG_LEMOTE_YEELOONG2F) += -I$(srctree)/arch/mips/include/asm/mach-lemote + +# # MIPS Malta board # core-$(CONFIG_MIPS_MALTA) += arch/mips/mti-malta/ diff --git a/arch/mips/include/asm/mach-lemote/dma-coherence.h b/arch/mips/include/asm/mach-lemote/dma-coherence.h index 38fad7d..b8d79e2 100644 --- a/arch/mips/include/asm/mach-lemote/dma-coherence.h +++ b/arch/mips/include/asm/mach-lemote/dma-coherence.h @@ -27,7 +27,18 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) { +#ifdef CONFIG_64BIT +#ifdef CONFIG_MACH_LM2F + if (dma_addr > 0x8fffffff) + return dma_addr; + else + return dma_addr & 0x0fffffff; +#else return dma_addr & 0x7fffffff; +#endif +#else + return dma_addr & 0x7fffffff; +#endif } static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr) diff --git a/arch/mips/include/asm/mips-boards/bonito64.h b/arch/mips/include/asm/mips-boards/bonito64.h index a0f04bb..4495f81 100644 --- a/arch/mips/include/asm/mips-boards/bonito64.h +++ b/arch/mips/include/asm/mips-boards/bonito64.h @@ -26,7 +26,7 @@ /* offsets from base register */ #define BONITO(x) (x) -#elif defined(CONFIG_LEMOTE_FULONG) +#elif defined(CONFIG_LEMOTE_FULONG) || defined(CONFIG_MACH_LM2F) #define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x))) #define BONITO_IRQ_BASE 32 diff --git a/arch/mips/lemote/lm2f/Kconfig b/arch/mips/lemote/lm2f/Kconfig new file mode 100644 index 0000000..25fb9c0 --- /dev/null +++ b/arch/mips/lemote/lm2f/Kconfig @@ -0,0 +1,70 @@ +choice + prompt "Machine type" + depends on MACH_LM2F + default LEMOTE_FULOONG2F + +config LEMOTE_FULOONG2F + bool "Lemote Fuloong mini-PC" + select ARCH_SPARSEMEM_ENABLE + select CEVT_R4K + select CSRC_R4K + select SYS_HAS_CPU_LOONGSON2 + select DMA_NONCOHERENT + select BOOT_ELF32 + select BOARD_SCACHE + select HW_HAS_PCI + select I8259 + select ISA + select IRQ_CPU + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_HAS_EARLY_PRINTK + select GENERIC_HARDIRQS_NO__DO_IRQ + select GENERIC_ISA_DMA_SUPPORT_BROKEN + select CPU_HAS_WB + select CS5536 + help + Lemote Fulong mini-PC board based on the Chinese Loongson-2F CPU + +config LEMOTE_YEELOONG2F + bool "Lemote Yeloong2F mini Notebook" + select ARCH_SPARSEMEM_ENABLE + select CEVT_R4K + select CSRC_R4K + select SYS_HAS_CPU_LOONGSON2 + select DMA_NONCOHERENT + select BOOT_ELF32 + select BOARD_SCACHE + select HW_HAS_PCI + select I8259 + select ISA + select IRQ_CPU + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_HAS_EARLY_PRINTK + select GENERIC_HARDIRQS_NO__DO_IRQ + select GENERIC_ISA_DMA_SUPPORT_BROKEN + select CPU_HAS_WB + select CS5536 + help + Lemote Notebook based on the Chinese Loongson-2F CPU + +endchoice + +config CS5536_RTC_BUG + bool + +config CS5536 + bool + select CS5536_RTC_BUG + +config LEMOTE_NAS + bool "Lemote NAS machine" + depends on LEMOTE_FULOONG2F + help + Lemote's Loongson-2F based network attached system + diff --git a/arch/mips/lemote/lm2f/common/Makefile b/arch/mips/lemote/lm2f/common/Makefile new file mode 100644 index 0000000..d13d2e8 --- /dev/null +++ b/arch/mips/lemote/lm2f/common/Makefile @@ -0,0 +1,9 @@ +# +# Copyright 2007, 2008 Lemote Tec +# Author: www.lemote.com Inc +# +# Makefile for the loongson2f CPUS, generic files +# + +obj-y += mem.o mipsdha.o pci.o mem.o plat.o +obj-$(CONFIG_CS5536) += cs5536_vsm.o diff --git a/arch/mips/lemote/lm2f/common/cs5536.h b/arch/mips/lemote/lm2f/common/cs5536.h new file mode 100644 index 0000000..c18522a --- /dev/null +++ b/arch/mips/lemote/lm2f/common/cs5536.h @@ -0,0 +1,578 @@ +/* + * cs5536.h + * + * The include file of cs5536 sourthbridge define which is used in the pmon only. + * you can modify it or change it, please set the modify time and steps. + * + * Author : jlliu <liujl@xxxxxxxxxx> + * Data : 07-6-27 + */ + +#ifndef _CS5536_H +#define _CS5536_H + +/*************************************************************************/ + +/* + * basic define + */ +#define PCI_IO_BASE 0x1fd00000 //( < 0x1fe00000) +#define PCI_IO_BASE_VA 0xbfd00000 +#define PCI_MEM_BASE 0x10000000 //( < 0x1c000000 ) +#define PCI_MEM_BASE_VA 0xb0000000 + +/* + * MSR module base + */ +#define CS5536_SB_MSR_BASE (0x00000000) +#define CS5536_GLIU_MSR_BASE (0x10000000) +#define CS5536_ILLEGAL_MSR_BASE (0x20000000) +#define CS5536_USB_MSR_BASE (0x40000000) +#define CS5536_IDE_MSR_BASE (0x60000000) +#define CS5536_DIVIL_MSR_BASE (0x80000000) +#define CS5536_ACC_MSR_BASE (0xa0000000) +#define CS5536_UNUSED_MSR_BASE (0xc0000000) +#define CS5536_GLCP_MSR_BASE (0xe0000000) + +#define SB_MSR_REG(offset) (CS5536_SB_MSR_BASE | offset) +#define GLIU_MSR_REG(offset) (CS5536_GLIU_MSR_BASE | offset) +#define ILLEGAL_MSR_REG(offset) (CS5536_ILLEGAL_MSR_BASE| offset) +#define USB_MSR_REG(offset) (CS5536_USB_MSR_BASE | offset) +#define IDE_MSR_REG(offset) (CS5536_IDE_MSR_BASE | offset) +#define DIVIL_MSR_REG(offset) (CS5536_DIVIL_MSR_BASE | offset) +#define ACC_MSR_REG(offset) (CS5536_ACC_MSR_BASE | offset) +#define UNUSED_MSR_REG(offset) (CS5536_UNUSED_MSR_BASE | offset) +#define GLCP_MSR_REG(offset) (CS5536_GLCP_MSR_BASE | offset) + +/* + * BAR SPACE OF VIRTUAL PCI : range for pci probe use, length is the actual size. + */ +// IO space for all DIVIL modules +#define CS5536_IRQ_RANGE 0xffffffe0 // USERD FOR PCI PROBE +#define CS5536_IRQ_LENGTH 0x20 // THE REGS ACTUAL LENGTH +#define CS5536_SMB_RANGE 0xfffffff8 +#define CS5536_SMB_LENGTH 0x08 +#define CS5536_GPIO_RANGE 0xffffff00 +#define CS5536_GPIO_LENGTH 0x100 +#define CS5536_MFGPT_RANGE 0xffffffc0 +#define CS5536_MFGPT_LENGTH 0x40 +#define CS5536_ACPI_RANGE 0xffffffe0 +#define CS5536_ACPI_LENGTH 0x20 +#define CS5536_PMS_RANGE 0xffffff80 +#define CS5536_PMS_LENGTH 0x80 +// MEM space for 4KB nand flash; IO space for 16B nor flash. +#ifdef CS5536_USE_NOR_FLASH +#define CS5536_FLSH0_RANGE 0xfffffff0 +#define CS5536_FLSH0_LENGTH 0x10 +#define CS5536_FLSH1_RANGE 0xfffffff0 +#define CS5536_FLSH1_LENGTH 0x10 +#define CS5536_FLSH2_RANGE 0xfffffff0 +#define CS5536_FLSH2_LENGTH 0x10 +#define CS5536_FLSH3_RANGE 0xfffffff0 +#define CS5536_FLSH3_LENGTH 0x10 +#else +#define CS5536_FLSH0_RANGE 0xfffff000 +#define CS5536_FLSH0_LENGTH 0x1000 +#define CS5536_FLSH1_RANGE 0xfffff000 +#define CS5536_FLSH1_LENGTH 0x1000 +#define CS5536_FLSH2_RANGE 0xfffff000 +#define CS5536_FLSH2_LENGTH 0x1000 +#define CS5536_FLSH3_RANGE 0xfffff000 +#define CS5536_FLSH3_LENGTH 0x1000 +#endif +// IO space for IDE +#define CS5536_IDE_RANGE 0xfffffff0 +#define CS5536_IDE_LENGTH 0x10 +// IO space for ACC +#define CS5536_ACC_RANGE 0xffffff80 +#define CS5536_ACC_LENGTH 0x80 +// MEM space for ALL USB modules +//#define CS5536_OHCI_RANGE 0xfffffff0 +#define CS5536_OHCI_RANGE 0xfffff000 +#define CS5536_OHCI_LENGTH 0x1000 +//#define CS5536_EHCI_RANGE 0xfffffff0 +#define CS5536_EHCI_RANGE 0xfffff000 +#define CS5536_EHCI_LENGTH 0x1000 +#define CS5536_UDC_RANGE 0xffffe000 +#define CS5536_UDC_LENGTH 0x2000 +#define CS5536_OTG_RANGE 0xfffff000 +#define CS5536_OTG_LENGTH 0x1000 + +/* + * PCI MSR ACCESS + */ +#define PCI_MSR_CTRL 0xF0 +#define PCI_MSR_ADDR 0xF4 +#define PCI_MSR_DATA_LO 0xF8 +#define PCI_MSR_DATA_HI 0xFC + +/******************************* MSR *********************************************/ + +/* + * GLIU STANDARD MSR + */ +#define GLIU_CAP 0x00 +#define GLIU_CONFIG 0x01 +#define GLIU_SMI 0x02 +#define GLIU_ERROR 0x03 +#define GLIU_PM 0x04 +#define GLIU_DIAG 0x05 + +/* + * GLIU SPEC. MSR + */ +#define GLIU_P2D_BM0 0x20 +#define GLIU_P2D_BM1 0x21 +#define GLIU_P2D_BM2 0x22 +#define GLIU_P2D_BMK0 0x23 +#define GLIU_P2D_BMK1 0x24 +#define GLIU_P2D_BM3 0x25 +#define GLIU_P2D_BM4 0x26 +#define GLIU_COH 0x80 +#define GLIU_PAE 0x81 +#define GLIU_ARB 0x82 +#define GLIU_ASMI 0x83 +#define GLIU_AERR 0x84 +#define GLIU_DEBUG 0x85 +#define GLIU_PHY_CAP 0x86 +#define GLIU_NOUT_RESP 0x87 +#define GLIU_NOUT_WDATA 0x88 +#define GLIU_WHOAMI 0x8B +#define GLIU_SLV_DIS 0x8C +#define GLIU_IOD_BM0 0xE0 +#define GLIU_IOD_BM1 0xE1 +#define GLIU_IOD_BM2 0xE2 +#define GLIU_IOD_BM3 0xE3 +#define GLIU_IOD_BM4 0xE4 +#define GLIU_IOD_BM5 0xE5 +#define GLIU_IOD_BM6 0xE6 +#define GLIU_IOD_BM7 0xE7 +#define GLIU_IOD_BM8 0xE8 +#define GLIU_IOD_BM9 0xE9 +#define GLIU_IOD_SC0 0xEA +#define GLIU_IOD_SC1 0xEB +#define GLIU_IOD_SC2 0xEC +#define GLIU_IOD_SC3 0xED +#define GLIU_IOD_SC4 0xEE +#define GLIU_IOD_SC5 0xEF +#define GLIU_IOD_SC6 0xF0 +#define GLIU_IOD_SC7 0xF1 + +/* + * SB STANDARD + */ +#define SB_CAP 0x00 +#define SB_CONFIG 0x01 +#define SB_SMI 0x02 +#define SB_ERROR 0x03 +#define SB_MAR_ERR_EN 0x00000001 +#define SB_TAR_ERR_EN 0x00000002 +#define SB_RSVD_BIT1 0x00000004 +#define SB_EXCEP_ERR_EN 0x00000008 +#define SB_SYSE_ERR_EN 0x00000010 +#define SB_PARE_ERR_EN 0x00000020 +#define SB_TAS_ERR_EN 0x00000040 +#define SB_MAR_ERR_FLAG 0x00010000 +#define SB_TAR_ERR_FLAG 0x00020000 +#define SB_RSVD_BIT2 0x00040000 +#define SB_EXCEP_ERR_FLAG 0x00080000 +#define SB_SYSE_ERR_FLAG 0x00100000 +#define SB_PARE_ERR_FLAG 0x00200000 +#define SB_TAS_ERR_FLAG 0x00400000 +#define SB_PM 0x04 +#define SB_DIAG 0x05 + +/* + * SB SPEC. + */ +#define SB_CTRL 0x10 +#define SB_R0 0x20 +#define SB_R1 0x21 +#define SB_R2 0x22 +#define SB_R3 0x23 +#define SB_R4 0x24 +#define SB_R5 0x25 +#define SB_R6 0x26 +#define SB_R7 0x27 +#define SB_R8 0x28 +#define SB_R9 0x29 +#define SB_R10 0x2A +#define SB_R11 0x2B +#define SB_R12 0x2C +#define SB_R13 0x2D +#define SB_R14 0x2E +#define SB_R15 0x2F + +/* + * GLCP STANDARD + */ +#define GLCP_CAP 0x00 +#define GLCP_CONFIG 0x01 +#define GLCP_SMI 0x02 +#define GLCP_ERROR 0x03 +#define GLCP_PM 0x04 +#define GLCP_DIAG 0x05 + +/* + * GLCP SPEC. + */ +#define GLCP_CLK_DIS_DELAY 0x08 +#define GLCP_PM_CLK_DISABLE 0x09 +#define GLCP_GLB_PM 0x0B +#define GLCP_DBG_OUT 0x0C +#define GLCP_RSVD1 0x0D +#define GLCP_SOFT_COM 0x0E +#define SOFT_BAR_SMB_FLAG 0x00000001 +#define SOFT_BAR_GPIO_FLAG 0x00000002 +#define SOFT_BAR_MFGPT_FLAG 0x00000004 +#define SOFT_BAR_IRQ_FLAG 0x00000008 +#define SOFT_BAR_PMS_FLAG 0x00000010 +#define SOFT_BAR_ACPI_FLAG 0x00000020 +#define SOFT_BAR_FLSH0_FLAG 0x00000040 +#define SOFT_BAR_FLSH1_FLAG 0x00000080 +#define SOFT_BAR_FLSH2_FLAG 0x00000100 +#define SOFT_BAR_FLSH3_FLAG 0x00000200 +#define SOFT_BAR_IDE_FLAG 0x00000400 +#define SOFT_BAR_ACC_FLAG 0x00000800 +#define SOFT_BAR_OHCI_FLAG 0x00001000 +#define SOFT_BAR_EHCI_FLAG 0x00002000 +#define SOFT_BAR_UDC_FLAG 0x00004000 +#define SOFT_BAR_OTG_FLAG 0x00008000 +#define GLCP_RSVD2 0x0F +#define GLCP_CLK_OFF 0x10 +#define GLCP_CLK_ACTIVE 0x11 +#define GLCP_CLK_DISABLE 0x12 +#define GLCP_CLK4ACK 0x13 +#define GLCP_SYS_RST 0x14 +#define GLCP_RSVD3 0x15 +#define GLCP_DBG_CLK_CTRL 0x16 +#define GLCP_CHIP_REV_ID 0x17 + +/* + * DIVIL STANDARD + */ +#define DIVIL_CAP 0x00 +#define DIVIL_CONFIG 0x01 +#define DIVIL_SMI 0x02 +#define DIVIL_ERROR 0x03 +#define DIVIL_PM 0x04 +#define DIVIL_DIAG 0x05 + +/* + * DIVIL SPEC. + */ +#define DIVIL_LBAR_IRQ 0x08 +#define DIVIL_LBAR_KEL 0x09 +#define DIVIL_LBAR_SMB 0x0B +#define DIVIL_LBAR_GPIO 0x0C +#define DIVIL_LBAR_MFGPT 0x0D +#define DIVIL_LBAR_ACPI 0x0E +#define DIVIL_LBAR_PMS 0x0F +#define DIVIL_LBAR_FLSH0 0x10 +#define DIVIL_LBAR_FLSH1 0x11 +#define DIVIL_LBAR_FLSH2 0x12 +#define DIVIL_LBAR_FLSH3 0x13 +#define DIVIL_LEG_IO 0x14 +#define DIVIL_BALL_OPTS 0x15 +#define DIVIL_SOFT_IRQ 0x16 +#define DIVIL_SOFT_RESET 0x17 +// NOR FLASH +#define NORF_CTRL 0x18 +#define NORF_T01 0x19 +#define NORF_T23 0x1A +// NAND FLASH +#define NANDF_DATA 0x1B +#define NANDF_CTRL 0x1C +#define NANDF_RSVD 0x1D +// KEL Keyboard Emulation Logic +#define KEL_CTRL 0x1F +// PIC +#define PIC_YSEL_LOW 0x20 +#define PIC_YSEL_LOW_USB_SHIFT 8 +#define PIC_YSEL_LOW_ACC_SHIFT 16 +#define PIC_YSEL_LOW_FLASH_SHIFT 24 +#define PIC_YSEL_HIGH 0x21 +#define PIC_ZSEL_LOW 0x22 +#define PIC_ZSEL_HIGH 0x23 +#define PIC_IRQM_PRIM 0x24 +#define PIC_IRQM_LPC 0x25 +#define PIC_XIRR_STS_LOW 0x26 +#define PIC_XIRR_STS_HIGH 0x27 +#define PCI_SHDW 0x34 +// MFGPT +#define MFGPT_IRQ 0x28 +#define MFGPT_NR 0x29 +#define MFGPT_RSVD 0x2A +#define MFGPT_SETUP 0x2B +// FLOPPY +#define FLPY_3F2_SHDW 0x30 +#define FLPY_3F7_SHDW 0x31 +#define FLPY_372_SHDW 0x32 +#define FLPY_377_SHDW 0x33 +// PIT +#define PIT_SHDW 0x36 +#define PIT_CNTRL 0x37 +// UART +#define UART1_MOD 0x38 +#define UART1_DONG 0x39 +#define UART1_CONF 0x3A +#define UART1_RSVD 0x3B +#define UART2_MOD 0x3C +#define UART2_DONG 0x3D +#define UART2_CONF 0x3E +#define UART2_RSVD 0x3F +// DMA +#define DIVIL_AC_DMA 0x1E +#define DMA_MAP 0x40 +#define DMA_SHDW_CH0 0x41 +#define DMA_SHDW_CH1 0x42 +#define DMA_SHDW_CH2 0x43 +#define DMA_SHDW_CH3 0x44 +#define DMA_SHDW_CH4 0x45 +#define DMA_SHDW_CH5 0x46 +#define DMA_SHDW_CH6 0x47 +#define DMA_SHDW_CH7 0x48 +#define DMA_MSK_SHDW 0x49 +// LPC +#define LPC_EADDR 0x4C +#define LPC_ESTAT 0x4D +#define LPC_SIRQ 0x4E +#define LPC_RSVD 0x4F +// PMC +#define PMC_LTMR 0x50 +#define PMC_RSVD 0x51 +// RTC +#define RTC_RAM_LOCK 0x54 +#define RTC_DOMA_OFFSET 0x55 +#define RTC_MONA_OFFSET 0x56 +#define RTC_CEN_OFFSET 0x57 + +/* + * IDE STANDARD + */ +#define IDE_CAP 0x00 +#define IDE_CONFIG 0x01 +#define IDE_SMI 0x02 +#define IDE_ERROR 0x03 +#define IDE_PM 0x04 +#define IDE_DIAG 0x05 + +/* + * IDE SPEC. + */ +#define IDE_IO_BAR 0x08 +#define IDE_CFG 0x10 +#define IDE_DTC 0x12 +#define IDE_CAST 0x13 +#define IDE_ETC 0x14 +#define IDE_INTERNAL_PM 0x15 + +/* + * ACC STANDARD + */ +#define ACC_CAP 0x00 +#define ACC_CONFIG 0x01 +#define ACC_SMI 0x02 +#define ACC_ERROR 0x03 +#define ACC_PM 0x04 +#define ACC_DIAG 0x05 + +/* + * USB STANDARD + */ +#define USB_CAP 0x00 +#define USB_CONFIG 0x01 +#define USB_SMI 0x02 +#define USB_ERROR 0x03 +#define USB_PM 0x04 +#define USB_DIAG 0x05 + +/* + * USB SPEC. + */ +#define USB_OHCI 0x08 +#define USB_EHCI 0x09 +#define USB_UDC 0x0A +#define USB_OTG 0x0B + +/********************************** NATIVE ****************************************/ +// IDE NATIVE registers +#define IDE_BM_CMD 0x00 +#define IDE_BM_STS 0x02 +#define IDE_BM_PRD 0x04 + +// OHCI native registers +#define OHCI_REVISION 0x00 +#define OHCI_CONTROL 0x04 +#define OHCI_COMMAND_STATUS 0x08 +#define OHCI_INT_STATUS 0x0C +#define OHCI_INT_ENABLE 0x10 +#define OHCI_INT_DISABLE 0x14 +#define OHCI_HCCA 0x18 +#define OHCI_PERI_CUR_ED 0x1C +#define OHCI_CTRL_HEAD_ED 0x20 +#define OHCI_CTRL_CUR_ED 0x24 +#define OHCI_BULK_HEAD_ED 0x28 +#define OHCI_BULK_CUR_ED 0x2C +#define OHCI_DONE_HEAD 0x30 +#define OHCI_FM_INTERVAL 0x34 +#define OHCI_FM_REMAINING 0x38 +#define OHCI_FM_NUMBER 0x3C +#define OHCI_PERI_START 0x40 +#define OHCI_LS_THRESHOLD 0x44 +#define OHCI_RH_DESCRIPTORA 0x48 +#define OHCI_RH_DESCRIPTORB 0x4C +#define OHCI_RH_STATUS 0x50 +#define OHCI_RH_PORT_STATUS1 0x54 +#define OHCI_RH_PORT_STATUS2 0x58 +#define OHCI_RH_PORT_STATUS3 0x5C +#define OHCI_RH_PORT_STATUS4 0x60 + +// KEL : MEM SPACE; REG :32BITS WIDTH +#define KEL_HCE_CTRL 0x100 +#define KEL_HCE_IN 0x104 +#define KEL_HCE_OUT 0x108 +#define KEL_HCE_STS 0x10C +#define KEL_PORTA 0x92 //8bits +// PIC : I/O SPACE; REG : 8BITS +#define PIC_ICW1_MASTER 0x20 +#define PIC_ICW1_SLAVE 0xA0 +#define PIC_ICW2_MASTER 0x21 +#define PIC_ICW2_SLAVE 0xA1 +#define PIC_ICW3_MASTER 0x21 +#define PIC_ICW3_SLAVE 0xA1 +#define PIC_ICW4_MASTER 0x21 +#define PIC_ICW4_SLAVE 0xA1 +#define PIC_OCW1_MASTER 0x21 +#define PIC_OCW1_SLAVE 0xA1 +#define PIC_OCW2_MASTER 0x20 +#define PIC_OCW2_SLAVE 0xA0 +#define PIC_OCW3_MASTER 0x20 +#define PIC_OCW3_SLAVE 0xA0 +#define PIC_IRR_MASTER 0x20 +#define PIC_IRR_SLAVE 0xA0 +#define PIC_ISR_MASTER 0x20 +#define PIC_ISR_SLAVE 0xA0 +#define PIC_INT_SEL1 0x4D0 +#define PIC_INT_SEL2 0x4D1 +// GPIO : I/O SPACE; REG : 32BITS +#define GPIOL_OUT_VAL 0x00 +#define GPIOL_OUT_EN 0x04 +#define GPIOL_OUT_OD_EN 0x08 +#define GPIOL_OUT_INVRT_EN 0x0c +#define GPIOL_OUT_AUX1_SEL 0x10 +#define GPIOL_OUT_AUX2_SEL 0x14 +#define GPIOL_PU_EN 0x18 +#define GPIOL_PD_EN 0x1c +#define GPIOL_IN_EN 0x20 +#define GPIOL_IN_INVRT_EN 0x24 +#define GPIOL_IN_FLTR_EN 0x28 +#define GPIOL_IN_EVNTCNT_EN 0x2c +#define GPIOL_IN_READBACK 0x30 +#define GPIOL_IN_AUX1_SEL 0x34 +#define GPIOL_EVNT_EN 0x38 +#define GPIOL_LOCK_EN 0x3c +#define GPIOL_IN_POSEDGE_EN 0x40 +#define GPIOL_IN_NEGEDGE_EN 0x44 +#define GPIOL_IN_POSEDGE_STS 0x48 +#define GPIOL_IN_NEGEDGE_STS 0x4c +#define GPIOH_OUT_VAL 0x80 +#define GPIOH_OUT_EN 0x84 +#define GPIOH_OUT_OD_EN 0x88 +#define GPIOH_OUT_INVRT_EN 0x8c +#define GPIOH_OUT_AUX1_SEL 0x90 +#define GPIOH_OUT_AUX2_SEL 0x94 +#define GPIOH_PU_EN 0x98 +#define GPIOH_PD_EN 0x9c +#define GPIOH_IN_EN 0xA0 +#define GPIOH_IN_INVRT_EN 0xA4 +#define GPIOH_IN_FLTR_EN 0xA8 +#define GPIOH_IN_EVNTCNT_EN 0xAc +#define GPIOH_IN_READBACK 0xB0 +#define GPIOH_IN_AUX1_SEL 0xB4 +#define GPIOH_EVNT_EN 0xB8 +#define GPIOH_LOCK_EN 0xBc +#define GPIOH_IN_POSEDGE_EN 0xC0 +#define GPIOH_IN_NEGEDGE_EN 0xC4 +#define GPIOH_IN_POSEDGE_STS 0xC8 +#define GPIOH_IN_NEGEDGE_STS 0xCC +// SMB : I/O SPACE, REG : 8BITS WIDTH +#define SMB_SDA 0x00 +#define SMB_STS 0x01 +#define SMB_STS_SLVSTP (1 << 7) +#define SMB_STS_SDAST (1 << 6) +#define SMB_STS_BER (1 << 5) +#define SMB_STS_NEGACK (1 << 4) +#define SMB_STS_STASTR (1 << 3) +#define SMB_STS_NMATCH (1 << 2) +#define SMB_STS_MASTER (1 << 1) +#define SMB_STS_XMIT (1 << 0) +#define SMB_CTRL_STS 0x02 +#define SMB_CSTS_TGSTL (1 << 5) +#define SMB_CSTS_TSDA (1 << 4) +#define SMB_CSTS_GCMTCH (1 << 3) +#define SMB_CSTS_MATCH (1 << 2) +#define SMB_CSTS_BB (1 << 1) +#define SMB_CSTS_BUSY (1 << 0) +#define SMB_CTRL1 0x03 +#define SMB_CTRL1_STASTRE (1 << 7) +#define SMB_CTRL1_NMINTE (1 << 6) +#define SMB_CTRL1_GCMEN (1 << 5) +#define SMB_CTRL1_ACK (1 << 4) +#define SMB_CTRL1_RSVD (1 << 3) +#define SMB_CTRL1_INTEN (1 << 2) +#define SMB_CTRL1_STOP (1 << 1) +#define SMB_CTRL1_START (1 << 0) +#define SMB_ADDR 0x04 +#define SMB_ADDR_SAEN (1 << 7) +#define SMB_CONTROLLER_ADDR (0xef << 0) +#define SMB_CTRL2 0x05 +#define SMB_FREQ (0x20 << 1) //(0x7f << 1) +#define SMB_ENABLE (0x01 << 0) +#define SMB_CTRL3 0x06 + +/*********************************** LEGACY I/O *******************************/ + +/* + * LEGACY I/O SPACE BASE + */ +#define CS5536_LEGACY_BASE_ADDR (PCI_IO_BASE_VA | 0x0000) + +/* + * IDE LEGACY REG : legacy IO address is 0x170~0x177 and 0x376 (0x1f0~0x1f7 and 0x3f6) + * all registers are 16bits except the IDE_LEGACY_DATA reg + * some registers are read only and the + */ +#define PRI_IDE_LEGACY_REG(offset) (CS5536_LEGACY_BASE_ADDR | 0x1f0 | offset) +#define SEC_IDE_LEGACY_REG(offset) (CS5536_LEGACY_BASE_ADDR | 0x170 | offset) + +#define IDE_LEGACY_DATA 0x00 // RW +#define IDE_LEGACY_ERROR 0x01 // RO +#define IDE_LEGACY_FEATURE 0x01 // WO +#define IDE_LEGACY_SECTOR_COUNT 0x02 // RW +#define IDE_LEGACY_SECTOR_NUM 0x03 // RW +#define IDE_LEGACY_CYL_LO 0x04 // RW +#define IDE_LEGACY_CYL_HI 0x05 // RW +#define IDE_LEGACY_HEAD 0x06 // RW +#define IDE_LEGACY_HEAD_DRV (1 << 4) +#define IDE_LEGACY_HEAD_LBA (1 << 6) +#define IDE_LEGACY_HEAD_IBM (1 << 7 | 1 << 5) +#define IDE_LEGACY_STATUS 0x07 // RO +#define IDE_LEGACY_STATUS_ERR (1 << 0) +#define IDE_LEGACY_STATUS_IDX (1 << 1) +#define IDE_LEGACY_STATUS_CORR (1 << 2) +#define IDE_LEGACY_STATUS_DRQ (1 << 3) +#define IDE_LEGACY_STATUS_DSC (1 << 4) +#define IDE_LEGACY_STATUS_DWF (1 << 5) +#define IDE_LEGACY_STATUS_DRDY (1 << 6) +#define IDE_LEGACY_STATUS_BUSY (1 << 7) +#define IDE_LEGACY_COMMAND 0x07 // WO +#define IDE_LEGACY_ASTATUS 0x206 // RO +#define IDE_LEGACY_CTRL 0x206 // WO +#define IDE_LEGACY_CTRL_IDS 0x02 +#define IDE_LEGACY_CTRL_RST 0x04 +#define IDE_LEGACY_CTRL_4BIT 0x08 + +/**********************************************************************************/ + +#endif /* _CS5536_H */ diff --git a/arch/mips/lemote/lm2f/common/cs5536_pci.h b/arch/mips/lemote/lm2f/common/cs5536_pci.h new file mode 100644 index 0000000..eed94fb --- /dev/null +++ b/arch/mips/lemote/lm2f/common/cs5536_pci.h @@ -0,0 +1,181 @@ +/* + * cs5536_vsm.h + * the definition file of cs5536 Virtual Support Module(VSM). + * pci configuration space can be accessed through the VSM, so + * there is no need the MSR read/write now, except the spec. MSR + * registers which are not implemented yet. + * + * Author : jlliu <liujl@xxxxxxxxxx> + * Date : 07-07-04 + * + */ + +#ifndef _CS5536_PCI_H +#define _CS5536_PCI_H + +/**********************************************************************/ + +//#define TEST_CS5536_USE_FLASH +//#ifdef TEST_CS5536_USE_FLASH +//#define TEST_CS5536_USE_NOR_FLASH +//#endif +#define TEST_CS5536_USE_EHCI +#define TEST_CS5536_USE_UDC +#define TEST_CS5536_USE_OTG + +/**********************************************************************/ + +#define PCI_SPECIAL_SHUTDOWN 1 +#define CS5536_FLASH_INTR 6 +#define CS5536_ACC_INTR 9 +#define CS5536_IDE_INTR 14 +#define CS5536_USB_INTR 11 +#define CS5536_UART1_INTR 4 +#define CS5536_UART2_INTR 3 + +/************************* PCI BUS DEVICE FUNCTION ********************/ + +/* + * PCI bus device function + */ +#define PCI_BUS_CS5536 0 +#define PCI_IDSEL_CS5536 14 +#define PCI_CFG_BASE 0x02000000 + +#define CS5536_ISA_FUNC 0 +#define CS5536_FLASH_FUNC 1 +#define CS5536_IDE_FUNC 2 +#define CS5536_ACC_FUNC 3 +#define CS5536_OHCI_FUNC 4 +#define CS5536_EHCI_FUNC 5 +#define CS5536_UDC_FUNC 6 +#define CS5536_OTG_FUNC 7 +#define CS5536_FUNC_START 0 +#define CS5536_FUNC_END 7 +#define CS5536_FUNC_COUNT (CS5536_FUNC_END - CS5536_FUNC_START + 1) + +/***************************** STANDARD PCI-2.2 EXPANSION ***********************/ + +/* + * PCI configuration space + * we have to virtualize the PCI configure space head, so we should + * define the necessary IDs and some others. + */ +/* VENDOR ID */ +#define CS5536_VENDOR_ID 0x1022 + +/* DEVICE ID */ +#define CS5536_ISA_DEVICE_ID 0x2090 +#define CS5536_FLASH_DEVICE_ID 0x2091 +#define CS5536_IDE_DEVICE_ID 0x209a +#define CS5536_ACC_DEVICE_ID 0x2093 +#define CS5536_OHCI_DEVICE_ID 0x2094 +#define CS5536_EHCI_DEVICE_ID 0x2095 +#define CS5536_UDC_DEVICE_ID 0x2096 +#define CS5536_OTG_DEVICE_ID 0x2097 + +/* CLASS CODE : CLASS SUB-CLASS INTERFACE */ +#define CS5536_ISA_CLASS_CODE 0x060100 +#define CS5536_FLASH_CLASS_CODE 0x050100 +#define CS5536_IDE_CLASS_CODE 0x010180 +#define CS5536_ACC_CLASS_CODE 0x040100 +#define CS5536_OHCI_CLASS_CODE 0x0C0310 +#define CS5536_EHCI_CLASS_CODE 0x0C0320 +#define CS5536_UDC_CLASS_CODE 0x0C03FE +#define CS5536_OTG_CLASS_CODE 0x0C0380 + +/* BHLC : BIST HEADER-TYPE LATENCY-TIMER CACHE-LINE-SIZE */ +#define PCI_NONE_BIST 0x00 //RO not implemented yet. +#define PCI_BRIDGE_HEADER_TYPE 0x80 //RO +#define PCI_NORMAL_HEADER_TYPE 0x00 +#define PCI_NORMAL_LATENCY_TIMER 0x00 +#define PCI_NORMAL_CACHE_LINE_SIZE 0x08 //RW + +/* BAR */ +#define PCI_BAR0_REG 0x10 +#define PCI_BAR1_REG 0x14 +#define PCI_BAR2_REG 0x18 +#define PCI_BAR3_REG 0x1c +#define PCI_BAR4_REG 0x20 +#define PCI_BAR5_REG 0x24 +#define PCI_BAR_COUNT 6 +#define PCI_BAR_RANGE_MASK 0xFFFFFFFF + +/* CARDBUS CIS POINTER */ +#define PCI_CARDBUS_CIS_POINTER 0x00000000 + +/* SUBSYSTEM VENDOR ID */ +#define CS5536_SUB_VENDOR_ID CS5536_VENDOR_ID + +/* SUBSYSTEM ID */ +#define CS5536_ISA_SUB_ID CS5536_ISA_DEVICE_ID +#define CS5536_FLASH_SUB_ID CS5536_FLASH_DEVICE_ID +#define CS5536_IDE_SUB_ID CS5536_IDE_DEVICE_ID +#define CS5536_ACC_SUB_ID CS5536_ACC_DEVICE_ID +#define CS5536_OHCI_SUB_ID CS5536_OHCI_DEVICE_ID +#define CS5536_EHCI_SUB_ID CS5536_EHCI_DEVICE_ID +#define CS5536_UDC_SUB_ID CS5536_UDC_DEVICE_ID +#define CS5536_OTG_SUB_ID CS5536_OTG_DEVICE_ID + +/* EXPANSION ROM BAR */ +#define PCI_EXPANSION_ROM_BAR 0x00000000 + +/* CAPABILITIES POINTER */ +#define PCI_CAPLIST_POINTER 0x00000000 +#define PCI_CAPLIST_USB_POINTER 0x40 +/* INTERRUPT */ +#define PCI_MAX_LATENCY 0x40 +#define PCI_MIN_GRANT 0x00 +#define PCI_DEFAULT_PIN 0x01 + +/**************************** EXPANSION PCI REG **************************************/ + +/* + * ISA EXPANSION + */ +#define PCI_UART1_INT_REG 0x50 +#define PCI_UART2_INT_REG 0x54 +#define PCI_ISA_FIXUP_REG 0x58 + +/* + * FLASH EXPANSION + */ +#define PCI_FLASH_INT_REG 0x50 +#define PCI_NOR_FLASH_CTRL_REG 0x40 +#define PCI_NOR_FLASH_T01_REG 0x44 +#define PCI_NOR_FLASH_T23_REG 0x48 +#define PCI_NAND_FLASH_TDATA_REG 0x60 +#define PCI_NAND_FLASH_TCTRL_REG 0x64 +#define PCI_NAND_FLASH_RSVD_REG 0x68 +#define PCI_FLASH_SELECT_REG 0x70 + +/* + * IDE EXPANSION + */ +#define PCI_IDE_CFG_REG 0x40 +#define CS5536_IDE_FLASH_SIGNATURE 0xDEADBEEF +#define PCI_IDE_DTC_REG 0x48 +#define PCI_IDE_CAST_REG 0x4C +#define PCI_IDE_ETC_REG 0x50 +#define PCI_IDE_PM_REG 0x54 +#define PCI_IDE_INT_REG 0x60 + +/* + * ACC EXPANSION + */ +#define PCI_ACC_INT_REG 0x50 + +/* + * OHCI EXPANSION : INTTERUPT IS IMPLEMENTED BY THE OHCI + */ +#define PCI_OHCI_PM_REG 0x40 +#define PCI_OHCI_INT_REG 0x50 + +/* + * EHCI EXPANSION + */ +#define PCI_EHCI_LEGSMIEN_REG 0x50 +#define PCI_EHCI_LEGSMISTS_REG 0x54 +#define PCI_EHCI_FLADJ_REG 0x60 + +#endif /* _CS5536_PCI_H_ */ diff --git a/arch/mips/lemote/lm2f/common/cs5536_vsm.c b/arch/mips/lemote/lm2f/common/cs5536_vsm.c new file mode 100644 index 0000000..01b06b1 --- /dev/null +++ b/arch/mips/lemote/lm2f/common/cs5536_vsm.c @@ -0,0 +1,2294 @@ +/* + * pci_machdep_cs5536.c + * the Virtual Support Module(VSM) for virtulize the PCI configure + * space. so user can access the PCI configure space directly as + * a normal multi-function PCI device which following the PCI-2.2 spec. + * + * Author : jlliu <liujl@xxxxxxxxxx> + * Date : 07-07-05 + * + */ +#include <linux/types.h> + +#include "cs5536.h" +#include "cs5536_pci.h" +#include "pcireg.h" + +extern void _wrmsr(u32 reg, u32 hi, u32 lo); +extern void _rdmsr(u32 reg, u32 *hi, u32 *lo); + +/******************************INTERNAL USED FUNCTIONS***********************************/ + +/* + * divil_lbar_enable_disable : enable/disable the divil module bar space. + * For all the DIVIL module LBAR, you should control the DIVIL LBAR reg + * and the RCONFx(0~5) reg to use the modules. + */ +static void divil_lbar_enable_disable(int enable) +{ + u32 hi, lo; + + /* + * The DIVIL IRQ is not used yet. and make the RCONF0 reserved. + */ + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), hi, lo); + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), hi, lo); + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_PMS), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_PMS), hi, lo); + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_ACPI), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_ACPI), hi, lo); + + /* + * RCONF0 is reserved to the DIVIL IRQ mdoule + */ +#if 0 + _rdmsr(SB_MSR_REG(SB_R1), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R1), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R2), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R2), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R3), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R3), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R4), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R4), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R5), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R5), hi, lo); +#endif + return; +} + +#ifdef TEST_CS5536_USE_FLASH +/* + * flash_lbar_enable_disable : enable or disable the region of flashs(NOR or NAND) + * the same as the DIVIL other modules above, two groups of regs should be modified + * here to control the region. DIVIL flash LBAR and the RCONFx(6~9 reserved). + */ +static void flash_lbar_enable_disable(int enable) +{ + u32 hi, lo; + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), hi, lo); + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH1), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH1), hi, lo); + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH2), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH2), hi, lo); + + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH3), &hi, &lo); + if(enable) + hi |= 0x01; + else + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH3), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R6), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R6), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R7), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R7), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R8), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R8), hi, lo); + + _rdmsr(SB_MSR_REG(SB_R9), &hi, &lo); + if(enable) + lo |= 0x01; + else + lo &= ~0x01; + _wrmsr(SB_MSR_REG(SB_R9), hi, lo); + + return; +} +#endif + + +/**********************************MODULES*********************************************/ + +/* + * isa_write : isa write transfering. + * WE assume that the ISA is not the BUS MASTER.!!! + */ +/* FAST BACK TO BACK '1' for BUS MASTER '0' for BUS SALVE */ +/* COMMAND : + * bit0 : IO SPACE ENABLE + * bit1 : MEMORY SPACE ENABLE(ignore) + * bit2 : BUS MASTER ENABLE(ignore) + * bit3 : SPECIAL CYCLE(ignore)? default is ignored. + * bit4 : MEMORY WRITE and INVALIDATE(ignore) + * bit5 : VGA PALETTE(ignore) + * bit6 : PARITY ERROR(ignore)? : default is ignored. + * bit7 : WAIT CYCLE CONTROL(ignore) + * bit8 : SYSTEM ERROR(ignore) + * bit9 : FAST BACK TO BACK(ignore) + * bit10-bit15 : RESERVED + * STATUS : + * bit0-bit3 : RESERVED + * bit4 : CAPABILITY LIST(ignore) + * bit5 : 66MHZ CAPABLE + * bit6 : RESERVED + * bit7 : FAST BACK TO BACK(ignore) + * bit8 : DATA PARITY ERROR DETECED(ignore) + * bit9-bit10 : DEVSEL TIMING(ALL MEDIUM) + * bit11: SIGNALED TARGET ABORT + * bit12: RECEIVED TARGET ABORT + * bit13: RECEIVED MASTER ABORT + * bit14: SIGNALED SYSTEM ERROR + * bit15: DETECTED PARITY ERROR + */ +static void pci_isa_write_reg(int reg, u32 value) +{ + u32 hi, lo; + u32 temp; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // command + if( value & PCI_COMMAND_IO_ENABLE ){ + divil_lbar_enable_disable(1); + }else{ + divil_lbar_enable_disable(0); + } +#if 0 + /* PER response enable or disable. */ + if( value & PCI_COMMAND_PARITY_ENABLE ){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + lo |= SB_PARE_ERR_EN; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + }else{ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + lo &= ~SB_PARE_ERR_EN; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } +#endif + // status + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + temp = lo & 0x0000ffff; + if( (value & PCI_STATUS_TARGET_TARGET_ABORT) && + (lo & SB_TAS_ERR_EN) ){ + temp |= SB_TAS_ERR_FLAG; + } + if( (value & PCI_STATUS_MASTER_TARGET_ABORT) && + (lo & SB_TAR_ERR_EN) ){ + temp |= SB_TAR_ERR_FLAG; + } + if( (value & PCI_STATUS_MASTER_ABORT) && + (lo & SB_MAR_ERR_EN) ){ + temp |= SB_MAR_ERR_FLAG; + } + if( (value & PCI_STATUS_PARITY_DETECT) && + (lo & SB_PARE_ERR_EN) ){ + temp |= SB_PARE_ERR_FLAG; + } + lo = temp; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + break; + case PCI_BHLC_REG : + value &= 0x0000ff00; + _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); + hi &= 0xffffff00; + hi |= (value >> 8); + _wrmsr(SB_MSR_REG(SB_CTRL), hi, lo); + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_SMB_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // SMB NATIVE IO space has 8bytes + hi = 0x0000f001; + lo = value & 0x0000fff8; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); + + // RCONFx is 4bytes in units for IO space. + hi = ((value & 0x000ffffc) << 12) | ((CS5536_SMB_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R0), hi, lo); + } + break; + case PCI_BAR1_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_GPIO_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // GPIO NATIVE reg is 256bytes + hi = 0x0000f001; + lo = value & 0x0000ff00; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), hi, lo); + + // RCONFx is 4bytes in units for IO space + hi = ((value & 0x000ffffc) << 12) | ((CS5536_GPIO_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R1), hi, lo); + } + break; + case PCI_BAR2_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_MFGPT_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // MFGPT NATIVE reg is 64bytes + hi = 0x0000f001; + lo = value & 0x0000ffc0; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), hi, lo); + + // RCONFx is 4bytes in units for IO space + hi = ((value & 0x000ffffc) << 12) | ((CS5536_MFGPT_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R2), hi, lo); + } + break; + case PCI_BAR3_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_IRQ_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // IRQ NATIVE reg is 32bytes + hi = 0x0000f001; + lo = value & 0x0000ffc0; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_IRQ), hi, lo); + + // RCONFx is 4bytes in units for IO space + hi = ((value & 0x000ffffc) << 12) | ((CS5536_IRQ_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R3), hi, lo); + } + break; + case PCI_BAR4_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_PMS_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // PMS NATIVE reg is 128bytes + hi = 0x0000f001; + lo = value & 0x0000ff80; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_PMS), hi, lo); + + // RCONFx is 4bytes in units for IO space. + hi = ((value & 0x000ffffc) << 12) | ((CS5536_PMS_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R4), hi, lo); + } + break; + case PCI_BAR5_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_ACPI_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // ACPI NATIVE reg is 32bytes + hi = 0x0000f001; + lo = value & 0x0000ffe0; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_ACPI), hi, lo); + + // RCONFx is 4bytes in units for IO space. + hi = ((value & 0x000ffffc) << 12) | ((CS5536_ACPI_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R5), hi, lo); + } + break; + case PCI_UART1_INT_REG : + if(value){ + /* enable uart1 interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); + lo &= ~(0xf << 24); + lo |= (CS5536_UART1_INTR << 24); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo); + }else{ + /* disable uart1 interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); + lo &= ~(0xf << 24); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo); + } + break; + case PCI_UART2_INT_REG : + if(value){ + /* enable uart2 interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); + lo &= ~(0xf << 28); + lo |= (CS5536_UART2_INTR << 28); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo); + }else{ + /* disable uart2 interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); + lo &= ~(0xf << 28); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo); + } + break; + case PCI_ISA_FIXUP_REG : + if(value){ + /* enable the TARGET ABORT/MASTER ABORT etc. */ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + lo |= 0x00000063; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + + default : + /* ALL OTHER PCI CONFIG SPACE HEADER IS NOT IMPLEMENTED. */ + break; + } + + return; +} + +/* + * isa_read : isa read transfering. + * we assume that the ISA is not the BUS MASTER. + */ + + /* COMMAND : + * bit0 : IO SPACE ENABLE + * bit1 : MEMORY SPACE ENABLE(ignore) + * bit2 : BUS MASTER ENABLE(ignore) + * bit3 : SPECIAL CYCLE(ignore)? default is ignored. + * bit4 : MEMORY WRITE and INVALIDATE(ignore) + * bit5 : VGA PALETTE(ignore) + * bit6 : PARITY ERROR(ignore)? : default is ignored. + * bit7 : WAIT CYCLE CONTROL(ignore) + * bit8 : SYSTEM ERROR(ignore) + * bit9 : FAST BACK TO BACK(ignore) + * bit10-bit15 : RESERVED + * STATUS : + * bit0-bit3 : RESERVED + * bit4 : CAPABILITY LIST(ignore) + * bit5 : 66MHZ CAPABLE + * bit6 : RESERVED + * bit7 : FAST BACK TO BACK(ignore) + * bit8 : DATA PARITY ERROR DETECED(ignore)? + * bit9-bit10 : DEVSEL TIMING(ALL MEDIUM) + * bit11: SIGNALED TARGET ABORT + * bit12: RECEIVED TARGET ABORT + * bit13: RECEIVED MASTER ABORT + * bit14: SIGNALED SYSTEM ERROR + * bit15: DETECTED PARITY ERROR(?) + */ + +static u32 pci_isa_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_ISA_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + // we just check the first LBAR for the IO enable bit, + // maybe we should changed later. + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), &hi, &lo); + if(hi & 0x01){ + conf_data |= PCI_COMMAND_IO_ENABLE; + } + //conf_data |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; +#if 0 + conf_data |= PCI_COMMAND_SPECIAL_ENABLE; +#endif +#if 0 + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_EN){ + conf_data |= PCI_COMMAND_PARITY_ENABLE; + }else{ + conf_data &= ~PCI_COMMAND_PARITY_ENABLE; + } +#endif + // STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; +#if 1 + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; +#endif + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_TAS_ERR_FLAG) + conf_data |= PCI_STATUS_TARGET_TARGET_ABORT; + if(lo & SB_TAR_ERR_FLAG) + conf_data |= PCI_STATUS_MASTER_TARGET_ABORT; + if(lo & SB_MAR_ERR_FLAG) + conf_data |= PCI_STATUS_MASTER_ABORT; + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_DETECT; + break; + case PCI_CLASS_REG : + _rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_ISA_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); + hi &= 0x000000f8; + conf_data = (PCI_NONE_BIST << 24) | (PCI_BRIDGE_HEADER_TYPE << 16) | + (hi << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + /* + * we only use the LBAR of DIVIL, no RCONF used. + * all of them are IO space. + */ + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_SMB_FLAG){ + conf_data = CS5536_SMB_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_SMB_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), &hi, &lo); + conf_data = lo & 0x0000fff8; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR1_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_GPIO_FLAG){ + conf_data = CS5536_GPIO_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_GPIO_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo); + conf_data = lo & 0x0000ff00; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR2_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_MFGPT_FLAG){ + conf_data = CS5536_MFGPT_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_MFGPT_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &hi, &lo); + conf_data = lo & 0x0000ffc0; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; +#if 1 + case PCI_BAR3_REG : + conf_data = 0; + break; +#else + case PCI_BAR3_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_IRQ_FLAG){ + conf_data = CS5536_IRQ_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_IRQ_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_IRQ), &hi, &lo); + conf_data = lo & 0x0000ffc0; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; +#endif + case PCI_BAR4_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_PMS_FLAG){ + conf_data = CS5536_PMS_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_PMS_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_PMS), &hi, &lo); + conf_data = lo & 0x0000ff80; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR5_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_ACPI_FLAG){ + conf_data = CS5536_ACPI_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_ACPI_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_ACPI), &hi, &lo); + conf_data = lo & 0x0000ffe0; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_ISA_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (0x00 << 8) | 0x00; + break; + default : + conf_data = 0; + break; + } + + return conf_data; +} + +#ifdef TEST_CS5536_USE_FLASH + +#ifndef TEST_CS5536_USE_NOR_FLASH /* for nand flash */ +static void pci_flash_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // command + if( value & PCI_COMMAND_MEM_ENABLE ){ + flash_lbar_enable_disable(1); + }else{ + flash_lbar_enable_disable(0); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + // make the flag for reading the bar length. + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH0_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + // mem space nand flash native reg base addr + hi = 0xfffff007; + lo = value & 0xfffff000; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), hi, lo); + + // RCONFx is 4KB in units for mem space. + hi = ((value & 0xfffff000) << 12) | ( (CS5536_FLSH0_LENGTH & 0xfffff000) - (1 << 12) ) | 0x00; + lo = ((value & 0xfffff000) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R6), hi, lo); + } + break; + case PCI_BAR1_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH1_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + // mem space nand flash native reg base addr + hi = 0xfffff007; + lo = value & 0xfffff000; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH1), hi, lo); + + // RCONFx is 4KB in units for mem space. + hi = ((value & 0xfffff000) << 12) | ( (CS5536_FLSH1_LENGTH & 0xfffff000) - (1 << 12) ) | 0x00; + lo = ((value & 0xfffff000) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R7), hi, lo); + } + break; + case PCI_BAR2_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH2_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + // mem space nand flash native reg base addr + hi = 0xfffff007; + lo = value & 0xfffff000; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH2), hi, lo); + + // RCONFx is 4KB in units for mem space. + hi = ((value & 0xfffff000) << 12) | ( (CS5536_FLSH2_LENGTH & 0xfffff000) - (1 << 12) ) | 0x00; + lo = ((value & 0xfffff000) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R8), hi, lo); + } + break; + case PCI_BAR3_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH3_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + // mem space nand flash native reg base addr + hi = 0xfffff007; + lo = value & 0xfffff000; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH3), hi, lo); + + // RCONFx is 4KB in units for mem space. + hi = ((value & 0xfffff000) << 12) | ( (CS5536_FLSH3_LENGTH & 0xfffff000)- (1 << 12) ) | 0x00; + lo = ((value & 0xfffff000) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R9), hi, lo); + } + break; + case PCI_FLASH_INT_REG : + if(value){ + /* enable all the flash interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << PIC_YSEL_LOW_FLASH_SHIFT); + lo |= (CS5536_FLASH_INTR << PIC_YSEL_LOW_FLASH_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + }else{ + /* disable all the flash interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << PIC_YSEL_LOW_FLASH_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + } + break; + case PCI_NAND_FLASH_TDATA_REG : + hi = 0; + lo = value; + _wrmsr(DIVIL_MSR_REG(NANDF_DATA), hi, lo); + break; + case PCI_NAND_FLASH_TCTRL_REG : + hi = 0; + lo = value & 0x00000fff; + _wrmsr(DIVIL_MSR_REG(NANDF_CTRL), hi, lo); + break; + case PCI_NAND_FLASH_RSVD_REG : + hi = 0; + lo = value; + _wrmsr(DIVIL_MSR_REG(NANDF_RSVD), hi, lo); + break; + case PCI_FLASH_SELECT_REG : + if(value == CS5536_IDE_FLASH_SIGNATURE){ + _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo); + lo &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo); + } + break; + default : + break; + } + + return; +} + +static u32 pci_flash_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_FLASH_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + // we just read one lbar for returning. + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), &hi, &lo); + if(hi & 0x01) + conf_data |= PCI_COMMAND_MEM_ENABLE; + //STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(DIVIL_MSR_REG(DIVIL_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_FLASH_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (PCI_NORMAL_LATENCY_TIMER << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH0_FLAG){ + conf_data = CS5536_FLSH0_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH0_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), &hi, &lo); + conf_data = lo; + conf_data &= ~0x0f; + } + break; + case PCI_BAR1_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH1_FLAG){ + conf_data = CS5536_FLSH1_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH1_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH1), &hi, &lo); + conf_data = lo; + conf_data &= ~0x0f; + } + break; + case PCI_BAR2_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH2_FLAG){ + conf_data = CS5536_FLSH2_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH2_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH2), &hi, &lo); + conf_data = lo; + conf_data &= ~0x0f; + } + break; + case PCI_BAR3_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH3_FLAG){ + conf_data = CS5536_FLSH3_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH3_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH3), &hi, &lo); + conf_data = lo; + conf_data &= ~0x0f; + } + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_FLASH_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_FLASH_INTR); + break; + case PCI_NAND_FLASH_TDATA_REG : + _rdmsr(DIVIL_MSR_REG(NANDF_DATA), &hi, &lo); + conf_data = lo; + break; + case PCI_NAND_FLASH_TCTRL_REG : + _rdmsr(DIVIL_MSR_REG(NANDF_CTRL), &hi, &lo); + conf_data = lo & 0x00000fff; + break; + case PCI_NAND_FLASH_RSVD_REG : + _rdmsr(DIVIL_MSR_REG(NANDF_RSVD), &hi, &lo); + conf_data = lo; + break; + case PCI_FLASH_SELECT_REG : + _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo); + conf_data = lo & 0x01; + break; + + } + return 0; +} + +#else /* nor flash */ + +static void pci_flash_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // command + if( value & PCI_COMMAND_IO_ENABLE ){ + flash_lbar_enable_disable(1); + }else{ + flash_lbar_enable_disable(0); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH0_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // IO space of 16bytes nor flash + hi = 0x0000fff1; + lo = value & 0x0000fff0; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), hi, lo); + + // RCONFx used for 16bytes reserved. + hi = ((value & 0x000ffffc) << 12) | ((CS5536_FLSH0_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R6), hi, lo); + } + break; + case PCI_BAR1_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH1_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // IO space of 16bytes nor flash + hi = 0x0000fff1; + lo = value & 0x0000fff0; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH1), hi, lo); + + // RCONFx used for 16bytes reserved. + hi = ((value & 0x000ffffc) << 12) | ((CS5536_FLSH1_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R7), hi, lo); + } + break; + case PCI_BAR2_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH2_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + hi = 0x0000fff1; + lo = value & 0x0000fff0; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH2), hi, lo); + + hi = ((value & 0x000ffffc) << 12) | ((CS5536_FLSH2_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R8), hi, lo); + } + break; + case PCI_BAR3_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_FLSH3_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + // 16bytes for nor flash + hi = 0x0000fff1; + lo = value & 0x0000fff0; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH3), hi, lo); + + // 16bytes of IO space of RCONFx region. + hi = ((value & 0x000ffffc) << 12) | ((CS5536_FLSH3_LENGTH - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(SB_MSR_REG(SB_R9), hi, lo); + } + break; + + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_FLASH_INTR); + break; + case PCI_FLASH_INT_REG : + if(value){ + /* enable all the flash interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << PIC_YSEL_LOW_FLASH_SHIFT); + lo |= (CS5536_FLASH_INTR << PIC_YSEL_LOW_FLASH_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + }else{ + /* disable all the flash interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << PIC_YSEL_LOW_FLASH_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + } + break; + case PCI_NOR_FLASH_CTRL_REG : + hi = 0; + lo = value & 0x000000ff; + _wrmsr(DIVIL_MSR_REG(NORF_CTRL), hi, lo); + break; + case PCI_NOR_FLASH_T01_REG : + hi = 0; + lo = value; + _wrmsr(DIVIL_MSR_REG(NORF_T01), hi, lo); + break; + case PCI_NOR_FLASH_T23_REG : + hi = 0; + lo = value; + _wrmsr(DIVIL_MSR_REG(NORF_T23), hi, lo); + break; + case PCI_FLASH_SELECT_REG : + if(value == CS5536_IDE_FLASH_SIGNATURE){ + _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo); + lo &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo); + } + break; + + default : + break; + } + + return; +} + +static u32 pci_flash_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_FLASH_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + // we just check one flash bar for returning. + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), &hi, &lo); + if(hi & 0x01) + conf_data |= PCI_COMMAND_IO_ENABLE; + //STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(DIVIL_MSR_REG(DIVIL_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_FLASH_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (PCI_NORMAL_LATENCY_TIMER << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH0_FLAG){ + conf_data = CS5536_FLSH0_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH0_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), &hi, &lo); + conf_data = lo & 0x0000ffff; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR1_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH1_FLAG){ + conf_data = CS5536_FLSH1_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH1_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH1), &hi, &lo); + conf_data = lo & 0x0000ffff; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR2_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH2_FLAG){ + conf_data = CS5536_FLSH2_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH2_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH2), &hi, &lo); + conf_data = lo & 0x0000ffff; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR3_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_FLSH3_FLAG){ + conf_data = CS5536_FLSH3_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_FLSH3_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH3), &hi, &lo); + conf_data = lo & 0x0000ffff; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_FLASH_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_FLASH_INTR); + break; + case PCI_NOR_FLASH_CTRL_REG : + _rdmsr(DIVIL_MSR_REG(NORF_CTRL), &hi, &lo); + conf_data = lo & 0x000000ff; + break; + case PCI_NOR_FLASH_T01_REG : + _rdmsr(DIVIL_MSR_REG(NORF_T01), &hi, &lo); + conf_data = lo; + break; + case PCI_NOR_FLASH_T23_REG : + _rdmsr(DIVIL_MSR_REG(NORF_T23), &hi, &lo); + conf_data = lo; + break; + default : + conf_data = 0; + break; + } + return conf_data; +} +#endif /* TEST_CS5536_USE_NOR_FLASH */ + +#else /* TEST_CS5536_USE_FLASH */ + +static void pci_flash_write_reg(int reg, u32 value) +{ + return; +} + +static u32 pci_flash_read_reg(int reg) +{ + return 0xffffffff; +} + +#endif /* TEST_CS5536_USE_FLASH */ + +/* + * ide_write : ide write transfering + */ +static void pci_ide_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // COMMAND + if(value & PCI_COMMAND_MASTER_ENABLE){ + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + lo |= (0x03 << 4); + _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo); + }else{ + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + lo &= ~(0x03 << 4); + _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BHLC_REG : + value &= 0x0000ff00; + _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); + hi &= 0xffffff00; + hi |= (value >> 8); + _wrmsr(SB_MSR_REG(SB_CTRL), hi, lo); + break; + case PCI_BAR4_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_IDE_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if(value & 0x01){ + hi = 0x00000000; + //lo = ((value & 0x0fffffff) << 4) | 0x001; + lo = (value & 0xfffffff0) | 0x1; + _wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo); + + value &= 0xfffffffc; + hi = 0x60000000 | ((value & 0x000ff000) >> 12); + lo = 0x000ffff0 | ((value & 0x00000fff) << 20); + _wrmsr(GLIU_MSR_REG(GLIU_IOD_BM2), hi, lo); + } + break; + case PCI_IDE_CFG_REG : + if(value == CS5536_IDE_FLASH_SIGNATURE){ + _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo); + lo |= 0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo); + }else{ + hi = 0; + lo = value; + _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo); + } + break; + case PCI_IDE_DTC_REG : + hi = 0; + lo = value; + _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo); + break; + case PCI_IDE_CAST_REG : + hi = 0; + lo = value; + _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo); + break; + case PCI_IDE_ETC_REG : + hi = 0; + lo = value; + _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo); + break; + case PCI_IDE_PM_REG : + hi = 0; + lo = value; + _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo); + break; + default : + break; + } + + return; +} + +/* + * ide_read : ide read tranfering. + */ +static u32 pci_ide_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_IDE_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo); + if(lo & 0xfffffff0) + conf_data |= PCI_COMMAND_IO_ENABLE; + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + if( (lo & 0x30) == 0x30 ) + conf_data |= PCI_COMMAND_MASTER_ENABLE; + /* conf_data |= PCI_COMMAND_BACKTOBACK_ENABLE??? HOW TO GET..*/ + //STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(IDE_MSR_REG(IDE_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_IDE_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); + hi &= 0x000000f8; + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (hi << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + conf_data = 0x00000000; + break; + case PCI_BAR1_REG : + conf_data = 0x00000000; + break; + case PCI_BAR2_REG : + conf_data = 0x00000000; + break; + case PCI_BAR3_REG : + conf_data = 0x00000000; + break; + case PCI_BAR4_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_IDE_FLAG){ + conf_data = CS5536_IDE_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_IDE_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo); + //conf_data = lo >> 4; + conf_data = lo & 0xfffffff0; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR5_REG : + conf_data = 0x00000000; + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_IDE_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_IDE_INTR); + break; + case PCI_IDE_CFG_REG : + _rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo); + conf_data = lo; + break; + case PCI_IDE_DTC_REG : + _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo); + conf_data = lo; + break; + case PCI_IDE_CAST_REG : + _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo); + conf_data = lo; + break; + case PCI_IDE_ETC_REG : + _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo); + conf_data = lo; + case PCI_IDE_PM_REG : + _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo); + conf_data = lo; + break; + + default : + conf_data = 0; + break; + } + + return conf_data; +} + +static void pci_acc_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // COMMAND + if(value & PCI_COMMAND_MASTER_ENABLE){ + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + lo |= (0x03 << 8); + _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo); + }else{ + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + lo &= ~(0x03 << 8); + _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_ACC_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( value & 0x01 ){ + value &= 0xfffffffc; + hi = 0xA0000000 | ((value & 0x000ff000) >> 12); + lo = 0x000fff80 | ((value & 0x00000fff) << 20); + _wrmsr(GLIU_MSR_REG(GLIU_IOD_BM1), hi, lo); + } + break; + case PCI_ACC_INT_REG : + if(value){ + /* enable all the acc interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << PIC_YSEL_LOW_ACC_SHIFT); + lo |= (CS5536_ACC_INTR << PIC_YSEL_LOW_ACC_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + }else{ + /* disable all the usb interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << PIC_YSEL_LOW_ACC_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + } + break; + default : + break; + } + + return; +} + +static u32 pci_acc_read_reg(int reg) +{ + u32 hi, lo; + u32 conf_data; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_ACC_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + + conf_data = 0; + // COMMAND + _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo); + if( ( (lo & 0xfff00000) || (hi & 0x000000ff) ) + && ((hi & 0xf0000000) == 0xa0000000) ) + conf_data |= PCI_COMMAND_IO_ENABLE; + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + if( (lo & 0x300) == 0x300 ) + conf_data |= PCI_COMMAND_MASTER_ENABLE; + /* conf_data |= PCI_COMMAND_BACKTOBACK_ENABLE??? HOW TO GET..*/ + //STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(ACC_MSR_REG(ACC_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_ACC_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (PCI_NORMAL_LATENCY_TIMER << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_ACC_FLAG){ + conf_data = CS5536_ACC_RANGE | PCI_MAPREG_TYPE_IO; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_ACC_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo); + conf_data = (hi & 0x000000ff) << 12; + conf_data |= (lo & 0xfff00000) >> 20; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_BAR1_REG : + conf_data = 0x000000; + break; + case PCI_BAR2_REG : + conf_data = 0x000000; + break; + case PCI_BAR3_REG : + conf_data = 0x000000; + break; + case PCI_BAR4_REG : + conf_data = 0x000000; + break; + case PCI_BAR5_REG : + conf_data = 0x000000; + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_ACC_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_ACC_INTR); + break; + default : + conf_data = 0; + break; + } + + return conf_data; +} + + +/* + * ohci_write : ohci write tranfering. + */ +static void pci_ohci_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // COMMAND + if(value & PCI_COMMAND_MASTER_ENABLE){ + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + hi |= (1 << 2); + _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + hi &= ~(1 << 2); + _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); + } + if(value & PCI_COMMAND_MEM_ENABLE){ + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + hi |= (1 << 1); + _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + hi &= ~(1 << 1); + _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_OHCI_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + //lo = (value & 0xffffff00) << 8; + lo = value; + _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); + + value &= 0xfffffff0; + hi = 0x40000000 | ((value & 0xff000000) >> 24); + lo = 0x000fffff | ((value & 0x00fff000) << 8); + _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM3), hi, lo); + } + break; + case PCI_INTERRUPT_REG : + value &= 0x000000ff; + break; + case PCI_OHCI_PM_REG : + break; + case PCI_OHCI_INT_REG : + if(value){ + /* enable all the usb interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << 8); + lo |= (CS5536_USB_INTR << 8); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + }else{ + /* disable all the usb interrupt in PIC */ + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << 8); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + } + break; + default : + break; + } + + return; +} + +/* + * ohci_read : ohci read transfering. + */ +static u32 pci_ohci_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_OHCI_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + if(hi & 0x04) + conf_data |= PCI_COMMAND_MASTER_ENABLE; + if(hi & 0x02) + conf_data |= PCI_COMMAND_MEM_ENABLE; + // STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_OHCI_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (0x00 << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_OHCI_FLAG){ + conf_data = CS5536_OHCI_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_OHCI_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + //conf_data = lo >> 8; + conf_data = lo & 0xffffff00; + conf_data &= ~0x0000000f; // 32bit mem + } + break; + case PCI_BAR1_REG : + conf_data = 0x000000; + break; + case PCI_BAR2_REG : + conf_data = 0x000000; + break; + case PCI_BAR3_REG : + conf_data = 0x000000; + break; + case PCI_BAR4_REG : + conf_data = 0x000000; + break; + case PCI_BAR5_REG : + conf_data = 0x000000; + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_OHCI_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_USB_INTR); + break; + case PCI_OHCI_PM_REG : + conf_data = 0; + break; + case PCI_OHCI_INT_REG : + _rdmsr(DIVIL_MSR_REG(0x20), &hi, &lo); + if((lo & 0x00000f00) == 11) + conf_data = 1; + else + conf_data = 0; + break; + default : + conf_data = 0; + break; + } + + return conf_data; +} + +#ifdef TEST_CS5536_USE_EHCI +static void pci_ehci_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // COMMAND + if(value & PCI_COMMAND_MASTER_ENABLE){ + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + hi |= (1 << 2); + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + hi &= ~(1 << 2); + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + } + if(value & PCI_COMMAND_MEM_ENABLE){ + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + hi |= (1 << 1); + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + hi &= ~(1 << 1); + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_EHCI_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + lo = value; + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + + value &= 0xfffffff0; + hi = 0x40000000 | ((value & 0xff000000) >> 24); + lo = 0x000fffff | ((value & 0x00fff000) << 8); + _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM4), hi, lo); + } + break; + case PCI_EHCI_LEGSMIEN_REG : + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + hi &= 0x003f0000; + hi |= (value & 0x3f) << 16; + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + break; + case PCI_EHCI_FLADJ_REG : + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + hi &= ~0x00003f00; + hi |= value & 0x00003f00; + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + break; + default : + break; + } + + return; +} + +static u32 pci_ehci_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_EHCI_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + if(hi & 0x04) + conf_data |= PCI_COMMAND_MASTER_ENABLE; + if(hi & 0x02) + conf_data |= PCI_COMMAND_MEM_ENABLE; + // STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_EHCI_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (PCI_NORMAL_LATENCY_TIMER << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_EHCI_FLAG){ + conf_data = CS5536_EHCI_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_EHCI_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + conf_data = lo & 0xfffff000; + } + break; + case PCI_BAR1_REG : + conf_data = 0x000000; + break; + case PCI_BAR2_REG : + conf_data = 0x000000; + break; + case PCI_BAR3_REG : + conf_data = 0x000000; + break; + case PCI_BAR4_REG : + conf_data = 0x000000; + break; + case PCI_BAR5_REG : + conf_data = 0x000000; + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_EHCI_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_USB_INTR); + break; + case PCI_EHCI_LEGSMIEN_REG : + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + conf_data = (hi & 0x003f0000) >> 16; + break; + case PCI_EHCI_LEGSMISTS_REG : + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + conf_data = (hi & 0x3f000000) >> 24; + break; + case PCI_EHCI_FLADJ_REG : + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + conf_data = hi & 0x00003f00; + break; + default : + conf_data = 0; + break; + } + + return conf_data; +} +#else +static void pci_ehci_write_reg(int reg, u32 value) +{ + return; +} + +static u32 pci_ehci_read_reg(int reg) +{ + return 0xffffffff; +} + + +#endif + +#ifdef TEST_CS5536_USE_UDC +static void pci_udc_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // COMMAND + if(value & PCI_COMMAND_MASTER_ENABLE){ + _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo); + hi |= (1 << 2); + _wrmsr(USB_MSR_REG(USB_UDC), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo); + hi &= ~(1 << 2); + _wrmsr(USB_MSR_REG(USB_UDC), hi, lo); + } + if(value & PCI_COMMAND_MEM_ENABLE){ + _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo); + hi |= (1 << 1); + _wrmsr(USB_MSR_REG(USB_UDC), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo); + hi &= ~(1 << 1); + _wrmsr(USB_MSR_REG(USB_UDC), hi, lo); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_UDC_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo); + lo = value; + _wrmsr(USB_MSR_REG(USB_UDC), hi, lo); + + value &= 0xfffffff0; + hi = 0x40000000 | ((value & 0xff000000) >> 24); + lo = 0x000fffff | ((value & 0x00fff000) << 8); + _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM0), hi, lo); + } + break; + default : + break; + } + + return; +} + +static u32 pci_udc_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_UDC_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo); + if(hi & 0x04) + conf_data |= PCI_COMMAND_MASTER_ENABLE; + if(hi & 0x02) + conf_data |= PCI_COMMAND_MEM_ENABLE; + // STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_UDC_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (0x00 << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_UDC_FLAG){ + conf_data = CS5536_UDC_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_UDC_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo); + conf_data = lo & 0xfffff000; + conf_data &= ~0x0000000f; // 32bit mem + } + break; + case PCI_BAR1_REG : + conf_data = 0x000000; + break; + case PCI_BAR2_REG : + conf_data = 0x000000; + break; + case PCI_BAR3_REG : + conf_data = 0x000000; + break; + case PCI_BAR4_REG : + conf_data = 0x000000; + break; + case PCI_BAR5_REG : + conf_data = 0x000000; + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_UDC_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_USB_INTR); + break; + default : + conf_data = 0; + break; + } + + return conf_data; +} + +#else /* TEST_CS5536_USE_UDC */ + +static void pci_udc_write_reg(int reg, u32 value) +{ + return; +} + +static u32 pci_udc_read_reg(int reg) +{ + return 0xffffffff; +} + +#endif /* TEST_CS5536_USE_UDC */ + + +#ifdef TEST_CS5536_USE_OTG +static void pci_otg_write_reg(int reg, u32 value) +{ + u32 hi, lo; + + switch(reg){ + case PCI_COMMAND_STATUS_REG : + // COMMAND + if(value & PCI_COMMAND_MEM_ENABLE){ + _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo); + hi |= (1 << 1); + _wrmsr(USB_MSR_REG(USB_OTG), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo); + hi &= ~(1 << 1); + _wrmsr(USB_MSR_REG(USB_OTG), hi, lo); + } + // STATUS + if(value & PCI_STATUS_PARITY_ERROR){ + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG){ + lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + } + } + break; + case PCI_BAR0_REG : + if(value == PCI_BAR_RANGE_MASK){ + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= SOFT_BAR_OTG_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else if( (value & 0x01) == 0x00 ){ + _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo); + lo = value & 0xffffff00; + _wrmsr(USB_MSR_REG(USB_OTG), hi, lo); + + value &= 0xfffffff0; + hi = 0x40000000 | ((value & 0xff000000) >> 24); + lo = 0x000fffff | ((value & 0x00fff000) << 8); + _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM1), hi, lo); + } + break; + default : + break; + } + + return; +} + +static u32 pci_otg_read_reg(int reg) +{ + u32 conf_data; + u32 hi, lo; + + switch(reg){ + case PCI_ID_REG : + conf_data = (CS5536_OTG_DEVICE_ID << 16 | CS5536_VENDOR_ID); + break; + case PCI_COMMAND_STATUS_REG : + conf_data = 0; + // COMMAND + _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo); + if(hi & 0x02) + conf_data |= PCI_COMMAND_MEM_ENABLE; + // STATUS + conf_data |= PCI_STATUS_66MHZ_SUPPORT; + conf_data |= PCI_STATUS_BACKTOBACK_SUPPORT; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if(lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY_ERROR; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REG : + _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_OTG_CLASS_CODE << 8); + break; + case PCI_BHLC_REG : + conf_data = (PCI_NONE_BIST << 24) | (PCI_NORMAL_HEADER_TYPE << 16) | + (0x00 << 8) | PCI_NORMAL_CACHE_LINE_SIZE; + break; + case PCI_BAR0_REG : + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if(lo & SOFT_BAR_OTG_FLAG){ + conf_data = CS5536_OTG_RANGE | PCI_MAPREG_TYPE_MEM; + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo &= ~SOFT_BAR_OTG_FLAG; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + }else{ + _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo); + conf_data = lo & 0xffffff00; + conf_data &= ~0x0000000f; + } + break; + case PCI_BAR1_REG : + conf_data = 0x000000; + break; + case PCI_BAR2_REG : + conf_data = 0x000000; + break; + case PCI_BAR3_REG : + conf_data = 0x000000; + break; + case PCI_BAR4_REG : + conf_data = 0x000000; + break; + case PCI_BAR5_REG : + conf_data = 0x000000; + break; + case PCI_CARDBUS_CIS_REG : + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYS_ID_REG : + conf_data = (CS5536_OTG_SUB_ID << 16) | CS5536_SUB_VENDOR_ID; + break; + case PCI_MAPREG_ROM : + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPLISTPTR_REG : + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_REG : + conf_data = (PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | + (PCI_DEFAULT_PIN << 8) | (CS5536_USB_INTR); + break; + default : + conf_data = 0; + break; + } + + return conf_data; +} + +#else /* TEST_CS5536_USE_OTG */ + +static void pci_otg_write_reg(int reg, u32 value) +{ + return; +} + +static u32 pci_otg_read_reg(int reg) +{ + return 0xffffffff; +} + +#endif /* TEST_CS5536_USE_OTG */ + +/*******************************************************************************/ + +/* + * writen : write to PCI config space and transfer it to MSR write. + */ +void cs5536_pci_conf_write4(int function, int reg, u32 value) +{ + /* some basic checking. */ + if( (function < CS5536_FUNC_START) || (function > CS5536_FUNC_END) ){ + return; + } + if( (reg < 0) || (reg > 0x100) || ((reg & 0x03) != 0) ){ + return; + } + + switch(function){ + case CS5536_ISA_FUNC : + pci_isa_write_reg(reg, value); + break; + + case CS5536_FLASH_FUNC : + pci_flash_write_reg(reg, value); + break; + + case CS5536_IDE_FUNC : + pci_ide_write_reg(reg, value); + break; + + case CS5536_ACC_FUNC : + pci_acc_write_reg(reg, value); + break; + + case CS5536_OHCI_FUNC : + pci_ohci_write_reg(reg, value); + break; + + case CS5536_EHCI_FUNC : + pci_ehci_write_reg(reg, value); + break; + + case CS5536_UDC_FUNC : + pci_udc_write_reg(reg, value); + break; + + case CS5536_OTG_FUNC : + pci_otg_write_reg(reg, value); + break; + + default : + break; + } + + return; +} + +/* + * readn : read PCI config space and transfer it to MSR access. + */ +u32 cs5536_pci_conf_read4(int function, int reg) +{ + u32 data = 0; + + /* some basic checking. */ + if( (function < CS5536_FUNC_START) || (function > CS5536_FUNC_END) ){ + return 0; + } + if( (reg < 0) || ((reg & 0x03) != 0) ){ + return 0; + } + if( reg > 0x100 ) + return 0xffffffff; + + switch(function){ + case CS5536_ISA_FUNC : + data = pci_isa_read_reg(reg); + break; + + case CS5536_FLASH_FUNC : + data = pci_flash_read_reg(reg); + break; + + case CS5536_IDE_FUNC : + data = pci_ide_read_reg(reg); + break; + + case CS5536_ACC_FUNC : + data = pci_acc_read_reg(reg); + break; + + case CS5536_OHCI_FUNC : + data = pci_ohci_read_reg(reg); + break; + + case CS5536_EHCI_FUNC : + data = pci_ehci_read_reg(reg); + break; + + case CS5536_UDC_FUNC : + data = pci_udc_read_reg(reg); + break; + + case CS5536_OTG_FUNC : + data = pci_otg_read_reg(reg); + break; + + default : + break; + + } + + return data; +} + +/**************************************************************************/ + diff --git a/arch/mips/lemote/lm2f/common/mem.c b/arch/mips/lemote/lm2f/common/mem.c new file mode 100644 index 0000000..aa25ad4 --- /dev/null +++ b/arch/mips/lemote/lm2f/common/mem.c @@ -0,0 +1,23 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/fs.h> +#include <linux/fcntl.h> +#include <linux/mm.h> + +/* override of arch/mips/mm/cache.c: __uncached_access */ +int __uncached_access(struct file *file, unsigned long addr) +{ + if (file->f_flags & O_SYNC) + return 1; + + /* + * On the Lemote 2f system, the peripheral IO/MMIO space + * reside between 0x1000:0000 and 0x8000:0000. + */ + return addr >= __pa(high_memory) || + ((addr >= 0x10000000) && (addr < 0x80000000)); +} diff --git a/arch/mips/lemote/lm2f/common/mfgpt.c b/arch/mips/lemote/lm2f/common/mfgpt.c new file mode 100644 index 0000000..e62a7fd --- /dev/null +++ b/arch/mips/lemote/lm2f/common/mfgpt.c @@ -0,0 +1,222 @@ +/* + * CS5536 General timer functions + * + */ +#include <linux/clockchips.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/spinlock.h> + +#include <asm/delay.h> +#include <asm/io.h> +#include <asm/time.h> + +DEFINE_SPINLOCK(mfgpt_lock); + +#if 1 +#define MFGFT_TICK_RATE 14318000 +#else +#define MFGFT_TICK_RATE (14318180 / 8) +#endif +#define COMPARE ((MFGFT_TICK_RATE + HZ/2) / HZ) + +extern void _wrmsr(u32 reg, u32 hi, u32 lo); +extern void _rdmsr(u32 reg, u32 *hi, u32 *lo); + +static u32 base ; + +/* + * Initialize the MFGPT timer. + * + * This is also called after resume to bring the MFGPT into operation again. + */ +/* setup register bit fields: + 15: counter enable + 14: compare2 output status, write 1 to clear when in event mode + 13: compare1 output status + 12: setup(ro) + 11: stop enable, stop on sleep + 10: external enable + 9:8 compare2 mode; 00: disable, 01: compare on equal; 10: compare on GE, 11 event: GE + irq + 7:6 compare1 mode + 5: reverse enable, bit reverse of the counter + 4: clock select. 0: 32KHz, 1: 14.318MHz + 3:0 counter prescaler scale factor. select the input clock divide-by value. 2^n + bit 11:0 is write once. +*/ + + +static void init_mfgpt_timer(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + spin_lock(&mfgpt_lock); + + switch(mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* set comparator2 */ + outw(COMPARE, base + 2); + /* set counter to 0 */ + outw(0, base + 4); + /* setup; enable, comparator2 to event mode,14.318MHz clock */ + //outw(0xe313, base + 6); + outw(0xe310, base + 6); + break; + + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + if (evt->mode == CLOCK_EVT_MODE_PERIODIC || + evt->mode == CLOCK_EVT_MODE_ONESHOT) { + /* disable counter */ + outw(inw(base+6) & 0x7fff, base + 6); + } + break; + + case CLOCK_EVT_MODE_ONESHOT: + /* One shot setup */ + break; + + case CLOCK_EVT_MODE_RESUME: + /* Nothing to do here */ + break; + } + spin_unlock(&mfgpt_lock); +} + +/* + * Program the next event in oneshot mode + * + * Delta is given in MFGPT ticks + */ +static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) +{ + spin_lock(&mfgpt_lock); + + /* set comparator2 */ + outw(delta & 0xffff, base + 2); + /* set counter to 0 */ + outw(0, base + 4); + /* setup; enable, comparator2 */ + outw(0xe310, base + 6); + + spin_unlock(&mfgpt_lock); + + return 0; +} + +static struct clock_event_device mfgpt_clockevent = { + .name = "mfgpt", + .features = CLOCK_EVT_FEAT_PERIODIC, + .set_mode = init_mfgpt_timer, + .set_next_event = mfgpt_next_event, + .rating = 2000, + .irq = 5, +}; + +static irqreturn_t timer_interrupt(int irq, void *dev_id) +{ + u32 basehi,baselo; + + _rdmsr(0x8000000d,&basehi,&baselo); + + base = baselo; + /* ack */ +// outw(0x0, baselo + 4); + outw(0xc000, baselo + 6); + + mfgpt_clockevent.event_handler(&mfgpt_clockevent); + + return IRQ_HANDLED; +} + +static struct irqaction irq5 = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED | IRQF_NOBALANCING, + .mask = CPU_MASK_NONE, + .name = "timer" +}; + +/* + * Initialize the conversion factor and the min/max deltas of the clock event + * structure and register the clock event source with the framework. + */ +void __init setup_mfgpt_timer(void) +{ + u32 basehi; + struct clock_event_device *cd = &mfgpt_clockevent; + unsigned int cpu = smp_processor_id(); + + cd->cpumask = cpumask_of_cpu(cpu); + clockevent_set_clock(cd, MFGFT_TICK_RATE); + cd->max_delta_ns = clockevent_delta2ns(0xFFFF, cd); + cd->min_delta_ns = clockevent_delta2ns(0xF, cd); + + /* connect multifunction timer0 comparator 2 to irq mapper*/ + _wrmsr(0x80000028, 0, 0x100); + + /* map unrestricted interrupt source Z4 to IG5 */ + _wrmsr(0x80000022, 0, 0x50000); + + _rdmsr(0x8000000d, &basehi, &base); + + irq5.mask = cpumask_of_cpu(cpu); + + clockevents_register_device(cd); + + setup_irq(5, &irq5); + +} + +/* + * Since the MFGPT overflows every tick, its not very useful + * to just read by itself. So use jiffies to emulate a free + * running counter: + */ +static cycle_t mfgpt_read(void) +{ + static cycle_t count, old_count; + static unsigned long old_jifs; + unsigned long jifs; + unsigned long flags; + + spin_lock_irqsave(&mfgpt_lock, flags); + + jifs = jiffies; + + count = inw(base + 4); + + /* overflow ?*/ + if (count < old_count && jifs == old_jifs) { + count = old_count; + } + old_count = count; + old_jifs = jifs; + + spin_unlock_irqrestore(&mfgpt_lock, flags); + + return (cycle_t)(jifs * COMPARE) + count; +} + +static struct clocksource clocksource_mfgpt = { + .name = "mfgpt", + .rating = 1200, + .read = mfgpt_read, + .mask = CLOCKSOURCE_MASK(32), + .mult = 0, + .shift = 22, +}; + +int __init init_mfgpt_clocksource(void) +{ + + if (num_possible_cpus() > 1) /* MFGPT does not scale! */ + return 0; + + setup_mfgpt_timer(); + + clocksource_mfgpt.mult = clocksource_hz2mult(MFGFT_TICK_RATE, 22); + return clocksource_register(&clocksource_mfgpt); +} +/* Too late for kernel calc delay */ +//arch_initcall(init_mfgpt_clocksource); diff --git a/arch/mips/lemote/lm2f/common/mipsdha.c b/arch/mips/lemote/lm2f/common/mipsdha.c new file mode 100644 index 0000000..fd90454 --- /dev/null +++ b/arch/mips/lemote/lm2f/common/mipsdha.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/kernel.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/mm.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/proc_fs.h> +#include <asm/uaccess.h> +#include <asm/io.h> + +static ssize_t mipsdha_proc_read(struct file *file, char *buf, size_t len, loff_t *ppos); + +static ssize_t mipsdha_proc_write(struct file *file, const char *buf, size_t len, loff_t *ppos); + + +static struct proc_dir_entry *mipsdha_proc_entry; + +#define INFO_SIZE 4096 +static char info_buf[INFO_SIZE]; + +static struct file_operations mipsdha_fops = +{ + owner: THIS_MODULE, + read: mipsdha_proc_read, + write: mipsdha_proc_write, +}; + +static enum {CMD_ERR, CMD_GIB, CMD_GPI} cmd; + +typedef struct pciinfo_s +{ + int bus,card,func; + unsigned short command; + unsigned short vendor,device; + unsigned base0,base1,base2,baserom; +} pciinfo_t; + + +extern struct proc_dir_entry proc_root; + +static int __init mipsdha_proc_init(void) +{ + mipsdha_proc_entry = create_proc_entry("mipsdha", S_IWUSR | S_IRUGO, &proc_root); + if (mipsdha_proc_entry == NULL) { + printk("MIPSDHA: register /proc/mipsdha failed!\n"); + return 0; + } + + mipsdha_proc_entry->owner = THIS_MODULE; + mipsdha_proc_entry->proc_fops = &mipsdha_fops; + + cmd=CMD_ERR; + return 0; +} + +static ssize_t mipsdha_proc_write (struct file *file, const char *buf, size_t len, loff_t *ppos) +{ + char cmd_gib[]="GET IO BASE"; + char cmd_gpi[]="GET PCI INFO"; + + if (len >= INFO_SIZE) return -ENOMEM; + + if (copy_from_user(info_buf, buf, len)) return -EFAULT; + info_buf[len] = '\0'; + + if (strncmp(info_buf, cmd_gib, sizeof(cmd_gib)-1)==0) { + cmd = CMD_GIB; + return len; + } else if (strncmp(info_buf, cmd_gpi, sizeof(cmd_gpi)-1)==0) { + cmd = CMD_GPI; + return len; + } else { + return -EINVAL; + } +} + +static ssize_t mipsdha_proc_read (struct file *file, char *buf, size_t len, loff_t *ppos) +{ + int info_cnt; + pciinfo_t *pciinfo; + struct pci_dev *dev = NULL; + + switch (cmd) { + default: + printk("MIPSDHA: BUG found in function %s!(cmd=%d)\n", + __FUNCTION__, cmd); + return -EINVAL; + + + case CMD_ERR: + return -EINVAL; + + + case CMD_GIB: + *(unsigned long *)info_buf = + virt_to_phys((void *) mips_io_port_base); + info_cnt=sizeof(unsigned long); + break; + + + case CMD_GPI: + pciinfo = (pciinfo_t *) info_buf; + info_cnt = 0; + for_each_pci_dev(dev) { + + if (info_cnt+sizeof(pciinfo_t)>INFO_SIZE) return -ENOMEM; + + pciinfo->bus = dev->bus->number; + pciinfo->card = PCI_SLOT(dev->devfn); + pciinfo->func = PCI_FUNC(dev->devfn); + + if (pci_read_config_word(dev, PCI_COMMAND, &pciinfo->command) + != PCIBIOS_SUCCESSFUL) { + printk("MIPSDHA: BUG found in function %s!\n", + __FUNCTION__); + pciinfo->command=0; + } + + pciinfo->vendor = dev->vendor; + pciinfo->device = dev->device; + + pciinfo->base0 = (dev->resource[0]).start; + pciinfo->base1 = (dev->resource[1]).start; + pciinfo->base2 = (dev->resource[2]).start; + pciinfo->baserom = (dev->resource[PCI_ROM_RESOURCE]).start; + + pciinfo++; + info_cnt += sizeof(pciinfo_t); + } + break; + } + + if (len < info_cnt) return -ENOMEM; + if (copy_to_user(buf, info_buf, info_cnt)) return -EFAULT; + + return info_cnt; +} + +__initcall(mipsdha_proc_init); diff --git a/arch/mips/lemote/lm2f/common/pci.c b/arch/mips/lemote/lm2f/common/pci.c new file mode 100644 index 0000000..f7acbe7 --- /dev/null +++ b/arch/mips/lemote/lm2f/common/pci.c @@ -0,0 +1,89 @@ +/* + * pci.c + * + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> + +extern struct pci_ops loongson2f_pci_pci_ops; +/* if you want to expand the pci memory space, you should config 64bits kernel too. */ + +static struct resource loongson2f_pci_mem_resource = { + .name = "LOONGSON2E PCI MEM", + .start = 0x14000000UL, + .end = 0x1fffffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource loongson2f_pci_io_resource = { + .name = "LOONGSON2E PCI IO MEM", + .start = 0x00004000UL, + .end = 0x0000ffffUL, + .flags = IORESOURCE_IO, +}; + + +static struct pci_controller loongson2f_pci_controller = { + .pci_ops = &loongson2f_pci_pci_ops, + .io_resource = &loongson2f_pci_io_resource, + .mem_resource = &loongson2f_pci_mem_resource, + .mem_offset = 0x00000000UL, + .io_offset = 0x00000000UL, +}; + +static int __init pcibios_init(void) +{ + extern int pci_probe_only; + pci_probe_only = 0; + +#ifdef CONFIG_TRACE_BOOT + printk(KERN_INFO"arch_initcall:pcibios_init\n"); + printk(KERN_INFO"register_pci_controller : %x\n",&loongson2f_pci_controller); +#endif + +#ifdef CONFIG_64BIT + loongson2f_pci_mem_resource.start = 0x50000000UL; + loongson2f_pci_mem_resource.end = 0x7fffffffUL; + __asm__(".set mips3\n" + "dli $2,0x900000003ff00000\n" + "li $3,0x40000000\n" + "sd $3,0x18($2)\n" + "or $3,1\n" + "sd $3,0x58($2)\n" + "dli $3,0xffffffffc0000000\n" + "sd $3,0x38($2)\n" + ".set mips0\n" + :::"$2","$3","memory" + ); +#endif + loongson2f_pci_controller.io_map_base = mips_io_port_base; + register_pci_controller(&loongson2f_pci_controller); + return 0; +} + +arch_initcall(pcibios_init); diff --git a/arch/mips/lemote/lm2f/common/pcireg.h b/arch/mips/lemote/lm2f/common/pcireg.h new file mode 100644 index 0000000..aa823d3 --- /dev/null +++ b/arch/mips/lemote/lm2f/common/pcireg.h @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2001, 2006 www.ict.ac.cn. + * Copyright (c) 2006, 2008 www.lemote.com.cn. + * + * 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 named License, + * or 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. + */ + +#ifndef _DEV_PCI_PCIREG_H_ +#define _DEV_PCI_PCIREG_H_ + + +/* + * Standardized PCI configuration information + * + * XXX This is not complete. + */ + +/* + * Device identification register; contains a vendor ID and a device ID. + */ +#define PCI_ID_REG 0x00 + +typedef u_int16_t pci_vendor_id_t; +typedef u_int16_t pci_product_id_t; + +#define PCI_VENDOR_SHIFT 0 +#define PCI_VENDOR_MASK 0xffff +#define PCI_VENDOR(id) \ + (((id) >> PCI_VENDOR_SHIFT) & PCI_VENDOR_MASK) + +#define PCI_PRODUCT_SHIFT 16 +#define PCI_PRODUCT_MASK 0xffff +#define PCI_PRODUCT(id) \ + (((id) >> PCI_PRODUCT_SHIFT) & PCI_PRODUCT_MASK) + +/* + * Command and status register. + */ +#define PCI_COMMAND_STATUS_REG 0x04 + +#define PCI_COMMAND_IO_ENABLE 0x00000001 +#define PCI_COMMAND_MEM_ENABLE 0x00000002 +#define PCI_COMMAND_MASTER_ENABLE 0x00000004 +#define PCI_COMMAND_SPECIAL_ENABLE 0x00000008 +#define PCI_COMMAND_INVALIDATE_ENABLE 0x00000010 +#define PCI_COMMAND_PALETTE_ENABLE 0x00000020 +#define PCI_COMMAND_PARITY_ENABLE 0x00000040 +#define PCI_COMMAND_STEPPING_ENABLE 0x00000080 +#define PCI_COMMAND_SERR_ENABLE 0x00000100 +#define PCI_COMMAND_BACKTOBACK_ENABLE 0x00000200 + +#define PCI_STATUS_CAPLIST_SUPPORT 0x00100000 +#define PCI_STATUS_66MHZ_SUPPORT 0x00200000 +#define PCI_STATUS_UDF_SUPPORT 0x00400000 +#define PCI_STATUS_BACKTOBACK_SUPPORT 0x00800000 +#define PCI_STATUS_PARITY_ERROR 0x01000000 +#define PCI_STATUS_DEVSEL_FAST 0x00000000 +#define PCI_STATUS_DEVSEL_MEDIUM 0x02000000 +#define PCI_STATUS_DEVSEL_SLOW 0x04000000 +#define PCI_STATUS_DEVSEL_MASK 0x06000000 +#define PCI_STATUS_TARGET_TARGET_ABORT 0x08000000 +#define PCI_STATUS_MASTER_TARGET_ABORT 0x10000000 +#define PCI_STATUS_MASTER_ABORT 0x20000000 +#define PCI_STATUS_SPECIAL_ERROR 0x40000000 +#define PCI_STATUS_PARITY_DETECT 0x80000000 + +/* + * PCI Class and Revision Register; defines type and revision of device. + */ +#define PCI_CLASS_REG 0x08 + +typedef u_int8_t pci_class_t; +typedef u_int8_t pci_subclass_t; +typedef u_int8_t pci_interface_t; +typedef u_int8_t pci_revision_t; + +#define PCI_CLASS_SHIFT 24 +#define PCI_CLASS_MASK 0xff +#define PCI_CLASS(cr) \ + (((cr) >> PCI_CLASS_SHIFT) & PCI_CLASS_MASK) + +#define PCI_SUBCLASS_SHIFT 16 +#define PCI_SUBCLASS_MASK 0xff +#define PCI_SUBCLASS(cr) \ + (((cr) >> PCI_SUBCLASS_SHIFT) & PCI_SUBCLASS_MASK) + +#define PCI_ISCLASS(what, class, subclass) \ + (((what) & 0xffff0000) == (class << 24 | subclass << 16)) + +#define PCI_INTERFACE_SHIFT 8 +#define PCI_INTERFACE_MASK 0xff +#define PCI_INTERFACE(cr) \ + (((cr) >> PCI_INTERFACE_SHIFT) & PCI_INTERFACE_MASK) + +#define PCI_REVISION_SHIFT 0 +#define PCI_REVISION_MASK 0xff +#define PCI_REVISION(cr) \ + (((cr) >> PCI_REVISION_SHIFT) & PCI_REVISION_MASK) + +/* base classes */ +#define PCI_CLASS_PREHISTORIC 0x00 +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_CLASS_MULTIMEDIA 0x04 +#define PCI_CLASS_MEMORY 0x05 +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_COMMUNICATIONS 0x07 +#define PCI_CLASS_SYSTEM 0x08 +#define PCI_CLASS_INPUT 0x09 +#define PCI_CLASS_DOCK 0x0a +#define PCI_CLASS_PROCESSOR 0x0b +#define PCI_CLASS_SERIALBUS 0x0c +#define PCI_CLASS_WIRELESS 0x0d +#define PCI_CLASS_I2O 0x0e +#define PCI_CLASS_SATCOM 0x0f +#define PCI_CLASS_CRYPTO 0x10 +#define PCI_CLASS_DASP 0x11 +#define PCI_CLASS_UNDEFINED 0xff + +/* 0x00 prehistoric subclasses */ +#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00 +#define PCI_SUBCLASS_PREHISTORIC_VGA 0x01 + +/* 0x01 mass storage subclasses */ +#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00 +#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x01 +#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x02 +#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x03 +#define PCI_SUBCLASS_MASS_STORAGE_RAID 0x04 +#define PCI_SUBCLASS_MASS_STORAGE_ATA 0x05 +#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x80 + +/* 0x02 network subclasses */ +#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00 +#define PCI_SUBCLASS_NETWORK_TOKENRING 0x01 +#define PCI_SUBCLASS_NETWORK_FDDI 0x02 +#define PCI_SUBCLASS_NETWORK_ATM 0x03 +#define PCI_SUBCLASS_NETWORK_ISDN 0x04 +#define PCI_SUBCLASS_NETWORK_WORLDFIP 0x05 +#define PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP 0x06 +#define PCI_SUBCLASS_NETWORK_MISC 0x80 + +/* 0x03 display subclasses */ +#define PCI_SUBCLASS_DISPLAY_VGA 0x00 +#define PCI_SUBCLASS_DISPLAY_XGA 0x01 +#define PCI_SUBCLASS_DISPLAY_3D 0x02 +#define PCI_SUBCLASS_DISPLAY_MISC 0x80 + +/* 0x04 multimedia subclasses */ +#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00 +#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x01 +#define PCI_SUBCLASS_MULTIMEDIA_TELEPHONY 0x02 +#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x80 + +/* 0x05 memory subclasses */ +#define PCI_SUBCLASS_MEMORY_RAM 0x00 +#define PCI_SUBCLASS_MEMORY_FLASH 0x01 +#define PCI_SUBCLASS_MEMORY_MISC 0x80 + +/* 0x06 bridge subclasses */ +#define PCI_SUBCLASS_BRIDGE_HOST 0x00 +#define PCI_SUBCLASS_BRIDGE_ISA 0x01 +#define PCI_SUBCLASS_BRIDGE_EISA 0x02 +#define PCI_SUBCLASS_BRIDGE_MC 0x03 +#define PCI_SUBCLASS_BRIDGE_PCI 0x04 +#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x05 +#define PCI_SUBCLASS_BRIDGE_NUBUS 0x06 +#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x07 +#define PCI_SUBCLASS_BRIDGE_RACEWAY 0x08 +#define PCI_SUBCLASS_BRIDGE_STPCI 0x09 +#define PCI_SUBCLASS_BRIDGE_INFINIBAND 0x0a +#define PCI_SUBCLASS_BRIDGE_MISC 0x80 + +/* 0x07 communications subclasses */ +#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00 +#define PCI_SUBCLASS_COMMUNICATIONS_PARALLEL 0x01 +#define PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL 0x02 +#define PCI_SUBCLASS_COMMUNICATIONS_MODEM 0x03 +#define PCI_SUBCLASS_COMMUNICATIONS_MISC 0x80 + +/* 0x08 system subclasses */ +#define PCI_SUBCLASS_SYSTEM_PIC 0x00 +#define PCI_SUBCLASS_SYSTEM_DMA 0x01 +#define PCI_SUBCLASS_SYSTEM_TIMER 0x02 +#define PCI_SUBCLASS_SYSTEM_RTC 0x03 +#define PCI_SUBCLASS_SYSTEM_PCIHOTPLUG 0x04 +#define PCI_SUBCLASS_SYSTEM_MISC 0x80 + +/* 0x09 input subclasses */ +#define PCI_SUBCLASS_INPUT_KEYBOARD 0x00 +#define PCI_SUBCLASS_INPUT_DIGITIZER 0x01 +#define PCI_SUBCLASS_INPUT_MOUSE 0x02 +#define PCI_SUBCLASS_INPUT_SCANNER 0x03 +#define PCI_SUBCLASS_INPUT_GAMEPORT 0x04 +#define PCI_SUBCLASS_INPUT_MISC 0x80 + +/* 0x0a dock subclasses */ +#define PCI_SUBCLASS_DOCK_GENERIC 0x00 +#define PCI_SUBCLASS_DOCK_MISC 0x80 + +/* 0x0b processor subclasses */ +#define PCI_SUBCLASS_PROCESSOR_386 0x00 +#define PCI_SUBCLASS_PROCESSOR_486 0x01 +#define PCI_SUBCLASS_PROCESSOR_PENTIUM 0x02 +#define PCI_SUBCLASS_PROCESSOR_ALPHA 0x10 +#define PCI_SUBCLASS_PROCESSOR_POWERPC 0x20 +#define PCI_SUBCLASS_PROCESSOR_MIPS 0x30 +#define PCI_SUBCLASS_PROCESSOR_COPROC 0x40 + +/* 0x0c serial bus subclasses */ +#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00 +#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x01 +#define PCI_SUBCLASS_SERIALBUS_SSA 0x02 +#define PCI_SUBCLASS_SERIALBUS_USB 0x03 +#define PCI_SUBCLASS_SERIALBUS_FIBER 0x04 +#define PCI_SUBCLASS_SERIALBUS_SMBUS 0x05 +#define PCI_SUBCLASS_SERIALBUS_INFINIBAND 0x06 +#define PCI_SUBCLASS_SERIALBUS_IPMI 0x07 +#define PCI_SUBCLASS_SERIALBUS_SERCOS 0x08 +#define PCI_SUBCLASS_SERIALBUS_CANBUS 0x09 + +/* 0x0d wireless subclasses */ +#define PCI_SUBCLASS_WIRELESS_IRDA 0x00 +#define PCI_SUBCLASS_WIRELESS_CONSUMERIR 0x01 +#define PCI_SUBCLASS_WIRELESS_RF 0x10 +#define PCI_SUBCLASS_WIRELESS_MISC 0x80 + +/* 0x0e I2O (Intelligent I/O) subclasses */ +#define PCI_SUBCLASS_I2O_STANDARD 0x00 + +/* 0x0f satellite communication subclasses */ +/* PCI_SUBCLASS_SATCOM_??? 0x00 / * XXX ??? */ +#define PCI_SUBCLASS_SATCOM_TV 0x01 +#define PCI_SUBCLASS_SATCOM_AUDIO 0x02 +#define PCI_SUBCLASS_SATCOM_VOICE 0x03 +#define PCI_SUBCLASS_SATCOM_DATA 0x04 + +/* 0x10 encryption/decryption subclasses */ +#define PCI_SUBCLASS_CRYPTO_NETCOMP 0x00 +#define PCI_SUBCLASS_CRYPTO_ENTERTAINMENT 0x10 +#define PCI_SUBCLASS_CRYPTO_MISC 0x80 + +/* 0x11 data acquisition and signal processing subclasses */ +#define PCI_SUBCLASS_DASP_DPIO 0x00 +#define PCI_SUBCLASS_DASP_TIMEFREQ 0x01 +#define PCI_SUBCLASS_DASP_MISC 0x80 + +/* + * PCI BIST/Header Type/Latency Timer/Cache Line Size Register. + */ +#define PCI_BHLC_REG 0x0c + +#define PCI_BIST_SHIFT 24 +#define PCI_BIST_MASK 0xff +#define PCI_BIST(bhlcr) \ + (((bhlcr) >> PCI_BIST_SHIFT) & PCI_BIST_MASK) + +#define PCI_HDRTYPE_SHIFT 16 +#define PCI_HDRTYPE_MASK 0xff +#define PCI_HDRTYPE(bhlcr) \ + (((bhlcr) >> PCI_HDRTYPE_SHIFT) & PCI_HDRTYPE_MASK) + +#define PCI_HDRTYPE_TYPE(bhlcr) \ + (PCI_HDRTYPE(bhlcr) & 0x7f) +#define PCI_HDRTYPE_MULTIFN(bhlcr) \ + ((PCI_HDRTYPE(bhlcr) & 0x80) != 0) + +#define PCI_LATTIMER_SHIFT 8 +#define PCI_LATTIMER_MASK 0xff +#define PCI_LATTIMER(bhlcr) \ + (((bhlcr) >> PCI_LATTIMER_SHIFT) & PCI_LATTIMER_MASK) + +#define PCI_CACHELINE_SHIFT 0 +#define PCI_CACHELINE_MASK 0xff +#define PCI_CACHELINE(bhlcr) \ + (((bhlcr) >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK) + +/* config registers for header type 0 devices */ + +#define PCI_MAPS 0x10 +#define PCI_CARDBUSCIS 0x28 +#define PCI_SUBVEND_0 0x2c +#define PCI_SUBDEV_0 0x2e +#define PCI_INTLINE 0x3c +#define PCI_INTPIN 0x3d +#define PCI_MINGNT 0x3e +#define PCI_MAXLAT 0x3f + +/* config registers for header type 1 devices */ + +#define PCI_SECSTAT_1 0 /**/ + +#define PCI_PRIBUS_1 0x18 +#define PCI_SECBUS_1 0x19 +#define PCI_SUBBUS_1 0x1a +#define PCI_SECLAT_1 0x1b + +#define PCI_IOBASEL_1 0x1c +#define PCI_IOLIMITL_1 0x1d +#define PCI_IOBASEH_1 0x30 /**/ +#define PCI_IOLIMITH_1 0x32 /**/ + +#define PCI_MEMBASE_1 0x20 +#define PCI_MEMLIMIT_1 0x22 + +#define PCI_PMBASEL_1 0x24 +#define PCI_PMLIMITL_1 0x26 +#define PCI_PMBASEH_1 0 /**/ +#define PCI_PMLIMITH_1 0 /**/ + +#define PCI_BRIDGECTL_1 0 /**/ + +#define PCI_SUBVEND_1 0x34 +#define PCI_SUBDEV_1 0x36 + +/* config registers for header type 2 devices */ + +#define PCI_SECSTAT_2 0x16 + +#define PCI_PRIBUS_2 0x18 +#define PCI_SECBUS_2 0x19 +#define PCI_SUBBUS_2 0x1a +#define PCI_SECLAT_2 0x1b + +#define PCI_MEMBASE0_2 0x1c +#define PCI_MEMLIMIT0_2 0x20 +#define PCI_MEMBASE1_2 0x24 +#define PCI_MEMLIMIT1_2 0x28 +#define PCI_IOBASE0_2 0x2c +#define PCI_IOLIMIT0_2 0x30 +#define PCI_IOBASE1_2 0x34 +#define PCI_IOLIMIT1_2 0x38 + +#define PCI_BRIDGECTL_2 0x3e + +#define PCI_SUBVEND_2 0x40 +#define PCI_SUBDEV_2 0x42 + +#define PCI_PCCARDIF_2 0x44 + +/* + * Mapping registers + */ +#define PCI_MAPREG_START 0x10 +#define PCI_MAPREG_END 0x28 +#define PCI_MAPREG_ROM 0x30 +#define PCI_MAPREG_PPB_END 0x18 +#define PCI_MAPREG_PCB_END 0x14 + +#define PCI_MAPREG_TYPE(mr) \ + ((mr) & PCI_MAPREG_TYPE_MASK) +#define PCI_MAPREG_TYPE_MASK 0x00000001 + +#define PCI_MAPREG_TYPE_MEM 0x00000000 +#define PCI_MAPREG_TYPE_IO 0x00000001 +#define PCI_MAPREG_TYPE_ROM 0x00000001 + +#define PCI_MAPREG_MEM_TYPE(mr) \ + ((mr) & PCI_MAPREG_MEM_TYPE_MASK) +#define PCI_MAPREG_MEM_TYPE_MASK 0x00000006 + +#define PCI_MAPREG_MEM_TYPE_32BIT 0x00000000 +#define PCI_MAPREG_MEM_TYPE_32BIT_1M 0x00000002 +#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004 + +#define PCI_MAPREG_MEM_CACHEABLE(mr) \ + (((mr) & PCI_MAPREG_MEM_CACHEABLE_MASK) != 0) +#define PCI_MAPREG_MEM_CACHEABLE_MASK 0x00000008 + +#define PCI_MAPREG_MEM_PREFETCHABLE(mr) \ + (((mr) & PCI_MAPREG_MEM_PREFETCHABLE_MASK) != 0) +#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008 + +#define PCI_MAPREG_MEM_ADDR(mr) \ + ((mr) & PCI_MAPREG_MEM_ADDR_MASK) +#define PCI_MAPREG_MEM_SIZE(mr) \ + (PCI_MAPREG_MEM_ADDR(mr) & -PCI_MAPREG_MEM_ADDR(mr)) +#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0 + +#define PCI_MAPREG_MEM64_ADDR(mr) \ + ((mr) & PCI_MAPREG_MEM64_ADDR_MASK) +#define PCI_MAPREG_MEM64_SIZE(mr) \ + (PCI_MAPREG_MEM64_ADDR(mr) & -PCI_MAPREG_MEM64_ADDR(mr)) +#define PCI_MAPREG_MEM64_ADDR_MASK 0xfffffffffffffff0 + +#define PCI_MAPREG_IO_ADDR(mr) \ + ((mr) & PCI_MAPREG_IO_ADDR_MASK) +#define PCI_MAPREG_IO_SIZE(mr) \ + (PCI_MAPREG_IO_ADDR(mr) & -PCI_MAPREG_IO_ADDR(mr)) +#define PCI_MAPREG_IO_ADDR_MASK 0xfffffffe + +#define PCI_MAPREG_ROM_ADDR(mr) \ + ((mr) & PCI_MAPREG_ROM_ADDR_MASK) +#define PCI_MAPREG_ROM_SIZE(mr) \ + (PCI_MAPREG_ROM_ADDR(mr) & -PCI_MAPREG_ROM_ADDR(mr)) +#define PCI_MAPREG_ROM_ADDR_MASK 0xfffff800 + +/* + * Cardbus CIS pointer (PCI rev. 2.1) + */ +#define PCI_CARDBUS_CIS_REG 0x28 + +/* + * Subsystem identification register; contains a vendor ID and a device ID. + * Types/macros for PCI_ID_REG apply. + * (PCI rev. 2.1) + */ +#define PCI_SUBSYS_ID_REG 0x2c + +/* + * capabilities link list (PCI rev. 2.2) + */ +#define PCI_CAPLISTPTR_REG 0x34 +#define PCI_CAPLIST_PTR(cpr) ((cpr) & 0xff) +#define PCI_CAPLIST_NEXT(cr) (((cr) >> 8) & 0xff) +#define PCI_CAPLIST_CAP(cr) ((cr) & 0xff) + +#define PCI_CAP_REESSERVED 0x00 +#define PCI_CAP_PWRMGMT 0x01 +#define PCI_CAP_AGP 0x02 +#define PCI_CAP_VPD 0x03 +#define PCI_CAP_SLOTID 0x04 +#define PCI_CAP_MBI 0x05 +#define PCI_CAP_CPCI_HOTSWAP 0x06 +#define PCI_CAP_PCIX 0x07 +#define PCI_CAP_LDT 0x08 +#define PCI_CAP_VENDSPEC 0x09 +#define PCI_CAP_DEBUGPORT 0x0a +#define PCI_CAP_CPCI_RSRCCTL 0x0b +#define PCI_CAP_HOTPLUG 0x0c + +/* + * Power Management Control Status Register; access via capability pointer. + */ +#define PCI_PMCSR_STATE_MASK 0x03 +#define PCI_PMCSR_STATE_D0 0x00 +#define PCI_PMCSR_STATE_D1 0x01 +#define PCI_PMCSR_STATE_D2 0x02 +#define PCI_PMCSR_STATE_D3 0x03 + +/* + * Interrupt Configuration Register; contains interrupt pin and line. + */ +#define PCI_INTERRUPT_REG 0x3c + +typedef u_int8_t pci_intr_pin_t; +typedef u_int8_t pci_intr_line_t; + +#define PCI_INTERRUPT_PIN_SHIFT 8 +#define PCI_INTERRUPT_PIN_MASK 0xff +#define PCI_INTERRUPT_PIN(icr) \ + (((icr) >> PCI_INTERRUPT_PIN_SHIFT) & PCI_INTERRUPT_PIN_MASK) + +#define PCI_INTERRUPT_LINE_SHIFT 0 +#define PCI_INTERRUPT_LINE_MASK 0xff +#define PCI_INTERRUPT_LINE(icr) \ + (((icr) >> PCI_INTERRUPT_LINE_SHIFT) & PCI_INTERRUPT_LINE_MASK) + +#define PCI_MIN_GNT_SHIFT 16 +#define PCI_MIN_GNT_MASK 0xff +#define PCI_MIN_GNT(icr) \ + (((icr) >> PCI_MIN_GNT_SHIFT) & PCI_MIN_GNT_MASK) + +#define PCI_MAX_LAT_SHIFT 24 +#define PCI_MAX_LAT_MASK 0xff +#define PCI_MAX_LAT(icr) \ + (((icr) >> PCI_MAX_LAT_SHIFT) & PCI_MAX_LAT_MASK) + +#define PCI_INTERRUPT_PIN_NONE 0x00 +#define PCI_INTERRUPT_PIN_A 0x01 +#define PCI_INTERRUPT_PIN_B 0x02 +#define PCI_INTERRUPT_PIN_C 0x03 +#define PCI_INTERRUPT_PIN_D 0x04 +#define PCI_INTERRUPT_PIN_MAX 0x04 + +#endif /* _DEV_PCI_PCIREG_H_ */ diff --git a/arch/mips/lemote/lm2f/common/plat.c b/arch/mips/lemote/lm2f/common/plat.c new file mode 100644 index 0000000..507351a --- /dev/null +++ b/arch/mips/lemote/lm2f/common/plat.c @@ -0,0 +1,82 @@ + +/* + * 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) 2009 yanhua (yanhua@xxxxxxxxxx) + * Copyright (C) 2007 Ralf Baechle (ralf@xxxxxxxxxxxxxx) + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/serial_8250.h> + +#ifdef CONFIG_64BIT +#define CPU_UART_BASE (void *)0xffffffffbff003f8 +#else +#define CPU_UART_BASE (void *)0xbff003f8 +#endif + +#define PORT(base, int) \ +{ \ + .iobase = base, \ + .irq = int, \ + .uartclk = 1843200, \ + .iotype = UPIO_PORT, \ + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \ + .regshift = 0, \ +} + +static struct plat_serial8250_port uart8250_data[] = { +#if defined(CONFIG_LEMOTE_YEELOONG2F) || defined(CONFIG_LEMOTE_NAS) + { .membase = CPU_UART_BASE, + .irq = 19, + .uartclk = 3686400, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .regshift = 0, + }, +#else + PORT(0x2F8, 3), +#endif + { }, +}; + +static struct platform_device uart8250_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = uart8250_data, + }, +}; + +static struct resource cmos_rsrc[] = { + { + .start = 0x70, + .end = 0x71, + .flags = IORESOURCE_IO + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device cmos_device = { + .name = "rtc_cmos", + .num_resources = ARRAY_SIZE(cmos_rsrc), + .resource = cmos_rsrc +}; + +static int __init plat_init(void) +{ + platform_device_register(&uart8250_device); + platform_device_register(&cmos_device); + + return 0; +} + +device_initcall(plat_init); + +MODULE_LICENSE("GPL"); diff --git a/arch/mips/lemote/lm2f/fuloong/Makefile b/arch/mips/lemote/lm2f/fuloong/Makefile new file mode 100644 index 0000000..dfb021b --- /dev/null +++ b/arch/mips/lemote/lm2f/fuloong/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Lemote Loongson-2F based mini box. +# + +obj-y += setup.o prom.o reset.o irq.o bonito-irq.o dbg_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/lemote/lm2f/fuloong/bonito-irq.c b/arch/mips/lemote/lm2f/fuloong/bonito-irq.c new file mode 100644 index 0000000..ce04b4d --- /dev/null +++ b/arch/mips/lemote/lm2f/fuloong/bonito-irq.c @@ -0,0 +1,105 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@xxxxxxxxxx or jsun@xxxxxxxxxx + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@xxxxxxx) + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/errno.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <asm/io.h> + +#include <asm/mips-boards/bonito64.h> + +#define bonito_irq_shutdown bonito_irq_disable + + +static inline void bonito_irq_enable(unsigned int irq) +{ + BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE)); + (void)BONITO_INTENSET; + mmiowb(); +} + +static unsigned int bonito_irq_startup(unsigned int irq) +{ + bonito_irq_enable(irq); + return 0; +} + +static inline void bonito_irq_ack(unsigned int irq) +{ + BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE)); + (void)BONITO_INTENCLR; + mmiowb(); +} + +static inline void bonito_irq_end(unsigned int irq) +{ + BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE )); + mmiowb(); +} + +static inline void bonito_irq_disable(unsigned int irq) +{ + BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE)); + (void)BONITO_INTENCLR; + mmiowb(); +} + +static struct irq_chip bonito_irq_type = { + .name = "bonito_irq", + .startup = bonito_irq_startup, + .shutdown = bonito_irq_shutdown, + .enable = bonito_irq_enable, + .disable = bonito_irq_disable, + .ack = bonito_irq_ack, + .end = bonito_irq_end, + .mask = bonito_irq_disable, + .mask_ack = bonito_irq_disable, + .unmask = bonito_irq_enable, +}; + +/* There is no need to handle the DMA IO problem on godson2f any more. */ +/* +static struct irqaction dma_timeout_irqaction = { + .handler = no_action, + .name = "dma_timeout", +}; +*/ + +void bonito_irq_init(void) +{ + u32 i; + + for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) { + set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq); + } + + /* setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction); */ +} diff --git a/arch/mips/lemote/lm2f/fuloong/dbg_io.c b/arch/mips/lemote/lm2f/fuloong/dbg_io.c new file mode 100644 index 0000000..5900fdc --- /dev/null +++ b/arch/mips/lemote/lm2f/fuloong/dbg_io.c @@ -0,0 +1,182 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@xxxxxxxxxx or jsun@xxxxxxxxxx + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@xxxxxxx) + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/io.h> +#include <asm/types.h> +#include <linux/init.h> +#include <linux/types.h> +#include <asm/serial.h> /* For the serial port location and base baud */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +#ifdef USE_GODSON2F_UART + +/* === CONFIG === */ +#ifdef CONFIG_64BIT +#define BASE (0xffffffffbff003f8) +#else +#define BASE (0xbff003f8) +#endif + +#else /* USE_CS5536_UART1/2 */ + +#ifdef CONFIG_64BIT +#define BASE 0xffffffffbfd002f8 +#else +#define BASE 0xbfd002f8 +#endif + +#endif /* end of USE_GODSON2F_UART */ + +#define MAX_BAUD BASE_BAUD +/* === END OF CONFIG === */ + +#define REG_OFFSET 1 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile u8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile u8*)(BASE + y))) = z) + +void debugInit(u32 baud, u8 data, u8 parity, u8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + u32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +u8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0) ; + return UART16550_READ(OFS_RCV_BUFFER); +} + +int putDebugChar(u8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + /* + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); */ + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0) ; + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} + +extern void prom_putchar(char c); + +void prom_printf(char *fmt, ...) +{ + va_list args; + char ppbuf[1024]; + char *bptr; + + va_start(args, fmt); + vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while (*bptr != 0) { + if (*bptr == '\n') + prom_putchar('\r'); + + prom_putchar(*bptr++); + } + va_end(args); +} diff --git a/arch/mips/lemote/lm2f/fuloong/irq.c b/arch/mips/lemote/lm2f/fuloong/irq.c new file mode 100644 index 0000000..622c7b0 --- /dev/null +++ b/arch/mips/lemote/lm2f/fuloong/irq.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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 <linux/irq.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/irq_cpu.h> +#include <asm/i8259.h> +#include <asm/mipsregs.h> +#include <asm/delay.h> +#include <asm/mips-boards/bonito64.h> + +#define BONITO_INT_BIT_GPIO0 (1 << 0) +#define BONITO_INT_BIT_GPIO1 (1 << 1) +#define BONITO_INT_BIT_GPIO2 (1 << 2) +#define BONITO_INT_BIT_GPIO3 (1 << 3) +#define BONITO_INT_BIT_PCI_INTA (1 << 4) +#define BONITO_INT_BIT_PCI_INTB (1 << 5) +#define BONITO_INT_BIT_PCI_INTC (1 << 6) +#define BONITO_INT_BIT_PCI_INTD (1 << 7) +#define BONITO_INT_BIT_PCI_PERR (1 << 8) +#define BONITO_INT_BIT_PCI_SERR (1 << 9) +#define BONITO_INT_BIT_DDR (1 << 10) +#define BONITO_INT_BIT_INT0 (1 << 11) +#define BONITO_INT_BIT_INT1 (1 << 12) +#define BONITO_INT_BIT_INT2 (1 << 13) +#define BONITO_INT_BIT_INT3 (1 << 14) + +#define BONITO_INT_TIMER_OFF 7 +#define BONITO_INT_BONITO_OFF 6 +#define BONITO_INT_UART_OFF 3 +#define BONITO_INT_I8259_OFF 2 + +/****************************************************************/ + +static void loongson2f_timer_dispatch(void) +{ + /* place the loongson2f timer interrupt on 23 */ + do_IRQ(MIPS_CPU_IRQ_BASE + BONITO_INT_TIMER_OFF); + return; +} + +static void loongson2f_bonito_dispatch(void) +{ + int int_status; + int i = 0; + + /* place the other interrupt on bit6 for bonito, inclding PCI and so on */ + int_status = BONITO_INTISR & BONITO_INTEN; + + for(i = 0; (i < 10) && int_status; i++){ + if(int_status & (1 << i)){ + if(i == 10) + printk("ddr int.\n"); + if(int_status & 0x000000f0) + do_IRQ(BONITO_IRQ_BASE + i); + int_status &= ~(1 << i); + } + } + + return; +} + +static void loongson2f_int3_dispatch(void) +{ + int int_status; + + int_status = BONITO_INTISR & BONITO_INTEN; + if(int_status & BONITO_INT_BIT_INT3){ + } + + return; +} + +static void loongson2f_int2_dispatch(void) +{ + int int_status; + + int_status = BONITO_INTISR & BONITO_INTEN; + if(int_status & BONITO_INT_BIT_INT2){ + } + + return; +} + +static void loongson2f_int1_dispatch(void) +{ + /* place the loongson2f uart interrupt on int1 */ + do_IRQ(MIPS_CPU_IRQ_BASE + BONITO_INT_UART_OFF); +} + +static void i8259_irqdispatch(void) +{ + int irq, isr, imr; + + if((BONITO_INTISR & BONITO_INTEN) & BONITO_INT_BIT_INT0) { + + imr = inb(0x21) | (inb(0xa1) << 8); + isr = inb(0x20) | (inb(0xa0) << 8); + isr &= ~0x4; // irq2 for cascade + isr &= ~imr; + irq = ffs(isr) - 1; + + if(irq >= 0) { + do_IRQ(irq); + } else { + spurious_interrupt(); + } + } +} + +static void loongson2f_steer1_dispatch(void) +{ + return; +} + +static void loongson2f_steer0_dispatch(void) +{ + return; +} + + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; + + if(pending & CAUSEF_IP7){ + loongson2f_timer_dispatch(); + }else if(pending & CAUSEF_IP6){ /* North Bridge, Performance counter */ + do_IRQ(MIPS_CPU_IRQ_BASE + 6); + loongson2f_bonito_dispatch(); + }else if(pending & CAUSEF_IP5){ + loongson2f_int3_dispatch(); + }else if(pending & CAUSEF_IP4){ + loongson2f_int2_dispatch(); + }else if(pending & CAUSEF_IP3){ /* CPU UART */ + loongson2f_int1_dispatch(); + }else if(pending & CAUSEF_IP2){ /* South Bridge */ + i8259_irqdispatch(); + }else if(pending & CAUSEF_IP1){ + loongson2f_steer1_dispatch(); + }else if(pending & CAUSEF_IP0){ + loongson2f_steer0_dispatch(); + }else{ + spurious_interrupt(); + } + return; +} + +static struct irqaction cascade_irqaction = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + +irqreturn_t ip6_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + return IRQ_HANDLED; +} + +static struct irqaction ip6_irqaction = { + .handler = ip6_action, + .mask = CPU_MASK_NONE, + .name = "cascade", + .flags = IRQF_SHARED, +}; + +void __init arch_init_irq(void) +{ + extern void bonito_irq_init(void); + + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_c0_status(ST0_IM | ST0_BEV); + local_irq_disable(); + + /* setup cs5536 as high level */ + BONITO_INTPOL = (1 << 11 | 1 << 12); + BONITO_INTEDGE &= ~(1 << 11 | 1 << 12); + + /* no steer */ + BONITO_INTSTEER = 0; + + /* + * Mask out all interrupt by writing "1" to all bit position in + * the interrupt reset reg. + */ + BONITO_INTENCLR = ~0; + + /* init all controller + * 0-15 ------> i8259 interrupt + * 16-23 ------> mips cpu interrupt + * 32-63 ------> bonito irq + */ + + /* Sets the first-level interrupt dispatcher. */ + mips_cpu_irq_init(); + + init_i8259_irqs(); + bonito_irq_init(); + + /* setup bonito interrupt */ + setup_irq(MIPS_CPU_IRQ_BASE + BONITO_INT_BONITO_OFF, &ip6_irqaction); + /* 8259 irq at IP2 */ + setup_irq(MIPS_CPU_IRQ_BASE + BONITO_INT_I8259_OFF, &cascade_irqaction); + +} diff --git a/arch/mips/lemote/lm2f/fuloong/prom.c b/arch/mips/lemote/lm2f/fuloong/prom.c new file mode 100644 index 0000000..d40a929 --- /dev/null +++ b/arch/mips/lemote/lm2f/fuloong/prom.c @@ -0,0 +1,106 @@ +/* + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@xxxxxxxxxx or jsun@xxxxxxxxxx + * + * Copyright 2003 ICT CAS + * Author: Michael Guo <guoyi@xxxxxxxxx> + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/bootmem.h> + +#include <asm/addrspace.h> +#include <asm/bootinfo.h> + +extern unsigned long bus_clock; +extern unsigned long cpu_clock_freq; +extern unsigned int memsize, highmemsize; +extern int putDebugChar(unsigned char byte); + +static int argc; +/* pmon passes arguments in 32bit pointers */ +static int *arg; +static int *env; + +const char *get_system_type(void) +{ + return "lemote-fuloong(2F)"; +} + +void __init prom_init_cmdline(void) +{ + int i; + long l; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + l = (long)arg[i]; + if (strlen(arcs_cmdline) + strlen(((char *)l) + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, ((char *)l)); + strcat(arcs_cmdline, " "); + } +} + +void __init prom_init(void) +{ + long l; + argc = fw_arg0; + arg = (int *)fw_arg1; + env = (int *)fw_arg2; + + prom_init_cmdline(); + + if ((strstr(arcs_cmdline, "console=")) == NULL) + strcat(arcs_cmdline, " console=ttyS0,115200"); + if ((strstr(arcs_cmdline, "root=")) == NULL) + strcat(arcs_cmdline, " root=/dev/hda1"); + + l = (long)*env; + while (l != 0) { + if (strncmp("busclock", (char *)l, strlen("busclock")) == 0) { + bus_clock = simple_strtol((char *)l + strlen("busclock="), + NULL, 10); + } + if (strncmp("cpuclock", (char *)l, strlen("cpuclock")) == 0) { + cpu_clock_freq = simple_strtol((char *)l + strlen("cpuclock="), + NULL, 10); + } + if (strncmp("memsize", (char *)l, strlen("memsize")) == 0) { + memsize = simple_strtol((char *)l + strlen("memsize="), + NULL, 10); + } + if (strncmp("highmemsize", (char *)l, strlen("highmemsize")) == 0) { + highmemsize = simple_strtol((char *)l + strlen("highmemsize="), + NULL, 10); + } + env++; + l = (long)*env; + } + if (memsize == 0) + memsize = 256; + + printk("busclock=%ld, cpuclock=%ld,memsize=%d,highmemsize=%d\n", + bus_clock, cpu_clock_freq, memsize, highmemsize); +} + +void __init prom_free_prom_memory(void) +{ +} + +void prom_putchar(char c) +{ + putDebugChar(c); +} diff --git a/arch/mips/lemote/lm2f/fuloong/reset.c b/arch/mips/lemote/lm2f/fuloong/reset.c new file mode 100644 index 0000000..64dfe84 --- /dev/null +++ b/arch/mips/lemote/lm2f/fuloong/reset.c @@ -0,0 +1,87 @@ +/* + * 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. + * + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + */ + +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/reboot.h> +#include <asm/system.h> + +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/pm.h> +#include <linux/delay.h> + +extern void _wrmsr(u32 reg, u32 hi, u32 lo); +extern void _rdmsr(u32 reg, u32 *hi, u32 *lo); + +static void loongson2f_restart(char *command) +{ + u32 hi, lo; + +#ifdef CONFIG_32BIT + *(volatile u32*)0xbfe00180 |= 0x7; +#else + *(volatile u32*)0xffffffffbfe00180 |= 0x7; +#endif + _rdmsr(0xe0000014, &hi, &lo); + lo |= 0x00000001; + _wrmsr(0xe0000014, hi, lo); + + printk("Hard reset not take effect!!\n"); + __asm__ __volatile__ ( + ".long 0x3c02bfc0\n" + ".long 0x00400008\n" + :::"v0" + ); +} + + +static void delay(void) +{ + volatile int i; + for (i=0; i<0x10000; i++); +} +static void loongson2f_halt(void) +{ +#ifdef CONFIG_32BIT + u32 base; +#else + u64 base; +#endif + u32 hi, lo, val; + + _rdmsr(0x8000000c, &hi, &lo); +#ifdef CONFIG_32BIT + base = (lo & 0xff00) | 0xbfd00000; +#else + base = (lo & 0xff00) | 0xffffffffbfd00000ULL; +#endif + val = (val & ~(1 << (16 + 13))) | (1 << 13); + delay(); + *(__volatile__ u32 *)(base + 0x04) = val; + delay(); + val = (val & ~(1 << (13))) | (1 << (16 + 13)); + delay(); + *(__volatile__ u32 *)(base + 0x00) = val; + delay(); +} + +static void loongson2f_power_off(void) +{ + loongson2f_halt(); +} + +void mips_reboot_setup(void) +{ + _machine_restart = loongson2f_restart; + _machine_halt = loongson2f_halt; + pm_power_off = loongson2f_power_off; +} diff --git a/arch/mips/lemote/lm2f/fuloong/setup.c b/arch/mips/lemote/lm2f/fuloong/setup.c new file mode 100644 index 0000000..e0c393e --- /dev/null +++ b/arch/mips/lemote/lm2f/fuloong/setup.c @@ -0,0 +1,132 @@ +/* + * BRIEF MODULE DESCRIPTION + * setup.c - board dependent boot routines + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/bootmem.h> +#include <linux/init.h> +#include <linux/irq.h> + +#include <asm/bootinfo.h> +#include <asm/mc146818-time.h> +#include <asm/time.h> +#include <asm/wbflush.h> + +#ifdef CONFIG_VT +#include <linux/console.h> +#include <linux/screen_info.h> +#endif + +extern void mips_reboot_setup(void); + +#ifdef CONFIG_64BIT +#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p))) +#else +#define PTR_PAD(p) (p) +#endif + +unsigned long cpu_clock_freq; +unsigned long bus_clock; +unsigned int memsize; +unsigned int highmemsize = 0; + +extern int __init init_mfgpt_clocksource(void); + +void __init plat_time_init(void) +{ + /* setup mips r4k timer */ + mips_hpt_frequency = cpu_clock_freq / 2; + +#ifdef CONFIG_LS2F_CPU_FREQ + init_mfgpt_clocksource(); +#endif +} + +unsigned long read_persistent_clock(void) +{ + return mc146818_get_cmos_time(); +} + +void (*__wbflush)(void); +EXPORT_SYMBOL(__wbflush); + +static void wbflush_loongson2f(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set mips3\n\t" + "sync\n\t" + "nop\n\t" + ".set\tpop\n\t" + ".set mips0\n\t"); +} + +void __init plat_mem_setup(void) +{ + set_io_port_base(PTR_PAD(0xbfd00000)); + + mips_reboot_setup(); + + __wbflush = wbflush_loongson2f; + + add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM); +#ifdef CONFIG_64BIT + __asm__( + ".set mips3\n" + "dli $2, 0x900000003ff00000\n" + "dli $3, 0x0000000080000000\n" + "sd $3, 0x10($2)\n" + "sd $0, 0x50($2)\n" + "dli $3, 0xffffffff80000000\n" + "sd $3, 0x30($2)\n" + ".set mips0\n" + :::"$2","$3","memory"); + if (highmemsize > 0) { + add_memory_region(0x90000000, highmemsize << 20, BOOT_MEM_RAM); + } +#endif + +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; + + screen_info = (struct screen_info) { + 0, 25, /* orig-x, orig-y */ + 0, /* unused */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0, 0, 0, /* ega_ax, ega_bx, ega_cx */ + 25, /* orig-video-lines */ + VIDEO_TYPE_VGAC, /* orig-video-isVGA */ + 16 /* orig-video-points */ + }; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif +#endif + +} diff --git a/arch/mips/lemote/lm2f/yeeloong/Makefile b/arch/mips/lemote/lm2f/yeeloong/Makefile new file mode 100644 index 0000000..92a19c3 --- /dev/null +++ b/arch/mips/lemote/lm2f/yeeloong/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Lemote Loongson-2F mini notebook +# + +obj-y += setup.o prom.o reset.o irq.o bonito-irq.o dbg_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/lemote/lm2f/yeeloong/bonito-irq.c b/arch/mips/lemote/lm2f/yeeloong/bonito-irq.c new file mode 100644 index 0000000..65e5659 --- /dev/null +++ b/arch/mips/lemote/lm2f/yeeloong/bonito-irq.c @@ -0,0 +1,104 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@xxxxxxxxxx or jsun@xxxxxxxxxx + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@xxxxxxx) + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/errno.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <asm/io.h> + +#include <asm/mips-boards/bonito64.h> + +#define bonito_irq_shutdown bonito_irq_disable + + +static inline void bonito_irq_enable(unsigned int irq) +{ + BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE)); + (void)BONITO_INTENSET; + mmiowb(); +} + +static unsigned int bonito_irq_startup(unsigned int irq) +{ + bonito_irq_enable(irq); + return 0; +} + +static inline void bonito_irq_ack(unsigned int irq) +{ + BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE)); + (void)BONITO_INTENCLR; + mmiowb(); +} + +static inline void bonito_irq_end(unsigned int irq) +{ + BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE )); + mmiowb(); +} + +static inline void bonito_irq_disable(unsigned int irq) +{ + BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE)); + (void)BONITO_INTENCLR; + mmiowb(); +} + +static struct irq_chip bonito_irq_type = { + .name = "bonito_irq", + .startup = bonito_irq_startup, + .shutdown = bonito_irq_shutdown, + .enable = bonito_irq_enable, + .disable = bonito_irq_disable, + .ack = bonito_irq_ack, + .end = bonito_irq_end, + .mask = bonito_irq_disable, + .mask_ack = bonito_irq_disable, + .unmask = bonito_irq_enable, +}; + +/* There is no need to handle the DMA IO problem on godson2f any more. */ +/* +static struct irqaction dma_timeout_irqaction = { + .handler = no_action, + .name = "dma_timeout", +}; +*/ + +void bonito_irq_init(void) +{ + u32 i; + + for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) { + set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq); + } + +} diff --git a/arch/mips/lemote/lm2f/yeeloong/dbg_io.c b/arch/mips/lemote/lm2f/yeeloong/dbg_io.c new file mode 100644 index 0000000..be80ca0 --- /dev/null +++ b/arch/mips/lemote/lm2f/yeeloong/dbg_io.c @@ -0,0 +1,170 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@xxxxxxxxxx or jsun@xxxxxxxxxx + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@xxxxxxx) + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/io.h> +#include <asm/types.h> +#include <linux/init.h> +#include <linux/types.h> +#include <asm/serial.h> /* For the serial port location and base baud */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ +#ifdef CONFIG_64BIT +#define BASE (0xffffffffbff003f8) +#else +#define BASE (0xbff003f8) +#endif + +#define MAX_BAUD BASE_BAUD +/* === END OF CONFIG === */ + +#define REG_OFFSET 1 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile u8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile u8*)(BASE + y))) = z) + +void debugInit(u32 baud, u8 data, u8 parity, u8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + u32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +u8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0) ; + return UART16550_READ(OFS_RCV_BUFFER); +} + +int putDebugChar(u8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + /* + debugInit(UART16550_BAUD_115200, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); */ + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0) ; + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} + +extern void prom_putchar(char c); + +void prom_printf(char *fmt, ...) +{ + va_list args; + char ppbuf[1024]; + char *bptr; + + va_start(args, fmt); + vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while (*bptr != 0) { + if (*bptr == '\n') + prom_putchar('\r'); + + prom_putchar(*bptr++); + } + va_end(args); +} diff --git a/arch/mips/lemote/lm2f/yeeloong/irq.c b/arch/mips/lemote/lm2f/yeeloong/irq.c new file mode 100644 index 0000000..622c7b0 --- /dev/null +++ b/arch/mips/lemote/lm2f/yeeloong/irq.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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 <linux/irq.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/irq_cpu.h> +#include <asm/i8259.h> +#include <asm/mipsregs.h> +#include <asm/delay.h> +#include <asm/mips-boards/bonito64.h> + +#define BONITO_INT_BIT_GPIO0 (1 << 0) +#define BONITO_INT_BIT_GPIO1 (1 << 1) +#define BONITO_INT_BIT_GPIO2 (1 << 2) +#define BONITO_INT_BIT_GPIO3 (1 << 3) +#define BONITO_INT_BIT_PCI_INTA (1 << 4) +#define BONITO_INT_BIT_PCI_INTB (1 << 5) +#define BONITO_INT_BIT_PCI_INTC (1 << 6) +#define BONITO_INT_BIT_PCI_INTD (1 << 7) +#define BONITO_INT_BIT_PCI_PERR (1 << 8) +#define BONITO_INT_BIT_PCI_SERR (1 << 9) +#define BONITO_INT_BIT_DDR (1 << 10) +#define BONITO_INT_BIT_INT0 (1 << 11) +#define BONITO_INT_BIT_INT1 (1 << 12) +#define BONITO_INT_BIT_INT2 (1 << 13) +#define BONITO_INT_BIT_INT3 (1 << 14) + +#define BONITO_INT_TIMER_OFF 7 +#define BONITO_INT_BONITO_OFF 6 +#define BONITO_INT_UART_OFF 3 +#define BONITO_INT_I8259_OFF 2 + +/****************************************************************/ + +static void loongson2f_timer_dispatch(void) +{ + /* place the loongson2f timer interrupt on 23 */ + do_IRQ(MIPS_CPU_IRQ_BASE + BONITO_INT_TIMER_OFF); + return; +} + +static void loongson2f_bonito_dispatch(void) +{ + int int_status; + int i = 0; + + /* place the other interrupt on bit6 for bonito, inclding PCI and so on */ + int_status = BONITO_INTISR & BONITO_INTEN; + + for(i = 0; (i < 10) && int_status; i++){ + if(int_status & (1 << i)){ + if(i == 10) + printk("ddr int.\n"); + if(int_status & 0x000000f0) + do_IRQ(BONITO_IRQ_BASE + i); + int_status &= ~(1 << i); + } + } + + return; +} + +static void loongson2f_int3_dispatch(void) +{ + int int_status; + + int_status = BONITO_INTISR & BONITO_INTEN; + if(int_status & BONITO_INT_BIT_INT3){ + } + + return; +} + +static void loongson2f_int2_dispatch(void) +{ + int int_status; + + int_status = BONITO_INTISR & BONITO_INTEN; + if(int_status & BONITO_INT_BIT_INT2){ + } + + return; +} + +static void loongson2f_int1_dispatch(void) +{ + /* place the loongson2f uart interrupt on int1 */ + do_IRQ(MIPS_CPU_IRQ_BASE + BONITO_INT_UART_OFF); +} + +static void i8259_irqdispatch(void) +{ + int irq, isr, imr; + + if((BONITO_INTISR & BONITO_INTEN) & BONITO_INT_BIT_INT0) { + + imr = inb(0x21) | (inb(0xa1) << 8); + isr = inb(0x20) | (inb(0xa0) << 8); + isr &= ~0x4; // irq2 for cascade + isr &= ~imr; + irq = ffs(isr) - 1; + + if(irq >= 0) { + do_IRQ(irq); + } else { + spurious_interrupt(); + } + } +} + +static void loongson2f_steer1_dispatch(void) +{ + return; +} + +static void loongson2f_steer0_dispatch(void) +{ + return; +} + + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; + + if(pending & CAUSEF_IP7){ + loongson2f_timer_dispatch(); + }else if(pending & CAUSEF_IP6){ /* North Bridge, Performance counter */ + do_IRQ(MIPS_CPU_IRQ_BASE + 6); + loongson2f_bonito_dispatch(); + }else if(pending & CAUSEF_IP5){ + loongson2f_int3_dispatch(); + }else if(pending & CAUSEF_IP4){ + loongson2f_int2_dispatch(); + }else if(pending & CAUSEF_IP3){ /* CPU UART */ + loongson2f_int1_dispatch(); + }else if(pending & CAUSEF_IP2){ /* South Bridge */ + i8259_irqdispatch(); + }else if(pending & CAUSEF_IP1){ + loongson2f_steer1_dispatch(); + }else if(pending & CAUSEF_IP0){ + loongson2f_steer0_dispatch(); + }else{ + spurious_interrupt(); + } + return; +} + +static struct irqaction cascade_irqaction = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + +irqreturn_t ip6_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + return IRQ_HANDLED; +} + +static struct irqaction ip6_irqaction = { + .handler = ip6_action, + .mask = CPU_MASK_NONE, + .name = "cascade", + .flags = IRQF_SHARED, +}; + +void __init arch_init_irq(void) +{ + extern void bonito_irq_init(void); + + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_c0_status(ST0_IM | ST0_BEV); + local_irq_disable(); + + /* setup cs5536 as high level */ + BONITO_INTPOL = (1 << 11 | 1 << 12); + BONITO_INTEDGE &= ~(1 << 11 | 1 << 12); + + /* no steer */ + BONITO_INTSTEER = 0; + + /* + * Mask out all interrupt by writing "1" to all bit position in + * the interrupt reset reg. + */ + BONITO_INTENCLR = ~0; + + /* init all controller + * 0-15 ------> i8259 interrupt + * 16-23 ------> mips cpu interrupt + * 32-63 ------> bonito irq + */ + + /* Sets the first-level interrupt dispatcher. */ + mips_cpu_irq_init(); + + init_i8259_irqs(); + bonito_irq_init(); + + /* setup bonito interrupt */ + setup_irq(MIPS_CPU_IRQ_BASE + BONITO_INT_BONITO_OFF, &ip6_irqaction); + /* 8259 irq at IP2 */ + setup_irq(MIPS_CPU_IRQ_BASE + BONITO_INT_I8259_OFF, &cascade_irqaction); + +} diff --git a/arch/mips/lemote/lm2f/yeeloong/prom.c b/arch/mips/lemote/lm2f/yeeloong/prom.c new file mode 100644 index 0000000..7e027ae --- /dev/null +++ b/arch/mips/lemote/lm2f/yeeloong/prom.c @@ -0,0 +1,157 @@ +/* + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@xxxxxxxxxx or jsun@xxxxxxxxxx + * + * Copyright 2003 ICT CAS + * Author: Michael Guo <guoyi@xxxxxxxxx> + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/bootmem.h> + +#include <asm/addrspace.h> +#include <asm/bootinfo.h> + +extern unsigned long bus_clock; +extern unsigned long cpu_clock_freq; +extern unsigned int memsize, highmemsize; +extern int putDebugChar(unsigned char byte); + +static int argc; +/* pmon passes arguments in 32bit pointers */ +static int *arg; +static int *env; + +const char *get_system_type(void) +{ + return "lemote-yeloong"; +} + +void __init prom_init_cmdline(void) +{ + int i; + long l; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + l = (long)arg[i]; + if (strlen(arcs_cmdline) + strlen(((char *)l) + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, ((char *)l)); + strcat(arcs_cmdline, " "); + } +} + +extern void _wrmsr(u32 msr, u32 hi, u32 lo); + +void __init prom_init(void) +{ + long l; + unsigned char default_root[50] = "/dev/hda1"; + argc = fw_arg0; + arg = (int *)fw_arg1; + env = (int *)fw_arg2; + + /* set lpc irq to quiet mode*/ + //_wrmsr(0x8000004e, 0, 0); + //_wrmsr(0x8000004e, 0, 0xc0); + _wrmsr(0x80000014, 0x00, 0x16000003); + + /*Emulate post for usb*/ + _wrmsr(0x40000001, 0x4, 0xBF000); + + prom_init_cmdline(); + +#if 1 + if (!strstr(arcs_cmdline, "no_auto_cmd")) { + char *pmon_ver, *ec_ver, *p, version[60], ec_version[64]; + + p = arcs_cmdline; + + pmon_ver = strstr(arcs_cmdline, "PMON_VER"); + if (pmon_ver) { + if((p = strstr(pmon_ver, " "))) + *p++ = '\0'; + strncpy(version, pmon_ver, 60); + } else + strncpy(version, "PMON_VER=Unknown", 60); + + ec_ver = strstr(p, "EC_VER"); + if (ec_ver) { + if((p = strstr(ec_ver, " "))) + *p = '\0'; + strncpy(ec_version, ec_ver, 64); + } else + strncpy(ec_version, "EC_VER=Unknown", 64); + + p = strstr(arcs_cmdline, "root="); + if(p) { + strncpy(default_root, p, sizeof(default_root)); + if(p=strstr(default_root, " ")) + *p = '\0'; + } + + memset(arcs_cmdline, 0, sizeof(arcs_cmdline)); + strcat(arcs_cmdline, version); + strcat(arcs_cmdline, " "); + strcat(arcs_cmdline, ec_version); + strcat(arcs_cmdline, " "); + strcat(arcs_cmdline, default_root); + strcat(arcs_cmdline, " console=tty2"); + strcat(arcs_cmdline, " quiet"); + } +#endif + if ((strstr(arcs_cmdline, "console=")) == NULL) + strcat(arcs_cmdline, " console=ttyS0,115200"); + + if ((strstr(arcs_cmdline, "root=")) == NULL) + strcat(arcs_cmdline, " root=/dev/hda1"); + + l = (long)*env; + while (l != 0) { + if (strncmp("busclock", (char *)l, strlen("busclock")) == 0) { + bus_clock = simple_strtol((char *)l + strlen("busclock="), + NULL, 10); + } + if (strncmp("cpuclock", (char *)l, strlen("cpuclock")) == 0) { + cpu_clock_freq = simple_strtol((char *)l + strlen("cpuclock="), + NULL, 10); + } + if (strncmp("memsize", (char *)l, strlen("memsize")) == 0) { + memsize = simple_strtol((char *)l + strlen("memsize="), + NULL, 10); + } + if (strncmp("highmemsize", (char *)l, strlen("highmemsize")) == 0) { + highmemsize = simple_strtol((char *)l + strlen("highmemsize="), + NULL, 10); + } + env++; + l = (long)*env; + } + if (memsize == 0) + memsize = 256; + + printk("busclock=%ld, cpuclock=%ld,memsize=%d,highmemsize=%d\n", + bus_clock, cpu_clock_freq, memsize, highmemsize); +} + +void __init prom_free_prom_memory(void) +{ +} + +void prom_putchar(char c) +{ + putDebugChar(c); +} diff --git a/arch/mips/lemote/lm2f/yeeloong/reset.c b/arch/mips/lemote/lm2f/yeeloong/reset.c new file mode 100644 index 0000000..f0323f7 --- /dev/null +++ b/arch/mips/lemote/lm2f/yeeloong/reset.c @@ -0,0 +1,80 @@ +/* + * 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. + * + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + */ + +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/reboot.h> +#include <asm/system.h> + +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/pm.h> +#include <linux/delay.h> + +extern void _wrmsr(u32 reg, u32 hi, u32 lo); +extern void _rdmsr(u32 reg, u32 *hi, u32 *lo); + +static void loongson2f_restart(char *command) +{ +#ifdef CONFIG_32BIT + *(volatile u32*)0xbfe00180 |= 0x7; +#else + *(volatile u32*)0xffffffffbfe00180 |= 0x7; +#endif + +#ifdef CONFIG_64BIT + *((volatile u8*)(0xffffffffbfd00381)) = 0xf4; + *((volatile u8*)(0xffffffffbfd00382)) = 0xec; + *((volatile u8*)(0xffffffffbfd00383)) = 0x01; +#else + *((volatile u8*)(0xbfd00381)) = 0xfe; + *((volatile u8*)(0xbfd00382)) = 0xec; + *((volatile u8*)(0xbfd00383)) = 0x01; +#endif + + while (1); + /* Wait the system reset completely */ +#if 0 + __asm__ __volatile__ ( + ".long 0x3c02bfc0\n" + ".long 0x00400008\n" + :::"v0" + ); +#endif +} + +static void loongson2f_halt(void) +{ +#ifdef CONFIG_64BIT + /* cpu-gpio0 output low */ + *((volatile u32*)(0xffffffffbfe0011c)) &= ~0x00000001; + /* cpu-gpio0 as output */ + *((volatile u32*)(0xffffffffbfe00120)) &= ~0x00000001; +#else + /* cpu-gpio0 output low */ + *((volatile u32*)(0xbfe0011c)) &= ~0x00000001; + /* cpu-gpio0 as output */ + *((volatile u32*)(0xbfe00120)) &= ~0x00000001; +#endif + +} + +static void loongson2f_power_off(void) +{ + loongson2f_halt(); +} + +void mips_reboot_setup(void) +{ + _machine_restart = loongson2f_restart; + _machine_halt = loongson2f_halt; + pm_power_off = loongson2f_power_off; +} diff --git a/arch/mips/lemote/lm2f/yeeloong/setup.c b/arch/mips/lemote/lm2f/yeeloong/setup.c new file mode 100644 index 0000000..33c422c --- /dev/null +++ b/arch/mips/lemote/lm2f/yeeloong/setup.c @@ -0,0 +1,134 @@ +/* + * BRIEF MODULE DESCRIPTION + * setup.c - board dependent boot routines + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/bootmem.h> +#include <linux/init.h> +#include <linux/irq.h> + +#include <asm/bootinfo.h> +#include <asm/mc146818-time.h> +#include <asm/time.h> +#include <asm/wbflush.h> + +#ifdef CONFIG_VT +#include <linux/console.h> +#include <linux/screen_info.h> +#endif + +extern void mips_reboot_setup(void); + +#ifdef CONFIG_64BIT +#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p))) +#else +#define PTR_PAD(p) (p) +#endif + +unsigned long cpu_clock_freq; +unsigned long bus_clock; +unsigned int memsize; +unsigned int highmemsize = 0; + +extern int __init init_mfgpt_clocksource(void); + +void __init plat_time_init(void) +{ + /* setup mips r4k timer */ + mips_hpt_frequency = cpu_clock_freq / 2; + +#ifdef CONFIG_LS2F_CPU_FREQ + init_mfgpt_clocksource(); +#endif +} + +unsigned long read_persistent_clock(void) +{ + return mc146818_get_cmos_time(); +} + +void (*__wbflush)(void); +EXPORT_SYMBOL(__wbflush); + +static void wbflush_loongson2f(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set mips3\n\t" + "sync\n\t" + "nop\n\t" + ".set\tpop\n\t" + ".set mips0\n\t"); +} + +void __init plat_mem_setup(void) +{ + set_io_port_base(PTR_PAD(0xbfd00000)); + + mips_reboot_setup(); + + __wbflush = wbflush_loongson2f; + + add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM); +#ifdef CONFIG_64BIT + __asm__( + ".set mips3\n" + "dli $2, 0x900000003ff00000\n" + "dli $3, 0x0000000080000000\n" + "sd $3, 0x10($2)\n" + "sd $0, 0x50($2)\n" + "dli $3, 0xffffffffc0000000\n" + "sd $3, 0x30($2)\n" + ".set mips0\n" + :::"$2","$3","memory"); + if (highmemsize > 0) { + add_memory_region(0x90000000, highmemsize << 20, BOOT_MEM_RAM); + } +#endif + +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; + + screen_info = (struct screen_info) { + 0, 25, /* orig-x, orig-y */ + 0, /* unused */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0, 0, 0, /* ega_ax, ega_bx, ega_cx */ + 25, /* orig-video-lines */ + VIDEO_TYPE_VGAC, /* orig-video-isVGA */ + 16 /* orig-video-points */ + }; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif +#endif + +} + +EXPORT_SYMBOL(cpu_clock_freq); diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index e8a97f5..9bcdff5 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -27,6 +27,8 @@ obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o obj-$(CONFIG_LEMOTE_FULONG) += fixup-lm2e.o ops-bonito64.o +obj-$(CONFIG_LEMOTE_FULOONG2F) += fixup-fl2f.o ops-lm2f.o +obj-$(CONFIG_LEMOTE_YEELOONG2F) += fixup-yl2f.o ops-lm2f.o obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o diff --git a/arch/mips/pci/fixup-fl2f.c b/arch/mips/pci/fixup-fl2f.c new file mode 100644 index 0000000..58a1a18 --- /dev/null +++ b/arch/mips/pci/fixup-fl2f.c @@ -0,0 +1,256 @@ +/* + * fixup-lm2f.c + * + * Copyright (C) 2004 ICT CAS + * Author: Li xiaoyu, ICT CAS + * lixy@xxxxxxxxx + * + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/pci.h> +#include <asm/mips-boards/bonito64.h> + +/* PCI interrupt pins */ +/* These should not be changed, or you should consider godson2f interrupt register and + * your pci card dispatch + */ +#define PCIA 4 +#define PCIB 5 +#define PCIC 6 +#define PCID 7 + +/* all the pci device has the PCIA pin, check the datasheet. */ +static char irq_tab[][5] __initdata = { + /* INTA INTB INTC INTD */ + {0, 0, 0, 0, 0 }, /* 11: Unused */ + {0, 0, 0, 0, 0 }, /* 12: Unused */ + {0, 0, 0, 0, 0 }, /* 13: Unused */ + {0, 0, 0, 0, 0 }, /* 14: Unused */ + {0, 0, 0, 0, 0 }, /* 15: Unused */ + {0, 0, 0, 0, 0 }, /* 16: Unused */ + {0, PCIA, 0, 0, 0 }, /* 17: RTL8110-0 */ + {0, PCIB, 0, 0, 0 }, /* 18: RTL8110-1 */ + {0, PCIC, 0, 0, 0 }, /* 19: SiI3114 */ + {0, PCID, 0, 0, 0 }, /* 20: 3-ports nec usb*/ + {0, PCIA, PCIB, PCIC, PCID }, /* 21: PCI-SLOT */ + {0, 0, 0, 0, 0 }, /* 22: Unused */ + {0, 0, 0, 0, 0 }, /* 23: Unused */ + {0, 0, 0, 0, 0 }, /* 24: Unused */ + {0, 0, 0, 0, 0 }, /* 25: Unused */ + {0, 0, 0, 0, 0 }, /* 26: Unused */ + {0, 0, 0, 0, 0 }, /* 27: Unused */ +}; + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int virq; + + if( (PCI_SLOT(dev->devfn) != (14)) && (PCI_SLOT(dev->devfn) < 32) ){ + virq = irq_tab[slot][pin]; + printk("slot: %d, pin: %d, irq: %d\n", slot, pin, virq+BONITO_IRQ_BASE); + if(virq != 0) + return (BONITO_IRQ_BASE + virq); + else + return 0; + }else if( PCI_SLOT(dev->devfn) == 14){ // cs5536 + switch(PCI_FUNC(dev->devfn)){ + case 2 : + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 14); + return 14; // for IDE + case 3 : + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 9); + return 9; // for AUDIO + case 4 : // for OHCI + case 5 : // for EHCI + case 6 : // for UDC + case 7 : // for OTG + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + return 11; + } + return dev->irq; + }else{ + printk(" strange pci slot number.\n"); + return 0; + } +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + +#ifndef TEST_NO_CS5536 + +extern void _wrmsr(u32 reg, u32 hi, u32 lo); +extern void _rdmsr(u32 reg, u32 *hi, u32 *lo); + +/* CS5536 SPEC. fixup */ +static void __init loongson2f_cs5536_isa_fixup(struct pci_dev *pdev) +{ + /* the uart1 and uart2 interrupt in PIC is enabled as default */ + pci_write_config_dword(pdev, 0x50, 1); + pci_write_config_dword(pdev, 0x54, 1); + /* enable the pci MASTER ABORT/ TARGET ABORT etc. */ + //pci_write_config_dword(pdev, 0x58, 1); + return; +} + + +static void __init loongson2f_cs5536_ide_fixup(struct pci_dev *pdev) +{ + /* setting the mutex pin as IDE function */ + /* the IDE interrupt in PIC is enabled as default */ + pci_write_config_dword(pdev, 0x40, 0xDEADBEEF); + return; +} + +static void __init loongson2f_cs5536_acc_fixup(struct pci_dev *pdev) +{ + u8 val; + + /* enable the AUDIO interrupt in PIC */ + pci_write_config_dword(pdev, 0x50, 1); + +#if 1 + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val); + printk("cs5536 acc latency %x\n", val); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0); +#endif + return; +} + +static void __init loongson2f_cs5536_ohci_fixup(struct pci_dev *pdev) +{ + /* enable the OHCI interrupt in PIC */ + /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */ + pci_write_config_dword(pdev, 0x50, 1); + return; +} + +static void __init loongson2f_cs5536_ehci_fixup(struct pci_dev *pdev) +{ + u32 hi, lo; +#if 0 + u32 bar; + void __iomem *base; +#endif + + /* Serial short detect enable */ + _rdmsr(0x40000001, &hi, &lo); + _wrmsr(0x40000001, (1<<1)|(1<<2)|(1<<3), lo); + +#if 0 + /* Write to clear diag register */ + _rdmsr(0x40000005, &hi, &lo); + _wrmsr(0x40000005, hi, lo); + + pci_read_config_dword(pdev, 0x10, &bar); + base = ioremap_nocache(bar, 0x100); + + /* Make HCCAPARMS writable */ + writel(readl(base + 0xA0) | (1<<1), (base + 0xA0)); + + /* EECP=50h, IST=01h, ASPC=1h */ + writel(0x00000012, base + 0x08); + iounmap(base); +#endif + + /* setting the USB2.0 micro frame length */ + pci_write_config_dword(pdev, 0x60, 0x2000); + return; +} +#endif /* TEST_NO_CS5536 */ + +static void __init loongson2f_fixup_pcimap(struct pci_dev *pdev) +{ + static int first = 1; + + (void)pdev; + if (first) + first = 0; + else + return; + + /* local to PCI mapping: [256M,512M] -> [256M,512M]; differ from pmon */ + /* + * cpu address space [256M,448M] is window for accessing pci space + * we set pcimap_lo[0,1,2] to map it to pci space [256M,448M] + * pcimap: bit18,pcimap_2; bit[17-12],lo2;bit[11-6],lo1;bit[5-0],lo0 + */ + /* 1,00 0110 ,0001 01,00 0000 */ + BONITO_PCIMAP = 0x46140; + //1, 00 0010, 0000,01, 00 0000 + //BONITO_PCIMAP = 0x42040; + + /* + * PCI to local mapping: [2G,2G+256M] -> [0,256M] + */ +#if 1 // for GODSON2F + BONITO_PCIBASE0 = 0x80000000; + BONITO_PCIBASE1 = 0x00000000; + BONITO(BONITO_REGBASE + 0x50) = 0xc000000c; + BONITO(BONITO_REGBASE + 0x54) = 0xffffffff; + BONITO(BONITO_REGBASE + 0x58) = 0x00000006; + BONITO(BONITO_REGBASE + 0x5c) = 0x00000000; + BONITO(BONITO_REGBASE + 0x60) = 0x00000006; + BONITO(BONITO_REGBASE + 0x64) = 0x00000000; +#else // for GODSON2E + BONITO_PCIBASE0 = 0x80000000; + BONITO_PCIBASE1 = 0x00800000; + BONITO_PCIBASE2 = 0x90000000; +#endif + +#ifdef CONFIG_64BIT + *(volatile u32*)0xffffffffbfe0004c = 0xd2000001; +#else + *(volatile u32*)0xbfe0004c = 0xd2000001; +#endif +} + +static void __init loongson2f_nec_fixup(struct pci_dev *pdev) +{ + unsigned int val; + + /* Configues port 1, 2, 3 to be validate*/ + pci_read_config_dword(pdev, 0xe0, &val); + pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2); /*Only 2 port be used*/ +} +#ifndef TEST_NO_CS5536 +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, + loongson2f_cs5536_isa_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC, + loongson2f_cs5536_ohci_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC, + loongson2f_cs5536_ehci_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, + loongson2f_cs5536_acc_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, + loongson2f_cs5536_ide_fixup); +#endif /* TEST_NO_CS5536 */ +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, loongson2f_fixup_pcimap); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, + loongson2f_nec_fixup); diff --git a/arch/mips/pci/fixup-yl2f.c b/arch/mips/pci/fixup-yl2f.c new file mode 100644 index 0000000..142f0a0 --- /dev/null +++ b/arch/mips/pci/fixup-yl2f.c @@ -0,0 +1,245 @@ +/* + * fixup-lm2f.c + * + * Copyright (C) 2008 Lemote Technology + * Copyright (C) 2004 ICT CAS + * Author: Li xiaoyu, ICT CAS + * lixy@xxxxxxxxx + * + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/pci.h> +#include <asm/mips-boards/bonito64.h> + +/* PCI interrupt pins */ +/* These should not be changed, or you should consider godson2f interrupt register and + * your pci card dispatch + */ +#define PCIA 4 +#define PCIB 5 +#define PCIC 6 +#define PCID 7 + +/* all the pci device has the PCIA pin, check the datasheet. */ +static char irq_tab[][5] __initdata = { + /* INTA INTB INTC INTD */ + {0, 0, 0, 0, 0 }, /* 11: Unused */ + {0, 0, 0, 0, 0 }, /* 12: Unused */ + {0, 0, 0, 0, 0 }, /* 13: Unused */ + {0, 0, 0, 0, 0 }, /* 14: Unused */ + {0, 0, 0, 0, 0 }, /* 15: Unused */ + {0, 0, 0, 0, 0 }, /* 16: Unused */ + {0, PCIA, 0, 0, 0 }, /* 17: RTL8110-0 */ + {0, PCIB, 0, 0, 0 }, /* 18: RTL8110-1 */ + {0, PCIC, 0, 0, 0 }, /* 19: SiI3114 */ + {0, PCID, 0, 0, 0 }, /* 20: 3-ports nec usb*/ + {0, PCIA, PCIB, PCIC, PCID }, /* 21: PCI-SLOT */ + {0, 0, 0, 0, 0 }, /* 22: Unused */ + {0, 0, 0, 0, 0 }, /* 23: Unused */ + {0, 0, 0, 0, 0 }, /* 24: Unused */ + {0, 0, 0, 0, 0 }, /* 25: Unused */ + {0, 0, 0, 0, 0 }, /* 26: Unused */ + {0, 0, 0, 0, 0 }, /* 27: Unused */ +}; + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int virq; + + if( (PCI_SLOT(dev->devfn) != (14)) && (PCI_SLOT(dev->devfn) < 32) ){ + virq = irq_tab[slot][pin]; + printk("slot: %d, pin: %d, irq: %d\n", slot, pin, virq+BONITO_IRQ_BASE); + if(virq != 0) + return (BONITO_IRQ_BASE + virq); + else + return 0; + }else if( PCI_SLOT(dev->devfn) == 14){ // cs5536 + switch(PCI_FUNC(dev->devfn)){ + case 2 : + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 14); + return 14; // for IDE + case 3 : + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 9); + return 9; // for AUDIO + case 4 : // for OHCI + case 5 : // for EHCI + case 6 : // for UDC + case 7 : // for OTG + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + return 11; + } + return dev->irq; + }else{ + printk(" strange pci slot number.\n"); + return 0; + } +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + +extern void _wrmsr(u32 reg, u32 hi, u32 lo); +extern void _rdmsr(u32 reg, u32 *hi, u32 *lo); + +/* CS5536 SPEC. fixup */ +static void __init loongson2f_cs5536_isa_fixup(struct pci_dev *pdev) +{ + /* the uart1 and uart2 interrupt in PIC is enabled as default */ + pci_write_config_dword(pdev, 0x50, 1); + pci_write_config_dword(pdev, 0x54, 1); + /* enable the pci MASTER ABORT/ TARGET ABORT etc. */ + //pci_write_config_dword(pdev, 0x58, 1); + return; +} + + +static void __init loongson2f_cs5536_ide_fixup(struct pci_dev *pdev) +{ + /* setting the mutex pin as IDE function */ + /* the IDE interrupt in PIC is enabled as default */ + pci_write_config_dword(pdev, 0x40, 0xDEADBEEF); + return; +} + +static void __init loongson2f_cs5536_acc_fixup(struct pci_dev *pdev) +{ + u8 val; + + /* enable the AUDIO interrupt in PIC */ + pci_write_config_dword(pdev, 0x50, 1); + +#if 1 + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val); + printk("cs5536 acc latency %x\n", val); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0); +#endif + return; +} + +static void __init loongson2f_cs5536_ohci_fixup(struct pci_dev *pdev) +{ + /* enable the OHCI interrupt in PIC */ + /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */ + pci_write_config_dword(pdev, 0x50, 1); + return; +} + +static void __init loongson2f_cs5536_ehci_fixup(struct pci_dev *pdev) +{ + u32 hi, lo; +#if 0 + u32 bar; + void __iomem *base; +#endif + + /* Serial short detect enable */ + _rdmsr(0x40000001, &hi, &lo); + _wrmsr(0x40000001, (1<<1)|(1<<2)|(1<<3), lo); + +#if 0 + /* Write to clear diag register */ + _rdmsr(0x40000005, &hi, &lo); + _wrmsr(0x40000005, hi, lo); + + pci_read_config_dword(pdev, 0x10, &bar); + base = ioremap_nocache(bar, 0x100); + + /* Make HCCAPARMS writable */ + writel(readl(base + 0xA0) | (1<<1), (base + 0xA0)); + + /* EECP=50h, IST=01h, ASPC=1h */ + writel(0x00000012, base + 0x08); + iounmap(base); +#endif + + /* setting the USB2.0 micro frame length */ + pci_write_config_dword(pdev, 0x60, 0x2000); + return; +} + +static void __init loongson2f_fixup_pcimap(struct pci_dev *pdev) +{ + static int first = 1; + + (void)pdev; + if (first) + first = 0; + else + return; + + /* local to PCI mapping: [256M,512M] -> [256M,512M]; differ from pmon */ + /* + * cpu address space [256M,448M] is window for accessing pci space + * we set pcimap_lo[0,1,2] to map it to pci space [256M,448M] + * pcimap: bit18,pcimap_2; bit[17-12],lo2;bit[11-6],lo1;bit[5-0],lo0 + */ + /* 1,00 0110 ,0001 01,00 0000 */ + BONITO_PCIMAP = 0x46140; + + /* + * PCI to local mapping: [2G,2G+256M] -> [0,256M] + */ + BONITO_PCIBASE0 = 0x80000000; + BONITO_PCIBASE1 = 0x00000000; + BONITO(BONITO_REGBASE + 0x50) = 0xc000000c; + BONITO(BONITO_REGBASE + 0x54) = 0xffffffff; + BONITO(BONITO_REGBASE + 0x58) = 0x00000006; + BONITO(BONITO_REGBASE + 0x5c) = 0x00000000; + BONITO(BONITO_REGBASE + 0x60) = 0x00000006; + BONITO(BONITO_REGBASE + 0x64) = 0x00000000; + + BONITO(0x4c) = 0xd2000001; +#ifdef CONFIG_64BIT + *(volatile u32*)0xffffffffbfe0004c = 0xd2000001; +#else + *(volatile u32*)0xbfe0004c = 0xd2000001; +#endif +} + +static void __init loongson2f_nec_fixup(struct pci_dev *pdev) +{ + unsigned int val; + + pci_read_config_dword(pdev, 0xe0, &val); + /* Only 2 port be used */ + pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2); +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, + loongson2f_cs5536_isa_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC, + loongson2f_cs5536_ohci_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC, + loongson2f_cs5536_ehci_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, + loongson2f_cs5536_acc_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, + loongson2f_cs5536_ide_fixup); +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, loongson2f_fixup_pcimap); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, + loongson2f_nec_fixup); diff --git a/arch/mips/pci/ops-lm2f.c b/arch/mips/pci/ops-lm2f.c new file mode 100644 index 0000000..08e8b7f --- /dev/null +++ b/arch/mips/pci/ops-lm2f.c @@ -0,0 +1,205 @@ +/* + * ops-lm2f.c + * + * Copyright (C) 2004 ICT CAS + * Author: Li xiaoyu, ICT CAS + * lixy@xxxxxxxxx + * + * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology + * Author: Fuxin Zhang, zhangfx@xxxxxxxxxx + * + * 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/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> + +#include <asm/mips-boards/bonito64.h> + +#define PCI_OPS_CS5536_IDSEL 14 + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +extern void cs5536_pci_conf_write4(int function, int reg, u32 value); +extern u32 cs5536_pci_conf_read4(int function, int reg); + +static inline void bflush(void) +{ + /* flush Bonito register writes */ + (void)BONITO_PCICMD; +} + +static int lm2f_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, + int where, u32 *data) +{ + u32 busnum = bus->number; + u32 addr, type; + void *addrp; + int device = PCI_SLOT(devfn); + int function = PCI_FUNC(devfn); + int reg = where & ~3; + + /************************************************************************/ + /* CS5536 PCI ACCESS ROUTINE : */ + /* Note the functions circle call : */ + /* lm2e_pci_config_access()--->cs5536_pci_conf_read/write4()---> */ + /* _rdmsr/_wrmsr()--->lm2e_pci_config_access() */ + /************************************************************************/ + if( (busnum == 0) && (device == PCI_OPS_CS5536_IDSEL) && (reg < 0xF0) ){ + switch(access_type){ + case PCI_ACCESS_READ : + *data = cs5536_pci_conf_read4(function, reg); + break; + case PCI_ACCESS_WRITE : + cs5536_pci_conf_write4(function, reg, *data); + break; + } + return 0; + } + + if (busnum == 0) { + /* Type 0 configuration on onboard PCI bus */ + if (device > 20 || function > 7) { + *data = -1; /* device out of range */ + return PCIBIOS_DEVICE_NOT_FOUND; + } + addr = (1 << (device + 11)) | (function << 8) | reg; + type = 0; + } else { + /* Type 1 configuration on offboard PCI bus */ + if (device > 31 || function > 7) { + *data = -1; /* device out of range */ + return PCIBIOS_DEVICE_NOT_FOUND; + } + addr = (busnum << 16) | (device << 11) | (function << 8) | reg; + type = 0x10000; + } + + /* clear aborts */ + BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR; + + BONITO_PCIMAP_CFG = (addr >> 16) | type; + bflush(); + + addrp = (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (addr & 0xffff)); + if (access_type == PCI_ACCESS_WRITE) { + *(volatile unsigned int *)addrp = cpu_to_le32(*data); + } else { + *data = le32_to_cpu(*(volatile unsigned int *)addrp); + } + + /* Detect Master/Target abort */ + if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR)) { + BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR; + *data = -1; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return PCIBIOS_SUCCESSFUL; + +} + +static int lm2f_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + int ret = lm2f_pci_config_access(PCI_ACCESS_READ, + bus, devfn, where, &data); + + if (ret != PCIBIOS_SUCCESSFUL) + return ret; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int lm2f_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + int ret; + + if (size == 4) + data = val; + else { + ret = lm2f_pci_config_access(PCI_ACCESS_READ, + bus, devfn, where, &data); + if (ret != PCIBIOS_SUCCESSFUL) + return ret; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + } + + ret = lm2f_pci_config_access(PCI_ACCESS_WRITE, + bus, devfn, where, &data); + if (ret != PCIBIOS_SUCCESSFUL) + return ret; + + return PCIBIOS_SUCCESSFUL; +} + +void _rdmsr(u32 msr, u32 *hi, u32 *lo) +{ + struct pci_bus bus = { + .number = 0 + }; + u32 devfn = PCI_DEVFN(14, 0); + lm2f_pci_pcibios_write(&bus, devfn, 0xf4, 4, msr); + lm2f_pci_pcibios_read(&bus, devfn, 0xf8, 4, lo); + lm2f_pci_pcibios_read(&bus, devfn, 0xfc, 4, hi); + //printk("rdmsr msr %x, lo %x, hi %x\n", msr, *lo, *hi); +} + +void _wrmsr(u32 msr, u32 hi, u32 lo) +{ + struct pci_bus bus = { + .number = 0 + }; + u32 devfn = PCI_DEVFN(14, 0); + lm2f_pci_pcibios_write(&bus, devfn, 0xf4, 4, msr); + lm2f_pci_pcibios_write(&bus, devfn, 0xf8, 4, lo); + lm2f_pci_pcibios_write(&bus, devfn, 0xfc, 4, hi); + //printk("wrmsr msr %x, lo %x, hi %x\n", msr, lo, hi); +} + +EXPORT_SYMBOL(_rdmsr); +EXPORT_SYMBOL(_wrmsr); + +struct pci_ops loongson2f_pci_pci_ops = { + .read = lm2f_pci_pcibios_read, + .write = lm2f_pci_pcibios_write +}; -- 1.5.6.5