diff options
25 files changed, 515 insertions, 175 deletions
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c index 14eb8c492da2..5ef06a164a82 100644 --- a/arch/mips/alchemy/common/power.c +++ b/arch/mips/alchemy/common/power.c | |||
| @@ -193,9 +193,15 @@ static void restore_core_regs(void) | |||
| 193 | 193 | ||
| 194 | void au_sleep(void) | 194 | void au_sleep(void) |
| 195 | { | 195 | { |
| 196 | save_core_regs(); | 196 | int cpuid = alchemy_get_cputype(); |
| 197 | au1xxx_save_and_sleep(); | 197 | if (cpuid != ALCHEMY_CPU_UNKNOWN) { |
| 198 | restore_core_regs(); | 198 | save_core_regs(); |
| 199 | if (cpuid <= ALCHEMY_CPU_AU1500) | ||
| 200 | alchemy_sleep_au1000(); | ||
| 201 | else if (cpuid <= ALCHEMY_CPU_AU1200) | ||
| 202 | alchemy_sleep_au1550(); | ||
| 203 | restore_core_regs(); | ||
| 204 | } | ||
| 199 | } | 205 | } |
| 200 | 206 | ||
| 201 | #endif /* CONFIG_PM */ | 207 | #endif /* CONFIG_PM */ |
diff --git a/arch/mips/alchemy/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S index 4f4b16741d12..77f3c743b716 100644 --- a/arch/mips/alchemy/common/sleeper.S +++ b/arch/mips/alchemy/common/sleeper.S | |||
| @@ -22,10 +22,9 @@ | |||
| 22 | .set noat | 22 | .set noat |
| 23 | .align 5 | 23 | .align 5 |
| 24 | 24 | ||
| 25 | /* Save all of the processor general registers and go to sleep. | 25 | |
| 26 | * A wakeup condition will get us back here to restore the registers. | 26 | /* preparatory stuff */ |
| 27 | */ | 27 | .macro SETUP_SLEEP |
| 28 | LEAF(au1xxx_save_and_sleep) | ||
| 29 | subu sp, PT_SIZE | 28 | subu sp, PT_SIZE |
| 30 | sw $1, PT_R1(sp) | 29 | sw $1, PT_R1(sp) |
| 31 | sw $2, PT_R2(sp) | 30 | sw $2, PT_R2(sp) |
| @@ -69,12 +68,32 @@ LEAF(au1xxx_save_and_sleep) | |||
| 69 | */ | 68 | */ |
| 70 | lui t3, 0xb190 /* sys_xxx */ | 69 | lui t3, 0xb190 /* sys_xxx */ |
| 71 | sw sp, 0x0018(t3) | 70 | sw sp, 0x0018(t3) |
| 72 | la k0, 3f /* resume path */ | 71 | la k0, alchemy_sleep_wakeup /* resume path */ |
| 73 | sw k0, 0x001c(t3) | 72 | sw k0, 0x001c(t3) |
| 73 | .endm | ||
| 74 | 74 | ||
| 75 | /* Put SDRAM into self refresh: Preload instructions into cache, | 75 | .macro DO_SLEEP |
| 76 | * issue a precharge, auto/self refresh, then sleep commands to it. | 76 | /* put power supply and processor to sleep */ |
| 77 | */ | 77 | sw zero, 0x0078(t3) /* sys_slppwr */ |
| 78 | sync | ||
| 79 | sw zero, 0x007c(t3) /* sys_sleep */ | ||
| 80 | sync | ||
| 81 | nop | ||
| 82 | nop | ||
| 83 | nop | ||
| 84 | nop | ||
| 85 | nop | ||
| 86 | nop | ||
| 87 | nop | ||
| 88 | nop | ||
| 89 | .endm | ||
| 90 | |||
| 91 | /* sleep code for Au1000/Au1100/Au1500 memory controller type */ | ||
| 92 | LEAF(alchemy_sleep_au1000) | ||
| 93 | |||
| 94 | SETUP_SLEEP | ||
| 95 | |||
| 96 | /* cache following instructions, as memory gets put to sleep */ | ||
| 78 | la t0, 1f | 97 | la t0, 1f |
| 79 | .set mips3 | 98 | .set mips3 |
| 80 | cache 0x14, 0(t0) | 99 | cache 0x14, 0(t0) |
| @@ -84,17 +103,32 @@ LEAF(au1xxx_save_and_sleep) | |||
| 84 | .set mips0 | 103 | .set mips0 |
| 85 | 104 | ||
| 86 | 1: lui a0, 0xb400 /* mem_xxx */ | 105 | 1: lui a0, 0xb400 /* mem_xxx */ |
| 87 | #if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \ | ||
| 88 | defined(CONFIG_SOC_AU1500) | ||
| 89 | sw zero, 0x001c(a0) /* Precharge */ | 106 | sw zero, 0x001c(a0) /* Precharge */ |
| 90 | sync | 107 | sync |
| 91 | sw zero, 0x0020(a0) /* Auto Refresh */ | 108 | sw zero, 0x0020(a0) /* Auto Refresh */ |
| 92 | sync | 109 | sync |
| 93 | sw zero, 0x0030(a0) /* Sleep */ | 110 | sw zero, 0x0030(a0) /* Sleep */ |
| 94 | sync | 111 | sync |
| 95 | #endif | ||
| 96 | 112 | ||
| 97 | #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) | 113 | DO_SLEEP |
| 114 | |||
| 115 | END(alchemy_sleep_au1000) | ||
| 116 | |||
| 117 | /* sleep code for Au1550/Au1200 memory controller type */ | ||
| 118 | LEAF(alchemy_sleep_au1550) | ||
| 119 | |||
| 120 | SETUP_SLEEP | ||
| 121 | |||
| 122 | /* cache following instructions, as memory gets put to sleep */ | ||
| 123 | la t0, 1f | ||
| 124 | .set mips3 | ||
| 125 | cache 0x14, 0(t0) | ||
| 126 | cache 0x14, 32(t0) | ||
| 127 | cache 0x14, 64(t0) | ||
| 128 | cache 0x14, 96(t0) | ||
| 129 | .set mips0 | ||
| 130 | |||
| 131 | 1: lui a0, 0xb400 /* mem_xxx */ | ||
| 98 | sw zero, 0x08c0(a0) /* Precharge */ | 132 | sw zero, 0x08c0(a0) /* Precharge */ |
| 99 | sync | 133 | sync |
| 100 | sw zero, 0x08d0(a0) /* Self Refresh */ | 134 | sw zero, 0x08d0(a0) /* Self Refresh */ |
| @@ -114,26 +148,17 @@ LEAF(au1xxx_save_and_sleep) | |||
| 114 | and t1, t0, t1 /* clear CE[1:0] */ | 148 | and t1, t0, t1 /* clear CE[1:0] */ |
| 115 | sw t1, 0x0840(a0) /* mem_sdconfiga */ | 149 | sw t1, 0x0840(a0) /* mem_sdconfiga */ |
| 116 | sync | 150 | sync |
| 117 | #endif | ||
| 118 | 151 | ||
| 119 | /* put power supply and processor to sleep */ | 152 | DO_SLEEP |
| 120 | sw zero, 0x0078(t3) /* sys_slppwr */ | 153 | |
| 121 | sync | 154 | END(alchemy_sleep_au1550) |
| 122 | sw zero, 0x007c(t3) /* sys_sleep */ | 155 | |
| 123 | sync | ||
| 124 | nop | ||
| 125 | nop | ||
| 126 | nop | ||
| 127 | nop | ||
| 128 | nop | ||
| 129 | nop | ||
| 130 | nop | ||
| 131 | nop | ||
| 132 | 156 | ||
| 133 | /* This is where we return upon wakeup. | 157 | /* This is where we return upon wakeup. |
| 134 | * Reload all of the registers and return. | 158 | * Reload all of the registers and return. |
| 135 | */ | 159 | */ |
| 136 | 3: lw k0, 0x20(sp) | 160 | LEAF(alchemy_sleep_wakeup) |
| 161 | lw k0, 0x20(sp) | ||
| 137 | mtc0 k0, CP0_STATUS | 162 | mtc0 k0, CP0_STATUS |
| 138 | lw k0, 0x1c(sp) | 163 | lw k0, 0x1c(sp) |
| 139 | mtc0 k0, CP0_CONTEXT | 164 | mtc0 k0, CP0_CONTEXT |
| @@ -169,4 +194,4 @@ LEAF(au1xxx_save_and_sleep) | |||
| 169 | lw $31, PT_R31(sp) | 194 | lw $31, PT_R31(sp) |
| 170 | jr ra | 195 | jr ra |
| 171 | addiu sp, PT_SIZE | 196 | addiu sp, PT_SIZE |
| 172 | END(au1xxx_save_and_sleep) | 197 | END(alchemy_sleep_wakeup) |
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 566f2d7f2ea3..8f31d1d59683 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c | |||
| @@ -542,7 +542,7 @@ static int __init ar7_register_uarts(void) | |||
| 542 | if (IS_ERR(bus_clk)) | 542 | if (IS_ERR(bus_clk)) |
| 543 | panic("unable to get bus clk\n"); | 543 | panic("unable to get bus clk\n"); |
| 544 | 544 | ||
| 545 | uart_port.type = PORT_16550A; | 545 | uart_port.type = PORT_AR7; |
| 546 | uart_port.uartclk = clk_get_rate(bus_clk) / 2; | 546 | uart_port.uartclk = clk_get_rate(bus_clk) / 2; |
| 547 | uart_port.iotype = UPIO_MEM32; | 547 | uart_port.iotype = UPIO_MEM32; |
| 548 | uart_port.regshift = 2; | 548 | uart_port.regshift = 2; |
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile index 35294b12d638..7465e8a72d9a 100644 --- a/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile | |||
| @@ -3,4 +3,4 @@ | |||
| 3 | # under Linux. | 3 | # under Linux. |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o | 6 | obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o |
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c new file mode 100644 index 000000000000..06e03b222f6d --- /dev/null +++ b/arch/mips/bcm47xx/nvram.c | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | /* | ||
| 2 | * BCM947xx nvram variable access | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Broadcom Corporation | ||
| 5 | * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/types.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/ssb/ssb.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/string.h> | ||
| 19 | #include <asm/addrspace.h> | ||
| 20 | #include <asm/mach-bcm47xx/nvram.h> | ||
| 21 | #include <asm/mach-bcm47xx/bcm47xx.h> | ||
| 22 | |||
| 23 | static char nvram_buf[NVRAM_SPACE]; | ||
| 24 | |||
| 25 | /* Probe for NVRAM header */ | ||
| 26 | static void __init early_nvram_init(void) | ||
| 27 | { | ||
| 28 | struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; | ||
| 29 | struct nvram_header *header; | ||
| 30 | int i; | ||
| 31 | u32 base, lim, off; | ||
| 32 | u32 *src, *dst; | ||
| 33 | |||
| 34 | base = mcore->flash_window; | ||
| 35 | lim = mcore->flash_window_size; | ||
| 36 | |||
| 37 | off = FLASH_MIN; | ||
| 38 | while (off <= lim) { | ||
| 39 | /* Windowed flash access */ | ||
| 40 | header = (struct nvram_header *) | ||
| 41 | KSEG1ADDR(base + off - NVRAM_SPACE); | ||
| 42 | if (header->magic == NVRAM_HEADER) | ||
| 43 | goto found; | ||
| 44 | off <<= 1; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ | ||
| 48 | header = (struct nvram_header *) KSEG1ADDR(base + 4096); | ||
| 49 | if (header->magic == NVRAM_HEADER) | ||
| 50 | goto found; | ||
| 51 | |||
| 52 | header = (struct nvram_header *) KSEG1ADDR(base + 1024); | ||
| 53 | if (header->magic == NVRAM_HEADER) | ||
| 54 | goto found; | ||
| 55 | |||
| 56 | return; | ||
| 57 | |||
| 58 | found: | ||
| 59 | src = (u32 *) header; | ||
| 60 | dst = (u32 *) nvram_buf; | ||
| 61 | for (i = 0; i < sizeof(struct nvram_header); i += 4) | ||
| 62 | *dst++ = *src++; | ||
| 63 | for (; i < header->len && i < NVRAM_SPACE; i += 4) | ||
| 64 | *dst++ = le32_to_cpu(*src++); | ||
| 65 | } | ||
| 66 | |||
| 67 | int nvram_getenv(char *name, char *val, size_t val_len) | ||
| 68 | { | ||
| 69 | char *var, *value, *end, *eq; | ||
| 70 | |||
| 71 | if (!name) | ||
| 72 | return 1; | ||
| 73 | |||
| 74 | if (!nvram_buf[0]) | ||
| 75 | early_nvram_init(); | ||
| 76 | |||
| 77 | /* Look for name=value and return value */ | ||
| 78 | var = &nvram_buf[sizeof(struct nvram_header)]; | ||
| 79 | end = nvram_buf + sizeof(nvram_buf) - 2; | ||
| 80 | end[0] = end[1] = '\0'; | ||
| 81 | for (; *var; var = value + strlen(value) + 1) { | ||
| 82 | eq = strchr(var, '='); | ||
| 83 | if (!eq) | ||
| 84 | break; | ||
| 85 | value = eq + 1; | ||
| 86 | if ((eq - var) == strlen(name) && | ||
| 87 | strncmp(var, name, (eq - var)) == 0) { | ||
| 88 | snprintf(val, val_len, "%s", value); | ||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | return 1; | ||
| 93 | } | ||
| 94 | EXPORT_SYMBOL(nvram_getenv); | ||
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index d442e11625fa..b1aee33efd11 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> | 2 | * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> |
| 3 | * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org> | ||
| 4 | * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> | 3 | * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> |
| 5 | * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de> | 4 | * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de> |
| 5 | * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org> | ||
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
| 8 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <asm/time.h> | 33 | #include <asm/time.h> |
| 34 | #include <bcm47xx.h> | 34 | #include <bcm47xx.h> |
| 35 | #include <asm/fw/cfe/cfe_api.h> | 35 | #include <asm/fw/cfe/cfe_api.h> |
| 36 | #include <asm/mach-bcm47xx/nvram.h> | ||
| 36 | 37 | ||
| 37 | struct ssb_bus ssb_bcm47xx; | 38 | struct ssb_bus ssb_bcm47xx; |
| 38 | EXPORT_SYMBOL(ssb_bcm47xx); | 39 | EXPORT_SYMBOL(ssb_bcm47xx); |
| @@ -81,28 +82,42 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, | |||
| 81 | /* Fill boardinfo structure */ | 82 | /* Fill boardinfo structure */ |
| 82 | memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); | 83 | memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); |
| 83 | 84 | ||
| 84 | if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0) | 85 | if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 || |
| 86 | nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) | ||
| 85 | iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); | 87 | iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); |
| 86 | if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0) | 88 | if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 || |
| 89 | nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) | ||
| 87 | iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); | 90 | iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); |
| 88 | if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0) | 91 | if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 || |
| 92 | nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) | ||
| 89 | iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); | 93 | iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); |
| 90 | 94 | ||
| 91 | /* Fill sprom structure */ | 95 | /* Fill sprom structure */ |
| 92 | memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); | 96 | memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); |
| 93 | iv->sprom.revision = 3; | 97 | iv->sprom.revision = 3; |
| 94 | 98 | ||
| 95 | if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0) | 99 | if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 || |
| 100 | nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) | ||
| 96 | str2eaddr(buf, iv->sprom.et0mac); | 101 | str2eaddr(buf, iv->sprom.et0mac); |
| 97 | if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0) | 102 | |
| 103 | if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 || | ||
| 104 | nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) | ||
| 98 | str2eaddr(buf, iv->sprom.et1mac); | 105 | str2eaddr(buf, iv->sprom.et1mac); |
| 99 | if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) | 106 | |
| 100 | iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10); | 107 | if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 || |
| 101 | if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) | 108 | nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) |
| 102 | iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10); | 109 | iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0); |
| 103 | if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0) | 110 | |
| 111 | if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 || | ||
| 112 | nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) | ||
| 113 | iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0); | ||
| 114 | |||
| 115 | if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 || | ||
| 116 | nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0) | ||
| 104 | iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); | 117 | iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); |
| 105 | if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0) | 118 | |
| 119 | if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 || | ||
| 120 | nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0) | ||
| 106 | iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); | 121 | iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); |
| 107 | 122 | ||
| 108 | return 0; | 123 | return 0; |
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index f1cf38943497..483ffea9ecb1 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h | |||
| @@ -50,7 +50,7 @@ | |||
| 50 | #define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00) | 50 | #define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00) |
| 51 | #define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00) | 51 | #define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00) |
| 52 | 52 | ||
| 53 | #define AR7_RESET_PEREPHERIAL 0x0 | 53 | #define AR7_RESET_PERIPHERAL 0x0 |
| 54 | #define AR7_RESET_SOFTWARE 0x4 | 54 | #define AR7_RESET_SOFTWARE 0x4 |
| 55 | #define AR7_RESET_STATUS 0x8 | 55 | #define AR7_RESET_STATUS 0x8 |
| 56 | 56 | ||
| @@ -128,7 +128,7 @@ static inline int ar7_has_high_cpmac(void) | |||
| 128 | static inline void ar7_device_enable(u32 bit) | 128 | static inline void ar7_device_enable(u32 bit) |
| 129 | { | 129 | { |
| 130 | void *reset_reg = | 130 | void *reset_reg = |
| 131 | (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); | 131 | (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL); |
| 132 | writel(readl(reset_reg) | (1 << bit), reset_reg); | 132 | writel(readl(reset_reg) | (1 << bit), reset_reg); |
| 133 | msleep(20); | 133 | msleep(20); |
| 134 | } | 134 | } |
| @@ -136,7 +136,7 @@ static inline void ar7_device_enable(u32 bit) | |||
| 136 | static inline void ar7_device_disable(u32 bit) | 136 | static inline void ar7_device_disable(u32 bit) |
| 137 | { | 137 | { |
| 138 | void *reset_reg = | 138 | void *reset_reg = |
| 139 | (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); | 139 | (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL); |
| 140 | writel(readl(reset_reg) & ~(1 << bit), reset_reg); | 140 | writel(readl(reset_reg) & ~(1 << bit), reset_reg); |
| 141 | msleep(20); | 141 | msleep(20); |
| 142 | } | 142 | } |
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h index 73f9b162c970..abc317c0372e 100644 --- a/arch/mips/include/asm/mach-ar7/gpio.h +++ b/arch/mips/include/asm/mach-ar7/gpio.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #define AR7_GPIO_MAX 32 | 24 | #define AR7_GPIO_MAX 32 |
| 25 | #define NR_BUILTIN_GPIO AR7_GPIO_MAX | 25 | #define NR_BUILTIN_GPIO AR7_GPIO_MAX |
| 26 | 26 | ||
| 27 | #define gpio_to_irq(gpio) NULL | 27 | #define gpio_to_irq(gpio) -1 |
| 28 | 28 | ||
| 29 | #define gpio_get_value __gpio_get_value | 29 | #define gpio_get_value __gpio_get_value |
| 30 | #define gpio_set_value __gpio_set_value | 30 | #define gpio_set_value __gpio_set_value |
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h index e76941db2312..a6976619160a 100644 --- a/arch/mips/include/asm/mach-au1x00/au1000.h +++ b/arch/mips/include/asm/mach-au1x00/au1000.h | |||
| @@ -188,7 +188,8 @@ extern unsigned long get_au1x00_uart_baud_base(void); | |||
| 188 | extern unsigned long au1xxx_calc_clock(void); | 188 | extern unsigned long au1xxx_calc_clock(void); |
| 189 | 189 | ||
| 190 | /* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */ | 190 | /* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */ |
| 191 | void au1xxx_save_and_sleep(void); | 191 | void alchemy_sleep_au1000(void); |
| 192 | void alchemy_sleep_au1550(void); | ||
| 192 | void au_sleep(void); | 193 | void au_sleep(void); |
| 193 | 194 | ||
| 194 | 195 | ||
diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h new file mode 100644 index 000000000000..0d8cc146f7a4 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005, Broadcom Corporation | ||
| 3 | * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License as published by the | ||
| 7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 8 | * option) any later version. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __NVRAM_H | ||
| 12 | #define __NVRAM_H | ||
| 13 | |||
| 14 | #include <linux/types.h> | ||
| 15 | |||
| 16 | struct nvram_header { | ||
| 17 | u32 magic; | ||
| 18 | u32 len; | ||
| 19 | u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */ | ||
| 20 | u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */ | ||
| 21 | u32 config_ncdl; /* ncdl values for memc */ | ||
| 22 | }; | ||
| 23 | |||
| 24 | #define NVRAM_HEADER 0x48534C46 /* 'FLSH' */ | ||
| 25 | #define NVRAM_VERSION 1 | ||
| 26 | #define NVRAM_HEADER_SIZE 20 | ||
| 27 | #define NVRAM_SPACE 0x8000 | ||
| 28 | |||
| 29 | #define FLASH_MIN 0x00020000 /* Minimum flash size */ | ||
| 30 | |||
| 31 | #define NVRAM_MAX_VALUE_LEN 255 | ||
| 32 | #define NVRAM_MAX_PARAM_LEN 64 | ||
| 33 | |||
| 34 | extern int nvram_getenv(char *name, char *val, size_t val_len); | ||
| 35 | |||
| 36 | #endif | ||
diff --git a/arch/mips/include/asm/mach-bcm63xx/gpio.h b/arch/mips/include/asm/mach-bcm63xx/gpio.h index 7cda8c0a3979..1eb534de8e3b 100644 --- a/arch/mips/include/asm/mach-bcm63xx/gpio.h +++ b/arch/mips/include/asm/mach-bcm63xx/gpio.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <bcm63xx_gpio.h> | 4 | #include <bcm63xx_gpio.h> |
| 5 | 5 | ||
| 6 | #define gpio_to_irq(gpio) NULL | 6 | #define gpio_to_irq(gpio) -1 |
| 7 | 7 | ||
| 8 | #define gpio_get_value __gpio_get_value | 8 | #define gpio_get_value __gpio_get_value |
| 9 | #define gpio_set_value __gpio_set_value | 9 | #define gpio_set_value __gpio_set_value |
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index e9e64e0ff7aa..5a84a1f11231 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Code for replacing ftrace calls with jumps. | 2 | * Code for replacing ftrace calls with jumps. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> | 4 | * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> |
| 5 | * Copyright (C) 2009 DSLab, Lanzhou University, China | 5 | * Copyright (C) 2009, 2010 DSLab, Lanzhou University, China |
| 6 | * Author: Wu Zhangjin <wuzhangjin@gmail.com> | 6 | * Author: Wu Zhangjin <wuzhangjin@gmail.com> |
| 7 | * | 7 | * |
| 8 | * Thanks goes to Steven Rostedt for writing the original x86 version. | 8 | * Thanks goes to Steven Rostedt for writing the original x86 version. |
| @@ -12,18 +12,62 @@ | |||
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/ftrace.h> | 13 | #include <linux/ftrace.h> |
| 14 | 14 | ||
| 15 | #include <asm/cacheflush.h> | ||
| 16 | #include <asm/asm.h> | 15 | #include <asm/asm.h> |
| 17 | #include <asm/asm-offsets.h> | 16 | #include <asm/asm-offsets.h> |
| 17 | #include <asm/cacheflush.h> | ||
| 18 | #include <asm/uasm.h> | ||
| 19 | |||
| 20 | /* | ||
| 21 | * If the Instruction Pointer is in module space (0xc0000000), return true; | ||
| 22 | * otherwise, it is in kernel space (0x80000000), return false. | ||
| 23 | * | ||
| 24 | * FIXME: This will not work when the kernel space and module space are the | ||
| 25 | * same. If they are the same, we need to modify scripts/recordmcount.pl, | ||
| 26 | * ftrace_make_nop/call() and the other related parts to ensure the | ||
| 27 | * enabling/disabling of the calling site to _mcount is right for both kernel | ||
| 28 | * and module. | ||
| 29 | */ | ||
| 30 | |||
| 31 | static inline int in_module(unsigned long ip) | ||
| 32 | { | ||
| 33 | return ip & 0x40000000; | ||
| 34 | } | ||
| 18 | 35 | ||
| 19 | #ifdef CONFIG_DYNAMIC_FTRACE | 36 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 20 | 37 | ||
| 21 | #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ | 38 | #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ |
| 22 | #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ | 39 | #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ |
| 23 | #define jump_insn_encode(op_code, addr) \ | ||
| 24 | ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK))) | ||
| 25 | 40 | ||
| 26 | static unsigned int ftrace_nop = 0x00000000; | 41 | #define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */ |
| 42 | #define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */ | ||
| 43 | #define INSN_NOP 0x00000000 /* nop */ | ||
| 44 | #define INSN_JAL(addr) \ | ||
| 45 | ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK))) | ||
| 46 | |||
| 47 | static unsigned int insn_jal_ftrace_caller __read_mostly; | ||
| 48 | static unsigned int insn_lui_v1_hi16_mcount __read_mostly; | ||
| 49 | static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly; | ||
| 50 | |||
| 51 | static inline void ftrace_dyn_arch_init_insns(void) | ||
| 52 | { | ||
| 53 | u32 *buf; | ||
| 54 | unsigned int v1; | ||
| 55 | |||
| 56 | /* lui v1, hi16_mcount */ | ||
| 57 | v1 = 3; | ||
| 58 | buf = (u32 *)&insn_lui_v1_hi16_mcount; | ||
| 59 | UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR); | ||
| 60 | |||
| 61 | /* jal (ftrace_caller + 8), jump over the first two instruction */ | ||
| 62 | buf = (u32 *)&insn_jal_ftrace_caller; | ||
| 63 | uasm_i_jal(&buf, (FTRACE_ADDR + 8)); | ||
| 64 | |||
| 65 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 66 | /* j ftrace_graph_caller */ | ||
| 67 | buf = (u32 *)&insn_j_ftrace_graph_caller; | ||
| 68 | uasm_i_j(&buf, (unsigned long)ftrace_graph_caller); | ||
| 69 | #endif | ||
| 70 | } | ||
| 27 | 71 | ||
| 28 | static int ftrace_modify_code(unsigned long ip, unsigned int new_code) | 72 | static int ftrace_modify_code(unsigned long ip, unsigned int new_code) |
| 29 | { | 73 | { |
| @@ -40,67 +84,56 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) | |||
| 40 | return 0; | 84 | return 0; |
| 41 | } | 85 | } |
| 42 | 86 | ||
| 43 | static int lui_v1; | ||
| 44 | static int jal_mcount; | ||
| 45 | |||
| 46 | int ftrace_make_nop(struct module *mod, | 87 | int ftrace_make_nop(struct module *mod, |
| 47 | struct dyn_ftrace *rec, unsigned long addr) | 88 | struct dyn_ftrace *rec, unsigned long addr) |
| 48 | { | 89 | { |
| 49 | unsigned int new; | 90 | unsigned int new; |
| 50 | int faulted; | ||
| 51 | unsigned long ip = rec->ip; | 91 | unsigned long ip = rec->ip; |
| 52 | 92 | ||
| 53 | /* We have compiled module with -mlong-calls, but compiled the kernel | 93 | /* |
| 54 | * without it, we need to cope with them respectively. */ | 94 | * We have compiled module with -mlong-calls, but compiled the kernel |
| 55 | if (ip & 0x40000000) { | 95 | * without it, we need to cope with them respectively. |
| 56 | /* record it for ftrace_make_call */ | 96 | */ |
| 57 | if (lui_v1 == 0) { | 97 | if (in_module(ip)) { |
| 58 | /* lui_v1 = *(unsigned int *)ip; */ | 98 | #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) |
| 59 | safe_load_code(lui_v1, ip, faulted); | 99 | /* |
| 60 | 100 | * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) | |
| 61 | if (unlikely(faulted)) | 101 | * addiu v1, v1, low_16bit_of_mcount |
| 62 | return -EFAULT; | 102 | * move at, ra |
| 63 | } | 103 | * move $12, ra_address |
| 64 | 104 | * jalr v1 | |
| 65 | /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) | 105 | * sub sp, sp, 8 |
| 106 | * 1: offset = 5 instructions | ||
| 107 | */ | ||
| 108 | new = INSN_B_1F_5; | ||
| 109 | #else | ||
| 110 | /* | ||
| 111 | * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) | ||
| 66 | * addiu v1, v1, low_16bit_of_mcount | 112 | * addiu v1, v1, low_16bit_of_mcount |
| 67 | * move at, ra | 113 | * move at, ra |
| 68 | * jalr v1 | 114 | * jalr v1 |
| 69 | * nop | 115 | * nop | move $12, ra_address | sub sp, sp, 8 |
| 70 | * 1f: (ip + 12) | 116 | * 1: offset = 4 instructions |
| 71 | */ | 117 | */ |
| 72 | new = 0x10000004; | 118 | new = INSN_B_1F_4; |
| 119 | #endif | ||
| 73 | } else { | 120 | } else { |
| 74 | /* record/calculate it for ftrace_make_call */ | 121 | /* |
| 75 | if (jal_mcount == 0) { | 122 | * move at, ra |
| 76 | /* We can record it directly like this: | 123 | * jal _mcount --> nop |
| 77 | * jal_mcount = *(unsigned int *)ip; | ||
| 78 | * Herein, jump over the first two nop instructions */ | ||
| 79 | jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8)); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* move at, ra | ||
| 83 | * jalr v1 --> nop | ||
| 84 | */ | 124 | */ |
| 85 | new = ftrace_nop; | 125 | new = INSN_NOP; |
| 86 | } | 126 | } |
| 87 | return ftrace_modify_code(ip, new); | 127 | return ftrace_modify_code(ip, new); |
| 88 | } | 128 | } |
| 89 | 129 | ||
| 90 | static int modified; /* initialized as 0 by default */ | ||
| 91 | |||
| 92 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 130 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
| 93 | { | 131 | { |
| 94 | unsigned int new; | 132 | unsigned int new; |
| 95 | unsigned long ip = rec->ip; | 133 | unsigned long ip = rec->ip; |
| 96 | 134 | ||
| 97 | /* We just need to remove the "b ftrace_stub" at the fist time! */ | ||
| 98 | if (modified == 0) { | ||
| 99 | modified = 1; | ||
| 100 | ftrace_modify_code(addr, ftrace_nop); | ||
| 101 | } | ||
| 102 | /* ip, module: 0xc0000000, kernel: 0x80000000 */ | 135 | /* ip, module: 0xc0000000, kernel: 0x80000000 */ |
| 103 | new = (ip & 0x40000000) ? lui_v1 : jal_mcount; | 136 | new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; |
| 104 | 137 | ||
| 105 | return ftrace_modify_code(ip, new); | 138 | return ftrace_modify_code(ip, new); |
| 106 | } | 139 | } |
| @@ -111,44 +144,48 @@ int ftrace_update_ftrace_func(ftrace_func_t func) | |||
| 111 | { | 144 | { |
| 112 | unsigned int new; | 145 | unsigned int new; |
| 113 | 146 | ||
| 114 | new = jump_insn_encode(JAL, (unsigned long)func); | 147 | new = INSN_JAL((unsigned long)func); |
| 115 | 148 | ||
| 116 | return ftrace_modify_code(FTRACE_CALL_IP, new); | 149 | return ftrace_modify_code(FTRACE_CALL_IP, new); |
| 117 | } | 150 | } |
| 118 | 151 | ||
| 119 | int __init ftrace_dyn_arch_init(void *data) | 152 | int __init ftrace_dyn_arch_init(void *data) |
| 120 | { | 153 | { |
| 154 | /* Encode the instructions when booting */ | ||
| 155 | ftrace_dyn_arch_init_insns(); | ||
| 156 | |||
| 157 | /* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */ | ||
| 158 | ftrace_modify_code(MCOUNT_ADDR, INSN_NOP); | ||
| 159 | |||
| 121 | /* The return code is retured via data */ | 160 | /* The return code is retured via data */ |
| 122 | *(unsigned long *)data = 0; | 161 | *(unsigned long *)data = 0; |
| 123 | 162 | ||
| 124 | return 0; | 163 | return 0; |
| 125 | } | 164 | } |
| 126 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 165 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
| 127 | 166 | ||
| 128 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 167 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 129 | 168 | ||
| 130 | #ifdef CONFIG_DYNAMIC_FTRACE | 169 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 131 | 170 | ||
| 132 | extern void ftrace_graph_call(void); | 171 | extern void ftrace_graph_call(void); |
| 133 | #define JMP 0x08000000 /* jump to target directly */ | ||
| 134 | #define CALL_FTRACE_GRAPH_CALLER \ | ||
| 135 | jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller)) | ||
| 136 | #define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call)) | 172 | #define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call)) |
| 137 | 173 | ||
| 138 | int ftrace_enable_ftrace_graph_caller(void) | 174 | int ftrace_enable_ftrace_graph_caller(void) |
| 139 | { | 175 | { |
| 140 | return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, | 176 | return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, |
| 141 | CALL_FTRACE_GRAPH_CALLER); | 177 | insn_j_ftrace_graph_caller); |
| 142 | } | 178 | } |
| 143 | 179 | ||
| 144 | int ftrace_disable_ftrace_graph_caller(void) | 180 | int ftrace_disable_ftrace_graph_caller(void) |
| 145 | { | 181 | { |
| 146 | return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop); | 182 | return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, INSN_NOP); |
| 147 | } | 183 | } |
| 148 | 184 | ||
| 149 | #endif /* !CONFIG_DYNAMIC_FTRACE */ | 185 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
| 150 | 186 | ||
| 151 | #ifndef KBUILD_MCOUNT_RA_ADDRESS | 187 | #ifndef KBUILD_MCOUNT_RA_ADDRESS |
| 188 | |||
| 152 | #define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ | 189 | #define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ |
| 153 | #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ | 190 | #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ |
| 154 | #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ | 191 | #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ |
| @@ -162,17 +199,17 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, | |||
| 162 | unsigned int code; | 199 | unsigned int code; |
| 163 | int faulted; | 200 | int faulted; |
| 164 | 201 | ||
| 165 | /* in module or kernel? */ | 202 | /* |
| 166 | if (self_addr & 0x40000000) { | 203 | * For module, move the ip from calling site of mcount to the |
| 167 | /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */ | 204 | * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for |
| 168 | ip = self_addr - 20; | 205 | * kernel, move to the instruction "move ra, at"(offset is 12) |
| 169 | } else { | 206 | */ |
| 170 | /* kernel: move to the instruction "move ra, at" */ | 207 | ip = self_addr - (in_module(self_addr) ? 20 : 12); |
| 171 | ip = self_addr - 12; | ||
| 172 | } | ||
| 173 | 208 | ||
| 174 | /* search the text until finding the non-store instruction or "s{d,w} | 209 | /* |
| 175 | * ra, offset(sp)" instruction */ | 210 | * search the text until finding the non-store instruction or "s{d,w} |
| 211 | * ra, offset(sp)" instruction | ||
| 212 | */ | ||
| 176 | do { | 213 | do { |
| 177 | ip -= 4; | 214 | ip -= 4; |
| 178 | 215 | ||
| @@ -181,10 +218,11 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, | |||
| 181 | 218 | ||
| 182 | if (unlikely(faulted)) | 219 | if (unlikely(faulted)) |
| 183 | return 0; | 220 | return 0; |
| 184 | 221 | /* | |
| 185 | /* If we hit the non-store instruction before finding where the | 222 | * If we hit the non-store instruction before finding where the |
| 186 | * ra is stored, then this is a leaf function and it does not | 223 | * ra is stored, then this is a leaf function and it does not |
| 187 | * store the ra on the stack. */ | 224 | * store the ra on the stack |
| 225 | */ | ||
| 188 | if ((code & S_R_SP) != S_R_SP) | 226 | if ((code & S_R_SP) != S_R_SP) |
| 189 | return parent_addr; | 227 | return parent_addr; |
| 190 | 228 | ||
| @@ -202,7 +240,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, | |||
| 202 | return 0; | 240 | return 0; |
| 203 | } | 241 | } |
| 204 | 242 | ||
| 205 | #endif | 243 | #endif /* !KBUILD_MCOUNT_RA_ADDRESS */ |
| 206 | 244 | ||
| 207 | /* | 245 | /* |
| 208 | * Hook the return address and push it in the stack of return addrs | 246 | * Hook the return address and push it in the stack of return addrs |
| @@ -220,7 +258,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, | |||
| 220 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | 258 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) |
| 221 | return; | 259 | return; |
| 222 | 260 | ||
| 223 | /* "parent" is the stack address saved the return address of the caller | 261 | /* |
| 262 | * "parent" is the stack address saved the return address of the caller | ||
| 224 | * of _mcount. | 263 | * of _mcount. |
| 225 | * | 264 | * |
| 226 | * if the gcc < 4.5, a leaf function does not save the return address | 265 | * if the gcc < 4.5, a leaf function does not save the return address |
| @@ -242,10 +281,11 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, | |||
| 242 | goto out; | 281 | goto out; |
| 243 | #ifndef KBUILD_MCOUNT_RA_ADDRESS | 282 | #ifndef KBUILD_MCOUNT_RA_ADDRESS |
| 244 | parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, | 283 | parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, |
| 245 | (unsigned long)parent, | 284 | (unsigned long)parent, fp); |
| 246 | fp); | 285 | /* |
| 247 | /* If fails when getting the stack address of the non-leaf function's | 286 | * If fails when getting the stack address of the non-leaf function's |
| 248 | * ra, stop function graph tracer and return */ | 287 | * ra, stop function graph tracer and return |
| 288 | */ | ||
| 249 | if (parent == 0) | 289 | if (parent == 0) |
| 250 | goto out; | 290 | goto out; |
| 251 | #endif | 291 | #endif |
| @@ -272,4 +312,4 @@ out: | |||
| 272 | ftrace_graph_stop(); | 312 | ftrace_graph_stop(); |
| 273 | WARN_ON(1); | 313 | WARN_ON(1); |
| 274 | } | 314 | } |
| 275 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 315 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 6851fc97a511..6bfcb7a00ec6 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * more details. | 6 | * more details. |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China | 8 | * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China |
| 9 | * Copyright (C) 2010 DSLab, Lanzhou University, China | ||
| 9 | * Author: Wu Zhangjin <wuzhangjin@gmail.com> | 10 | * Author: Wu Zhangjin <wuzhangjin@gmail.com> |
| 10 | */ | 11 | */ |
| 11 | 12 | ||
| @@ -45,8 +46,6 @@ | |||
| 45 | PTR_L a5, PT_R9(sp) | 46 | PTR_L a5, PT_R9(sp) |
| 46 | PTR_L a6, PT_R10(sp) | 47 | PTR_L a6, PT_R10(sp) |
| 47 | PTR_L a7, PT_R11(sp) | 48 | PTR_L a7, PT_R11(sp) |
| 48 | #endif | ||
| 49 | #ifdef CONFIG_64BIT | ||
| 50 | PTR_ADDIU sp, PT_SIZE | 49 | PTR_ADDIU sp, PT_SIZE |
| 51 | #else | 50 | #else |
| 52 | PTR_ADDIU sp, (PT_SIZE + 8) | 51 | PTR_ADDIU sp, (PT_SIZE + 8) |
| @@ -58,6 +57,12 @@ | |||
| 58 | move ra, AT | 57 | move ra, AT |
| 59 | .endm | 58 | .endm |
| 60 | 59 | ||
| 60 | /* | ||
| 61 | * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass | ||
| 62 | * the location of the parent's return address. | ||
| 63 | */ | ||
| 64 | #define MCOUNT_RA_ADDRESS_REG $12 | ||
| 65 | |||
| 61 | #ifdef CONFIG_DYNAMIC_FTRACE | 66 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 62 | 67 | ||
| 63 | NESTED(ftrace_caller, PT_SIZE, ra) | 68 | NESTED(ftrace_caller, PT_SIZE, ra) |
| @@ -71,14 +76,14 @@ _mcount: | |||
| 71 | 76 | ||
| 72 | MCOUNT_SAVE_REGS | 77 | MCOUNT_SAVE_REGS |
| 73 | #ifdef KBUILD_MCOUNT_RA_ADDRESS | 78 | #ifdef KBUILD_MCOUNT_RA_ADDRESS |
| 74 | PTR_S t0, PT_R12(sp) /* t0 saved the location of the return address(at) by -mmcount-ra-address */ | 79 | PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) |
| 75 | #endif | 80 | #endif |
| 76 | 81 | ||
| 77 | move a0, ra /* arg1: next ip, selfaddr */ | 82 | move a0, ra /* arg1: self return address */ |
| 78 | .globl ftrace_call | 83 | .globl ftrace_call |
| 79 | ftrace_call: | 84 | ftrace_call: |
| 80 | nop /* a placeholder for the call to a real tracing function */ | 85 | nop /* a placeholder for the call to a real tracing function */ |
| 81 | move a1, AT /* arg2: the caller's next ip, parent */ | 86 | move a1, AT /* arg2: parent's return address */ |
| 82 | 87 | ||
| 83 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 88 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 84 | .globl ftrace_graph_call | 89 | .globl ftrace_graph_call |
| @@ -119,9 +124,9 @@ NESTED(_mcount, PT_SIZE, ra) | |||
| 119 | static_trace: | 124 | static_trace: |
| 120 | MCOUNT_SAVE_REGS | 125 | MCOUNT_SAVE_REGS |
| 121 | 126 | ||
| 122 | move a0, ra /* arg1: next ip, selfaddr */ | 127 | move a0, ra /* arg1: self return address */ |
| 123 | jalr t2 /* (1) call *ftrace_trace_function */ | 128 | jalr t2 /* (1) call *ftrace_trace_function */ |
| 124 | move a1, AT /* arg2: the caller's next ip, parent */ | 129 | move a1, AT /* arg2: parent's return address */ |
| 125 | 130 | ||
| 126 | MCOUNT_RESTORE_REGS | 131 | MCOUNT_RESTORE_REGS |
| 127 | .globl ftrace_stub | 132 | .globl ftrace_stub |
| @@ -134,28 +139,34 @@ ftrace_stub: | |||
| 134 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 139 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 135 | 140 | ||
| 136 | NESTED(ftrace_graph_caller, PT_SIZE, ra) | 141 | NESTED(ftrace_graph_caller, PT_SIZE, ra) |
| 137 | #ifdef CONFIG_DYNAMIC_FTRACE | 142 | #ifndef CONFIG_DYNAMIC_FTRACE |
| 138 | PTR_L a1, PT_R31(sp) /* load the original ra from the stack */ | ||
| 139 | #ifdef KBUILD_MCOUNT_RA_ADDRESS | ||
| 140 | PTR_L t0, PT_R12(sp) /* load the original t0 from the stack */ | ||
| 141 | #endif | ||
| 142 | #else | ||
| 143 | MCOUNT_SAVE_REGS | 143 | MCOUNT_SAVE_REGS |
| 144 | move a1, ra /* arg2: next ip, selfaddr */ | ||
| 145 | #endif | 144 | #endif |
| 146 | 145 | ||
| 146 | /* arg1: Get the location of the parent's return address */ | ||
| 147 | #ifdef KBUILD_MCOUNT_RA_ADDRESS | 147 | #ifdef KBUILD_MCOUNT_RA_ADDRESS |
| 148 | bnez t0, 1f /* non-leaf func: t0 saved the location of the return address */ | 148 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 149 | PTR_L a0, PT_R12(sp) | ||
| 150 | #else | ||
| 151 | move a0, MCOUNT_RA_ADDRESS_REG | ||
| 152 | #endif | ||
| 153 | bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ | ||
| 149 | nop | 154 | nop |
| 150 | PTR_LA t0, PT_R1(sp) /* leaf func: get the location of at(old ra) from our own stack */ | 155 | #endif |
| 151 | 1: move a0, t0 /* arg1: the location of the return address */ | 156 | PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ |
| 157 | 1: | ||
| 158 | |||
| 159 | /* arg2: Get self return address */ | ||
| 160 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 161 | PTR_L a1, PT_R31(sp) | ||
| 152 | #else | 162 | #else |
| 153 | PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */ | 163 | move a1, ra |
| 154 | #endif | 164 | #endif |
| 155 | jal prepare_ftrace_return | 165 | |
| 166 | /* arg3: Get frame pointer of current stack */ | ||
| 156 | #ifdef CONFIG_FRAME_POINTER | 167 | #ifdef CONFIG_FRAME_POINTER |
| 157 | move a2, fp /* arg3: frame pointer */ | 168 | move a2, fp |
| 158 | #else | 169 | #else /* ! CONFIG_FRAME_POINTER */ |
| 159 | #ifdef CONFIG_64BIT | 170 | #ifdef CONFIG_64BIT |
| 160 | PTR_LA a2, PT_SIZE(sp) | 171 | PTR_LA a2, PT_SIZE(sp) |
| 161 | #else | 172 | #else |
| @@ -163,6 +174,8 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) | |||
| 163 | #endif | 174 | #endif |
| 164 | #endif | 175 | #endif |
| 165 | 176 | ||
| 177 | jal prepare_ftrace_return | ||
| 178 | nop | ||
| 166 | MCOUNT_RESTORE_REGS | 179 | MCOUNT_RESTORE_REGS |
| 167 | RETURN_BACK | 180 | RETURN_BACK |
| 168 | END(ftrace_graph_caller) | 181 | END(ftrace_graph_caller) |
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index f5981c499109..2340f11dc29c 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * Copyright (C) 2005 Mips Technologies, Inc | 3 | * Copyright (C) 2005 Mips Technologies, Inc |
| 4 | */ | 4 | */ |
| 5 | #include <linux/cpu.h> | 5 | #include <linux/cpu.h> |
| 6 | #include <linux/cpuset.h> | ||
| 6 | #include <linux/cpumask.h> | 7 | #include <linux/cpumask.h> |
| 7 | #include <linux/delay.h> | 8 | #include <linux/delay.h> |
| 8 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| @@ -39,6 +40,21 @@ static inline struct task_struct *find_process_by_pid(pid_t pid) | |||
| 39 | return pid ? find_task_by_vpid(pid) : current; | 40 | return pid ? find_task_by_vpid(pid) : current; |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 43 | /* | ||
| 44 | * check the target process has a UID that matches the current process's | ||
| 45 | */ | ||
| 46 | static bool check_same_owner(struct task_struct *p) | ||
| 47 | { | ||
| 48 | const struct cred *cred = current_cred(), *pcred; | ||
| 49 | bool match; | ||
| 50 | |||
| 51 | rcu_read_lock(); | ||
| 52 | pcred = __task_cred(p); | ||
| 53 | match = (cred->euid == pcred->euid || | ||
| 54 | cred->euid == pcred->uid); | ||
| 55 | rcu_read_unlock(); | ||
| 56 | return match; | ||
| 57 | } | ||
| 42 | 58 | ||
| 43 | /* | 59 | /* |
| 44 | * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process | 60 | * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process |
| @@ -46,12 +62,10 @@ static inline struct task_struct *find_process_by_pid(pid_t pid) | |||
| 46 | asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, | 62 | asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, |
| 47 | unsigned long __user *user_mask_ptr) | 63 | unsigned long __user *user_mask_ptr) |
| 48 | { | 64 | { |
| 49 | cpumask_t new_mask; | 65 | cpumask_var_t cpus_allowed, new_mask, effective_mask; |
| 50 | cpumask_t effective_mask; | ||
| 51 | int retval; | ||
| 52 | struct task_struct *p; | ||
| 53 | struct thread_info *ti; | 66 | struct thread_info *ti; |
| 54 | uid_t euid; | 67 | struct task_struct *p; |
| 68 | int retval; | ||
| 55 | 69 | ||
| 56 | if (len < sizeof(new_mask)) | 70 | if (len < sizeof(new_mask)) |
| 57 | return -EINVAL; | 71 | return -EINVAL; |
| @@ -60,53 +74,74 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, | |||
| 60 | return -EFAULT; | 74 | return -EFAULT; |
| 61 | 75 | ||
| 62 | get_online_cpus(); | 76 | get_online_cpus(); |
| 63 | read_lock(&tasklist_lock); | 77 | rcu_read_lock(); |
| 64 | 78 | ||
| 65 | p = find_process_by_pid(pid); | 79 | p = find_process_by_pid(pid); |
| 66 | if (!p) { | 80 | if (!p) { |
| 67 | read_unlock(&tasklist_lock); | 81 | rcu_read_unlock(); |
| 68 | put_online_cpus(); | 82 | put_online_cpus(); |
| 69 | return -ESRCH; | 83 | return -ESRCH; |
| 70 | } | 84 | } |
| 71 | 85 | ||
| 72 | /* | 86 | /* Prevent p going away */ |
| 73 | * It is not safe to call set_cpus_allowed with the | ||
| 74 | * tasklist_lock held. We will bump the task_struct's | ||
| 75 | * usage count and drop tasklist_lock before invoking | ||
| 76 | * set_cpus_allowed. | ||
| 77 | */ | ||
| 78 | get_task_struct(p); | 87 | get_task_struct(p); |
| 88 | rcu_read_unlock(); | ||
| 79 | 89 | ||
| 80 | euid = current_euid(); | 90 | if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) { |
| 91 | retval = -ENOMEM; | ||
| 92 | goto out_put_task; | ||
| 93 | } | ||
| 94 | if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { | ||
| 95 | retval = -ENOMEM; | ||
| 96 | goto out_free_cpus_allowed; | ||
| 97 | } | ||
| 98 | if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) { | ||
| 99 | retval = -ENOMEM; | ||
| 100 | goto out_free_new_mask; | ||
| 101 | } | ||
| 81 | retval = -EPERM; | 102 | retval = -EPERM; |
| 82 | if (euid != p->cred->euid && euid != p->cred->uid && | 103 | if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) |
| 83 | !capable(CAP_SYS_NICE)) { | ||
| 84 | read_unlock(&tasklist_lock); | ||
| 85 | goto out_unlock; | 104 | goto out_unlock; |
| 86 | } | ||
| 87 | 105 | ||
| 88 | retval = security_task_setscheduler(p, 0, NULL); | 106 | retval = security_task_setscheduler(p, 0, NULL); |
| 89 | if (retval) | 107 | if (retval) |
| 90 | goto out_unlock; | 108 | goto out_unlock; |
| 91 | 109 | ||
| 92 | /* Record new user-specified CPU set for future reference */ | 110 | /* Record new user-specified CPU set for future reference */ |
| 93 | p->thread.user_cpus_allowed = new_mask; | 111 | cpumask_copy(&p->thread.user_cpus_allowed, new_mask); |
| 94 | |||
| 95 | /* Unlock the task list */ | ||
| 96 | read_unlock(&tasklist_lock); | ||
| 97 | 112 | ||
| 113 | again: | ||
| 98 | /* Compute new global allowed CPU set if necessary */ | 114 | /* Compute new global allowed CPU set if necessary */ |
| 99 | ti = task_thread_info(p); | 115 | ti = task_thread_info(p); |
| 100 | if (test_ti_thread_flag(ti, TIF_FPUBOUND) && | 116 | if (test_ti_thread_flag(ti, TIF_FPUBOUND) && |
| 101 | cpus_intersects(new_mask, mt_fpu_cpumask)) { | 117 | cpus_intersects(*new_mask, mt_fpu_cpumask)) { |
| 102 | cpus_and(effective_mask, new_mask, mt_fpu_cpumask); | 118 | cpus_and(*effective_mask, *new_mask, mt_fpu_cpumask); |
| 103 | retval = set_cpus_allowed_ptr(p, &effective_mask); | 119 | retval = set_cpus_allowed_ptr(p, effective_mask); |
| 104 | } else { | 120 | } else { |
| 121 | cpumask_copy(effective_mask, new_mask); | ||
| 105 | clear_ti_thread_flag(ti, TIF_FPUBOUND); | 122 | clear_ti_thread_flag(ti, TIF_FPUBOUND); |
| 106 | retval = set_cpus_allowed_ptr(p, &new_mask); | 123 | retval = set_cpus_allowed_ptr(p, new_mask); |
| 107 | } | 124 | } |
| 108 | 125 | ||
| 126 | if (!retval) { | ||
| 127 | cpuset_cpus_allowed(p, cpus_allowed); | ||
| 128 | if (!cpumask_subset(effective_mask, cpus_allowed)) { | ||
| 129 | /* | ||
| 130 | * We must have raced with a concurrent cpuset | ||
| 131 | * update. Just reset the cpus_allowed to the | ||
| 132 | * cpuset's cpus_allowed | ||
| 133 | */ | ||
| 134 | cpumask_copy(new_mask, cpus_allowed); | ||
| 135 | goto again; | ||
| 136 | } | ||
| 137 | } | ||
| 109 | out_unlock: | 138 | out_unlock: |
| 139 | free_cpumask_var(effective_mask); | ||
| 140 | out_free_new_mask: | ||
| 141 | free_cpumask_var(new_mask); | ||
| 142 | out_free_cpus_allowed: | ||
| 143 | free_cpumask_var(cpus_allowed); | ||
| 144 | out_put_task: | ||
| 110 | put_task_struct(p); | 145 | put_task_struct(p); |
| 111 | put_online_cpus(); | 146 | put_online_cpus(); |
| 112 | return retval; | 147 | return retval; |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8bdd6a663c7f..852780868fb4 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -976,7 +976,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 976 | 976 | ||
| 977 | case 2: | 977 | case 2: |
| 978 | raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); | 978 | raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); |
| 979 | break; | 979 | return; |
| 980 | 980 | ||
| 981 | case 3: | 981 | case 3: |
| 982 | break; | 982 | break; |
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 3df1967dea08..c97ca69b94e0 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig | |||
| @@ -23,6 +23,7 @@ config LEMOTE_FULOONG2E | |||
| 23 | select GENERIC_HARDIRQS_NO__DO_IRQ | 23 | select GENERIC_HARDIRQS_NO__DO_IRQ |
| 24 | select GENERIC_ISA_DMA_SUPPORT_BROKEN | 24 | select GENERIC_ISA_DMA_SUPPORT_BROKEN |
| 25 | select CPU_HAS_WB | 25 | select CPU_HAS_WB |
| 26 | select LOONGSON_MC146818 | ||
| 26 | help | 27 | help |
| 27 | Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and | 28 | Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and |
| 28 | an FPGA northbridge | 29 | an FPGA northbridge |
| @@ -51,6 +52,7 @@ config LEMOTE_MACH2F | |||
| 51 | select SYS_SUPPORTS_64BIT_KERNEL | 52 | select SYS_SUPPORTS_64BIT_KERNEL |
| 52 | select SYS_SUPPORTS_HIGHMEM | 53 | select SYS_SUPPORTS_HIGHMEM |
| 53 | select SYS_SUPPORTS_LITTLE_ENDIAN | 54 | select SYS_SUPPORTS_LITTLE_ENDIAN |
| 55 | select LOONGSON_MC146818 | ||
| 54 | help | 56 | help |
| 55 | Lemote Loongson 2F family machines utilize the 2F revision of | 57 | Lemote Loongson 2F family machines utilize the 2F revision of |
| 56 | Loongson processor and the AMD CS5536 south bridge. | 58 | Loongson processor and the AMD CS5536 south bridge. |
| @@ -83,3 +85,7 @@ config LOONGSON_UART_BASE | |||
| 83 | bool | 85 | bool |
| 84 | default y | 86 | default y |
| 85 | depends on EARLY_PRINTK || SERIAL_8250 | 87 | depends on EARLY_PRINTK || SERIAL_8250 |
| 88 | |||
| 89 | config LOONGSON_MC146818 | ||
| 90 | bool | ||
| 91 | default n | ||
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index cdd2e812ba1a..e526488df655 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile | |||
| @@ -12,6 +12,7 @@ obj-$(CONFIG_GENERIC_GPIO) += gpio.o | |||
| 12 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 12 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
| 13 | obj-$(CONFIG_SERIAL_8250) += serial.o | 13 | obj-$(CONFIG_SERIAL_8250) += serial.o |
| 14 | obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o | 14 | obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o |
| 15 | obj-$(CONFIG_LOONGSON_MC146818) += rtc.o | ||
| 15 | 16 | ||
| 16 | # | 17 | # |
| 17 | # Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure | 18 | # Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure |
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/arch/mips/loongson/common/cs5536/cs5536_ehci.c index eaf8b86e3318..5b5cbba699b3 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_ehci.c +++ b/arch/mips/loongson/common/cs5536/cs5536_ehci.c | |||
| @@ -49,6 +49,8 @@ void pci_ehci_write_reg(int reg, u32 value) | |||
| 49 | lo |= SOFT_BAR_EHCI_FLAG; | 49 | lo |= SOFT_BAR_EHCI_FLAG; |
| 50 | _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); | 50 | _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); |
| 51 | } else if ((value & 0x01) == 0x00) { | 51 | } else if ((value & 0x01) == 0x00) { |
| 52 | _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo); | ||
| 53 | lo = value; | ||
| 52 | _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); | 54 | _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); |
| 53 | 55 | ||
| 54 | value &= 0xfffffff0; | 56 | value &= 0xfffffff0; |
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson/common/cs5536/cs5536_ide.c index 9a96b5664c78..681d1291a2c7 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_ide.c +++ b/arch/mips/loongson/common/cs5536/cs5536_ide.c | |||
| @@ -51,6 +51,7 @@ void pci_ide_write_reg(int reg, u32 value) | |||
| 51 | lo |= SOFT_BAR_IDE_FLAG; | 51 | lo |= SOFT_BAR_IDE_FLAG; |
| 52 | _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); | 52 | _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); |
| 53 | } else if (value & 0x01) { | 53 | } else if (value & 0x01) { |
| 54 | _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo); | ||
| 54 | lo = (value & 0xfffffff0) | 0x1; | 55 | lo = (value & 0xfffffff0) | 0x1; |
| 55 | _wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo); | 56 | _wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo); |
| 56 | 57 | ||
| @@ -65,19 +66,30 @@ void pci_ide_write_reg(int reg, u32 value) | |||
| 65 | _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo); | 66 | _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo); |
| 66 | lo |= 0x01; | 67 | lo |= 0x01; |
| 67 | _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo); | 68 | _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo); |
| 68 | } else | 69 | } else { |
| 70 | _rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo); | ||
| 71 | lo = value; | ||
| 69 | _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo); | 72 | _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo); |
| 73 | } | ||
| 70 | break; | 74 | break; |
| 71 | case PCI_IDE_DTC_REG: | 75 | case PCI_IDE_DTC_REG: |
| 76 | _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo); | ||
| 77 | lo = value; | ||
| 72 | _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo); | 78 | _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo); |
| 73 | break; | 79 | break; |
| 74 | case PCI_IDE_CAST_REG: | 80 | case PCI_IDE_CAST_REG: |
| 81 | _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo); | ||
| 82 | lo = value; | ||
| 75 | _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo); | 83 | _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo); |
| 76 | break; | 84 | break; |
| 77 | case PCI_IDE_ETC_REG: | 85 | case PCI_IDE_ETC_REG: |
| 86 | _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo); | ||
| 87 | lo = value; | ||
| 78 | _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo); | 88 | _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo); |
| 79 | break; | 89 | break; |
| 80 | case PCI_IDE_PM_REG: | 90 | case PCI_IDE_PM_REG: |
| 91 | _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo); | ||
| 92 | lo = value; | ||
| 81 | _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo); | 93 | _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo); |
| 82 | break; | 94 | break; |
| 83 | default: | 95 | default: |
| @@ -167,6 +179,7 @@ u32 pci_ide_read_reg(int reg) | |||
| 167 | case PCI_IDE_ETC_REG: | 179 | case PCI_IDE_ETC_REG: |
| 168 | _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo); | 180 | _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo); |
| 169 | conf_data = lo; | 181 | conf_data = lo; |
| 182 | break; | ||
| 170 | case PCI_IDE_PM_REG: | 183 | case PCI_IDE_PM_REG: |
| 171 | _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo); | 184 | _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo); |
| 172 | conf_data = lo; | 185 | conf_data = lo; |
diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c index f5c0818831b2..4d9f65abeaff 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_isa.c +++ b/arch/mips/loongson/common/cs5536/cs5536_isa.c | |||
| @@ -61,7 +61,7 @@ static void divil_lbar_enable(void) | |||
| 61 | for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { | 61 | for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { |
| 62 | _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); | 62 | _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); |
| 63 | hi |= 0x01; | 63 | hi |= 0x01; |
| 64 | _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); | 64 | _wrmsr(DIVIL_MSR_REG(offset), hi, lo); |
| 65 | } | 65 | } |
| 66 | } | 66 | } |
| 67 | 67 | ||
| @@ -76,7 +76,7 @@ static void divil_lbar_disable(void) | |||
| 76 | for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { | 76 | for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { |
| 77 | _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); | 77 | _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); |
| 78 | hi &= ~0x01; | 78 | hi &= ~0x01; |
| 79 | _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); | 79 | _wrmsr(DIVIL_MSR_REG(offset), hi, lo); |
| 80 | } | 80 | } |
| 81 | } | 81 | } |
| 82 | 82 | ||
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson/common/cs5536/cs5536_ohci.c index db5900aadd6b..bdedf512baf7 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_ohci.c +++ b/arch/mips/loongson/common/cs5536/cs5536_ohci.c | |||
| @@ -49,6 +49,8 @@ void pci_ohci_write_reg(int reg, u32 value) | |||
| 49 | lo |= SOFT_BAR_OHCI_FLAG; | 49 | lo |= SOFT_BAR_OHCI_FLAG; |
| 50 | _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); | 50 | _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); |
| 51 | } else if ((value & 0x01) == 0x00) { | 51 | } else if ((value & 0x01) == 0x00) { |
| 52 | _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo); | ||
| 53 | lo = value; | ||
| 52 | _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); | 54 | _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); |
| 53 | 55 | ||
| 54 | value &= 0xfffffff0; | 56 | value &= 0xfffffff0; |
diff --git a/arch/mips/loongson/common/rtc.c b/arch/mips/loongson/common/rtc.c new file mode 100644 index 000000000000..a90d87c01555 --- /dev/null +++ b/arch/mips/loongson/common/rtc.c | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* | ||
| 2 | * Lemote Fuloong platform support | ||
| 3 | * | ||
| 4 | * Copyright(c) 2010 Arnaud Patard <apatard@mandriva.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/mc146818rtc.h> | ||
| 16 | |||
| 17 | struct resource loongson_rtc_resources[] = { | ||
| 18 | { | ||
| 19 | .start = RTC_PORT(0), | ||
| 20 | .end = RTC_PORT(1), | ||
| 21 | .flags = IORESOURCE_IO, | ||
| 22 | }, { | ||
| 23 | .start = RTC_IRQ, | ||
| 24 | .end = RTC_IRQ, | ||
| 25 | .flags = IORESOURCE_IRQ, | ||
| 26 | } | ||
| 27 | }; | ||
| 28 | |||
| 29 | static struct platform_device loongson_rtc_device = { | ||
| 30 | .name = "rtc_cmos", | ||
| 31 | .id = -1, | ||
| 32 | .resource = loongson_rtc_resources, | ||
| 33 | .num_resources = ARRAY_SIZE(loongson_rtc_resources), | ||
| 34 | }; | ||
| 35 | |||
| 36 | |||
| 37 | static int __init loongson_rtc_platform_init(void) | ||
| 38 | { | ||
| 39 | platform_device_register(&loongson_rtc_device); | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | device_initcall(loongson_rtc_platform_init); | ||
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index d9ae1dbabda7..b90974246e5b 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c | |||
| @@ -78,6 +78,7 @@ ieee754dp ieee754dp_abs(ieee754dp x) | |||
| 78 | DPSIGN(x) = 0; | 78 | DPSIGN(x) = 0; |
| 79 | 79 | ||
| 80 | if (xc == IEEE754_CLASS_SNAN) { | 80 | if (xc == IEEE754_CLASS_SNAN) { |
| 81 | SETCX(IEEE754_INVALID_OPERATION); | ||
| 81 | return ieee754dp_nanxcpt(ieee754dp_indef(), "abs"); | 82 | return ieee754dp_nanxcpt(ieee754dp_indef(), "abs"); |
| 82 | } | 83 | } |
| 83 | 84 | ||
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index 3175477d36f6..2fd53c920e99 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c | |||
| @@ -78,6 +78,7 @@ ieee754sp ieee754sp_abs(ieee754sp x) | |||
| 78 | SPSIGN(x) = 0; | 78 | SPSIGN(x) = 0; |
| 79 | 79 | ||
| 80 | if (xc == IEEE754_CLASS_SNAN) { | 80 | if (xc == IEEE754_CLASS_SNAN) { |
| 81 | SETCX(IEEE754_INVALID_OPERATION); | ||
| 81 | return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); | 82 | return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); |
| 82 | } | 83 | } |
| 83 | 84 | ||
diff --git a/arch/mips/oprofile/op_model_loongson2.c b/arch/mips/oprofile/op_model_loongson2.c index d0d24e047676..60d3ea602118 100644 --- a/arch/mips/oprofile/op_model_loongson2.c +++ b/arch/mips/oprofile/op_model_loongson2.c | |||
| @@ -43,6 +43,12 @@ static struct loongson2_register_config { | |||
| 43 | static char *oprofid = "LoongsonPerf"; | 43 | static char *oprofid = "LoongsonPerf"; |
| 44 | static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id); | 44 | static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id); |
| 45 | 45 | ||
| 46 | static void reset_counters(void *arg) | ||
| 47 | { | ||
| 48 | write_c0_perfctrl(0); | ||
| 49 | write_c0_perfcnt(0); | ||
| 50 | } | ||
| 51 | |||
| 46 | static void loongson2_reg_setup(struct op_counter_config *cfg) | 52 | static void loongson2_reg_setup(struct op_counter_config *cfg) |
| 47 | { | 53 | { |
| 48 | unsigned int ctrl = 0; | 54 | unsigned int ctrl = 0; |
| @@ -139,7 +145,7 @@ static int __init loongson2_init(void) | |||
| 139 | 145 | ||
| 140 | static void loongson2_exit(void) | 146 | static void loongson2_exit(void) |
| 141 | { | 147 | { |
| 142 | write_c0_perfctrl(0); | 148 | reset_counters(NULL); |
| 143 | free_irq(LOONGSON2_PERFCNT_IRQ, oprofid); | 149 | free_irq(LOONGSON2_PERFCNT_IRQ, oprofid); |
| 144 | } | 150 | } |
| 145 | 151 | ||
