From 659da2ba3ebf53dc49f7f9a357a1aef046bf3139 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 16 Oct 2009 14:17:15 +0800 Subject: MIPS: Loongson: Register reserved memory pages Register reserved pages for Loongson family machines. Signed-off-by: Wu Zhangjin Cc: Linux-MIPS Cc: yanh@lemote.com, Cc: huhb@lemote.com Cc: Zhang Le Cc: zhangfx@lemote.com, Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/mem.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c index e94ef158f98..3f7f153b197 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson/common/mem.c @@ -12,14 +12,22 @@ #include #include +#include void __init prom_init_memory(void) { add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM); + + add_memory_region(memsize << 20, LOONGSON_PCI_MEM_START - (memsize << + 20), BOOT_MEM_RESERVED); #ifdef CONFIG_64BIT if (highmemsize > 0) add_memory_region(LOONGSON_HIGHMEM_START, highmemsize << 20, BOOT_MEM_RAM); + + add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START - + LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED); + #endif /* CONFIG_64BIT */ } -- cgit v1.2.3 From f6d4ff02c60e18797279270d09791768e43cd269 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 16 Oct 2009 14:17:14 +0800 Subject: MIPS: Fuloong2e: Cleanup Kconfig Changes indention from whitespace to tabs in arch/mips/loongson/Kconfig. Signed-off-by: Wu Zhangjin Cc: Linux-MIPS Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Zhang Le Cc: zhangfx@lemote.com Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index d45092505fa..818a0289711 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -1,31 +1,31 @@ choice - prompt "Machine Type" - depends on MACH_LOONGSON + prompt "Machine Type" + depends on MACH_LOONGSON config LEMOTE_FULOONG2E - bool "Lemote Fuloong(2e) mini-PC" - select ARCH_SPARSEMEM_ENABLE - select CEVT_R4K - select CSRC_R4K - select SYS_HAS_CPU_LOONGSON2E - 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 - help - Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and - an FPGA northbridge + bool "Lemote Fuloong(2e) mini-PC" + select ARCH_SPARSEMEM_ENABLE + select CEVT_R4K + select CSRC_R4K + select SYS_HAS_CPU_LOONGSON2E + 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 + help + Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and + an FPGA northbridge - Lemote Fuloong(2e) mini PC have a VIA686B south bridge. + Lemote Fuloong(2e) mini PC have a VIA686B south bridge. endchoice -- cgit v1.2.3 From db54ff246eae5acb6b7dffec2c05e682f91e0f4e Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 16 Oct 2009 14:17:16 +0800 Subject: MIPS: Loongson early_printk: Fix variable type of uart_base The uart_base variable here is not a physical address, so, we replace it by unsigned char *. Signed-off-by: Wu Zhangjin Cc: Linux-MIPS Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Zhang Le Cc: zhangfx@lemote.com Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/early_printk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson/common/early_printk.c index bc73edc0cfd..8ec4fb2066a 100644 --- a/arch/mips/loongson/common/early_printk.c +++ b/arch/mips/loongson/common/early_printk.c @@ -1,7 +1,7 @@ /* early printk support * * Copyright (c) 2009 Philippe Vachon - * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology + * Copyright (c) 2009 Lemote Inc. * Author: Wu Zhangjin, wuzj@lemote.com * * This program is free software; you can redistribute it and/or modify it @@ -16,20 +16,20 @@ #define PORT(base, offset) (u8 *)(base + offset) -static inline unsigned int serial_in(phys_addr_t base, int offset) +static inline unsigned int serial_in(unsigned char *base, int offset) { return readb(PORT(base, offset)); } -static inline void serial_out(phys_addr_t base, int offset, int value) +static inline void serial_out(unsigned char *base, int offset, int value) { writeb(value, PORT(base, offset)); } void prom_putchar(char c) { - phys_addr_t uart_base = - (phys_addr_t) ioremap_nocache(LOONGSON_UART_BASE, 8); + unsigned char *uart_base = + (unsigned char *) ioremap_nocache(LOONGSON_UART_BASE, 8); while ((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) ; -- cgit v1.2.3 From e8be5283881cb96bafb751e1f9ea34c4e6fc2845 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 16 Oct 2009 14:17:18 +0800 Subject: MIPS: Loongson: Add serial port support This patch add serial port support for all of the existing loongson family machines. most of the board specific part are put in serial.c, and the base address of the serial ports are defined as macros in machine.h for sharing it between serial.c and early_printk.c Signed-off-by: Wu Zhangjin Cc: Linux-MIPS Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Zhang Le Cc: zhangfx@lemote.com Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/Makefile | 1 + arch/mips/loongson/common/serial.c | 71 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 arch/mips/loongson/common/serial.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index 656b3cc0a2a..d21d1163fad 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -9,3 +9,4 @@ obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ # Early printk support # obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_SERIAL_8250) += serial.o diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c new file mode 100644 index 00000000000..6d341e426f6 --- /dev/null +++ b/arch/mips/loongson/common/serial.c @@ -0,0 +1,71 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Yan hua (yanhua@lemote.com) + * Author: Wu Zhangjin (wuzj@lemote.com) + */ + +#include +#include +#include + +#include + +#include +#include + +#define PORT(int) \ +{ \ + .irq = int, \ + .uartclk = 1843200, \ + .iobase = (LOONGSON_UART_BASE - LOONGSON_PCIIO_BASE),\ + .iotype = UPIO_PORT, \ + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \ + .regshift = 0, \ +} + +#define PORT_M(int) \ +{ \ + .irq = MIPS_CPU_IRQ_BASE + (int), \ + .uartclk = 3686400, \ + .iotype = UPIO_MEM, \ + .membase = (void __iomem *)NULL, \ + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \ + .regshift = 0, \ +} + +static struct plat_serial8250_port uart8250_data[][2] = { + [MACH_LOONGSON_UNKNOWN] {}, + [MACH_LEMOTE_FL2E] {PORT(4), {} }, + [MACH_LEMOTE_FL2F] {PORT(3), {} }, + [MACH_LEMOTE_ML2F7] {PORT_M(3), {} }, + [MACH_LEMOTE_YL2F89] {PORT_M(3), {} }, + [MACH_DEXXON_GDIUM2F10] {PORT_M(3), {} }, + [MACH_LOONGSON_END] {}, +}; + +static struct platform_device uart8250_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = uart8250_data[LOONGSON_MACHTYPE], + }, +}; + +static int __init serial_init(void) +{ + if (uart8250_data[LOONGSON_MACHTYPE][0].iotype == UPIO_MEM) + uart8250_data[LOONGSON_MACHTYPE][0].membase = + ioremap_nocache(LOONGSON_UART_BASE, 8); + + platform_device_register(&uart8250_device); + + return 0; +} + +device_initcall(serial_init); -- cgit v1.2.3 From e2fee5723bbda4a05c86f16a9d0f889a2c4ecede Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 16 Oct 2009 14:17:19 +0800 Subject: MIPS: Bonito64: Make Loongson independent from Bonito64 code. The built-in Loongson 2E/2F northbridge in is bonito64-compatible but not identical with it. To avoid influencing the original bonito64 support and make the loongson support more maintainable, it's better to separate the Bonito64 code from the Loongson code. This also prepares the kernel for the coming Loongson 2f machines family support. Signed-off-by: Wu Zhangjin Cc: Linux-MIPS Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Zhang Le Cc: zhangfx@lemote.com, Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/bonito-irq.c | 8 ++++---- arch/mips/loongson/common/init.c | 2 +- arch/mips/loongson/common/irq.c | 12 ++++++------ arch/mips/loongson/common/pci.c | 12 ++++++------ arch/mips/loongson/common/reset.c | 2 +- arch/mips/loongson/fuloong-2e/irq.c | 4 ++-- arch/mips/loongson/fuloong-2e/reset.c | 4 ++-- 7 files changed, 22 insertions(+), 22 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/bonito-irq.c b/arch/mips/loongson/common/bonito-irq.c index 3e31e7ad713..a1cbd110a6e 100644 --- a/arch/mips/loongson/common/bonito-irq.c +++ b/arch/mips/loongson/common/bonito-irq.c @@ -17,13 +17,13 @@ static inline void bonito_irq_enable(unsigned int irq) { - BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE)); + LOONGSON_INTENSET = (1 << (irq - LOONGSON_IRQ_BASE)); mmiowb(); } static inline void bonito_irq_disable(unsigned int irq) { - BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE)); + LOONGSON_INTENCLR = (1 << (irq - LOONGSON_IRQ_BASE)); mmiowb(); } @@ -44,8 +44,8 @@ void bonito_irq_init(void) { u32 i; - for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) + for (i = LOONGSON_IRQ_BASE; i < LOONGSON_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); + setup_irq(LOONGSON_IRQ_BASE + 10, &dma_timeout_irqaction); } diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c index 3abe927422a..b7e4913627a 100644 --- a/arch/mips/loongson/common/init.c +++ b/arch/mips/loongson/common/init.c @@ -18,7 +18,7 @@ void __init prom_init(void) { /* init base address of io space */ set_io_port_base((unsigned long) - ioremap(BONITO_PCIIO_BASE, BONITO_PCIIO_SIZE)); + ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE)); prom_init_cmdline(); prom_init_env(); diff --git a/arch/mips/loongson/common/irq.c b/arch/mips/loongson/common/irq.c index b32b4a3e513..20e73283197 100644 --- a/arch/mips/loongson/common/irq.c +++ b/arch/mips/loongson/common/irq.c @@ -20,21 +20,21 @@ void bonito_irqdispatch(void) int i; /* workaround the IO dma problem: let cpu looping to allow DMA finish */ - int_status = BONITO_INTISR; + int_status = LOONGSON_INTISR; if (int_status & (1 << 10)) { while (int_status & (1 << 10)) { udelay(1); - int_status = BONITO_INTISR; + int_status = LOONGSON_INTISR; } } /* Get pending sources, masked by current enables */ - int_status = BONITO_INTISR & BONITO_INTEN; + int_status = LOONGSON_INTISR & LOONGSON_INTEN; if (int_status != 0) { i = __ffs(int_status); int_status &= ~(1 << i); - do_IRQ(BONITO_IRQ_BASE + i); + do_IRQ(LOONGSON_IRQ_BASE + i); } } @@ -60,13 +60,13 @@ void __init arch_init_irq(void) set_irq_trigger_mode(); /* no steer */ - BONITO_INTSTEER = 0; + LOONGSON_INTSTEER = 0; /* * Mask out all interrupt by writing "1" to all bit position in * the interrupt reset reg. */ - BONITO_INTENCLR = ~0; + LOONGSON_INTENCLR = ~0; /* machine specific irq init */ mach_init_irq(); diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c index a3a4abfb6c9..a7eb8b9c44e 100644 --- a/arch/mips/loongson/common/pci.c +++ b/arch/mips/loongson/common/pci.c @@ -27,7 +27,7 @@ static struct resource loongson_pci_io_resource = { }; static struct pci_controller loongson_pci_controller = { - .pci_ops = &bonito64_pci_ops, + .pci_ops = &loongson_pci_ops, .io_resource = &loongson_pci_io_resource, .mem_resource = &loongson_pci_mem_resource, .mem_offset = 0x00000000UL, @@ -44,15 +44,15 @@ static void __init setup_pcimap(void) * pcimap: PCI_MAP2 PCI_Mem_Lo2 PCI_Mem_Lo1 PCI_Mem_Lo0 * [<2G] [384M,448M] [320M,384M] [0M,64M] */ - BONITO_PCIMAP = BONITO_PCIMAP_PCIMAP_2 | - BONITO_PCIMAP_WIN(2, BONITO_PCILO2_BASE) | - BONITO_PCIMAP_WIN(1, BONITO_PCILO1_BASE) | - BONITO_PCIMAP_WIN(0, 0); + LOONGSON_PCIMAP = LOONGSON_PCIMAP_PCIMAP_2 | + LOONGSON_PCIMAP_WIN(2, LOONGSON_PCILO2_BASE) | + LOONGSON_PCIMAP_WIN(1, LOONGSON_PCILO1_BASE) | + LOONGSON_PCIMAP_WIN(0, 0); /* * PCI-DMA to local mapping: [2G,2G+256M] -> [0M,256M] */ - BONITO_PCIBASE0 = 0x80000000ul; /* base: 2G -> mmap: 0M */ + LOONGSON_PCIBASE0 = 0x80000000ul; /* base: 2G -> mmap: 0M */ /* size: 256M, burst transmission, pre-fetch enable, 64bit */ LOONGSON_PCI_HIT0_SEL_L = 0xc000000cul; LOONGSON_PCI_HIT0_SEL_H = 0xfffffffful; diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c index 97e918251ed..d57f1719da9 100644 --- a/arch/mips/loongson/common/reset.c +++ b/arch/mips/loongson/common/reset.c @@ -22,7 +22,7 @@ static void loongson_restart(char *command) mach_prepare_reboot(); /* reboot via jumping to boot base address */ - ((void (*)(void))ioremap_nocache(BONITO_BOOT_BASE, 4)) (); + ((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) (); } static void loongson_halt(void) diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson/fuloong-2e/irq.c index 7888cf69424..320e9379bdd 100644 --- a/arch/mips/loongson/fuloong-2e/irq.c +++ b/arch/mips/loongson/fuloong-2e/irq.c @@ -47,8 +47,8 @@ static struct irqaction cascade_irqaction = { void __init set_irq_trigger_mode(void) { /* most bonito irq should be level triggered */ - BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR | - BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES; + LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR | + LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES; } void __init mach_init_irq(void) diff --git a/arch/mips/loongson/fuloong-2e/reset.c b/arch/mips/loongson/fuloong-2e/reset.c index 677fe186db9..fc16c677d47 100644 --- a/arch/mips/loongson/fuloong-2e/reset.c +++ b/arch/mips/loongson/fuloong-2e/reset.c @@ -14,8 +14,8 @@ void mach_prepare_reboot(void) { - BONITO_BONGENCFG &= ~(1 << 2); - BONITO_BONGENCFG |= (1 << 2); + LOONGSON_GENCFG &= ~(1 << 2); + LOONGSON_GENCFG |= (1 << 2); } void mach_prepare_shutdown(void) -- cgit v1.2.3 From 04cfb90a92a2f9f7b56b2f85c528be7d1561e0e5 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 6 Nov 2009 18:35:33 +0800 Subject: MIPS: Loongson: Cleanup machtype support To choose code for different machines by the value of machtype it needs to be initialized as early as possible. So move initialization of mips_machtype to prom_init(). Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/cmdline.c | 4 +++- arch/mips/loongson/common/machtype.c | 23 +++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson/common/cmdline.c index 75f1b243ee4..7ad47f22747 100644 --- a/arch/mips/loongson/common/cmdline.c +++ b/arch/mips/loongson/common/cmdline.c @@ -9,7 +9,7 @@ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * - * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2009 Lemote Inc. * Author: Wu Zhangjin, wuzj@lemote.com * * This program is free software; you can redistribute it and/or modify it @@ -49,4 +49,6 @@ void __init prom_init_cmdline(void) strcat(arcs_cmdline, " console=ttyS0,115200"); if ((strstr(arcs_cmdline, "root=")) == NULL) strcat(arcs_cmdline, " root=/dev/hda1"); + + prom_init_machtype(); } diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c index 7b348248de7..7545fe69089 100644 --- a/arch/mips/loongson/common/machtype.c +++ b/arch/mips/loongson/common/machtype.c @@ -15,6 +15,9 @@ #include #include +/* please ensure the length of the machtype string is less than 50 */ +#define MACHTYPE_LEN 50 + static const char *system_types[] = { [MACH_LOONGSON_UNKNOWN] "unknown loongson machine", [MACH_LEMOTE_FL2E] "lemote-fuloong-2e-box", @@ -27,24 +30,28 @@ static const char *system_types[] = { const char *get_system_type(void) { - if (mips_machtype == MACH_UNKNOWN) - mips_machtype = LOONGSON_MACHTYPE; - return system_types[mips_machtype]; } -static __init int machtype_setup(char *str) +void __init prom_init_machtype(void) { + char *p, str[MACHTYPE_LEN]; int machtype = MACH_LEMOTE_FL2E; - if (!str) - return -EINVAL; + mips_machtype = LOONGSON_MACHTYPE; + + p = strstr(arcs_cmdline, "machtype="); + if (!p) + return; + p += strlen("machtype="); + strncpy(str, p, MACHTYPE_LEN); + p = strstr(str, " "); + if (p) + *p = '\0'; for (; system_types[machtype]; machtype++) if (strstr(system_types[machtype], str)) { mips_machtype = machtype; break; } - return 0; } -__setup("machtype=", machtype_setup); -- cgit v1.2.3 From a3ed495190ebe918f4584291ed8c76f1c97a84fd Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 6 Nov 2009 18:35:34 +0800 Subject: MIPS: Loongson: Cleanup the serial port support To share the same kernel image amon different machines we have added the machtype command line support. In the old serial port implementation the UART base address is hardcoded as a macro in machine.h which breaks with machtype, so change that to discover the address dynamically. Also move the initialization of the UART base address to uart_base.c to avoid remapping twice for early_printk.c and serial.c. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/581/ Patchwork: http://patchwork.linux-mips.org/patch/682/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/Makefile | 2 +- arch/mips/loongson/common/early_printk.c | 11 +++++++---- arch/mips/loongson/common/init.c | 11 +++++++---- arch/mips/loongson/common/serial.c | 17 ++++++++-------- arch/mips/loongson/common/uart_base.c | 34 ++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 arch/mips/loongson/common/uart_base.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index d21d1163fad..be6adf7eb82 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -3,7 +3,7 @@ # obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ - pci.o bonito-irq.o mem.o machtype.o + pci.o bonito-irq.o mem.o machtype.o uart_base.o # # Early printk support diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson/common/early_printk.c index 8ec4fb2066a..23e7a8f8897 100644 --- a/arch/mips/loongson/common/early_printk.c +++ b/arch/mips/loongson/common/early_printk.c @@ -12,7 +12,6 @@ #include #include -#include #define PORT(base, offset) (u8 *)(base + offset) @@ -28,10 +27,14 @@ static inline void serial_out(unsigned char *base, int offset, int value) void prom_putchar(char c) { - unsigned char *uart_base = - (unsigned char *) ioremap_nocache(LOONGSON_UART_BASE, 8); + int timeout; + unsigned char *uart_base; - while ((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) + uart_base = (unsigned char *)_loongson_uart_base; + timeout = 1024; + + while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) && + (timeout-- > 0)) ; serial_out(uart_base, UART_TX, c); diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c index b7e4913627a..3b1dbc1ca24 100644 --- a/arch/mips/loongson/common/init.c +++ b/arch/mips/loongson/common/init.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2009 Lemote Inc. * Author: Wu Zhangjin, wuzj@lemote.com * * This program is free software; you can redistribute it and/or modify it @@ -10,19 +10,22 @@ #include -#include - #include void __init prom_init(void) { - /* init base address of io space */ + /* init base address of io space */ set_io_port_base((unsigned long) ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE)); prom_init_cmdline(); prom_init_env(); prom_init_memory(); + + /*init the uart base address */ +#if defined(CONFIG_EARLY_PRINTK) || defined(CONFIG_SERIAL_8250) + prom_init_uart_base(); +#endif } void __init prom_free_prom_memory(void) diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c index 6d341e426f6..dc6488c1476 100644 --- a/arch/mips/loongson/common/serial.c +++ b/arch/mips/loongson/common/serial.c @@ -23,7 +23,6 @@ { \ .irq = int, \ .uartclk = 1843200, \ - .iobase = (LOONGSON_UART_BASE - LOONGSON_PCIIO_BASE),\ .iotype = UPIO_PORT, \ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \ .regshift = 0, \ @@ -52,20 +51,20 @@ static struct plat_serial8250_port uart8250_data[][2] = { static struct platform_device uart8250_device = { .name = "serial8250", .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = uart8250_data[LOONGSON_MACHTYPE], - }, }; static int __init serial_init(void) { - if (uart8250_data[LOONGSON_MACHTYPE][0].iotype == UPIO_MEM) - uart8250_data[LOONGSON_MACHTYPE][0].membase = - ioremap_nocache(LOONGSON_UART_BASE, 8); + if (uart8250_data[mips_machtype][0].iotype == UPIO_MEM) + uart8250_data[mips_machtype][0].membase = + (void __iomem *)_loongson_uart_base; + else if (uart8250_data[mips_machtype][0].iotype == UPIO_PORT) + uart8250_data[mips_machtype][0].iobase = + uart8250_base[mips_machtype] - LOONGSON_PCIIO_BASE; - platform_device_register(&uart8250_device); + uart8250_device.dev.platform_data = uart8250_data[mips_machtype]; - return 0; + return platform_device_register(&uart8250_device); } device_initcall(serial_init); diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c new file mode 100644 index 00000000000..233c708fc12 --- /dev/null +++ b/arch/mips/loongson/common/uart_base.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 Lemote Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +#include + +unsigned long __maybe_unused _loongson_uart_base; +EXPORT_SYMBOL(_loongson_uart_base); + +unsigned long __maybe_unused uart8250_base[] = { + [MACH_LOONGSON_UNKNOWN] 0, + [MACH_LEMOTE_FL2E] (LOONGSON_PCIIO_BASE + 0x3f8), + [MACH_LEMOTE_FL2F] (LOONGSON_PCIIO_BASE + 0x2f8), + [MACH_LEMOTE_ML2F7] (LOONGSON_LIO1_BASE + 0x3f8), + [MACH_LEMOTE_YL2F89] (LOONGSON_LIO1_BASE + 0x3f8), + [MACH_DEXXON_GDIUM2F10] (LOONGSON_LIO1_BASE + 0x3f8), + [MACH_LOONGSON_END] 0, +}; +EXPORT_SYMBOL(uart8250_base); + +void __maybe_unused prom_init_uart_base(void) +{ + _loongson_uart_base = + (unsigned long)ioremap_nocache(uart8250_base[mips_machtype], 8); +} -- cgit v1.2.3 From 6f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 6 Nov 2009 18:45:05 +0800 Subject: MIPS: Loongson: Add basic Loongson 2F support Loongson 2F has built-in DDR2 and PCI-X controller. The PCI-X controller has a programming interface similiar to the the FPGA northbridge used on Loongson 2E. The main differences between Loongson 2E and Loongson 2F include: 1. Loongson 2F has an extra address window configuration module, which is used to map CPU address space to DDR or PCI address space, or map the PCI-DMA address space to DDR or LIO address space. 2. Loongson 2F supports 8 levels of software configurable CPu frequency which can be configured in the LOONGSON_CHIPCFG0 register. The coming cpufreq and standby support are based on this feature. Loongson.h abstracts the modules and corresponding methods are abstracted. Add other Loongson-2F-specific source code including gcc 4.4 support, PCI memory space, PCI IO space, DMA address. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/bonito-irq.c | 5 ++++- arch/mips/loongson/common/init.c | 8 ++++++++ arch/mips/loongson/common/mem.c | 33 +++++++++++++++++++++++++-------- arch/mips/loongson/common/pci.c | 8 ++++++++ 4 files changed, 45 insertions(+), 9 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/bonito-irq.c b/arch/mips/loongson/common/bonito-irq.c index a1cbd110a6e..2dc2a4cc632 100644 --- a/arch/mips/loongson/common/bonito-irq.c +++ b/arch/mips/loongson/common/bonito-irq.c @@ -12,6 +12,7 @@ * option) any later version. */ #include +#include #include @@ -35,7 +36,7 @@ static struct irq_chip bonito_irq_type = { .unmask = bonito_irq_enable, }; -static struct irqaction dma_timeout_irqaction = { +static struct irqaction __maybe_unused dma_timeout_irqaction = { .handler = no_action, .name = "dma_timeout", }; @@ -47,5 +48,7 @@ void bonito_irq_init(void) for (i = LOONGSON_IRQ_BASE; i < LOONGSON_IRQ_BASE + 32; i++) set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq); +#ifdef CONFIG_CPU_LOONGSON2E setup_irq(LOONGSON_IRQ_BASE + 10, &dma_timeout_irqaction); +#endif } diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c index 3b1dbc1ca24..743d3571f01 100644 --- a/arch/mips/loongson/common/init.c +++ b/arch/mips/loongson/common/init.c @@ -12,12 +12,20 @@ #include +/* Loongson CPU address windows config space base address */ +unsigned long __maybe_unused _loongson_addrwincfg_base; + void __init prom_init(void) { /* init base address of io space */ set_io_port_base((unsigned long) ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE)); +#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) + _loongson_addrwincfg_base = (unsigned long) + ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE); +#endif + prom_init_cmdline(); prom_init_env(); prom_init_memory(); diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c index 3f7f153b197..e93551dbc9e 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson/common/mem.c @@ -21,14 +21,31 @@ void __init prom_init_memory(void) add_memory_region(memsize << 20, LOONGSON_PCI_MEM_START - (memsize << 20), BOOT_MEM_RESERVED); #ifdef CONFIG_64BIT - if (highmemsize > 0) - add_memory_region(LOONGSON_HIGHMEM_START, - highmemsize << 20, BOOT_MEM_RAM); - - add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START - - LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED); - -#endif /* CONFIG_64BIT */ +#ifdef CONFIG_CPU_LOONGSON2F + { + int bit; + + bit = fls(memsize + highmemsize); + if (bit != ffs(memsize + highmemsize)) + bit += 20; + else + bit = bit + 20 - 1; + + /* set cpu window3 to map CPU to DDR: 2G -> 2G */ + LOONGSON_ADDRWIN_CPUTODDR(ADDRWIN_WIN3, 0x80000000ul, + 0x80000000ul, (1 << bit)); + mmiowb(); + } +#endif /* CONFIG_CPU_LOONGSON2F */ + + if (highmemsize > 0) + add_memory_region(LOONGSON_HIGHMEM_START, + highmemsize << 20, BOOT_MEM_RAM); + + add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START - + LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED); + +#endif /* CONFIG_64BIT */ } /* override of arch/mips/mm/cache.c: __uncached_access */ diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c index a7eb8b9c44e..eac43b8f695 100644 --- a/arch/mips/loongson/common/pci.c +++ b/arch/mips/loongson/common/pci.c @@ -67,6 +67,14 @@ static void __init setup_pcimap(void) /* can not change gnt to break pci transfer when device's gnt not deassert for some broken device */ LOONGSON_PXARB_CFG = 0x00fe0105ul; + +#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) + /* + * set cpu addr window2 to map CPU address space to PCI address space + */ + LOONGSON_ADDRWIN_CPUTOPCI(ADDRWIN_WIN2, LOONGSON_CPU_MEM_SRC, + LOONGSON_PCI_MEM_DST, MMAP_CPUTOPCI_SIZE); +#endif } static int __init pcibios_init(void) -- cgit v1.2.3 From 7d32c6dd816bb0c595aef62294b714a9b8a0f864 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 10 Nov 2009 00:06:10 +0800 Subject: MIPS: Lemote 2F: Add a LEMOTE_MACH2F kernel option Add a new kernel option for Lemote Loongson 2F family machines. Lemote loongson2f family machines utilize the 2f revision of loongson processor and the AMD CS5536 south bridge. Family members include Fuloong 2F mini PC, Yeeloong 2F notebook, LingLoong all-in-one PC and others. Signed-off-by: Wu Zhangjin Cc: zhangfx@lemote.com Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Nicholas Mc Guire Cc: Arnaud Patard Cc: loongson-dev@googlegroups.com Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 818a0289711..3100237b3f1 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -28,4 +28,33 @@ config LEMOTE_FULOONG2E an FPGA northbridge Lemote Fuloong(2e) mini PC have a VIA686B south bridge. + +config LEMOTE_MACH2F + bool "Lemote Loongson 2F family machines" + select ARCH_SPARSEMEM_ENABLE + select BOARD_SCACHE + select BOOT_ELF32 + select CEVT_R4K + select CPU_HAS_WB + select CS5536 + select CSRC_R4K + select DMA_NONCOHERENT + select GENERIC_HARDIRQS_NO__DO_IRQ + select GENERIC_ISA_DMA_SUPPORT_BROKEN + select HW_HAS_PCI + select I8259 + select IRQ_CPU + select ISA + select SYS_HAS_CPU_LOONGSON2F + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_LITTLE_ENDIAN + help + Lemote Loongson 2F family machines utilize the 2F revision of + Loongson processor and the AMD CS5536 south bridge. + + These family machines include fuloong2f mini PC, yeeloong2f notebook, + LingLoong allinone PC and so forth. endchoice -- cgit v1.2.3 From 22c21003a91b543d82e87ef2e5195b888b5b9575 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 10 Nov 2009 00:06:12 +0800 Subject: MIPS: Lemote 2F: Add basic CS5536 VSM support Lemote Loongson 2F family machines use CS5536 as their south bridge and need these lowlevel interfaces to access the devices on CS5536. Virtualize the legacy devices on CS5536 as PCI devices. This way users can access the CS5536 PCI config space directly as a normal multi-function PCI 2.2 device. Signed-off-by: Wu Zhangjin Cc: zhangfx@lemote.com Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Nicholas Mc Guire Cc: Arnaud Patard Cc: loongson-dev@googlegroups.com Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 3 + arch/mips/loongson/common/Makefile | 6 + arch/mips/loongson/common/cs5536/Makefile | 8 + arch/mips/loongson/common/cs5536/cs5536_acc.c | 140 +++++++++++ arch/mips/loongson/common/cs5536/cs5536_ehci.c | 158 +++++++++++++ arch/mips/loongson/common/cs5536/cs5536_ide.c | 179 ++++++++++++++ arch/mips/loongson/common/cs5536/cs5536_isa.c | 316 +++++++++++++++++++++++++ arch/mips/loongson/common/cs5536/cs5536_ohci.c | 147 ++++++++++++ arch/mips/loongson/common/cs5536/cs5536_pci.c | 87 +++++++ 9 files changed, 1044 insertions(+) create mode 100644 arch/mips/loongson/common/cs5536/Makefile create mode 100644 arch/mips/loongson/common/cs5536/cs5536_acc.c create mode 100644 arch/mips/loongson/common/cs5536/cs5536_ehci.c create mode 100644 arch/mips/loongson/common/cs5536/cs5536_ide.c create mode 100644 arch/mips/loongson/common/cs5536/cs5536_isa.c create mode 100644 arch/mips/loongson/common/cs5536/cs5536_ohci.c create mode 100644 arch/mips/loongson/common/cs5536/cs5536_pci.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 3100237b3f1..a214127895f 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -58,3 +58,6 @@ config LEMOTE_MACH2F These family machines include fuloong2f mini PC, yeeloong2f notebook, LingLoong allinone PC and so forth. endchoice + +config CS5536 + bool diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index be6adf7eb82..a82527fdfb6 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -10,3 +10,9 @@ obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ # obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_SERIAL_8250) += serial.o + +# +# Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure +# space +# +obj-$(CONFIG_CS5536) += cs5536/ diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile new file mode 100644 index 00000000000..31657ee037d --- /dev/null +++ b/arch/mips/loongson/common/cs5536/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for CS5536 support. +# + +obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \ + cs5536_isa.o cs5536_ehci.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/mips/loongson/common/cs5536/cs5536_acc.c b/arch/mips/loongson/common/cs5536/cs5536_acc.c new file mode 100644 index 00000000000..b49485f187e --- /dev/null +++ b/arch/mips/loongson/common/cs5536/cs5536_acc.c @@ -0,0 +1,140 @@ +/* + * the ACC Virtual Support Module of AMD CS5536 + * + * Copyright (C) 2007 Lemote, Inc. + * Author : jlliu, liujl@lemote.com + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +void pci_acc_write_reg(int reg, u32 value) +{ + u32 hi = 0, lo = value; + + switch (reg) { + case PCI_COMMAND: + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + if (value & PCI_COMMAND_MASTER) + lo |= (0x03 << 8); + else + lo &= ~(0x03 << 8); + _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo); + break; + case PCI_STATUS: + if (value & PCI_STATUS_PARITY) { + _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: + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + /* disable all the usb interrupt in PIC */ + lo &= ~(0xf << PIC_YSEL_LOW_ACC_SHIFT); + if (value) /* enable all the acc interrupt in PIC */ + lo |= (CS5536_ACC_INTR << PIC_YSEL_LOW_ACC_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + break; + default: + break; + } +} + +u32 pci_acc_read_reg(int reg) +{ + u32 hi, lo; + u32 conf_data = 0; + + switch (reg) { + case PCI_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_ACC_DEVICE_ID, CS5536_VENDOR_ID); + break; + case PCI_COMMAND: + _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo); + if (((lo & 0xfff00000) || (hi & 0x000000ff)) + && ((hi & 0xf0000000) == 0xa0000000)) + conf_data |= PCI_COMMAND_IO; + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + if ((lo & 0x300) == 0x300) + conf_data |= PCI_COMMAND_MASTER; + break; + case PCI_STATUS: + conf_data |= PCI_STATUS_66MHZ; + conf_data |= PCI_STATUS_FAST_BACK; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if (lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REVISION: + _rdmsr(ACC_MSR_REG(ACC_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_ACC_CLASS_CODE << 8); + break; + case PCI_CACHE_LINE_SIZE: + conf_data = + CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, + PCI_NORMAL_LATENCY_TIMER); + 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_BASE_ADDRESS_SPACE_IO; + 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_CARDBUS_CIS: + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_ACC_SUB_ID, CS5536_SUB_VENDOR_ID); + break; + case PCI_ROM_ADDRESS: + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPABILITY_LIST: + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_LINE: + conf_data = + CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_ACC_INTR); + break; + default: + break; + } + + return conf_data; +} diff --git a/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/arch/mips/loongson/common/cs5536/cs5536_ehci.c new file mode 100644 index 00000000000..74f9c59d36a --- /dev/null +++ b/arch/mips/loongson/common/cs5536/cs5536_ehci.c @@ -0,0 +1,158 @@ +/* + * the EHCI Virtual Support Module of AMD CS5536 + * + * Copyright (C) 2007 Lemote, Inc. + * Author : jlliu, liujl@lemote.com + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +void pci_ehci_write_reg(int reg, u32 value) +{ + u32 hi = 0, lo = value; + + switch (reg) { + case PCI_COMMAND: + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + if (value & PCI_COMMAND_MASTER) + hi |= PCI_COMMAND_MASTER; + else + hi &= ~PCI_COMMAND_MASTER; + + if (value & PCI_COMMAND_MEMORY) + hi |= PCI_COMMAND_MEMORY; + else + hi &= ~PCI_COMMAND_MEMORY; + _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); + break; + case PCI_STATUS: + if (value & PCI_STATUS_PARITY) { + _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) { + _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; + } +} + +u32 pci_ehci_read_reg(int reg) +{ + u32 conf_data = 0; + u32 hi, lo; + + switch (reg) { + case PCI_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_EHCI_DEVICE_ID, CS5536_VENDOR_ID); + break; + case PCI_COMMAND: + _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); + if (hi & PCI_COMMAND_MASTER) + conf_data |= PCI_COMMAND_MASTER; + if (hi & PCI_COMMAND_MEMORY) + conf_data |= PCI_COMMAND_MEMORY; + break; + case PCI_STATUS: + conf_data |= PCI_STATUS_66MHZ; + conf_data |= PCI_STATUS_FAST_BACK; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if (lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REVISION: + _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_EHCI_CLASS_CODE << 8); + break; + case PCI_CACHE_LINE_SIZE: + conf_data = + CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, + PCI_NORMAL_LATENCY_TIMER); + 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_BASE_ADDRESS_SPACE_MEMORY; + 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_CARDBUS_CIS: + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_EHCI_SUB_ID, CS5536_SUB_VENDOR_ID); + break; + case PCI_ROM_ADDRESS: + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPABILITY_LIST: + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_LINE: + conf_data = + CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, 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: + break; + } + + return conf_data; +} diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson/common/cs5536/cs5536_ide.c new file mode 100644 index 00000000000..3f61594b388 --- /dev/null +++ b/arch/mips/loongson/common/cs5536/cs5536_ide.c @@ -0,0 +1,179 @@ +/* + * the IDE Virtual Support Module of AMD CS5536 + * + * Copyright (C) 2007 Lemote, Inc. + * Author : jlliu, liujl@lemote.com + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +void pci_ide_write_reg(int reg, u32 value) +{ + u32 hi = 0, lo = value; + + switch (reg) { + case PCI_COMMAND: + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + if (value & PCI_COMMAND_MASTER) + lo |= (0x03 << 4); + else + lo &= ~(0x03 << 4); + _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo); + break; + case PCI_STATUS: + if (value & PCI_STATUS_PARITY) { + _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_CACHE_LINE_SIZE: + 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) { + 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 + _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo); + break; + case PCI_IDE_DTC_REG: + _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo); + break; + case PCI_IDE_CAST_REG: + _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo); + break; + case PCI_IDE_ETC_REG: + _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo); + break; + case PCI_IDE_PM_REG: + _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo); + break; + default: + break; + } +} + +u32 pci_ide_read_reg(int reg) +{ + u32 conf_data = 0; + u32 hi, lo; + + switch (reg) { + case PCI_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_IDE_DEVICE_ID, CS5536_VENDOR_ID); + break; + case PCI_COMMAND: + _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo); + if (lo & 0xfffffff0) + conf_data |= PCI_COMMAND_IO; + _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo); + if ((lo & 0x30) == 0x30) + conf_data |= PCI_COMMAND_MASTER; + break; + case PCI_STATUS: + conf_data |= PCI_STATUS_66MHZ; + conf_data |= PCI_STATUS_FAST_BACK; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if (lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REVISION: + _rdmsr(IDE_MSR_REG(IDE_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_IDE_CLASS_CODE << 8); + break; + case PCI_CACHE_LINE_SIZE: + _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); + hi &= 0x000000f8; + conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, hi); + 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_BASE_ADDRESS_SPACE_IO; + 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 & 0xfffffff0; + conf_data |= 0x01; + conf_data &= ~0x02; + } + break; + case PCI_CARDBUS_CIS: + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_IDE_SUB_ID, CS5536_SUB_VENDOR_ID); + break; + case PCI_ROM_ADDRESS: + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPABILITY_LIST: + conf_data = PCI_CAPLIST_POINTER; + break; + case PCI_INTERRUPT_LINE: + conf_data = + CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, 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: + break; + } + + return conf_data; +} diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c new file mode 100644 index 00000000000..b6f17f538e4 --- /dev/null +++ b/arch/mips/loongson/common/cs5536/cs5536_isa.c @@ -0,0 +1,316 @@ +/* + * the ISA Virtual Support Module of AMD CS5536 + * + * Copyright (C) 2007 Lemote, Inc. + * Author : jlliu, liujl@lemote.com + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +/* common variables for PCI_ISA_READ/WRITE_BAR */ +static const u32 divil_msr_reg[6] = { + DIVIL_MSR_REG(DIVIL_LBAR_SMB), DIVIL_MSR_REG(DIVIL_LBAR_GPIO), + DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), DIVIL_MSR_REG(DIVIL_LBAR_IRQ), + DIVIL_MSR_REG(DIVIL_LBAR_PMS), DIVIL_MSR_REG(DIVIL_LBAR_ACPI), +}; + +static const u32 soft_bar_flag[6] = { + SOFT_BAR_SMB_FLAG, SOFT_BAR_GPIO_FLAG, SOFT_BAR_MFGPT_FLAG, + SOFT_BAR_IRQ_FLAG, SOFT_BAR_PMS_FLAG, SOFT_BAR_ACPI_FLAG, +}; + +static const u32 sb_msr_reg[6] = { + SB_MSR_REG(SB_R0), SB_MSR_REG(SB_R1), SB_MSR_REG(SB_R2), + SB_MSR_REG(SB_R3), SB_MSR_REG(SB_R4), SB_MSR_REG(SB_R5), +}; + +static const u32 bar_space_range[6] = { + CS5536_SMB_RANGE, CS5536_GPIO_RANGE, CS5536_MFGPT_RANGE, + CS5536_IRQ_RANGE, CS5536_PMS_RANGE, CS5536_ACPI_RANGE, +}; + +static const int bar_space_len[6] = { + CS5536_SMB_LENGTH, CS5536_GPIO_LENGTH, CS5536_MFGPT_LENGTH, + CS5536_IRQ_LENGTH, CS5536_PMS_LENGTH, CS5536_ACPI_LENGTH, +}; + +/* + * enable 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(void) +{ + u32 hi, lo; + int offset; + + /* + * The DIVIL IRQ is not used yet. and make the RCONF0 reserved. + */ + + for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { + _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); + hi |= 0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); + } +} + +/* + * disable the divil module bar space. + */ +static void divil_lbar_disable(void) +{ + u32 hi, lo; + int offset; + + for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { + _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); + hi &= ~0x01; + _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); + } +} + +/* + * BAR write: write value to the n BAR + */ + +void pci_isa_write_bar(int n, u32 value) +{ + u32 hi = 0, lo = value; + + if (value == PCI_BAR_RANGE_MASK) { + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + lo |= soft_bar_flag[n]; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + } else if (value & 0x01) { + /* NATIVE reg */ + hi = 0x0000f001; + lo &= bar_space_range[n]; + _wrmsr(divil_msr_reg[n], hi, lo); + + /* RCONFx is 4bytes in units for I/O space */ + hi = ((value & 0x000ffffc) << 12) | + ((bar_space_len[n] - 4) << 12) | 0x01; + lo = ((value & 0x000ffffc) << 12) | 0x01; + _wrmsr(sb_msr_reg[n], hi, lo); + } +} + +/* + * BAR read: read the n BAR + */ + +u32 pci_isa_read_bar(int n) +{ + u32 conf_data = 0; + u32 hi, lo; + + _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); + if (lo & soft_bar_flag[n]) { + conf_data = bar_space_range[n] | PCI_BASE_ADDRESS_SPACE_IO; + lo &= ~soft_bar_flag[n]; + _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); + } else { + _rdmsr(divil_msr_reg[n], &hi, &lo); + conf_data = lo & bar_space_range[n]; + conf_data |= 0x01; + conf_data &= ~0x02; + } + return conf_data; +} + +/* + * isa_write: ISA write transfer + * + * We assume that this is not a bus master transfer. + */ +void pci_isa_write_reg(int reg, u32 value) +{ + u32 hi = 0, lo = value; + u32 temp; + + switch (reg) { + case PCI_COMMAND: + if (value & PCI_COMMAND_IO) + divil_lbar_enable(); + else + divil_lbar_disable(); + break; + case PCI_STATUS: + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + temp = lo & 0x0000ffff; + if ((value & PCI_STATUS_SIG_TARGET_ABORT) && + (lo & SB_TAS_ERR_EN)) + temp |= SB_TAS_ERR_FLAG; + + if ((value & PCI_STATUS_REC_TARGET_ABORT) && + (lo & SB_TAR_ERR_EN)) + temp |= SB_TAR_ERR_FLAG; + + if ((value & PCI_STATUS_REC_MASTER_ABORT) + && (lo & SB_MAR_ERR_EN)) + temp |= SB_MAR_ERR_FLAG; + + if ((value & PCI_STATUS_DETECTED_PARITY) + && (lo & SB_PARE_ERR_EN)) + temp |= SB_PARE_ERR_FLAG; + + lo = temp; + _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); + break; + case PCI_CACHE_LINE_SIZE: + 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: + pci_isa_write_bar(0, value); + break; + case PCI_BAR1_REG: + pci_isa_write_bar(1, value); + break; + case PCI_BAR2_REG: + pci_isa_write_bar(2, value); + break; + case PCI_BAR3_REG: + pci_isa_write_bar(3, value); + break; + case PCI_BAR4_REG: + pci_isa_write_bar(4, value); + break; + case PCI_BAR5_REG: + pci_isa_write_bar(5, value); + break; + case PCI_UART1_INT_REG: + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); + /* disable uart1 interrupt in PIC */ + lo &= ~(0xf << 24); + if (value) /* enable uart1 interrupt in PIC */ + lo |= (CS5536_UART1_INTR << 24); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo); + break; + case PCI_UART2_INT_REG: + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); + /* disable uart2 interrupt in PIC */ + lo &= ~(0xf << 28); + if (value) /* enable uart2 interrupt in PIC */ + lo |= (CS5536_UART2_INTR << 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; + } +} + +/* + * isa_read: ISA read transfers + * + * We assume that this is not a bus master transfer. + */ +u32 pci_isa_read_reg(int reg) +{ + u32 conf_data = 0; + u32 hi, lo; + + switch (reg) { + case PCI_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_ISA_DEVICE_ID, CS5536_VENDOR_ID); + break; + case PCI_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; + break; + case PCI_STATUS: + conf_data |= PCI_STATUS_66MHZ; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + conf_data |= PCI_STATUS_FAST_BACK; + + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if (lo & SB_TAS_ERR_FLAG) + conf_data |= PCI_STATUS_SIG_TARGET_ABORT; + if (lo & SB_TAR_ERR_FLAG) + conf_data |= PCI_STATUS_REC_TARGET_ABORT; + if (lo & SB_MAR_ERR_FLAG) + conf_data |= PCI_STATUS_REC_MASTER_ABORT; + if (lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_DETECTED_PARITY; + break; + case PCI_CLASS_REVISION: + _rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_ISA_CLASS_CODE << 8); + break; + case PCI_CACHE_LINE_SIZE: + _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); + hi &= 0x000000f8; + conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_BRIDGE_HEADER_TYPE, hi); + break; + /* + * we only use the LBAR of DIVIL, no RCONF used. + * all of them are IO space. + */ + case PCI_BAR0_REG: + return pci_isa_read_bar(0); + break; + case PCI_BAR1_REG: + return pci_isa_read_bar(1); + break; + case PCI_BAR2_REG: + return pci_isa_read_bar(2); + break; + case PCI_BAR3_REG: + break; + case PCI_BAR4_REG: + return pci_isa_read_bar(4); + break; + case PCI_BAR5_REG: + return pci_isa_read_bar(5); + break; + case PCI_CARDBUS_CIS: + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_ISA_SUB_ID, CS5536_SUB_VENDOR_ID); + break; + case PCI_ROM_ADDRESS: + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPABILITY_LIST: + conf_data = PCI_CAPLIST_POINTER; + break; + case PCI_INTERRUPT_LINE: + /* no interrupt used here */ + conf_data = CFG_PCI_INTERRUPT_LINE(0x00, 0x00); + break; + default: + break; + } + + return conf_data; +} diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson/common/cs5536/cs5536_ohci.c new file mode 100644 index 00000000000..8fdb02b6e90 --- /dev/null +++ b/arch/mips/loongson/common/cs5536/cs5536_ohci.c @@ -0,0 +1,147 @@ +/* + * the OHCI Virtual Support Module of AMD CS5536 + * + * Copyright (C) 2007 Lemote, Inc. + * Author : jlliu, liujl@lemote.com + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +void pci_ohci_write_reg(int reg, u32 value) +{ + u32 hi = 0, lo = value; + + switch (reg) { + case PCI_COMMAND: + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + if (value & PCI_COMMAND_MASTER) + hi |= PCI_COMMAND_MASTER; + else + hi &= ~PCI_COMMAND_MASTER; + + if (value & PCI_COMMAND_MEMORY) + hi |= PCI_COMMAND_MEMORY; + else + hi &= ~PCI_COMMAND_MEMORY; + _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); + break; + case PCI_STATUS: + if (value & PCI_STATUS_PARITY) { + _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) { + _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_OHCI_INT_REG: + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + lo &= ~(0xf << PIC_YSEL_LOW_USB_SHIFT); + if (value) /* enable all the usb interrupt in PIC */ + lo |= (CS5536_USB_INTR << PIC_YSEL_LOW_USB_SHIFT); + _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo); + break; + default: + break; + } +} + +u32 pci_ohci_read_reg(int reg) +{ + u32 conf_data = 0; + u32 hi, lo; + + switch (reg) { + case PCI_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_OHCI_DEVICE_ID, CS5536_VENDOR_ID); + break; + case PCI_COMMAND: + _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); + if (hi & PCI_COMMAND_MASTER) + conf_data |= PCI_COMMAND_MASTER; + if (hi & PCI_COMMAND_MEMORY) + conf_data |= PCI_COMMAND_MEMORY; + break; + case PCI_STATUS: + conf_data |= PCI_STATUS_66MHZ; + conf_data |= PCI_STATUS_FAST_BACK; + _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); + if (lo & SB_PARE_ERR_FLAG) + conf_data |= PCI_STATUS_PARITY; + conf_data |= PCI_STATUS_DEVSEL_MEDIUM; + break; + case PCI_CLASS_REVISION: + _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo); + conf_data = lo & 0x000000ff; + conf_data |= (CS5536_OHCI_CLASS_CODE << 8); + break; + case PCI_CACHE_LINE_SIZE: + conf_data = + CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, + PCI_NORMAL_LATENCY_TIMER); + 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_BASE_ADDRESS_SPACE_MEMORY; + 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 & 0xffffff00; + conf_data &= ~0x0000000f; /* 32bit mem */ + } + break; + case PCI_CARDBUS_CIS: + conf_data = PCI_CARDBUS_CIS_POINTER; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + conf_data = + CFG_PCI_VENDOR_ID(CS5536_OHCI_SUB_ID, CS5536_SUB_VENDOR_ID); + break; + case PCI_ROM_ADDRESS: + conf_data = PCI_EXPANSION_ROM_BAR; + break; + case PCI_CAPABILITY_LIST: + conf_data = PCI_CAPLIST_USB_POINTER; + break; + case PCI_INTERRUPT_LINE: + conf_data = + CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR); + break; + case PCI_OHCI_INT_REG: + _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo); + if ((lo & 0x00000f00) == CS5536_USB_INTR) + conf_data = 1; + break; + default: + break; + } + + return conf_data; +} diff --git a/arch/mips/loongson/common/cs5536/cs5536_pci.c b/arch/mips/loongson/common/cs5536/cs5536_pci.c new file mode 100644 index 00000000000..e23f3d7d2c1 --- /dev/null +++ b/arch/mips/loongson/common/cs5536/cs5536_pci.c @@ -0,0 +1,87 @@ +/* + * read/write operation to the PCI config space of CS5536 + * + * Copyright (C) 2007 Lemote, Inc. + * Author : jlliu, liujl@lemote.com + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * the Virtual Support Module(VSM) for virtulizing the PCI + * configure space are defined in cs5536_modulename.c respectively, + * + * after this virtulizing, user can access the PCI configure space + * directly as a normal multi-function PCI device which follows + * the PCI-2.2 spec. + */ + +#include +#include + +enum { + CS5536_FUNC_START = -1, + CS5536_ISA_FUNC, + reserved_func, + CS5536_IDE_FUNC, + CS5536_ACC_FUNC, + CS5536_OHCI_FUNC, + CS5536_EHCI_FUNC, + CS5536_FUNC_END, +}; + +static const cs5536_pci_vsm_write vsm_conf_write[] = { + [CS5536_ISA_FUNC] pci_isa_write_reg, + [reserved_func] NULL, + [CS5536_IDE_FUNC] pci_ide_write_reg, + [CS5536_ACC_FUNC] pci_acc_write_reg, + [CS5536_OHCI_FUNC] pci_ohci_write_reg, + [CS5536_EHCI_FUNC] pci_ehci_write_reg, +}; + +static const cs5536_pci_vsm_read vsm_conf_read[] = { + [CS5536_ISA_FUNC] pci_isa_read_reg, + [reserved_func] NULL, + [CS5536_IDE_FUNC] pci_ide_read_reg, + [CS5536_ACC_FUNC] pci_acc_read_reg, + [CS5536_OHCI_FUNC] pci_ohci_read_reg, + [CS5536_EHCI_FUNC] pci_ehci_read_reg, +}; + +/* + * write to PCI config space and transfer it to MSR write. + */ +void cs5536_pci_conf_write4(int function, int reg, u32 value) +{ + if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END)) + return; + if ((reg < 0) || (reg > 0x100) || ((reg & 0x03) != 0)) + return; + + if (vsm_conf_write[function] != NULL) + vsm_conf_write[function](reg, value); +} + +/* + * read PCI config space and transfer it to MSR access. + */ +u32 cs5536_pci_conf_read4(int function, int reg) +{ + u32 data = 0; + + if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END)) + return 0; + if ((reg < 0) || ((reg & 0x03) != 0)) + return 0; + if (reg > 0x100) + return 0xffffffff; + + if (vsm_conf_read[function] != NULL) + data = vsm_conf_read[function](reg); + + return data; +} -- cgit v1.2.3 From 6616db78eecab1236781c546670391e1e5dff256 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 10 Nov 2009 00:06:14 +0800 Subject: MIPS: Lemote 2F: Add IRQ support The generic i8259_irq() will make kernel hang on booting, so Loongson 2F needs its own polling method. IP6 is shared by the bonito interrupt and perfcounter interrupts. Signed-off-by: Wu Zhangjin Cc: zhangfx@lemote.com Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Nicholas Mc Guire Cc: Arnaud Patard Cc: loongson-dev@googlegroups.com Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle --- arch/mips/loongson/Makefile | 6 ++ arch/mips/loongson/lemote-2f/Makefile | 5 ++ arch/mips/loongson/lemote-2f/irq.c | 132 ++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 arch/mips/loongson/lemote-2f/Makefile create mode 100644 arch/mips/loongson/lemote-2f/irq.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile index 39048c455d7..2b76cb0fb07 100644 --- a/arch/mips/loongson/Makefile +++ b/arch/mips/loongson/Makefile @@ -9,3 +9,9 @@ obj-$(CONFIG_MACH_LOONGSON) += common/ # obj-$(CONFIG_LEMOTE_FULOONG2E) += fuloong-2e/ + +# +# Lemote loongson2f family machines +# + +obj-$(CONFIG_LEMOTE_MACH2F) += lemote-2f/ diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile new file mode 100644 index 00000000000..2e188974d56 --- /dev/null +++ b/arch/mips/loongson/lemote-2f/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for lemote loongson2f family machines +# + +obj-y += irq.o diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c new file mode 100644 index 00000000000..50e7bb6012b --- /dev/null +++ b/arch/mips/loongson/lemote-2f/irq.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2007 Lemote Inc. + * Author: Fuxin Zhang, zhangfx@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include + +#include +#include +#include + +#include +#include + +#define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7) /* cpu timer */ +#define LOONGSON_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */ +#define LOONGSON_NORTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 6) /* bonito */ +#define LOONGSON_UART_IRQ (MIPS_CPU_IRQ_BASE + 3) /* cpu serial port */ +#define LOONGSON_SOUTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 2) /* i8259 */ + +#define LOONGSON_INT_BIT_INT0 (1 << 11) +#define LOONGSON_INT_BIT_INT1 (1 << 12) + +/* + * The generic i8259_irq() make the kernel hang on booting. Since we cannot + * get the irq via the IRR directly, we access the ISR instead. + */ +static inline int mach_i8259_irq(void) +{ + int irq, isr; + + irq = -1; + + if ((LOONGSON_INTISR & LOONGSON_INTEN) & LOONGSON_INT_BIT_INT0) { + spin_lock(&i8259A_lock); + isr = inb(PIC_MASTER_CMD) & + ~inb(PIC_MASTER_IMR) & ~(1 << PIC_CASCADE_IR); + if (!isr) + isr = (inb(PIC_SLAVE_CMD) & ~inb(PIC_SLAVE_IMR)) << 8; + irq = ffs(isr) - 1; + if (unlikely(irq == 7)) { + /* + * This may be a spurious interrupt. + * + * Read the interrupt status register (ISR). If the most + * significant bit is not set then there is no valid + * interrupt. + */ + outb(0x0B, PIC_MASTER_ISR); /* ISR register */ + if (~inb(PIC_MASTER_ISR) & 0x80) + irq = -1; + } + spin_unlock(&i8259A_lock); + } + + return irq; +} + +static void i8259_irqdispatch(void) +{ + int irq; + + irq = mach_i8259_irq(); + if (irq >= 0) + do_IRQ(irq); + else + spurious_interrupt(); +} + +void mach_irq_dispatch(unsigned int pending) +{ + if (pending & CAUSEF_IP7) + do_IRQ(LOONGSON_TIMER_IRQ); + else if (pending & CAUSEF_IP6) { /* North Bridge, Perf counter */ +#ifdef CONFIG_OPROFILE + do_IRQ(LOONGSON2_PERFCNT_IRQ); +#endif + bonito_irqdispatch(); + } else if (pending & CAUSEF_IP3) /* CPU UART */ + do_IRQ(LOONGSON_UART_IRQ); + else if (pending & CAUSEF_IP2) /* South Bridge */ + i8259_irqdispatch(); + else + spurious_interrupt(); +} + +void __init set_irq_trigger_mode(void) +{ + /* setup cs5536 as high level trigger */ + LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1; + LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1); +} + +static irqreturn_t ip6_action(int cpl, void *dev_id) +{ + return IRQ_HANDLED; +} + +struct irqaction ip6_irqaction = { + .handler = ip6_action, + .name = "cascade", + .flags = IRQF_SHARED, +}; + +struct irqaction cascade_irqaction = { + .handler = no_action, + .name = "cascade", +}; + +void __init mach_init_irq(void) +{ + /* 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 north bridge irq (bonito) */ + setup_irq(LOONGSON_NORTH_BRIDGE_IRQ, &ip6_irqaction); + /* setup source bridge irq (i8259) */ + setup_irq(LOONGSON_SOUTH_BRIDGE_IRQ, &cascade_irqaction); +} -- cgit v1.2.3 From 2ee98e0f46a12423d5ecd7da520a1dd94540c37d Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 10 Nov 2009 00:06:15 +0800 Subject: MIPS: Lemote 2F: Add reset support Fuloong 2F, Yeeloong 2F and Menglong 2F have different reset / shutdown logic. Signed-off-by: Wu Zhangjin Cc: zhangfx@lemote.com Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Nicholas Mc Guire Cc: Arnaud Patard Cc: loongson-dev@googlegroups.com Cc: linux-mips@linux-mips.org Signed-off-by: Ralf Baechle --- arch/mips/loongson/lemote-2f/Makefile | 2 +- arch/mips/loongson/lemote-2f/reset.c | 172 ++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 arch/mips/loongson/lemote-2f/reset.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile index 2e188974d56..da543b1b51e 100644 --- a/arch/mips/loongson/lemote-2f/Makefile +++ b/arch/mips/loongson/lemote-2f/Makefile @@ -2,4 +2,4 @@ # Makefile for lemote loongson2f family machines # -obj-y += irq.o +obj-y += irq.o reset.o diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c new file mode 100644 index 00000000000..0458a1c5641 --- /dev/null +++ b/arch/mips/loongson/lemote-2f/reset.c @@ -0,0 +1,172 @@ +/* Board-specific reboot/shutdown routines + * + * Copyright (c) 2009 Philippe Vachon + * + * Copyright (C) 2009 Lemote Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include + +#include + +#include + +#include + +static void reset_cpu(void) +{ + /* + * reset cpu to full speed, this is needed when enabling cpu frequency + * scalling + */ + LOONGSON_CHIPCFG0 |= 0x7; +} + +/* reset support for fuloong2f */ + +static void fl2f_reboot(void) +{ + reset_cpu(); + + /* send a reset signal to south bridge. + * + * NOTE: if enable "Power Management" in kernel, rtl8169 will not reset + * normally with this reset operation and it will not work in PMON, but + * you can type halt command and then reboot, seems the hardware reset + * logic not work normally. + */ + { + u32 hi, lo; + _rdmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), &hi, &lo); + lo |= 0x00000001; + _wrmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), hi, lo); + } +} + +static void fl2f_shutdown(void) +{ + u32 hi, lo, val; + int gpio_base; + + /* get gpio base */ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo); + gpio_base = lo & 0xff00; + + /* make cs5536 gpio13 output enable */ + val = inl(gpio_base + GPIOL_OUT_EN); + val &= ~(1 << (16 + 13)); + val |= (1 << 13); + outl(val, gpio_base + GPIOL_OUT_EN); + mmiowb(); + /* make cs5536 gpio13 output low level voltage. */ + val = inl(gpio_base + GPIOL_OUT_VAL) & ~(1 << (13)); + val |= (1 << (16 + 13)); + outl(val, gpio_base + GPIOL_OUT_VAL); + mmiowb(); +} + +/* reset support for yeeloong2f and mengloong2f notebook */ + +/* + * The following registers are determined by the EC index configuration. + * 1. fill the PORT_HIGH as EC register high part. + * 2. fill the PORT_LOW as EC register low part. + * 3. fill the PORT_DATA as EC register write data or get the data from it. + */ + +#define EC_IO_PORT_HIGH 0x0381 +#define EC_IO_PORT_LOW 0x0382 +#define EC_IO_PORT_DATA 0x0383 +#define REG_RESET_HIGH 0xF4 /* reset the machine auto-clear : rd/wr */ +#define REG_RESET_LOW 0xEC +#define BIT_RESET_ON (1 << 0) + +void ml2f_reboot(void) +{ + reset_cpu(); + + /* sending an reset signal to EC(embedded controller) */ + outb(REG_RESET_HIGH, EC_IO_PORT_HIGH); + outb(REG_RESET_LOW, EC_IO_PORT_LOW); + mmiowb(); + outb(BIT_RESET_ON, EC_IO_PORT_DATA); + mmiowb(); +} + +#define yl2f89_reboot ml2f_reboot + +/* menglong(7inches) laptop has different shutdown logic from 8.9inches */ +#define EC_SHUTDOWN_IO_PORT_HIGH 0xff2d +#define EC_SHUTDOWN_IO_PORT_LOW 0xff2e +#define EC_SHUTDOWN_IO_PORT_DATA 0xff2f +#define REG_SHUTDOWN_HIGH 0xFC +#define REG_SHUTDOWN_LOW 0x29 +#define BIT_SHUTDOWN_ON (1 << 1) + +static void ml2f_shutdown(void) +{ + u8 val; + u64 i; + + outb(REG_SHUTDOWN_HIGH, EC_SHUTDOWN_IO_PORT_HIGH); + outb(REG_SHUTDOWN_LOW, EC_SHUTDOWN_IO_PORT_LOW); + mmiowb(); + val = inb(EC_SHUTDOWN_IO_PORT_DATA); + outb(val & (~BIT_SHUTDOWN_ON), EC_SHUTDOWN_IO_PORT_DATA); + mmiowb(); + /* need enough wait here... how many microseconds needs? */ + for (i = 0; i < 0x10000; i++) + delay(); + outb(val | BIT_SHUTDOWN_ON, EC_SHUTDOWN_IO_PORT_DATA); + mmiowb(); +} + +static void yl2f89_shutdown(void) +{ + /* cpu-gpio0 output low */ + LOONGSON_GPIODATA &= ~0x00000001; + /* cpu-gpio0 as output */ + LOONGSON_GPIOIE &= ~0x00000001; +} + +void mach_prepare_reboot(void) +{ + switch (mips_machtype) { + case MACH_LEMOTE_FL2F: + fl2f_reboot(); + break; + case MACH_LEMOTE_ML2F7: + ml2f_reboot(); + break; + case MACH_LEMOTE_YL2F89: + yl2f89_reboot(); + break; + default: + break; + } +} + +void mach_prepare_shutdown(void) +{ + switch (mips_machtype) { + case MACH_LEMOTE_FL2F: + fl2f_shutdown(); + break; + case MACH_LEMOTE_ML2F7: + ml2f_shutdown(); + break; + case MACH_LEMOTE_YL2F89: + yl2f89_shutdown(); + break; + default: + break; + } +} -- cgit v1.2.3 From 55045ff5557bc804752e84dca5d1b1f1d4bb4e31 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 11 Nov 2009 13:39:12 +0800 Subject: MIPS: Loongson 2F: Cleanup the #if clauses This patch adds two new kernel options: CPU_SUPPORTS_CPUFREQ and CPU_SUPPORTS_ADDRWINCFG to describe the new features of Loongons 2F and replaces the several ugly #if clauses by them. These two options will be utilized by the future loongson revisions and related drivers such as the coming Loongson 2F CPUFreq driver. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: Wu Zhangjin Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/init.c | 2 +- arch/mips/loongson/common/mem.c | 8 ++++---- arch/mips/loongson/common/pci.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c index 743d3571f01..2b92a23d29d 100644 --- a/arch/mips/loongson/common/init.c +++ b/arch/mips/loongson/common/init.c @@ -21,7 +21,7 @@ void __init prom_init(void) set_io_port_base((unsigned long) ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE)); -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) +#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG _loongson_addrwincfg_base = (unsigned long) ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE); #endif diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c index e93551dbc9e..981e9190f39 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson/common/mem.c @@ -20,8 +20,7 @@ void __init prom_init_memory(void) add_memory_region(memsize << 20, LOONGSON_PCI_MEM_START - (memsize << 20), BOOT_MEM_RESERVED); -#ifdef CONFIG_64BIT -#ifdef CONFIG_CPU_LOONGSON2F +#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG { int bit; @@ -36,8 +35,9 @@ void __init prom_init_memory(void) 0x80000000ul, (1 << bit)); mmiowb(); } -#endif /* CONFIG_CPU_LOONGSON2F */ +#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */ +#ifdef CONFIG_64BIT if (highmemsize > 0) add_memory_region(LOONGSON_HIGHMEM_START, highmemsize << 20, BOOT_MEM_RAM); @@ -45,7 +45,7 @@ void __init prom_init_memory(void) add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START - LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED); -#endif /* CONFIG_64BIT */ +#endif /* !CONFIG_64BIT */ } /* override of arch/mips/mm/cache.c: __uncached_access */ diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c index eac43b8f695..31d8c5ecd16 100644 --- a/arch/mips/loongson/common/pci.c +++ b/arch/mips/loongson/common/pci.c @@ -68,7 +68,7 @@ static void __init setup_pcimap(void) deassert for some broken device */ LOONGSON_PXARB_CFG = 0x00fe0105ul; -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT) +#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG /* * set cpu addr window2 to map CPU address space to PCI address space */ -- cgit v1.2.3 From 22f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 11 Nov 2009 13:59:23 +0800 Subject: MIPS: Add support for uncached accelerated mappings. Loongson2f support video acceleration. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/624/ Patchwork: http://patchwork.linux-mips.org/patch/625/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/mem.c | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c index 981e9190f39..ceacd092b44 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson/common/mem.c @@ -58,3 +58,61 @@ int __uncached_access(struct file *file, unsigned long addr) ((addr >= LOONGSON_MMIO_MEM_START) && (addr < LOONGSON_MMIO_MEM_END)); } + +#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED + +#include +#include +#include + +static unsigned long uca_start, uca_end; + +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot) +{ + unsigned long offset = pfn << PAGE_SHIFT; + unsigned long end = offset + size; + + if (__uncached_access(file, offset)) { + if (((uca_start && offset) >= uca_start) && + (end <= uca_end)) + return __pgprot((pgprot_val(vma_prot) & + ~_CACHE_MASK) | + _CACHE_UNCACHED_ACCELERATED); + else + return pgprot_noncached(vma_prot); + } + return vma_prot; +} + +static int __init find_vga_mem_init(void) +{ + struct pci_dev *dev = 0; + struct resource *r; + int idx; + + if (uca_start) + return 0; + + for_each_pci_dev(dev) { + if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { + for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) + continue; + if (r->flags & IORESOURCE_IO) + continue; + if (r->flags & IORESOURCE_MEM) { + uca_start = r->start; + uca_end = r->end; + return 0; + } + } + } + } + + return 0; +} + +late_initcall(find_vga_mem_init); +#endif /* !CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED */ -- cgit v1.2.3 From f181bf60e3f31cdab48bd8b9d913201ed2f9e522 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 11 Nov 2009 14:57:05 +0800 Subject: MIPS: Loongson 2F: Add suspend support framework This patch add basic suspend support for loongson2f family machines, loongson2f have a specific feature: when we set it's frequency to ZERO, it will go into a wait mode, and then can be waked up by the external interrupt. so, if we setup suitable interrupts before putting it into wait mode, we will be able wake it up whenever we want via sending the relative interrupts to it. These interrupts are board-specific, Yeeloong2F use the keyboard interrupt and SCI interrupt, but LingLoong and Fuloong2F use the interrupts connected to the processors directly. and BTW: some old LingLoong and FuLoong2F have no such interrupts connected, so, there is no way to wake them up from suspend mode. and therefore, please do not enable the kernel support for them. The board-specific support will be added in the coming patches. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Wu Zhangjin Cc: Len Brown Cc: Rafael J. Wysocki Cc: linux-pm@lists.linux-foundation.org Patchwork: http://patchwork.linux-mips.org/patch/629/ Acked-by: Pavel Machek Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 5 ++ arch/mips/loongson/common/Makefile | 6 ++ arch/mips/loongson/common/pm.c | 161 +++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 arch/mips/loongson/common/pm.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index a214127895f..17e72fde908 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -61,3 +61,8 @@ endchoice config CS5536 bool + +config LOONGSON_SUSPEND + bool + default y + depends on CPU_SUPPORTS_CPUFREQ && SUSPEND diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index a82527fdfb6..a21724d50e2 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -16,3 +16,9 @@ obj-$(CONFIG_SERIAL_8250) += serial.o # space # obj-$(CONFIG_CS5536) += cs5536/ + +# +# Suspend Support +# + +obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson/common/pm.c new file mode 100644 index 00000000000..b625fec8a4d --- /dev/null +++ b/arch/mips/loongson/common/pm.c @@ -0,0 +1,161 @@ +/* + * loongson-specific suspend support + * + * Copyright (C) 2009 Lemote Inc. + * Author: Wu Zhangjin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include + +#include +#include + +#include + +static unsigned int __maybe_unused cached_master_mask; /* i8259A */ +static unsigned int __maybe_unused cached_slave_mask; +static unsigned int __maybe_unused cached_bonito_irq_mask; /* bonito */ + +void arch_suspend_disable_irqs(void) +{ + /* disable all mips events */ + local_irq_disable(); + +#ifdef CONFIG_I8259 + /* disable all events of i8259A */ + cached_slave_mask = inb(PIC_SLAVE_IMR); + cached_master_mask = inb(PIC_MASTER_IMR); + + outb(0xff, PIC_SLAVE_IMR); + inb(PIC_SLAVE_IMR); + outb(0xff, PIC_MASTER_IMR); + inb(PIC_MASTER_IMR); +#endif + /* disable all events of bonito */ + cached_bonito_irq_mask = LOONGSON_INTEN; + LOONGSON_INTENCLR = 0xffff; + (void)LOONGSON_INTENCLR; +} + +void arch_suspend_enable_irqs(void) +{ + /* enable all mips events */ + local_irq_enable(); +#ifdef CONFIG_I8259 + /* only enable the cached events of i8259A */ + outb(cached_slave_mask, PIC_SLAVE_IMR); + outb(cached_master_mask, PIC_MASTER_IMR); +#endif + /* enable all cached events of bonito */ + LOONGSON_INTENSET = cached_bonito_irq_mask; + (void)LOONGSON_INTENSET; +} + +/* + * Setup the board-specific events for waking up loongson from wait mode + */ +void __weak setup_wakeup_events(void) +{ +} + +/* + * Check wakeup events + */ +int __weak wakeup_loongson(void) +{ + return 1; +} + +/* + * If the events are really what we want to wakeup the CPU, wake it up + * otherwise put the CPU asleep again. + */ +static void wait_for_wakeup_events(void) +{ + while (!wakeup_loongson()) + LOONGSON_CHIPCFG0 &= ~0x7; +} + +/* + * Stop all perf counters + * + * $24 is the control register of Loongson perf counter + */ +static inline void stop_perf_counters(void) +{ + __write_64bit_c0_register($24, 0, 0); +} + + +static void loongson_suspend_enter(void) +{ + static unsigned int cached_cpu_freq; + + /* setup wakeup events via enabling the IRQs */ + setup_wakeup_events(); + + stop_perf_counters(); + + cached_cpu_freq = LOONGSON_CHIPCFG0; + + /* Put CPU into wait mode */ + LOONGSON_CHIPCFG0 &= ~0x7; + + /* wait for the given events to wakeup cpu from wait mode */ + wait_for_wakeup_events(); + + LOONGSON_CHIPCFG0 = cached_cpu_freq; + mmiowb(); +} + +void __weak mach_suspend(void) +{ +} + +void __weak mach_resume(void) +{ +} + +static int loongson_pm_enter(suspend_state_t state) +{ + mach_suspend(); + + /* processor specific suspend */ + loongson_suspend_enter(); + + mach_resume(); + + return 0; +} + +static int loongson_pm_valid_state(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_ON: + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + + default: + return 0; + } +} + +static struct platform_suspend_ops loongson_pm_ops = { + .valid = loongson_pm_valid_state, + .enter = loongson_pm_enter, +}; + +static int __init loongson_pm_init(void) +{ + suspend_set_ops(&loongson_pm_ops); + + return 0; +} +arch_initcall(loongson_pm_init); -- cgit v1.2.3 From a9e8641f4c252f93875cf30cb28c0f333539f0bf Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Wed, 11 Nov 2009 14:57:41 +0800 Subject: MIPS: Yeeloong 2F: Add board specific suspend support Lemote Loongson 2F family machines need an external interrupt to wake the system from the suspend mode. For YeeLoong 2F and Mengloong 2F setup the keyboard interrupt as the wakeup interrupt. The new Fuloong 2F and LingLoong 2F have a button to directly send an interrupt to the CPU so there is no need to setup an interrupt. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: yanh@lemote.com Cc: huhb@lemote.com Cc: Wu Zhangjin Cc: Len Brown Cc: Rafael J. Wysocki Cc: linux-pm@lists.linux-foundation.org Patchwork: http://patchwork.linux-mips.org/patch/630/ Acked-by: Pavel Machek Signed-off-by: Ralf Baechle --- arch/mips/loongson/lemote-2f/Makefile | 6 +++ arch/mips/loongson/lemote-2f/pm.c | 73 +++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 arch/mips/loongson/lemote-2f/pm.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile index da543b1b51e..5add7b2ead1 100644 --- a/arch/mips/loongson/lemote-2f/Makefile +++ b/arch/mips/loongson/lemote-2f/Makefile @@ -3,3 +3,9 @@ # obj-y += irq.o reset.o + +# +# Suspend Support +# + +obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson/lemote-2f/pm.c new file mode 100644 index 00000000000..8090d051422 --- /dev/null +++ b/arch/mips/loongson/lemote-2f/pm.c @@ -0,0 +1,73 @@ +/* + * Lemote loongson2f family machines' specific suspend support + * + * Copyright (C) 2009 Lemote Inc. + * Author: Wu Zhangjin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define I8042_KBD_IRQ 1 +#define I8042_CTR_KBDINT 0x01 +#define I8042_CTR_KBDDIS 0x10 + +static unsigned char i8042_ctr; + +static int i8042_enable_kbd_port(void) +{ + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { + pr_err("i8042.c: Can't read CTR while enabling i8042 kbd port." + "\n"); + return -EIO; + } + + i8042_ctr &= ~I8042_CTR_KBDDIS; + i8042_ctr |= I8042_CTR_KBDINT; + + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { + i8042_ctr &= ~I8042_CTR_KBDINT; + i8042_ctr |= I8042_CTR_KBDDIS; + pr_err("i8042.c: Failed to enable KBD port.\n"); + + return -EIO; + } + + return 0; +} + +/* + * The i8042 is connnected to i8259A + */ +void setup_wakeup_events(void) +{ + int irq_mask; + + switch (mips_machtype) { + case MACH_LEMOTE_ML2F7: + case MACH_LEMOTE_YL2F89: + /* open the keyboard irq in i8259A */ + outb((0xff & ~(1 << I8042_KBD_IRQ)), PIC_MASTER_IMR); + irq_mask = inb(PIC_MASTER_IMR); + + /* enable keyboard port */ + i8042_enable_kbd_port(); + break; + + default: + break; + } +} -- cgit v1.2.3 From e13fb77661b62f49170ef30d707272c568f81681 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 17 Nov 2009 00:58:14 +0800 Subject: MIPS: Lemote 2F: Add NAS support Kernel support for this machine is almost the same as Fuloong 2F; the only difference is that it uses the serial port provided by Loongson 2F processor as Yeeloong 2F does. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/656/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/machtype.c | 1 + arch/mips/loongson/common/serial.c | 1 + arch/mips/loongson/common/uart_base.c | 1 + arch/mips/loongson/lemote-2f/reset.c | 2 ++ 4 files changed, 5 insertions(+) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c index 7545fe69089..d57e1f4503a 100644 --- a/arch/mips/loongson/common/machtype.c +++ b/arch/mips/loongson/common/machtype.c @@ -25,6 +25,7 @@ static const char *system_types[] = { [MACH_LEMOTE_ML2F7] "lemote-mengloong-2f-7inches", [MACH_LEMOTE_YL2F89] "lemote-yeeloong-2f-8.9inches", [MACH_DEXXON_GDIUM2F10] "dexxon-gidum-2f-10inches", + [MACH_LEMOTE_NAS] "lemote-nas-2f", [MACH_LOONGSON_END] NULL, }; diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c index dc6488c1476..45601e4315d 100644 --- a/arch/mips/loongson/common/serial.c +++ b/arch/mips/loongson/common/serial.c @@ -45,6 +45,7 @@ static struct plat_serial8250_port uart8250_data[][2] = { [MACH_LEMOTE_ML2F7] {PORT_M(3), {} }, [MACH_LEMOTE_YL2F89] {PORT_M(3), {} }, [MACH_DEXXON_GDIUM2F10] {PORT_M(3), {} }, + [MACH_LEMOTE_NAS] {PORT_M(3), {} }, [MACH_LOONGSON_END] {}, }; diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c index 233c708fc12..e34d699f6f3 100644 --- a/arch/mips/loongson/common/uart_base.c +++ b/arch/mips/loongson/common/uart_base.c @@ -23,6 +23,7 @@ unsigned long __maybe_unused uart8250_base[] = { [MACH_LEMOTE_ML2F7] (LOONGSON_LIO1_BASE + 0x3f8), [MACH_LEMOTE_YL2F89] (LOONGSON_LIO1_BASE + 0x3f8), [MACH_DEXXON_GDIUM2F10] (LOONGSON_LIO1_BASE + 0x3f8), + [MACH_LEMOTE_NAS] (LOONGSON_LIO1_BASE + 0x3f8), [MACH_LOONGSON_END] 0, }; EXPORT_SYMBOL(uart8250_base); diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c index 0458a1c5641..980299dbeac 100644 --- a/arch/mips/loongson/lemote-2f/reset.c +++ b/arch/mips/loongson/lemote-2f/reset.c @@ -141,6 +141,7 @@ void mach_prepare_reboot(void) { switch (mips_machtype) { case MACH_LEMOTE_FL2F: + case MACH_LEMOTE_NAS: fl2f_reboot(); break; case MACH_LEMOTE_ML2F7: @@ -158,6 +159,7 @@ void mach_prepare_shutdown(void) { switch (mips_machtype) { case MACH_LEMOTE_FL2F: + case MACH_LEMOTE_NAS: fl2f_shutdown(); break; case MACH_LEMOTE_ML2F7: -- cgit v1.2.3 From 6e552c9b3aa7ba3be57b9569ec92a38af5c65e48 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 17 Nov 2009 00:58:15 +0800 Subject: MIPS: Lemote 2F: Add Lynloong support Add a new machtype and kernel options for the Lynloong. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/657/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/machtype.c | 1 + arch/mips/loongson/common/serial.c | 1 + arch/mips/loongson/common/uart_base.c | 1 + arch/mips/loongson/lemote-2f/reset.c | 2 ++ 4 files changed, 5 insertions(+) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c index d57e1f4503a..0ed52b3f531 100644 --- a/arch/mips/loongson/common/machtype.c +++ b/arch/mips/loongson/common/machtype.c @@ -26,6 +26,7 @@ static const char *system_types[] = { [MACH_LEMOTE_YL2F89] "lemote-yeeloong-2f-8.9inches", [MACH_DEXXON_GDIUM2F10] "dexxon-gidum-2f-10inches", [MACH_LEMOTE_NAS] "lemote-nas-2f", + [MACH_LEMOTE_LL2F] "lemote-lynloong-2f", [MACH_LOONGSON_END] NULL, }; diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c index 45601e4315d..ea29db099ae 100644 --- a/arch/mips/loongson/common/serial.c +++ b/arch/mips/loongson/common/serial.c @@ -46,6 +46,7 @@ static struct plat_serial8250_port uart8250_data[][2] = { [MACH_LEMOTE_YL2F89] {PORT_M(3), {} }, [MACH_DEXXON_GDIUM2F10] {PORT_M(3), {} }, [MACH_LEMOTE_NAS] {PORT_M(3), {} }, + [MACH_LEMOTE_LL2F] {PORT(3), {} }, [MACH_LOONGSON_END] {}, }; diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c index e34d699f6f3..1d636f4f750 100644 --- a/arch/mips/loongson/common/uart_base.c +++ b/arch/mips/loongson/common/uart_base.c @@ -24,6 +24,7 @@ unsigned long __maybe_unused uart8250_base[] = { [MACH_LEMOTE_YL2F89] (LOONGSON_LIO1_BASE + 0x3f8), [MACH_DEXXON_GDIUM2F10] (LOONGSON_LIO1_BASE + 0x3f8), [MACH_LEMOTE_NAS] (LOONGSON_LIO1_BASE + 0x3f8), + [MACH_LEMOTE_LL2F] (LOONGSON_PCIIO_BASE + 0x2f8), [MACH_LOONGSON_END] 0, }; EXPORT_SYMBOL(uart8250_base); diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c index 980299dbeac..44bb984d58d 100644 --- a/arch/mips/loongson/lemote-2f/reset.c +++ b/arch/mips/loongson/lemote-2f/reset.c @@ -142,6 +142,7 @@ void mach_prepare_reboot(void) switch (mips_machtype) { case MACH_LEMOTE_FL2F: case MACH_LEMOTE_NAS: + case MACH_LEMOTE_LL2F: fl2f_reboot(); break; case MACH_LEMOTE_ML2F7: @@ -160,6 +161,7 @@ void mach_prepare_shutdown(void) switch (mips_machtype) { case MACH_LEMOTE_FL2F: case MACH_LEMOTE_NAS: + case MACH_LEMOTE_LL2F: fl2f_shutdown(); break; case MACH_LEMOTE_ML2F7: -- cgit v1.2.3 From 916daba8a9f2617ded8b9255e6b39f066ef60178 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 17 Nov 2009 01:32:57 +0800 Subject: MIPS: Lemote 2F: Add cs5536 MFGPT timer support CPUFreq support for Loongson 2F requires an external timer. Because the frequency of the MIPS Timer is related to the CPU frequency which itself is variable another timer of constant frequency is required. Export the mfgpt0 counter disable / enable operations for the coming suspend support to suspend / resume the timer. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: cpufreq@vger.kernel.org, Cc: Dave Jones , Cc: Dominik Brodowski , Cc: yanh@lemote.com Cc: huhb@lemote.com, Patchwork: http://patchwork.linux-mips.org/patch/658/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 11 ++ arch/mips/loongson/common/cs5536/Makefile | 5 + arch/mips/loongson/common/cs5536/cs5536_mfgpt.c | 217 ++++++++++++++++++++++++ arch/mips/loongson/common/time.c | 3 + 4 files changed, 236 insertions(+) create mode 100644 arch/mips/loongson/common/cs5536/cs5536_mfgpt.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 17e72fde908..8b5cc138611 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -62,6 +62,17 @@ endchoice config CS5536 bool +config CS5536_MFGPT + bool "CS5536 MFGPT Timer" + depends on CS5536 + help + This option enables the mfgpt0 timer of AMD CS5536. + + If you want to enable the Loongson2 CPUFreq Driver, Please enable + this option at first, otherwise, You will get wrong system time. + + If unsure, say Yes. + config LOONGSON_SUSPEND bool default y diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile index 31657ee037d..510d4cdc237 100644 --- a/arch/mips/loongson/common/cs5536/Makefile +++ b/arch/mips/loongson/common/cs5536/Makefile @@ -5,4 +5,9 @@ obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \ cs5536_isa.o cs5536_ehci.o +# +# Enable cs5536 mfgpt Timer +# +obj-$(CONFIG_CS5536_MFGPT) += cs5536_mfgpt.o + EXTRA_CFLAGS += -Werror diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c new file mode 100644 index 00000000000..6cb44dbaeec --- /dev/null +++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c @@ -0,0 +1,217 @@ +/* + * CS5536 General timer functions + * + * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology + * Author: Yanhua, yanh@lemote.com + * + * Copyright (C) 2009 Lemote Inc. + * Author: Wu zhangjin, wuzj@lemote.com + * + * Reference: AMD Geode(TM) CS5536 Companion Device Data Book + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +DEFINE_SPINLOCK(mfgpt_lock); +EXPORT_SYMBOL(mfgpt_lock); + +static u32 mfgpt_base; + +/* + * Initialize the MFGPT timer. + * + * This is also called after resume to bring the MFGPT into operation again. + */ + +/* disable counter */ +void disable_mfgpt0_counter(void) +{ + outw(inw(MFGPT0_SETUP) & 0x7fff, MFGPT0_SETUP); +} +EXPORT_SYMBOL(disable_mfgpt0_counter); + +/* enable counter, comparator2 to event mode, 14.318MHz clock */ +void enable_mfgpt0_counter(void) +{ + outw(0xe310, MFGPT0_SETUP); +} +EXPORT_SYMBOL(enable_mfgpt0_counter); + +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: + outw(COMPARE, MFGPT0_CMP2); /* set comparator2 */ + outw(0, MFGPT0_CNT); /* set counter to 0 */ + enable_mfgpt0_counter(); + 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_mfgpt0_counter(); + break; + + case CLOCK_EVT_MODE_ONESHOT: + /* The oneshot mode have very high deviation, Not use it! */ + break; + + case CLOCK_EVT_MODE_RESUME: + /* Nothing to do here */ + break; + } + spin_unlock(&mfgpt_lock); +} + +static struct clock_event_device mfgpt_clockevent = { + .name = "mfgpt", + .features = CLOCK_EVT_FEAT_PERIODIC, + .set_mode = init_mfgpt_timer, + .irq = CS5536_MFGPT_INTR, +}; + +static irqreturn_t timer_interrupt(int irq, void *dev_id) +{ + u32 basehi; + + /* + * get MFGPT base address + * + * NOTE: do not remove me, it's need for the value of mfgpt_base is + * variable + */ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &basehi, &mfgpt_base); + + /* ack */ + outw(inw(MFGPT0_SETUP) | 0x4000, MFGPT0_SETUP); + + mfgpt_clockevent.event_handler(&mfgpt_clockevent); + + return IRQ_HANDLED; +} + +static struct irqaction irq5 = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER, + .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_mfgpt0_timer(void) +{ + u32 basehi; + struct clock_event_device *cd = &mfgpt_clockevent; + unsigned int cpu = smp_processor_id(); + + cd->cpumask = cpumask_of(cpu); + clockevent_set_clock(cd, MFGPT_TICK_RATE); + cd->max_delta_ns = clockevent_delta2ns(0xffff, cd); + cd->min_delta_ns = clockevent_delta2ns(0xf, cd); + + /* Enable MFGPT0 Comparator 2 Output to the Interrupt Mapper */ + _wrmsr(DIVIL_MSR_REG(MFGPT_IRQ), 0, 0x100); + + /* Enable Interrupt Gate 5 */ + _wrmsr(DIVIL_MSR_REG(PIC_ZSEL_LOW), 0, 0x50000); + + /* get MFGPT base address */ + _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &basehi, &mfgpt_base); + + clockevents_register_device(cd); + + setup_irq(CS5536_MFGPT_INTR, &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(struct clocksource *cs) +{ + unsigned long flags; + int count; + u32 jifs; + static int old_count; + static u32 old_jifs; + + spin_lock_irqsave(&mfgpt_lock, flags); + /* + * Although our caller may have the read side of xtime_lock, + * this is now a seqlock, and we are cheating in this routine + * by having side effects on state that we cannot undo if + * there is a collision on the seqlock and our caller has to + * retry. (Namely, old_jifs and old_count.) So we must treat + * jiffies as volatile despite the lock. We read jiffies + * before latching the timer count to guarantee that although + * the jiffies value might be older than the count (that is, + * the counter may underflow between the last point where + * jiffies was incremented and the point where we latch the + * count), it cannot be newer. + */ + jifs = jiffies; + /* read the count */ + count = inw(MFGPT0_CNT); + + /* + * It's possible for count to appear to go the wrong way for this + * reason: + * + * The timer counter underflows, but we haven't handled the resulting + * interrupt and incremented jiffies yet. + * + * Previous attempts to handle these cases intelligently were buggy, so + * we just do the simple thing now. + */ + 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 = 120, /* Functional for real use, but not desired */ + .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; + + clocksource_mfgpt.mult = clocksource_hz2mult(MFGPT_TICK_RATE, 22); + return clocksource_register(&clocksource_mfgpt); +} + +arch_initcall(init_mfgpt_clocksource); diff --git a/arch/mips/loongson/common/time.c b/arch/mips/loongson/common/time.c index 6e08c8270ab..35f0b66a94f 100644 --- a/arch/mips/loongson/common/time.c +++ b/arch/mips/loongson/common/time.c @@ -14,11 +14,14 @@ #include #include +#include void __init plat_time_init(void) { /* setup mips r4k timer */ mips_hpt_frequency = cpu_clock_freq / 2; + + setup_mfgpt0_timer(); } void read_persistent_clock(struct timespec *ts) -- cgit v1.2.3 From f8ede0f700f5478851f242f291d203cde54ca6cf Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 17 Nov 2009 01:32:59 +0800 Subject: MIPS: Loongson 2F: Add CPU frequency scaling support Loongson 2F supports CPU clock scaling. When put it into wait mode by setting the frequency as ZERO it will stay in this mode until an external interrupt wakes the CPU again. To enable clock scaling support, an external timer of a known stable rate is required. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Cc: cpufreq@vger.kernel.org, Cc: Dave Jones , Cc: Dominik Brodowski , Cc: yanh@lemote.com Cc: huhb@lemote.com, Patchwork: http://patchwork.linux-mips.org/patch/660/ Patchwork: http://patchwork.linux-mips.org/patch/751/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 5 +++-- arch/mips/loongson/common/Makefile | 2 +- arch/mips/loongson/common/env.c | 3 +++ arch/mips/loongson/common/platform.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 arch/mips/loongson/common/platform.c (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 8b5cc138611..7a86987b478 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -34,10 +34,10 @@ config LEMOTE_MACH2F select ARCH_SPARSEMEM_ENABLE select BOARD_SCACHE select BOOT_ELF32 - select CEVT_R4K + select CEVT_R4K if ! MIPS_EXTERNAL_TIMER select CPU_HAS_WB select CS5536 - select CSRC_R4K + select CSRC_R4K if ! MIPS_EXTERNAL_TIMER select DMA_NONCOHERENT select GENERIC_HARDIRQS_NO__DO_IRQ select GENERIC_ISA_DMA_SUPPORT_BROKEN @@ -65,6 +65,7 @@ config CS5536 config CS5536_MFGPT bool "CS5536 MFGPT Timer" depends on CS5536 + select MIPS_EXTERNAL_TIMER help This option enables the mfgpt0 timer of AMD CS5536. diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index a21724d50e2..8d71892413d 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -3,7 +3,7 @@ # obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ - pci.o bonito-irq.o mem.o machtype.o uart_base.o + pci.o bonito-irq.o mem.o machtype.o platform.o uart_base.o # # Early printk support diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c index b9ef5038554..196d947d929 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson/common/env.c @@ -17,11 +17,14 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ +#include + #include #include unsigned long bus_clock, cpu_clock_freq; +EXPORT_SYMBOL(cpu_clock_freq); unsigned long memsize, highmemsize; /* pmon passes arguments in 32bit pointers */ diff --git a/arch/mips/loongson/common/platform.c b/arch/mips/loongson/common/platform.c new file mode 100644 index 00000000000..be81777eb94 --- /dev/null +++ b/arch/mips/loongson/common/platform.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 Lemote Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include + +static struct platform_device loongson2_cpufreq_device = { + .name = "loongson2_cpufreq", + .id = -1, +}; + +static int __init loongson2_cpufreq_init(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + /* Only 2F revision and it's successors support CPUFreq */ + if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON2F) + return platform_device_register(&loongson2_cpufreq_device); + + return -ENODEV; +} + +arch_initcall(loongson2_cpufreq_init); -- cgit v1.2.3 From ec614d80b58677de30b876a16fdd3fde85bebdc1 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 21 Nov 2009 19:05:23 +0800 Subject: MIPS: Yeeloong 2F: Add basic EC operations YeeLoong2F has a KB3310b embedded controller. Add basic operations for future related drivers and board support. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/684/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/lemote-2f/Makefile | 2 +- arch/mips/loongson/lemote-2f/ec_kb3310b.c | 130 +++++++++++++++++++++ arch/mips/loongson/lemote-2f/ec_kb3310b.h | 188 ++++++++++++++++++++++++++++++ 3 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 arch/mips/loongson/lemote-2f/ec_kb3310b.c create mode 100644 arch/mips/loongson/lemote-2f/ec_kb3310b.h (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile index 5add7b2ead1..4d84b27dc41 100644 --- a/arch/mips/loongson/lemote-2f/Makefile +++ b/arch/mips/loongson/lemote-2f/Makefile @@ -2,7 +2,7 @@ # Makefile for lemote loongson2f family machines # -obj-y += irq.o reset.o +obj-y += irq.o reset.o ec_kb3310b.o # # Suspend Support diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/arch/mips/loongson/lemote-2f/ec_kb3310b.c new file mode 100644 index 00000000000..4d84111a2cd --- /dev/null +++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.c @@ -0,0 +1,130 @@ +/* + * Basic KB3310B Embedded Controller support for the YeeLoong 2F netbook + * + * Copyright (C) 2008 Lemote Inc. + * Author: liujl , 2008-04-20 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +#include "ec_kb3310b.h" + +static DEFINE_SPINLOCK(index_access_lock); +static DEFINE_SPINLOCK(port_access_lock); + +unsigned char ec_read(unsigned short addr) +{ + unsigned char value; + unsigned long flags; + + spin_lock_irqsave(&index_access_lock, flags); + outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH); + outb((addr & 0x00ff), EC_IO_PORT_LOW); + value = inb(EC_IO_PORT_DATA); + spin_unlock_irqrestore(&index_access_lock, flags); + + return value; +} +EXPORT_SYMBOL_GPL(ec_read); + +void ec_write(unsigned short addr, unsigned char val) +{ + unsigned long flags; + + spin_lock_irqsave(&index_access_lock, flags); + outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH); + outb((addr & 0x00ff), EC_IO_PORT_LOW); + outb(val, EC_IO_PORT_DATA); + /* flush the write action */ + inb(EC_IO_PORT_DATA); + spin_unlock_irqrestore(&index_access_lock, flags); + + return; +} +EXPORT_SYMBOL_GPL(ec_write); + +/* + * This function is used for EC command writes and corresponding status queries. + */ +int ec_query_seq(unsigned char cmd) +{ + int timeout; + unsigned char status; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&port_access_lock, flags); + + /* make chip goto reset mode */ + udelay(EC_REG_DELAY); + outb(cmd, EC_CMD_PORT); + udelay(EC_REG_DELAY); + + /* check if the command is received by ec */ + timeout = EC_CMD_TIMEOUT; + status = inb(EC_STS_PORT); + while (timeout-- && (status & (1 << 1))) { + status = inb(EC_STS_PORT); + udelay(EC_REG_DELAY); + } + + if (timeout <= 0) { + printk(KERN_ERR "%s: deadable error : timeout...\n", __func__); + ret = -EINVAL; + } else + printk(KERN_INFO + "(%x/%d)ec issued command %d status : 0x%x\n", + timeout, EC_CMD_TIMEOUT - timeout, cmd, status); + + spin_unlock_irqrestore(&port_access_lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(ec_query_seq); + +/* + * Send query command to EC to get the proper event number + */ +int ec_query_event_num(void) +{ + return ec_query_seq(CMD_GET_EVENT_NUM); +} +EXPORT_SYMBOL(ec_query_event_num); + +/* + * Get event number from EC + * + * NOTE: This routine must follow the query_event_num function in the + * interrupt. + */ +int ec_get_event_num(void) +{ + int timeout = 100; + unsigned char value; + unsigned char status; + + udelay(EC_REG_DELAY); + status = inb(EC_STS_PORT); + udelay(EC_REG_DELAY); + while (timeout-- && !(status & (1 << 0))) { + status = inb(EC_STS_PORT); + udelay(EC_REG_DELAY); + } + if (timeout <= 0) { + pr_info("%s: get event number timeout.\n", __func__); + + return -EINVAL; + } + value = inb(EC_DAT_PORT); + udelay(EC_REG_DELAY); + + return value; +} +EXPORT_SYMBOL(ec_get_event_num); diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.h b/arch/mips/loongson/lemote-2f/ec_kb3310b.h new file mode 100644 index 00000000000..1595a21b315 --- /dev/null +++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.h @@ -0,0 +1,188 @@ +/* + * KB3310B Embedded Controller + * + * Copyright (C) 2008 Lemote Inc. + * Author: liujl , 2008-03-14 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _EC_KB3310B_H +#define _EC_KB3310B_H + +extern unsigned char ec_read(unsigned short addr); +extern void ec_write(unsigned short addr, unsigned char val); +extern int ec_query_seq(unsigned char cmd); +extern int ec_query_event_num(void); +extern int ec_get_event_num(void); + +typedef int (*sci_handler) (int status); +extern sci_handler yeeloong_report_lid_status; + +#define SCI_IRQ_NUM 0x0A + +/* + * The following registers are determined by the EC index configuration. + * 1, fill the PORT_HIGH as EC register high part. + * 2, fill the PORT_LOW as EC register low part. + * 3, fill the PORT_DATA as EC register write data or get the data from it. + */ +#define EC_IO_PORT_HIGH 0x0381 +#define EC_IO_PORT_LOW 0x0382 +#define EC_IO_PORT_DATA 0x0383 + +/* + * EC delay time is 500us for register and status access + */ +#define EC_REG_DELAY 500 /* unit : us */ +#define EC_CMD_TIMEOUT 0x1000 + +/* + * EC access port for SCI communication + */ +#define EC_CMD_PORT 0x66 +#define EC_STS_PORT 0x66 +#define EC_DAT_PORT 0x62 +#define CMD_INIT_IDLE_MODE 0xdd +#define CMD_EXIT_IDLE_MODE 0xdf +#define CMD_INIT_RESET_MODE 0xd8 +#define CMD_REBOOT_SYSTEM 0x8c +#define CMD_GET_EVENT_NUM 0x84 +#define CMD_PROGRAM_PIECE 0xda + +/* temperature & fan registers */ +#define REG_TEMPERATURE_VALUE 0xF458 +#define REG_FAN_AUTO_MAN_SWITCH 0xF459 +#define BIT_FAN_AUTO 0 +#define BIT_FAN_MANUAL 1 +#define REG_FAN_CONTROL 0xF4D2 +#define BIT_FAN_CONTROL_ON (1 << 0) +#define BIT_FAN_CONTROL_OFF (0 << 0) +#define REG_FAN_STATUS 0xF4DA +#define BIT_FAN_STATUS_ON (1 << 0) +#define BIT_FAN_STATUS_OFF (0 << 0) +#define REG_FAN_SPEED_HIGH 0xFE22 +#define REG_FAN_SPEED_LOW 0xFE23 +#define REG_FAN_SPEED_LEVEL 0xF4CC +/* fan speed divider */ +#define FAN_SPEED_DIVIDER 480000 /* (60*1000*1000/62.5/2)*/ + +/* battery registers */ +#define REG_BAT_DESIGN_CAP_HIGH 0xF77D +#define REG_BAT_DESIGN_CAP_LOW 0xF77E +#define REG_BAT_FULLCHG_CAP_HIGH 0xF780 +#define REG_BAT_FULLCHG_CAP_LOW 0xF781 +#define REG_BAT_DESIGN_VOL_HIGH 0xF782 +#define REG_BAT_DESIGN_VOL_LOW 0xF783 +#define REG_BAT_CURRENT_HIGH 0xF784 +#define REG_BAT_CURRENT_LOW 0xF785 +#define REG_BAT_VOLTAGE_HIGH 0xF786 +#define REG_BAT_VOLTAGE_LOW 0xF787 +#define REG_BAT_TEMPERATURE_HIGH 0xF788 +#define REG_BAT_TEMPERATURE_LOW 0xF789 +#define REG_BAT_RELATIVE_CAP_HIGH 0xF492 +#define REG_BAT_RELATIVE_CAP_LOW 0xF493 +#define REG_BAT_VENDOR 0xF4C4 +#define FLAG_BAT_VENDOR_SANYO 0x01 +#define FLAG_BAT_VENDOR_SIMPLO 0x02 +#define REG_BAT_CELL_COUNT 0xF4C6 +#define FLAG_BAT_CELL_3S1P 0x03 +#define FLAG_BAT_CELL_3S2P 0x06 +#define REG_BAT_CHARGE 0xF4A2 +#define FLAG_BAT_CHARGE_DISCHARGE 0x01 +#define FLAG_BAT_CHARGE_CHARGE 0x02 +#define FLAG_BAT_CHARGE_ACPOWER 0x00 +#define REG_BAT_STATUS 0xF4B0 +#define BIT_BAT_STATUS_LOW (1 << 5) +#define BIT_BAT_STATUS_DESTROY (1 << 2) +#define BIT_BAT_STATUS_FULL (1 << 1) +#define BIT_BAT_STATUS_IN (1 << 0) +#define REG_BAT_CHARGE_STATUS 0xF4B1 +#define BIT_BAT_CHARGE_STATUS_OVERTEMP (1 << 2) +#define BIT_BAT_CHARGE_STATUS_PRECHG (1 << 1) +#define REG_BAT_STATE 0xF482 +#define BIT_BAT_STATE_CHARGING (1 << 1) +#define BIT_BAT_STATE_DISCHARGING (1 << 0) +#define REG_BAT_POWER 0xF440 +#define BIT_BAT_POWER_S3 (1 << 2) +#define BIT_BAT_POWER_ON (1 << 1) +#define BIT_BAT_POWER_ACIN (1 << 0) + +/* other registers */ +/* Audio: rd/wr */ +#define REG_AUDIO_VOLUME 0xF46C +#define REG_AUDIO_MUTE 0xF4E7 +#define REG_AUDIO_BEEP 0xF4D0 +/* USB port power or not: rd/wr */ +#define REG_USB0_FLAG 0xF461 +#define REG_USB1_FLAG 0xF462 +#define REG_USB2_FLAG 0xF463 +#define BIT_USB_FLAG_ON 1 +#define BIT_USB_FLAG_OFF 0 +/* LID */ +#define REG_LID_DETECT 0xF4BD +#define BIT_LID_DETECT_ON 1 +#define BIT_LID_DETECT_OFF 0 +/* CRT */ +#define REG_CRT_DETECT 0xF4AD +#define BIT_CRT_DETECT_PLUG 1 +#define BIT_CRT_DETECT_UNPLUG 0 +/* LCD backlight brightness adjust: 9 levels */ +#define REG_DISPLAY_BRIGHTNESS 0xF4F5 +/* Black screen Status */ +#define BIT_DISPLAY_LCD_ON 1 +#define BIT_DISPLAY_LCD_OFF 0 +/* LCD backlight control: off/restore */ +#define REG_BACKLIGHT_CTRL 0xF7BD +#define BIT_BACKLIGHT_ON 1 +#define BIT_BACKLIGHT_OFF 0 +/* Reset the machine auto-clear: rd/wr */ +#define REG_RESET 0xF4EC +#define BIT_RESET_ON 1 +/* Light the led: rd/wr */ +#define REG_LED 0xF4C8 +#define BIT_LED_RED_POWER (1 << 0) +#define BIT_LED_ORANGE_POWER (1 << 1) +#define BIT_LED_GREEN_CHARGE (1 << 2) +#define BIT_LED_RED_CHARGE (1 << 3) +#define BIT_LED_NUMLOCK (1 << 4) +/* Test led mode, all led on/off */ +#define REG_LED_TEST 0xF4C2 +#define BIT_LED_TEST_IN 1 +#define BIT_LED_TEST_OUT 0 +/* Camera on/off */ +#define REG_CAMERA_STATUS 0xF46A +#define BIT_CAMERA_STATUS_ON 1 +#define BIT_CAMERA_STATUS_OFF 0 +#define REG_CAMERA_CONTROL 0xF7B7 +#define BIT_CAMERA_CONTROL_OFF 0 +#define BIT_CAMERA_CONTROL_ON 1 +/* Wlan Status */ +#define REG_WLAN 0xF4FA +#define BIT_WLAN_ON 1 +#define BIT_WLAN_OFF 0 +#define REG_DISPLAY_LCD 0xF79F + +/* SCI Event Number from EC */ +enum { + EVENT_LID = 0x23, /* LID open/close */ + EVENT_DISPLAY_TOGGLE, /* Fn+F3 for display switch */ + EVENT_SLEEP, /* Fn+F1 for entering sleep mode */ + EVENT_OVERTEMP, /* Over-temperature happened */ + EVENT_CRT_DETECT, /* CRT is connected */ + EVENT_CAMERA, /* Camera on/off */ + EVENT_USB_OC2, /* USB2 Over Current occurred */ + EVENT_USB_OC0, /* USB0 Over Current occurred */ + EVENT_BLACK_SCREEN, /* Turn on/off backlight */ + EVENT_AUDIO_MUTE, /* Mute on/off */ + EVENT_DISPLAY_BRIGHTNESS,/* LCD backlight brightness adjust */ + EVENT_AC_BAT, /* AC & Battery relative issue */ + EVENT_AUDIO_VOLUME, /* Volume adjust */ + EVENT_WLAN, /* Wlan on/off */ + EVENT_END +}; + +#endif /* !_EC_KB3310B_H */ -- cgit v1.2.3 From cb1ed9e117098269de3c0dfff816dff453dd4b59 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 21 Nov 2009 19:05:24 +0800 Subject: MIPS: Yeeloong 2F: Add LID open event as the wakeup event Yeeloong 2F netbook has an KB3310B embedded controller to manage the LID action. When the LID is closed or opened a SCI interrupt is sent out and the corresponding event is saved to an EC register for later query. Allow the LID open interrupt to wake the processor from wait mode if it is in the suspend mode. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/685/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/lemote-2f/irq.c | 4 ++- arch/mips/loongson/lemote-2f/pm.c | 71 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c index 50e7bb6012b..77d32f9cf31 100644 --- a/arch/mips/loongson/lemote-2f/irq.c +++ b/arch/mips/loongson/lemote-2f/irq.c @@ -9,6 +9,7 @@ */ #include +#include #include #include @@ -30,7 +31,7 @@ * The generic i8259_irq() make the kernel hang on booting. Since we cannot * get the irq via the IRR directly, we access the ISR instead. */ -static inline int mach_i8259_irq(void) +int mach_i8259_irq(void) { int irq, isr; @@ -60,6 +61,7 @@ static inline int mach_i8259_irq(void) return irq; } +EXPORT_SYMBOL(mach_i8259_irq); static void i8259_irqdispatch(void) { diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson/lemote-2f/pm.c index 8090d051422..81c06410aa7 100644 --- a/arch/mips/loongson/lemote-2f/pm.c +++ b/arch/mips/loongson/lemote-2f/pm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -21,6 +22,8 @@ #include +#include "ec_kb3310b.h" + #define I8042_KBD_IRQ 1 #define I8042_CTR_KBDINT 0x01 #define I8042_CTR_KBDDIS 0x10 @@ -49,9 +52,6 @@ static int i8042_enable_kbd_port(void) return 0; } -/* - * The i8042 is connnected to i8259A - */ void setup_wakeup_events(void) { int irq_mask; @@ -65,9 +65,74 @@ void setup_wakeup_events(void) /* enable keyboard port */ i8042_enable_kbd_port(); + + /* Wakeup CPU via SCI lid open event */ + outb(irq_mask & ~(1 << PIC_CASCADE_IR), PIC_MASTER_IMR); + inb(PIC_MASTER_IMR); + outb(0xff & ~(1 << (SCI_IRQ_NUM - 8)), PIC_SLAVE_IMR); + inb(PIC_SLAVE_IMR); + break; default: break; } } + +static struct delayed_work lid_task; +static int initialized; +/* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */ +sci_handler yeeloong_report_lid_status; +EXPORT_SYMBOL(yeeloong_report_lid_status); +static void yeeloong_lid_update_task(struct work_struct *work) +{ + if (yeeloong_report_lid_status) + yeeloong_report_lid_status(BIT_LID_DETECT_ON); +} + +int wakeup_loongson(void) +{ + int irq; + + /* query the interrupt number */ + irq = mach_i8259_irq(); + if (irq < 0) + return 0; + + printk(KERN_INFO "%s: irq = %d\n", __func__, irq); + + if (irq == I8042_KBD_IRQ) + return 1; + else if (irq == SCI_IRQ_NUM) { + int ret, sci_event; + /* query the event number */ + ret = ec_query_seq(CMD_GET_EVENT_NUM); + if (ret < 0) + return 0; + sci_event = ec_get_event_num(); + if (sci_event < 0) + return 0; + if (sci_event == EVENT_LID) { + int lid_status; + /* check the LID status */ + lid_status = ec_read(REG_LID_DETECT); + /* wakeup cpu when people open the LID */ + if (lid_status == BIT_LID_DETECT_ON) { + /* If we call it directly here, the WARNING + * will be sent out by getnstimeofday + * via "WARN_ON(timekeeping_suspended);" + * because we can not schedule in suspend mode. + */ + if (initialized == 0) { + INIT_DELAYED_WORK(&lid_task, + yeeloong_lid_update_task); + initialized = 1; + } + schedule_delayed_work(&lid_task, 1); + return 1; + } + } + } + + return 0; +} -- cgit v1.2.3 From 70ab711df44ada438973ceba0213121afeb8e8b3 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 21 Nov 2009 19:05:25 +0800 Subject: MIPS: Yeeloong 2F: Cleanup reset logic using the new ec_write function Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/683/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/lemote-2f/reset.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c index 44bb984d58d..51d1a60d534 100644 --- a/arch/mips/loongson/lemote-2f/reset.c +++ b/arch/mips/loongson/lemote-2f/reset.c @@ -20,6 +20,7 @@ #include #include +#include "ec_kb3310b.h" static void reset_cpu(void) { @@ -75,30 +76,12 @@ static void fl2f_shutdown(void) /* reset support for yeeloong2f and mengloong2f notebook */ -/* - * The following registers are determined by the EC index configuration. - * 1. fill the PORT_HIGH as EC register high part. - * 2. fill the PORT_LOW as EC register low part. - * 3. fill the PORT_DATA as EC register write data or get the data from it. - */ - -#define EC_IO_PORT_HIGH 0x0381 -#define EC_IO_PORT_LOW 0x0382 -#define EC_IO_PORT_DATA 0x0383 -#define REG_RESET_HIGH 0xF4 /* reset the machine auto-clear : rd/wr */ -#define REG_RESET_LOW 0xEC -#define BIT_RESET_ON (1 << 0) - void ml2f_reboot(void) { reset_cpu(); /* sending an reset signal to EC(embedded controller) */ - outb(REG_RESET_HIGH, EC_IO_PORT_HIGH); - outb(REG_RESET_LOW, EC_IO_PORT_LOW); - mmiowb(); - outb(BIT_RESET_ON, EC_IO_PORT_DATA); - mmiowb(); + ec_write(REG_RESET, BIT_RESET_ON); } #define yl2f89_reboot ml2f_reboot -- cgit v1.2.3 From c47a48d83a7a82c86ff3e74bdcabeee8f6e6b730 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Tue, 24 Nov 2009 21:48:36 +0800 Subject: MIPS: Lemote 2F: Suspend CS5536 MFGPT Timer Before putting the Loongson 2F into wait mode, suspend the MFGPT Timer and after wake-up resume it. This may save some power. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/706/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/lemote-2f/pm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson/lemote-2f/pm.c index 81c06410aa7..d7af2e61659 100644 --- a/arch/mips/loongson/lemote-2f/pm.c +++ b/arch/mips/loongson/lemote-2f/pm.c @@ -22,6 +22,7 @@ #include +#include #include "ec_kb3310b.h" #define I8042_KBD_IRQ 1 @@ -136,3 +137,13 @@ int wakeup_loongson(void) return 0; } + +void __weak mach_suspend(void) +{ + disable_mfgpt0_counter(); +} + +void __weak mach_resume(void) +{ + enable_mfgpt0_counter(); +} -- cgit v1.2.3 From c3d8d85019c9e4f6e4f23d194b6432a2c2464372 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Sat, 28 Nov 2009 14:21:50 +0800 Subject: MIPS: Loongson: Cleanups of serial port support This patchs uses a loongson_uart_base variable instead of the uart_base[] array and adds a new kernel option to avoid to compile uart_base.c all the time, which will save a little bit of memory for us. Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org http://patchwork.linux-mips.org/patch/727/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/Kconfig | 5 +++++ arch/mips/loongson/common/Makefile | 5 +++-- arch/mips/loongson/common/init.c | 2 -- arch/mips/loongson/common/serial.c | 10 ++++++--- arch/mips/loongson/common/uart_base.c | 41 +++++++++++++++++++++-------------- 5 files changed, 40 insertions(+), 23 deletions(-) (limited to 'arch/mips/loongson') diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 7a86987b478..3df1967dea0 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -78,3 +78,8 @@ config LOONGSON_SUSPEND bool default y depends on CPU_SUPPORTS_CPUFREQ && SUSPEND + +config LOONGSON_UART_BASE + bool + default y + depends on EARLY_PRINTK || SERIAL_8250 diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index 8d71892413d..7668c4de115 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -3,13 +3,14 @@ # obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ - pci.o bonito-irq.o mem.o machtype.o platform.o uart_base.o + pci.o bonito-irq.o mem.o machtype.o platform.o # -# Early printk support +# Serial port support # obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_SERIAL_8250) += serial.o +obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o # # Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c index 2b92a23d29d..a2abd935573 100644 --- a/arch/mips/loongson/common/init.c +++ b/arch/mips/loongson/common/init.c @@ -31,9 +31,7 @@ void __init prom_init(void) prom_init_memory(); /*init the uart base address */ -#if defined(CONFIG_EARLY_PRINTK) || defined(CONFIG_SERIAL_8250) prom_init_uart_base(); -#endif } void __init prom_free_prom_memory(void) diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c index ea29db099ae..23b66a5f88c 100644 --- a/arch/mips/loongson/common/serial.c +++ b/arch/mips/loongson/common/serial.c @@ -57,12 +57,16 @@ static struct platform_device uart8250_device = { static int __init serial_init(void) { - if (uart8250_data[mips_machtype][0].iotype == UPIO_MEM) + unsigned char iotype; + + iotype = uart8250_data[mips_machtype][0].iotype; + + if (UPIO_MEM == iotype) uart8250_data[mips_machtype][0].membase = (void __iomem *)_loongson_uart_base; - else if (uart8250_data[mips_machtype][0].iotype == UPIO_PORT) + else if (UPIO_PORT == iotype) uart8250_data[mips_machtype][0].iobase = - uart8250_base[mips_machtype] - LOONGSON_PCIIO_BASE; + loongson_uart_base - LOONGSON_PCIIO_BASE; uart8250_device.dev.platform_data = uart8250_data[mips_machtype]; diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c index 1d636f4f750..78ff66ae749 100644 --- a/arch/mips/loongson/common/uart_base.c +++ b/arch/mips/loongson/common/uart_base.c @@ -13,24 +13,33 @@ #include -unsigned long __maybe_unused _loongson_uart_base; +/* ioremapped */ +unsigned long _loongson_uart_base; EXPORT_SYMBOL(_loongson_uart_base); +/* raw */ +unsigned long loongson_uart_base; +EXPORT_SYMBOL(loongson_uart_base); -unsigned long __maybe_unused uart8250_base[] = { - [MACH_LOONGSON_UNKNOWN] 0, - [MACH_LEMOTE_FL2E] (LOONGSON_PCIIO_BASE + 0x3f8), - [MACH_LEMOTE_FL2F] (LOONGSON_PCIIO_BASE + 0x2f8), - [MACH_LEMOTE_ML2F7] (LOONGSON_LIO1_BASE + 0x3f8), - [MACH_LEMOTE_YL2F89] (LOONGSON_LIO1_BASE + 0x3f8), - [MACH_DEXXON_GDIUM2F10] (LOONGSON_LIO1_BASE + 0x3f8), - [MACH_LEMOTE_NAS] (LOONGSON_LIO1_BASE + 0x3f8), - [MACH_LEMOTE_LL2F] (LOONGSON_PCIIO_BASE + 0x2f8), - [MACH_LOONGSON_END] 0, -}; -EXPORT_SYMBOL(uart8250_base); - -void __maybe_unused prom_init_uart_base(void) +void prom_init_loongson_uart_base(void) { + switch (mips_machtype) { + case MACH_LEMOTE_FL2E: + loongson_uart_base = LOONGSON_PCIIO_BASE + 0x3f8; + break; + case MACH_LEMOTE_FL2F: + case MACH_LEMOTE_LL2F: + loongson_uart_base = LOONGSON_PCIIO_BASE + 0x2f8; + break; + case MACH_LEMOTE_ML2F7: + case MACH_LEMOTE_YL2F89: + case MACH_DEXXON_GDIUM2F10: + case MACH_LEMOTE_NAS: + default: + /* The CPU provided serial port */ + loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8; + break; + } + _loongson_uart_base = - (unsigned long)ioremap_nocache(uart8250_base[mips_machtype], 8); + (unsigned long)ioremap_nocache(loongson_uart_base, 8); } -- cgit v1.2.3