diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-05-30 20:01:50 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-05-30 20:01:50 -0400 |
| commit | ecca1a34befbb13fc23d9a2cc0d6b725c7727fb2 (patch) | |
| tree | 6539480b50258f30af799a6ab38529d7b2d7e538 | |
| parent | 3d00d4ff11686895925f46265f4a78dc78196c2e (diff) | |
| parent | 48936a08b85518c22a9467a8eaac35d43af54ab4 (diff) | |
Merge commit 'kumar/next' into next
Conflicts:
arch/powerpc/sysdev/fsl_msi.c
| -rw-r--r-- | arch/powerpc/Kconfig | 2 | ||||
| -rw-r--r-- | arch/powerpc/boot/dts/mpc8548cds.dts | 4 | ||||
| -rw-r--r-- | arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts | 15 | ||||
| -rw-r--r-- | arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts | 7 | ||||
| -rw-r--r-- | arch/powerpc/boot/dts/p1021mds.dts | 698 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/cputable.h | 1 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/kexec.h | 13 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/reg_booke.h | 33 | ||||
| -rw-r--r-- | arch/powerpc/kernel/Makefile | 8 | ||||
| -rw-r--r-- | arch/powerpc/kernel/cputable.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/crash.c | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/fsl_booke_entry_mapping.S | 237 | ||||
| -rw-r--r-- | arch/powerpc/kernel/head_fsl_booke.S | 200 | ||||
| -rw-r--r-- | arch/powerpc/kernel/misc_32.S | 17 | ||||
| -rw-r--r-- | arch/powerpc/kernel/swsusp_booke.S | 193 | ||||
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 88 | ||||
| -rw-r--r-- | arch/powerpc/platforms/85xx/mpc85xx_mds.c | 102 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 117 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 3 |
19 files changed, 1494 insertions, 250 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 66a315e06dce..328774bd41ee 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -351,7 +351,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE | |||
| 351 | 351 | ||
| 352 | config KEXEC | 352 | config KEXEC |
| 353 | bool "kexec system call (EXPERIMENTAL)" | 353 | bool "kexec system call (EXPERIMENTAL)" |
| 354 | depends on PPC_BOOK3S && EXPERIMENTAL | 354 | depends on (PPC_BOOK3S || (FSL_BOOKE && !SMP)) && EXPERIMENTAL |
| 355 | help | 355 | help |
| 356 | kexec is a system call that implements the ability to shutdown your | 356 | kexec is a system call that implements the ability to shutdown your |
| 357 | current kernel, and to start another kernel. It is like a reboot | 357 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts index 4173af387c63..0f5262452682 100644 --- a/arch/powerpc/boot/dts/mpc8548cds.dts +++ b/arch/powerpc/boot/dts/mpc8548cds.dts | |||
| @@ -20,10 +20,8 @@ | |||
| 20 | aliases { | 20 | aliases { |
| 21 | ethernet0 = &enet0; | 21 | ethernet0 = &enet0; |
| 22 | ethernet1 = &enet1; | 22 | ethernet1 = &enet1; |
| 23 | /* | ||
| 24 | ethernet2 = &enet2; | 23 | ethernet2 = &enet2; |
| 25 | ethernet3 = &enet3; | 24 | ethernet3 = &enet3; |
| 26 | */ | ||
| 27 | serial0 = &serial0; | 25 | serial0 = &serial0; |
| 28 | serial1 = &serial1; | 26 | serial1 = &serial1; |
| 29 | pci0 = &pci0; | 27 | pci0 = &pci0; |
| @@ -254,7 +252,6 @@ | |||
| 254 | }; | 252 | }; |
| 255 | }; | 253 | }; |
| 256 | 254 | ||
| 257 | /* eTSEC 3/4 are currently broken | ||
| 258 | enet2: ethernet@26000 { | 255 | enet2: ethernet@26000 { |
| 259 | #address-cells = <1>; | 256 | #address-cells = <1>; |
| 260 | #size-cells = <1>; | 257 | #size-cells = <1>; |
| @@ -310,7 +307,6 @@ | |||
| 310 | }; | 307 | }; |
| 311 | }; | 308 | }; |
| 312 | }; | 309 | }; |
| 313 | */ | ||
| 314 | 310 | ||
| 315 | serial0: serial@4500 { | 311 | serial0: serial@4500 { |
| 316 | cell-index = <0>; | 312 | cell-index = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts index 5bd1011fde96..3375c2ab0c32 100644 --- a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts +++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts | |||
| @@ -215,6 +215,18 @@ | |||
| 215 | clock-frequency = <0>; | 215 | clock-frequency = <0>; |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | msi@41600 { | ||
| 219 | compatible = "fsl,mpc8572-msi", "fsl,mpic-msi"; | ||
| 220 | reg = <0x41600 0x80>; | ||
| 221 | msi-available-ranges = <0 0x80>; | ||
| 222 | interrupts = < | ||
| 223 | 0xe0 0 | ||
| 224 | 0xe1 0 | ||
| 225 | 0xe2 0 | ||
| 226 | 0xe3 0>; | ||
| 227 | interrupt-parent = <&mpic>; | ||
| 228 | }; | ||
| 229 | |||
| 218 | global-utilities@e0000 { //global utilities block | 230 | global-utilities@e0000 { //global utilities block |
| 219 | compatible = "fsl,mpc8572-guts"; | 231 | compatible = "fsl,mpc8572-guts"; |
| 220 | reg = <0xe0000 0x1000>; | 232 | reg = <0xe0000 0x1000>; |
| @@ -243,8 +255,7 @@ | |||
| 243 | protected-sources = < | 255 | protected-sources = < |
| 244 | 31 32 33 37 38 39 /* enet2 enet3 */ | 256 | 31 32 33 37 38 39 /* enet2 enet3 */ |
| 245 | 76 77 78 79 26 42 /* dma2 pci2 serial*/ | 257 | 76 77 78 79 26 42 /* dma2 pci2 serial*/ |
| 246 | 0xe0 0xe1 0xe2 0xe3 /* msi */ | 258 | 0xe4 0xe5 0xe6 0xe7 /* msi */ |
| 247 | 0xe4 0xe5 0xe6 0xe7 | ||
| 248 | >; | 259 | >; |
| 249 | }; | 260 | }; |
| 250 | }; | 261 | }; |
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts index 0efc3456e297..e7b477f6a3fe 100644 --- a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts +++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts | |||
| @@ -154,12 +154,8 @@ | |||
| 154 | msi@41600 { | 154 | msi@41600 { |
| 155 | compatible = "fsl,mpc8572-msi", "fsl,mpic-msi"; | 155 | compatible = "fsl,mpc8572-msi", "fsl,mpic-msi"; |
| 156 | reg = <0x41600 0x80>; | 156 | reg = <0x41600 0x80>; |
| 157 | msi-available-ranges = <0 0x100>; | 157 | msi-available-ranges = <0x80 0x80>; |
| 158 | interrupts = < | 158 | interrupts = < |
| 159 | 0xe0 0 | ||
| 160 | 0xe1 0 | ||
| 161 | 0xe2 0 | ||
| 162 | 0xe3 0 | ||
| 163 | 0xe4 0 | 159 | 0xe4 0 |
| 164 | 0xe5 0 | 160 | 0xe5 0 |
| 165 | 0xe6 0 | 161 | 0xe6 0 |
| @@ -190,6 +186,7 @@ | |||
| 190 | 0x1 0x2 0x3 0x4 /* pci slot */ | 186 | 0x1 0x2 0x3 0x4 /* pci slot */ |
| 191 | 0x9 0xa 0xb 0xc /* usb */ | 187 | 0x9 0xa 0xb 0xc /* usb */ |
| 192 | 0x6 0x7 0xe 0x5 /* Audio elgacy SATA */ | 188 | 0x6 0x7 0xe 0x5 /* Audio elgacy SATA */ |
| 189 | 0xe0 0xe1 0xe2 0xe3 /* msi */ | ||
| 193 | >; | 190 | >; |
| 194 | }; | 191 | }; |
| 195 | }; | 192 | }; |
diff --git a/arch/powerpc/boot/dts/p1021mds.dts b/arch/powerpc/boot/dts/p1021mds.dts new file mode 100644 index 000000000000..7fad2df25981 --- /dev/null +++ b/arch/powerpc/boot/dts/p1021mds.dts | |||
| @@ -0,0 +1,698 @@ | |||
| 1 | /* | ||
| 2 | * P1021 MDS Device Tree Source | ||
| 3 | * | ||
| 4 | * Copyright 2010 Freescale Semiconductor Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | /dts-v1/; | ||
| 13 | / { | ||
| 14 | model = "fsl,P1021"; | ||
| 15 | compatible = "fsl,P1021MDS"; | ||
| 16 | #address-cells = <2>; | ||
| 17 | #size-cells = <2>; | ||
| 18 | |||
| 19 | aliases { | ||
| 20 | serial0 = &serial0; | ||
| 21 | serial1 = &serial1; | ||
| 22 | ethernet0 = &enet0; | ||
| 23 | ethernet1 = &enet1; | ||
| 24 | ethernet2 = &enet2; | ||
| 25 | ethernet3 = &enet3; | ||
| 26 | ethernet4 = &enet4; | ||
| 27 | pci0 = &pci0; | ||
| 28 | pci1 = &pci1; | ||
| 29 | }; | ||
| 30 | |||
| 31 | cpus { | ||
| 32 | #address-cells = <1>; | ||
| 33 | #size-cells = <0>; | ||
| 34 | |||
| 35 | PowerPC,P1021@0 { | ||
| 36 | device_type = "cpu"; | ||
| 37 | reg = <0x0>; | ||
| 38 | next-level-cache = <&L2>; | ||
| 39 | }; | ||
| 40 | |||
| 41 | PowerPC,P1021@1 { | ||
| 42 | device_type = "cpu"; | ||
| 43 | reg = <0x1>; | ||
| 44 | next-level-cache = <&L2>; | ||
| 45 | }; | ||
| 46 | }; | ||
| 47 | |||
| 48 | memory { | ||
| 49 | device_type = "memory"; | ||
| 50 | }; | ||
| 51 | |||
| 52 | localbus@ffe05000 { | ||
| 53 | #address-cells = <2>; | ||
| 54 | #size-cells = <1>; | ||
| 55 | compatible = "fsl,p1021-elbc", "fsl,elbc", "simple-bus"; | ||
| 56 | reg = <0 0xffe05000 0 0x1000>; | ||
| 57 | interrupts = <19 2>; | ||
| 58 | interrupt-parent = <&mpic>; | ||
| 59 | |||
| 60 | /* NAND Flash, BCSR, PMC0/1*/ | ||
| 61 | ranges = <0x0 0x0 0x0 0xfc000000 0x02000000 | ||
| 62 | 0x1 0x0 0x0 0xf8000000 0x00008000 | ||
| 63 | 0x2 0x0 0x0 0xf8010000 0x00020000 | ||
| 64 | 0x3 0x0 0x0 0xf8020000 0x00020000>; | ||
| 65 | |||
| 66 | nand@0,0 { | ||
| 67 | #address-cells = <1>; | ||
| 68 | #size-cells = <1>; | ||
| 69 | compatible = "fsl,p1021-fcm-nand", | ||
| 70 | "fsl,elbc-fcm-nand"; | ||
| 71 | reg = <0x0 0x0 0x40000>; | ||
| 72 | |||
| 73 | partition@0 { | ||
| 74 | /* This location must not be altered */ | ||
| 75 | /* 1MB for u-boot Bootloader Image */ | ||
| 76 | reg = <0x0 0x00100000>; | ||
| 77 | label = "NAND (RO) U-Boot Image"; | ||
| 78 | read-only; | ||
| 79 | }; | ||
| 80 | |||
| 81 | partition@100000 { | ||
| 82 | /* 1MB for DTB Image */ | ||
| 83 | reg = <0x00100000 0x00100000>; | ||
| 84 | label = "NAND (RO) DTB Image"; | ||
| 85 | read-only; | ||
| 86 | }; | ||
| 87 | |||
| 88 | partition@200000 { | ||
| 89 | /* 4MB for Linux Kernel Image */ | ||
| 90 | reg = <0x00200000 0x00400000>; | ||
| 91 | label = "NAND (RO) Linux Kernel Image"; | ||
| 92 | read-only; | ||
| 93 | }; | ||
| 94 | |||
| 95 | partition@600000 { | ||
| 96 | /* 5MB for Compressed Root file System Image */ | ||
| 97 | reg = <0x00600000 0x00500000>; | ||
| 98 | label = "NAND (RO) Compressed RFS Image"; | ||
| 99 | read-only; | ||
| 100 | }; | ||
| 101 | |||
| 102 | partition@b00000 { | ||
| 103 | /* 6MB for JFFS2 based Root file System */ | ||
| 104 | reg = <0x00a00000 0x00600000>; | ||
| 105 | label = "NAND (RW) JFFS2 Root File System"; | ||
| 106 | }; | ||
| 107 | |||
| 108 | partition@1100000 { | ||
| 109 | /* 14MB for JFFS2 based Root file System */ | ||
| 110 | reg = <0x01100000 0x00e00000>; | ||
| 111 | label = "NAND (RW) Writable User area"; | ||
| 112 | }; | ||
| 113 | |||
| 114 | partition@1f00000 { | ||
| 115 | /* 1MB for microcode */ | ||
| 116 | reg = <0x01f00000 0x00100000>; | ||
| 117 | label = "NAND (RO) QE Ucode"; | ||
| 118 | read-only; | ||
| 119 | }; | ||
| 120 | }; | ||
| 121 | |||
| 122 | bcsr@1,0 { | ||
| 123 | #address-cells = <1>; | ||
| 124 | #size-cells = <1>; | ||
| 125 | compatible = "fsl,p1021mds-bcsr"; | ||
| 126 | reg = <1 0 0x8000>; | ||
| 127 | ranges = <0 1 0 0x8000>; | ||
| 128 | }; | ||
| 129 | |||
| 130 | pib@2,0 { | ||
| 131 | compatible = "fsl,p1021mds-pib"; | ||
| 132 | reg = <2 0 0x10000>; | ||
| 133 | }; | ||
| 134 | |||
| 135 | pib@3,0 { | ||
| 136 | compatible = "fsl,p1021mds-pib"; | ||
| 137 | reg = <3 0 0x10000>; | ||
| 138 | }; | ||
| 139 | }; | ||
| 140 | |||
| 141 | soc@ffe00000 { | ||
| 142 | |||
| 143 | #address-cells = <1>; | ||
| 144 | #size-cells = <1>; | ||
| 145 | device_type = "soc"; | ||
| 146 | compatible = "fsl,p1021-immr", "simple-bus"; | ||
| 147 | ranges = <0x0 0x0 0xffe00000 0x100000>; | ||
| 148 | bus-frequency = <0>; // Filled out by uboot. | ||
| 149 | |||
| 150 | ecm-law@0 { | ||
| 151 | compatible = "fsl,ecm-law"; | ||
| 152 | reg = <0x0 0x1000>; | ||
| 153 | fsl,num-laws = <12>; | ||
| 154 | }; | ||
| 155 | |||
| 156 | ecm@1000 { | ||
| 157 | compatible = "fsl,p1021-ecm", "fsl,ecm"; | ||
| 158 | reg = <0x1000 0x1000>; | ||
| 159 | interrupts = <16 2>; | ||
| 160 | interrupt-parent = <&mpic>; | ||
| 161 | }; | ||
| 162 | |||
| 163 | memory-controller@2000 { | ||
| 164 | compatible = "fsl,p1021-memory-controller"; | ||
| 165 | reg = <0x2000 0x1000>; | ||
| 166 | interrupt-parent = <&mpic>; | ||
| 167 | interrupts = <16 2>; | ||
| 168 | }; | ||
| 169 | |||
| 170 | i2c@3000 { | ||
| 171 | #address-cells = <1>; | ||
| 172 | #size-cells = <0>; | ||
| 173 | cell-index = <0>; | ||
| 174 | compatible = "fsl-i2c"; | ||
| 175 | reg = <0x3000 0x100>; | ||
| 176 | interrupts = <43 2>; | ||
| 177 | interrupt-parent = <&mpic>; | ||
| 178 | dfsrr; | ||
| 179 | rtc@68 { | ||
| 180 | compatible = "dallas,ds1374"; | ||
| 181 | reg = <0x68>; | ||
| 182 | }; | ||
| 183 | }; | ||
| 184 | |||
| 185 | i2c@3100 { | ||
| 186 | #address-cells = <1>; | ||
| 187 | #size-cells = <0>; | ||
| 188 | cell-index = <1>; | ||
| 189 | compatible = "fsl-i2c"; | ||
| 190 | reg = <0x3100 0x100>; | ||
| 191 | interrupts = <43 2>; | ||
| 192 | interrupt-parent = <&mpic>; | ||
| 193 | dfsrr; | ||
| 194 | }; | ||
| 195 | |||
| 196 | serial0: serial@4500 { | ||
| 197 | cell-index = <0>; | ||
| 198 | device_type = "serial"; | ||
| 199 | compatible = "ns16550"; | ||
| 200 | reg = <0x4500 0x100>; | ||
| 201 | clock-frequency = <0>; | ||
| 202 | interrupts = <42 2>; | ||
| 203 | interrupt-parent = <&mpic>; | ||
| 204 | }; | ||
| 205 | |||
| 206 | serial1: serial@4600 { | ||
| 207 | cell-index = <1>; | ||
| 208 | device_type = "serial"; | ||
| 209 | compatible = "ns16550"; | ||
| 210 | reg = <0x4600 0x100>; | ||
| 211 | clock-frequency = <0>; | ||
| 212 | interrupts = <42 2>; | ||
| 213 | interrupt-parent = <&mpic>; | ||
| 214 | }; | ||
| 215 | |||
| 216 | spi@7000 { | ||
| 217 | cell-index = <0>; | ||
| 218 | #address-cells = <1>; | ||
| 219 | #size-cells = <0>; | ||
| 220 | compatible = "fsl,espi"; | ||
| 221 | reg = <0x7000 0x1000>; | ||
| 222 | interrupts = <59 0x2>; | ||
| 223 | interrupt-parent = <&mpic>; | ||
| 224 | espi,num-ss-bits = <4>; | ||
| 225 | mode = "cpu"; | ||
| 226 | |||
| 227 | fsl_m25p80@0 { | ||
| 228 | #address-cells = <1>; | ||
| 229 | #size-cells = <1>; | ||
| 230 | compatible = "fsl,espi-flash"; | ||
| 231 | reg = <0>; | ||
| 232 | linux,modalias = "fsl_m25p80"; | ||
| 233 | spi-max-frequency = <40000000>; /* input clock */ | ||
| 234 | partition@u-boot { | ||
| 235 | label = "u-boot-spi"; | ||
| 236 | reg = <0x00000000 0x00100000>; | ||
| 237 | read-only; | ||
| 238 | }; | ||
| 239 | partition@kernel { | ||
| 240 | label = "kernel-spi"; | ||
| 241 | reg = <0x00100000 0x00500000>; | ||
| 242 | read-only; | ||
| 243 | }; | ||
| 244 | partition@dtb { | ||
| 245 | label = "dtb-spi"; | ||
| 246 | reg = <0x00600000 0x00100000>; | ||
| 247 | read-only; | ||
| 248 | }; | ||
| 249 | partition@fs { | ||
| 250 | label = "file system-spi"; | ||
| 251 | reg = <0x00700000 0x00900000>; | ||
| 252 | }; | ||
| 253 | }; | ||
| 254 | }; | ||
| 255 | |||
| 256 | gpio: gpio-controller@f000 { | ||
| 257 | #gpio-cells = <2>; | ||
| 258 | compatible = "fsl,mpc8572-gpio"; | ||
| 259 | reg = <0xf000 0x100>; | ||
| 260 | interrupts = <47 0x2>; | ||
| 261 | interrupt-parent = <&mpic>; | ||
| 262 | gpio-controller; | ||
| 263 | }; | ||
| 264 | |||
| 265 | L2: l2-cache-controller@20000 { | ||
| 266 | compatible = "fsl,p1021-l2-cache-controller"; | ||
| 267 | reg = <0x20000 0x1000>; | ||
| 268 | cache-line-size = <32>; // 32 bytes | ||
| 269 | cache-size = <0x40000>; // L2,256K | ||
| 270 | interrupt-parent = <&mpic>; | ||
| 271 | interrupts = <16 2>; | ||
| 272 | }; | ||
| 273 | |||
| 274 | dma@21300 { | ||
| 275 | #address-cells = <1>; | ||
| 276 | #size-cells = <1>; | ||
| 277 | compatible = "fsl,eloplus-dma"; | ||
| 278 | reg = <0x21300 0x4>; | ||
| 279 | ranges = <0x0 0x21100 0x200>; | ||
| 280 | cell-index = <0>; | ||
| 281 | dma-channel@0 { | ||
| 282 | compatible = "fsl,eloplus-dma-channel"; | ||
| 283 | reg = <0x0 0x80>; | ||
| 284 | cell-index = <0>; | ||
| 285 | interrupt-parent = <&mpic>; | ||
| 286 | interrupts = <20 2>; | ||
| 287 | }; | ||
| 288 | dma-channel@80 { | ||
| 289 | compatible = "fsl,eloplus-dma-channel"; | ||
| 290 | reg = <0x80 0x80>; | ||
| 291 | cell-index = <1>; | ||
| 292 | interrupt-parent = <&mpic>; | ||
| 293 | interrupts = <21 2>; | ||
| 294 | }; | ||
| 295 | dma-channel@100 { | ||
| 296 | compatible = "fsl,eloplus-dma-channel"; | ||
| 297 | reg = <0x100 0x80>; | ||
| 298 | cell-index = <2>; | ||
| 299 | interrupt-parent = <&mpic>; | ||
| 300 | interrupts = <22 2>; | ||
| 301 | }; | ||
| 302 | dma-channel@180 { | ||
| 303 | compatible = "fsl,eloplus-dma-channel"; | ||
| 304 | reg = <0x180 0x80>; | ||
| 305 | cell-index = <3>; | ||
| 306 | interrupt-parent = <&mpic>; | ||
| 307 | interrupts = <23 2>; | ||
| 308 | }; | ||
| 309 | }; | ||
| 310 | |||
| 311 | usb@22000 { | ||
| 312 | #address-cells = <1>; | ||
| 313 | #size-cells = <0>; | ||
| 314 | compatible = "fsl-usb2-dr"; | ||
| 315 | reg = <0x22000 0x1000>; | ||
| 316 | interrupt-parent = <&mpic>; | ||
| 317 | interrupts = <28 0x2>; | ||
| 318 | phy_type = "ulpi"; | ||
| 319 | }; | ||
| 320 | |||
| 321 | mdio@24000 { | ||
| 322 | #address-cells = <1>; | ||
| 323 | #size-cells = <0>; | ||
| 324 | compatible = "fsl,etsec2-mdio"; | ||
| 325 | reg = <0x24000 0x1000 0xb0030 0x4>; | ||
| 326 | |||
| 327 | phy0: ethernet-phy@0 { | ||
| 328 | interrupt-parent = <&mpic>; | ||
| 329 | interrupts = <1 1>; | ||
| 330 | reg = <0x0>; | ||
| 331 | }; | ||
| 332 | phy1: ethernet-phy@1 { | ||
| 333 | interrupt-parent = <&mpic>; | ||
| 334 | interrupts = <2 1>; | ||
| 335 | reg = <0x1>; | ||
| 336 | }; | ||
| 337 | phy4: ethernet-phy@4 { | ||
| 338 | interrupt-parent = <&mpic>; | ||
| 339 | reg = <0x4>; | ||
| 340 | }; | ||
| 341 | }; | ||
| 342 | |||
| 343 | mdio@25000 { | ||
| 344 | #address-cells = <1>; | ||
| 345 | #size-cells = <0>; | ||
| 346 | compatible = "fsl,etsec2-tbi"; | ||
| 347 | reg = <0x25000 0x1000 0xb1030 0x4>; | ||
| 348 | tbi0: tbi-phy@11 { | ||
| 349 | reg = <0x11>; | ||
| 350 | device_type = "tbi-phy"; | ||
| 351 | }; | ||
| 352 | }; | ||
| 353 | |||
| 354 | enet0: ethernet@B0000 { | ||
| 355 | #address-cells = <1>; | ||
| 356 | #size-cells = <1>; | ||
| 357 | cell-index = <0>; | ||
| 358 | device_type = "network"; | ||
| 359 | model = "eTSEC"; | ||
| 360 | compatible = "fsl,etsec2"; | ||
| 361 | fsl,num_rx_queues = <0x8>; | ||
| 362 | fsl,num_tx_queues = <0x8>; | ||
| 363 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 364 | interrupt-parent = <&mpic>; | ||
| 365 | phy-handle = <&phy0>; | ||
| 366 | phy-connection-type = "rgmii-id"; | ||
| 367 | queue-group@0{ | ||
| 368 | #address-cells = <1>; | ||
| 369 | #size-cells = <1>; | ||
| 370 | reg = <0xB0000 0x1000>; | ||
| 371 | interrupts = <29 2 30 2 34 2>; | ||
| 372 | }; | ||
| 373 | queue-group@1{ | ||
| 374 | #address-cells = <1>; | ||
| 375 | #size-cells = <1>; | ||
| 376 | reg = <0xB4000 0x1000>; | ||
| 377 | interrupts = <17 2 18 2 24 2>; | ||
| 378 | }; | ||
| 379 | }; | ||
| 380 | |||
| 381 | enet1: ethernet@B1000 { | ||
| 382 | #address-cells = <1>; | ||
| 383 | #size-cells = <1>; | ||
| 384 | cell-index = <0>; | ||
| 385 | device_type = "network"; | ||
| 386 | model = "eTSEC"; | ||
| 387 | compatible = "fsl,etsec2"; | ||
| 388 | fsl,num_rx_queues = <0x8>; | ||
| 389 | fsl,num_tx_queues = <0x8>; | ||
| 390 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 391 | interrupt-parent = <&mpic>; | ||
| 392 | phy-handle = <&phy4>; | ||
| 393 | tbi-handle = <&tbi0>; | ||
| 394 | phy-connection-type = "sgmii"; | ||
| 395 | queue-group@0{ | ||
| 396 | #address-cells = <1>; | ||
| 397 | #size-cells = <1>; | ||
| 398 | reg = <0xB1000 0x1000>; | ||
| 399 | interrupts = <35 2 36 2 40 2>; | ||
| 400 | }; | ||
| 401 | queue-group@1{ | ||
| 402 | #address-cells = <1>; | ||
| 403 | #size-cells = <1>; | ||
| 404 | reg = <0xB5000 0x1000>; | ||
| 405 | interrupts = <51 2 52 2 67 2>; | ||
| 406 | }; | ||
| 407 | }; | ||
| 408 | |||
| 409 | enet2: ethernet@B2000 { | ||
| 410 | #address-cells = <1>; | ||
| 411 | #size-cells = <1>; | ||
| 412 | cell-index = <0>; | ||
| 413 | device_type = "network"; | ||
| 414 | model = "eTSEC"; | ||
| 415 | compatible = "fsl,etsec2"; | ||
| 416 | fsl,num_rx_queues = <0x8>; | ||
| 417 | fsl,num_tx_queues = <0x8>; | ||
| 418 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 419 | interrupt-parent = <&mpic>; | ||
| 420 | phy-handle = <&phy1>; | ||
| 421 | phy-connection-type = "rgmii-id"; | ||
| 422 | queue-group@0{ | ||
| 423 | #address-cells = <1>; | ||
| 424 | #size-cells = <1>; | ||
| 425 | reg = <0xB2000 0x1000>; | ||
| 426 | interrupts = <31 2 32 2 33 2>; | ||
| 427 | }; | ||
| 428 | queue-group@1{ | ||
| 429 | #address-cells = <1>; | ||
| 430 | #size-cells = <1>; | ||
| 431 | reg = <0xB6000 0x1000>; | ||
| 432 | interrupts = <25 2 26 2 27 2>; | ||
| 433 | }; | ||
| 434 | }; | ||
| 435 | |||
| 436 | sdhci@2e000 { | ||
| 437 | compatible = "fsl,p1021-esdhc", "fsl,esdhc"; | ||
| 438 | reg = <0x2e000 0x1000>; | ||
| 439 | interrupts = <72 0x2>; | ||
| 440 | interrupt-parent = <&mpic>; | ||
| 441 | /* Filled in by U-Boot */ | ||
| 442 | clock-frequency = <0>; | ||
| 443 | }; | ||
| 444 | |||
| 445 | crypto@30000 { | ||
| 446 | compatible = "fsl,sec3.3", "fsl,sec3.1", | ||
| 447 | "fsl,sec3.0", "fsl,sec2.4", | ||
| 448 | "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0"; | ||
| 449 | reg = <0x30000 0x10000>; | ||
| 450 | interrupts = <45 2 58 2>; | ||
| 451 | interrupt-parent = <&mpic>; | ||
| 452 | fsl,num-channels = <4>; | ||
| 453 | fsl,channel-fifo-len = <24>; | ||
| 454 | fsl,exec-units-mask = <0x97c>; | ||
| 455 | fsl,descriptor-types-mask = <0x3a30abf>; | ||
| 456 | }; | ||
| 457 | |||
| 458 | mpic: pic@40000 { | ||
| 459 | interrupt-controller; | ||
| 460 | #address-cells = <0>; | ||
| 461 | #interrupt-cells = <2>; | ||
| 462 | reg = <0x40000 0x40000>; | ||
| 463 | compatible = "chrp,open-pic"; | ||
| 464 | device_type = "open-pic"; | ||
| 465 | }; | ||
| 466 | |||
| 467 | msi@41600 { | ||
| 468 | compatible = "fsl,p1021-msi", "fsl,mpic-msi"; | ||
| 469 | reg = <0x41600 0x80>; | ||
| 470 | msi-available-ranges = <0 0x100>; | ||
| 471 | interrupts = < | ||
| 472 | 0xe0 0 | ||
| 473 | 0xe1 0 | ||
| 474 | 0xe2 0 | ||
| 475 | 0xe3 0 | ||
| 476 | 0xe4 0 | ||
| 477 | 0xe5 0 | ||
| 478 | 0xe6 0 | ||
| 479 | 0xe7 0>; | ||
| 480 | interrupt-parent = <&mpic>; | ||
| 481 | }; | ||
| 482 | |||
| 483 | global-utilities@e0000 { //global utilities block | ||
| 484 | compatible = "fsl,p1021-guts"; | ||
| 485 | reg = <0xe0000 0x1000>; | ||
| 486 | fsl,has-rstcr; | ||
| 487 | }; | ||
| 488 | |||
| 489 | par_io@e0100 { | ||
| 490 | #address-cells = <1>; | ||
| 491 | #size-cells = <1>; | ||
| 492 | reg = <0xe0100 0x60>; | ||
| 493 | ranges = <0x0 0xe0100 0x60>; | ||
| 494 | device_type = "par_io"; | ||
| 495 | num-ports = <3>; | ||
| 496 | pio1: ucc_pin@01 { | ||
| 497 | pio-map = < | ||
| 498 | /* port pin dir open_drain assignment has_irq */ | ||
| 499 | 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */ | ||
| 500 | 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */ | ||
| 501 | 0x0 0x17 0x2 0x0 0x2 0x0 /* CLK12 */ | ||
| 502 | 0x0 0x18 0x2 0x0 0x1 0x0 /* CLK9 | ||
| 503 | */ | ||
| 504 | 0x0 0x7 0x1 0x0 0x2 0x0 /* ENET1_TXD0_SER1_TXD0 */ | ||
| 505 | 0x0 0x9 0x1 0x0 0x2 0x0 /* ENET1_TXD1_SER1_TXD1 */ | ||
| 506 | 0x0 0xb 0x1 0x0 0x2 0x0 /* ENET1_TXD2_SER1_TXD2 */ | ||
| 507 | 0x0 0xc 0x1 0x0 0x2 0x0 /* ENET1_TXD3_SER1_TXD3 */ | ||
| 508 | 0x0 0x6 0x2 0x0 0x2 0x0 /* ENET1_RXD0_SER1_RXD0 */ | ||
| 509 | 0x0 0xa 0x2 0x0 0x2 0x0 /* ENET1_RXD1_SER1_RXD1 */ | ||
| 510 | 0x0 0xe 0x2 0x0 0x2 0x0 /* ENET1_RXD2_SER1_RXD2 */ | ||
| 511 | 0x0 0xf 0x2 0x0 0x2 0x0 /* ENET1_RXD3_SER1_RXD3 */ | ||
| 512 | 0x0 0x5 0x1 0x0 0x2 0x0 /* ENET1_TX_EN_SER1_RTS_B */ | ||
| 513 | 0x0 0xd 0x1 0x0 0x2 0x0 /* ENET1_TX_ER */ | ||
| 514 | 0x0 0x4 0x2 0x0 0x2 0x0 /* ENET1_RX_DV_SER1_CTS_B */ | ||
| 515 | 0x0 0x8 0x2 0x0 0x2 0x0 /* ENET1_RX_ER_SER1_CD_B */ | ||
| 516 | 0x0 0x11 0x2 0x0 0x2 0x0 /* ENET1_CRS */ | ||
| 517 | 0x0 0x10 0x2 0x0 0x2 0x0>; /* ENET1_COL */ | ||
| 518 | }; | ||
| 519 | |||
| 520 | pio2: ucc_pin@02 { | ||
| 521 | pio-map = < | ||
| 522 | /* port pin dir open_drain assignment has_irq */ | ||
| 523 | 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */ | ||
| 524 | 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */ | ||
| 525 | 0x1 0xb 0x2 0x0 0x1 0x0 /* CLK13 */ | ||
| 526 | 0x1 0x7 0x1 0x0 0x2 0x0 /* ENET5_TXD0_SER5_TXD0 */ | ||
| 527 | 0x1 0xa 0x1 0x0 0x2 0x0 /* ENET5_TXD1_SER5_TXD1 */ | ||
| 528 | 0x1 0x6 0x2 0x0 0x2 0x0 /* ENET5_RXD0_SER5_RXD0 */ | ||
| 529 | 0x1 0x9 0x2 0x0 0x2 0x0 /* ENET5_RXD1_SER5_RXD1 */ | ||
| 530 | 0x1 0x5 0x1 0x0 0x2 0x0 /* ENET5_TX_EN_SER5_RTS_B */ | ||
| 531 | 0x1 0x4 0x2 0x0 0x2 0x0 /* ENET5_RX_DV_SER5_CTS_B */ | ||
| 532 | 0x1 0x8 0x2 0x0 0x2 0x0>; /* ENET5_RX_ER_SER5_CD_B */ | ||
| 533 | }; | ||
| 534 | }; | ||
| 535 | }; | ||
| 536 | |||
| 537 | pci0: pcie@ffe09000 { | ||
| 538 | compatible = "fsl,mpc8548-pcie"; | ||
| 539 | device_type = "pci"; | ||
| 540 | #interrupt-cells = <1>; | ||
| 541 | #size-cells = <2>; | ||
| 542 | #address-cells = <3>; | ||
| 543 | reg = <0 0xffe09000 0 0x1000>; | ||
| 544 | bus-range = <0 255>; | ||
| 545 | ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000 | ||
| 546 | 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>; | ||
| 547 | clock-frequency = <33333333>; | ||
| 548 | interrupt-parent = <&mpic>; | ||
| 549 | interrupts = <16 2>; | ||
| 550 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 551 | interrupt-map = < | ||
| 552 | /* IDSEL 0x0 */ | ||
| 553 | 0000 0 0 1 &mpic 4 1 | ||
| 554 | 0000 0 0 2 &mpic 5 1 | ||
| 555 | 0000 0 0 3 &mpic 6 1 | ||
| 556 | 0000 0 0 4 &mpic 7 1 | ||
| 557 | >; | ||
| 558 | pcie@0 { | ||
| 559 | reg = <0x0 0x0 0x0 0x0 0x0>; | ||
| 560 | #size-cells = <2>; | ||
| 561 | #address-cells = <3>; | ||
| 562 | device_type = "pci"; | ||
| 563 | ranges = <0x2000000 0x0 0xa0000000 | ||
| 564 | 0x2000000 0x0 0xa0000000 | ||
| 565 | 0x0 0x20000000 | ||
| 566 | |||
| 567 | 0x1000000 0x0 0x0 | ||
| 568 | 0x1000000 0x0 0x0 | ||
| 569 | 0x0 0x100000>; | ||
| 570 | }; | ||
| 571 | }; | ||
| 572 | |||
| 573 | pci1: pcie@ffe0a000 { | ||
| 574 | compatible = "fsl,mpc8548-pcie"; | ||
| 575 | device_type = "pci"; | ||
| 576 | #interrupt-cells = <1>; | ||
| 577 | #size-cells = <2>; | ||
| 578 | #address-cells = <3>; | ||
| 579 | reg = <0 0xffe0a000 0 0x1000>; | ||
| 580 | bus-range = <0 255>; | ||
| 581 | ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000 | ||
| 582 | 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>; | ||
| 583 | clock-frequency = <33333333>; | ||
| 584 | interrupt-parent = <&mpic>; | ||
| 585 | interrupts = <16 2>; | ||
| 586 | interrupt-map-mask = <0xf800 0 0 7>; | ||
| 587 | interrupt-map = < | ||
| 588 | /* IDSEL 0x0 */ | ||
| 589 | 0000 0 0 1 &mpic 0 1 | ||
| 590 | 0000 0 0 2 &mpic 1 1 | ||
| 591 | 0000 0 0 3 &mpic 2 1 | ||
| 592 | 0000 0 0 4 &mpic 3 1 | ||
| 593 | >; | ||
| 594 | pcie@0 { | ||
| 595 | reg = <0x0 0x0 0x0 0x0 0x0>; | ||
| 596 | #size-cells = <2>; | ||
| 597 | #address-cells = <3>; | ||
| 598 | device_type = "pci"; | ||
| 599 | ranges = <0x2000000 0x0 0xc0000000 | ||
| 600 | 0x2000000 0x0 0xc0000000 | ||
| 601 | 0x0 0x20000000 | ||
| 602 | |||
| 603 | 0x1000000 0x0 0x0 | ||
| 604 | 0x1000000 0x0 0x0 | ||
| 605 | 0x0 0x100000>; | ||
| 606 | }; | ||
| 607 | }; | ||
| 608 | |||
| 609 | qe@ffe80000 { | ||
| 610 | #address-cells = <1>; | ||
| 611 | #size-cells = <1>; | ||
| 612 | device_type = "qe"; | ||
| 613 | compatible = "fsl,qe"; | ||
| 614 | ranges = <0x0 0x0 0xffe80000 0x40000>; | ||
| 615 | reg = <0 0xffe80000 0 0x480>; | ||
| 616 | brg-frequency = <0>; | ||
| 617 | bus-frequency = <0>; | ||
| 618 | fsl,qe-num-riscs = <1>; | ||
| 619 | fsl,qe-num-snums = <28>; | ||
| 620 | |||
| 621 | qeic: interrupt-controller@80 { | ||
| 622 | interrupt-controller; | ||
| 623 | compatible = "fsl,qe-ic"; | ||
| 624 | #address-cells = <0>; | ||
| 625 | #interrupt-cells = <1>; | ||
| 626 | reg = <0x80 0x80>; | ||
| 627 | interrupts = <63 2 60 2>; //high:47 low:44 | ||
| 628 | interrupt-parent = <&mpic>; | ||
| 629 | }; | ||
| 630 | |||
| 631 | enet3: ucc@2000 { | ||
| 632 | device_type = "network"; | ||
| 633 | compatible = "ucc_geth"; | ||
| 634 | cell-index = <1>; | ||
| 635 | reg = <0x2000 0x200>; | ||
| 636 | interrupts = <32>; | ||
| 637 | interrupt-parent = <&qeic>; | ||
| 638 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 639 | rx-clock-name = "clk12"; | ||
| 640 | tx-clock-name = "clk9"; | ||
| 641 | pio-handle = <&pio1>; | ||
| 642 | phy-handle = <&qe_phy0>; | ||
| 643 | phy-connection-type = "mii"; | ||
| 644 | }; | ||
| 645 | |||
| 646 | mdio@2120 { | ||
| 647 | #address-cells = <1>; | ||
| 648 | #size-cells = <0>; | ||
| 649 | reg = <0x2120 0x18>; | ||
| 650 | compatible = "fsl,ucc-mdio"; | ||
| 651 | |||
| 652 | qe_phy0: ethernet-phy@0 { | ||
| 653 | interrupt-parent = <&mpic>; | ||
| 654 | interrupts = <4 1>; | ||
| 655 | reg = <0x0>; | ||
| 656 | device_type = "ethernet-phy"; | ||
| 657 | }; | ||
| 658 | qe_phy1: ethernet-phy@03 { | ||
| 659 | interrupt-parent = <&mpic>; | ||
| 660 | interrupts = <5 1>; | ||
| 661 | reg = <0x3>; | ||
| 662 | device_type = "ethernet-phy"; | ||
| 663 | }; | ||
| 664 | tbi-phy@11 { | ||
| 665 | reg = <0x11>; | ||
| 666 | device_type = "tbi-phy"; | ||
| 667 | }; | ||
| 668 | }; | ||
| 669 | |||
| 670 | enet4: ucc@2400 { | ||
| 671 | device_type = "network"; | ||
| 672 | compatible = "ucc_geth"; | ||
| 673 | cell-index = <5>; | ||
| 674 | reg = <0x2400 0x200>; | ||
| 675 | interrupts = <40>; | ||
| 676 | interrupt-parent = <&qeic>; | ||
| 677 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 678 | rx-clock-name = "none"; | ||
| 679 | tx-clock-name = "clk13"; | ||
| 680 | pio-handle = <&pio2>; | ||
| 681 | phy-handle = <&qe_phy1>; | ||
| 682 | phy-connection-type = "rmii"; | ||
| 683 | }; | ||
| 684 | |||
| 685 | muram@10000 { | ||
| 686 | #address-cells = <1>; | ||
| 687 | #size-cells = <1>; | ||
| 688 | compatible = "fsl,qe-muram", "fsl,cpm-muram"; | ||
| 689 | ranges = <0x0 0x10000 0x6000>; | ||
| 690 | |||
| 691 | data-only@0 { | ||
| 692 | compatible = "fsl,qe-muram-data", | ||
| 693 | "fsl,cpm-muram-data"; | ||
| 694 | reg = <0x0 0x6000>; | ||
| 695 | }; | ||
| 696 | }; | ||
| 697 | }; | ||
| 698 | }; | ||
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index e3cba4e1eb34..b0b21134f61a 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
| @@ -70,6 +70,7 @@ struct pt_regs; | |||
| 70 | extern int machine_check_generic(struct pt_regs *regs); | 70 | extern int machine_check_generic(struct pt_regs *regs); |
| 71 | extern int machine_check_4xx(struct pt_regs *regs); | 71 | extern int machine_check_4xx(struct pt_regs *regs); |
| 72 | extern int machine_check_440A(struct pt_regs *regs); | 72 | extern int machine_check_440A(struct pt_regs *regs); |
| 73 | extern int machine_check_e500mc(struct pt_regs *regs); | ||
| 73 | extern int machine_check_e500(struct pt_regs *regs); | 74 | extern int machine_check_e500(struct pt_regs *regs); |
| 74 | extern int machine_check_e200(struct pt_regs *regs); | 75 | extern int machine_check_e200(struct pt_regs *regs); |
| 75 | extern int machine_check_47x(struct pt_regs *regs); | 76 | extern int machine_check_47x(struct pt_regs *regs); |
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h index a6ca6da1430b..2a9cd74a841e 100644 --- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h | |||
| @@ -2,6 +2,18 @@ | |||
| 2 | #define _ASM_POWERPC_KEXEC_H | 2 | #define _ASM_POWERPC_KEXEC_H |
| 3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
| 4 | 4 | ||
| 5 | #ifdef CONFIG_FSL_BOOKE | ||
| 6 | |||
| 7 | /* | ||
| 8 | * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory | ||
| 9 | * and therefore we can only deal with memory within this range | ||
| 10 | */ | ||
| 11 | #define KEXEC_SOURCE_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL) | ||
| 12 | #define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL) | ||
| 13 | #define KEXEC_CONTROL_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL) | ||
| 14 | |||
| 15 | #else | ||
| 16 | |||
| 5 | /* | 17 | /* |
| 6 | * Maximum page that is mapped directly into kernel memory. | 18 | * Maximum page that is mapped directly into kernel memory. |
| 7 | * XXX: Since we copy virt we can use any page we allocate | 19 | * XXX: Since we copy virt we can use any page we allocate |
| @@ -21,6 +33,7 @@ | |||
| 21 | /* TASK_SIZE, probably left over from use_mm ?? */ | 33 | /* TASK_SIZE, probably left over from use_mm ?? */ |
| 22 | #define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE | 34 | #define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE |
| 23 | #endif | 35 | #endif |
| 36 | #endif | ||
| 24 | 37 | ||
| 25 | #define KEXEC_CONTROL_PAGE_SIZE 4096 | 38 | #define KEXEC_CONTROL_PAGE_SIZE 4096 |
| 26 | 39 | ||
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index 5304a37ba425..2360317179a9 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h | |||
| @@ -4,6 +4,12 @@ | |||
| 4 | * are not true Book E PowerPCs, they borrowed a number of features | 4 | * are not true Book E PowerPCs, they borrowed a number of features |
| 5 | * before Book E was finalized, and are included here as well. Unfortunatly, | 5 | * before Book E was finalized, and are included here as well. Unfortunatly, |
| 6 | * they sometimes used different locations than true Book E CPUs did. | 6 | * they sometimes used different locations than true Book E CPUs did. |
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License version 2 | ||
| 10 | * as published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * Copyright 2009-2010 Freescale Semiconductor, Inc. | ||
| 7 | */ | 13 | */ |
| 8 | #ifdef __KERNEL__ | 14 | #ifdef __KERNEL__ |
| 9 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ | 15 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ |
| @@ -88,6 +94,7 @@ | |||
| 88 | #define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */ | 94 | #define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */ |
| 89 | #define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */ | 95 | #define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */ |
| 90 | #define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */ | 96 | #define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */ |
| 97 | #define SPRN_MCARU 0x239 /* Machine Check Address Register Upper */ | ||
| 91 | #define SPRN_MCSRR0 0x23A /* Machine Check Save and Restore Register 0 */ | 98 | #define SPRN_MCSRR0 0x23A /* Machine Check Save and Restore Register 0 */ |
| 92 | #define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */ | 99 | #define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */ |
| 93 | #define SPRN_MCSR 0x23C /* Machine Check Status Register */ | 100 | #define SPRN_MCSR 0x23C /* Machine Check Status Register */ |
| @@ -196,8 +203,11 @@ | |||
| 196 | #define PPC47x_MCSR_IPR 0x00400000 /* Imprecise Machine Check Exception */ | 203 | #define PPC47x_MCSR_IPR 0x00400000 /* Imprecise Machine Check Exception */ |
| 197 | 204 | ||
| 198 | #ifdef CONFIG_E500 | 205 | #ifdef CONFIG_E500 |
| 206 | /* All e500 */ | ||
| 199 | #define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ | 207 | #define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ |
| 200 | #define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */ | 208 | #define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */ |
| 209 | |||
| 210 | /* e500v1/v2 */ | ||
| 201 | #define MCSR_DCP_PERR 0x20000000UL /* D-Cache Push Parity Error */ | 211 | #define MCSR_DCP_PERR 0x20000000UL /* D-Cache Push Parity Error */ |
| 202 | #define MCSR_DCPERR 0x10000000UL /* D-Cache Parity Error */ | 212 | #define MCSR_DCPERR 0x10000000UL /* D-Cache Parity Error */ |
| 203 | #define MCSR_BUS_IAERR 0x00000080UL /* Instruction Address Error */ | 213 | #define MCSR_BUS_IAERR 0x00000080UL /* Instruction Address Error */ |
| @@ -209,12 +219,20 @@ | |||
| 209 | #define MCSR_BUS_IPERR 0x00000002UL /* Instruction parity Error */ | 219 | #define MCSR_BUS_IPERR 0x00000002UL /* Instruction parity Error */ |
| 210 | #define MCSR_BUS_RPERR 0x00000001UL /* Read parity Error */ | 220 | #define MCSR_BUS_RPERR 0x00000001UL /* Read parity Error */ |
| 211 | 221 | ||
| 212 | /* e500 parts may set unused bits in MCSR; mask these off */ | 222 | /* e500mc */ |
| 213 | #define MCSR_MASK (MCSR_MCP | MCSR_ICPERR | MCSR_DCP_PERR | \ | 223 | #define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */ |
| 214 | MCSR_DCPERR | MCSR_BUS_IAERR | MCSR_BUS_RAERR | \ | 224 | #define MCSR_L2MMU_MHIT 0x04000000UL /* Hit on multiple TLB entries */ |
| 215 | MCSR_BUS_WAERR | MCSR_BUS_IBERR | MCSR_BUS_RBERR | \ | 225 | #define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */ |
| 216 | MCSR_BUS_WBERR | MCSR_BUS_IPERR | MCSR_BUS_RPERR) | 226 | #define MCSR_MAV 0x00080000UL /* MCAR address valid */ |
| 227 | #define MCSR_MEA 0x00040000UL /* MCAR is effective address */ | ||
| 228 | #define MCSR_IF 0x00010000UL /* Instruction Fetch */ | ||
| 229 | #define MCSR_LD 0x00008000UL /* Load */ | ||
| 230 | #define MCSR_ST 0x00004000UL /* Store */ | ||
| 231 | #define MCSR_LDG 0x00002000UL /* Guarded Load */ | ||
| 232 | #define MCSR_TLBSYNC 0x00000002UL /* Multiple tlbsyncs detected */ | ||
| 233 | #define MCSR_BSL2_ERR 0x00000001UL /* Backside L2 cache error */ | ||
| 217 | #endif | 234 | #endif |
| 235 | |||
| 218 | #ifdef CONFIG_E200 | 236 | #ifdef CONFIG_E200 |
| 219 | #define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ | 237 | #define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ |
| 220 | #define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */ | 238 | #define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */ |
| @@ -225,11 +243,6 @@ | |||
| 225 | #define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */ | 243 | #define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */ |
| 226 | #define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered | 244 | #define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered |
| 227 | store or cache line push */ | 245 | store or cache line push */ |
| 228 | |||
| 229 | /* e200 parts may set unused bits in MCSR; mask these off */ | ||
| 230 | #define MCSR_MASK (MCSR_MCP | MCSR_CP_PERR | MCSR_CPERR | \ | ||
| 231 | MCSR_EXCP_ERR | MCSR_BUS_IRERR | MCSR_BUS_DRERR | \ | ||
| 232 | MCSR_BUS_WRERR) | ||
| 233 | #endif | 246 | #endif |
| 234 | 247 | ||
| 235 | /* Bit definitions for the DBSR. */ | 248 | /* Bit definitions for the DBSR. */ |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 877326320e74..58d0572de6f9 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | |||
| 57 | obj-$(CONFIG_E500) += idle_e500.o | 57 | obj-$(CONFIG_E500) += idle_e500.o |
| 58 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o | 58 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o |
| 59 | obj-$(CONFIG_TAU) += tau_6xx.o | 59 | obj-$(CONFIG_TAU) += tau_6xx.o |
| 60 | obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ | 60 | obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o |
| 61 | swsusp_$(CONFIG_WORD_SIZE).o | 61 | ifeq ($(CONFIG_FSL_BOOKE),y) |
| 62 | obj-$(CONFIG_HIBERNATION) += swsusp_booke.o | ||
| 63 | else | ||
| 64 | obj-$(CONFIG_HIBERNATION) += swsusp_$(CONFIG_WORD_SIZE).o | ||
| 65 | endif | ||
| 62 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o | 66 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o |
| 63 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o | 67 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o |
| 64 | obj-$(CONFIG_44x) += cpu_setup_44x.o | 68 | obj-$(CONFIG_44x) += cpu_setup_44x.o |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 9556be903e96..87aa0f3c6047 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -1840,7 +1840,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1840 | .oprofile_cpu_type = "ppc/e500mc", | 1840 | .oprofile_cpu_type = "ppc/e500mc", |
| 1841 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | 1841 | .oprofile_type = PPC_OPROFILE_FSL_EMB, |
| 1842 | .cpu_setup = __setup_cpu_e500mc, | 1842 | .cpu_setup = __setup_cpu_e500mc, |
| 1843 | .machine_check = machine_check_e500, | 1843 | .machine_check = machine_check_e500mc, |
| 1844 | .platform = "ppce500mc", | 1844 | .platform = "ppce500mc", |
| 1845 | }, | 1845 | }, |
| 1846 | { /* default match */ | 1846 | { /* default match */ |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 8c066d6a8e4b..b46f2e09bd81 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
| @@ -163,6 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu) | |||
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | /* wait for all the CPUs to hit real mode but timeout if they don't come in */ | 165 | /* wait for all the CPUs to hit real mode but timeout if they don't come in */ |
| 166 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
| 166 | static void crash_kexec_wait_realmode(int cpu) | 167 | static void crash_kexec_wait_realmode(int cpu) |
| 167 | { | 168 | { |
| 168 | unsigned int msecs; | 169 | unsigned int msecs; |
| @@ -187,6 +188,7 @@ static void crash_kexec_wait_realmode(int cpu) | |||
| 187 | } | 188 | } |
| 188 | mb(); | 189 | mb(); |
| 189 | } | 190 | } |
| 191 | #endif | ||
| 190 | 192 | ||
| 191 | /* | 193 | /* |
| 192 | * This function will be called by secondary cpus or by kexec cpu | 194 | * This function will be called by secondary cpus or by kexec cpu |
| @@ -445,7 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
| 445 | crash_kexec_prepare_cpus(crashing_cpu); | 447 | crash_kexec_prepare_cpus(crashing_cpu); |
| 446 | cpu_set(crashing_cpu, cpus_in_crash); | 448 | cpu_set(crashing_cpu, cpus_in_crash); |
| 447 | crash_kexec_stop_spus(); | 449 | crash_kexec_stop_spus(); |
| 450 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
| 448 | crash_kexec_wait_realmode(crashing_cpu); | 451 | crash_kexec_wait_realmode(crashing_cpu); |
| 452 | #endif | ||
| 449 | if (ppc_md.kexec_cpu_down) | 453 | if (ppc_md.kexec_cpu_down) |
| 450 | ppc_md.kexec_cpu_down(1, 0); | 454 | ppc_md.kexec_cpu_down(1, 0); |
| 451 | } | 455 | } |
diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S new file mode 100644 index 000000000000..beb4d78a2304 --- /dev/null +++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | |||
| 2 | /* 1. Find the index of the entry we're executing in */ | ||
| 3 | bl invstr /* Find our address */ | ||
| 4 | invstr: mflr r6 /* Make it accessible */ | ||
| 5 | mfmsr r7 | ||
| 6 | rlwinm r4,r7,27,31,31 /* extract MSR[IS] */ | ||
| 7 | mfspr r7, SPRN_PID0 | ||
| 8 | slwi r7,r7,16 | ||
| 9 | or r7,r7,r4 | ||
| 10 | mtspr SPRN_MAS6,r7 | ||
| 11 | tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */ | ||
| 12 | mfspr r7,SPRN_MAS1 | ||
| 13 | andis. r7,r7,MAS1_VALID@h | ||
| 14 | bne match_TLB | ||
| 15 | |||
| 16 | mfspr r7,SPRN_MMUCFG | ||
| 17 | rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */ | ||
| 18 | cmpwi r7,3 | ||
| 19 | bne match_TLB /* skip if NPIDS != 3 */ | ||
| 20 | |||
| 21 | mfspr r7,SPRN_PID1 | ||
| 22 | slwi r7,r7,16 | ||
| 23 | or r7,r7,r4 | ||
| 24 | mtspr SPRN_MAS6,r7 | ||
| 25 | tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */ | ||
| 26 | mfspr r7,SPRN_MAS1 | ||
| 27 | andis. r7,r7,MAS1_VALID@h | ||
| 28 | bne match_TLB | ||
| 29 | mfspr r7, SPRN_PID2 | ||
| 30 | slwi r7,r7,16 | ||
| 31 | or r7,r7,r4 | ||
| 32 | mtspr SPRN_MAS6,r7 | ||
| 33 | tlbsx 0,r6 /* Fall through, we had to match */ | ||
| 34 | |||
| 35 | match_TLB: | ||
| 36 | mfspr r7,SPRN_MAS0 | ||
| 37 | rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */ | ||
| 38 | |||
| 39 | mfspr r7,SPRN_MAS1 /* Insure IPROT set */ | ||
| 40 | oris r7,r7,MAS1_IPROT@h | ||
| 41 | mtspr SPRN_MAS1,r7 | ||
| 42 | tlbwe | ||
| 43 | |||
| 44 | /* 2. Invalidate all entries except the entry we're executing in */ | ||
| 45 | mfspr r9,SPRN_TLB1CFG | ||
| 46 | andi. r9,r9,0xfff | ||
| 47 | li r6,0 /* Set Entry counter to 0 */ | ||
| 48 | 1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 49 | rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */ | ||
| 50 | mtspr SPRN_MAS0,r7 | ||
| 51 | tlbre | ||
| 52 | mfspr r7,SPRN_MAS1 | ||
| 53 | rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */ | ||
| 54 | cmpw r3,r6 | ||
| 55 | beq skpinv /* Dont update the current execution TLB */ | ||
| 56 | mtspr SPRN_MAS1,r7 | ||
| 57 | tlbwe | ||
| 58 | isync | ||
| 59 | skpinv: addi r6,r6,1 /* Increment */ | ||
| 60 | cmpw r6,r9 /* Are we done? */ | ||
| 61 | bne 1b /* If not, repeat */ | ||
| 62 | |||
| 63 | /* Invalidate TLB0 */ | ||
| 64 | li r6,0x04 | ||
| 65 | tlbivax 0,r6 | ||
| 66 | TLBSYNC | ||
| 67 | /* Invalidate TLB1 */ | ||
| 68 | li r6,0x0c | ||
| 69 | tlbivax 0,r6 | ||
| 70 | TLBSYNC | ||
| 71 | |||
| 72 | /* 3. Setup a temp mapping and jump to it */ | ||
| 73 | andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */ | ||
| 74 | addi r5, r5, 0x1 | ||
| 75 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 76 | rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ | ||
| 77 | mtspr SPRN_MAS0,r7 | ||
| 78 | tlbre | ||
| 79 | |||
| 80 | /* grab and fixup the RPN */ | ||
| 81 | mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */ | ||
| 82 | rlwinm r6,r6,25,27,31 | ||
| 83 | li r8,-1 | ||
| 84 | addi r6,r6,10 | ||
| 85 | slw r6,r8,r6 /* convert to mask */ | ||
| 86 | |||
| 87 | bl 1f /* Find our address */ | ||
| 88 | 1: mflr r7 | ||
| 89 | |||
| 90 | mfspr r8,SPRN_MAS3 | ||
| 91 | #ifdef CONFIG_PHYS_64BIT | ||
| 92 | mfspr r23,SPRN_MAS7 | ||
| 93 | #endif | ||
| 94 | and r8,r6,r8 | ||
| 95 | subfic r9,r6,-4096 | ||
| 96 | and r9,r9,r7 | ||
| 97 | |||
| 98 | or r25,r8,r9 | ||
| 99 | ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR) | ||
| 100 | |||
| 101 | /* Just modify the entry ID and EPN for the temp mapping */ | ||
| 102 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 103 | rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */ | ||
| 104 | mtspr SPRN_MAS0,r7 | ||
| 105 | xori r6,r4,1 /* Setup TMP mapping in the other Address space */ | ||
| 106 | slwi r6,r6,12 | ||
| 107 | oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h | ||
| 108 | ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l | ||
| 109 | mtspr SPRN_MAS1,r6 | ||
| 110 | mfspr r6,SPRN_MAS2 | ||
| 111 | li r7,0 /* temp EPN = 0 */ | ||
| 112 | rlwimi r7,r6,0,20,31 | ||
| 113 | mtspr SPRN_MAS2,r7 | ||
| 114 | mtspr SPRN_MAS3,r8 | ||
| 115 | tlbwe | ||
| 116 | |||
| 117 | xori r6,r4,1 | ||
| 118 | slwi r6,r6,5 /* setup new context with other address space */ | ||
| 119 | bl 1f /* Find our address */ | ||
| 120 | 1: mflr r9 | ||
| 121 | rlwimi r7,r9,0,20,31 | ||
| 122 | addi r7,r7,(2f - 1b) | ||
| 123 | mtspr SPRN_SRR0,r7 | ||
| 124 | mtspr SPRN_SRR1,r6 | ||
| 125 | rfi | ||
| 126 | 2: | ||
| 127 | /* 4. Clear out PIDs & Search info */ | ||
| 128 | li r6,0 | ||
| 129 | mtspr SPRN_MAS6,r6 | ||
| 130 | mtspr SPRN_PID0,r6 | ||
| 131 | |||
| 132 | mfspr r7,SPRN_MMUCFG | ||
| 133 | rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */ | ||
| 134 | cmpwi r7,3 | ||
| 135 | bne 2f /* skip if NPIDS != 3 */ | ||
| 136 | |||
| 137 | mtspr SPRN_PID1,r6 | ||
| 138 | mtspr SPRN_PID2,r6 | ||
| 139 | |||
| 140 | /* 5. Invalidate mapping we started in */ | ||
| 141 | 2: | ||
| 142 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 143 | rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ | ||
| 144 | mtspr SPRN_MAS0,r7 | ||
| 145 | tlbre | ||
| 146 | mfspr r6,SPRN_MAS1 | ||
| 147 | rlwinm r6,r6,0,2,0 /* clear IPROT */ | ||
| 148 | mtspr SPRN_MAS1,r6 | ||
| 149 | tlbwe | ||
| 150 | /* Invalidate TLB1 */ | ||
| 151 | li r9,0x0c | ||
| 152 | tlbivax 0,r9 | ||
| 153 | TLBSYNC | ||
| 154 | |||
| 155 | /* The mapping only needs to be cache-coherent on SMP */ | ||
| 156 | #ifdef CONFIG_SMP | ||
| 157 | #define M_IF_SMP MAS2_M | ||
| 158 | #else | ||
| 159 | #define M_IF_SMP 0 | ||
| 160 | #endif | ||
| 161 | |||
| 162 | #if defined(ENTRY_MAPPING_BOOT_SETUP) | ||
| 163 | |||
| 164 | /* 6. Setup KERNELBASE mapping in TLB1[0] */ | ||
| 165 | lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */ | ||
| 166 | mtspr SPRN_MAS0,r6 | ||
| 167 | lis r6,(MAS1_VALID|MAS1_IPROT)@h | ||
| 168 | ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l | ||
| 169 | mtspr SPRN_MAS1,r6 | ||
| 170 | lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h | ||
| 171 | ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l | ||
| 172 | mtspr SPRN_MAS2,r6 | ||
| 173 | mtspr SPRN_MAS3,r8 | ||
| 174 | tlbwe | ||
| 175 | |||
| 176 | /* 7. Jump to KERNELBASE mapping */ | ||
| 177 | lis r6,(KERNELBASE & ~0xfff)@h | ||
| 178 | ori r6,r6,(KERNELBASE & ~0xfff)@l | ||
| 179 | |||
| 180 | #elif defined(ENTRY_MAPPING_KEXEC_SETUP) | ||
| 181 | /* | ||
| 182 | * 6. Setup a 1:1 mapping in TLB1. Esel 0 is unsued, 1 or 2 contains the tmp | ||
| 183 | * mapping so we start at 3. We setup 8 mappings, each 256MiB in size. This | ||
| 184 | * will cover the first 2GiB of memory. | ||
| 185 | */ | ||
| 186 | |||
| 187 | lis r10, (MAS1_VALID|MAS1_IPROT)@h | ||
| 188 | ori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@l | ||
| 189 | li r11, 0 | ||
| 190 | li r0, 8 | ||
| 191 | mtctr r0 | ||
| 192 | |||
| 193 | next_tlb_setup: | ||
| 194 | addi r0, r11, 3 | ||
| 195 | rlwinm r0, r0, 16, 4, 15 // Compute esel | ||
| 196 | rlwinm r9, r11, 28, 0, 3 // Compute [ER]PN | ||
| 197 | oris r0, r0, (MAS0_TLBSEL(1))@h | ||
| 198 | mtspr SPRN_MAS0,r0 | ||
| 199 | mtspr SPRN_MAS1,r10 | ||
| 200 | mtspr SPRN_MAS2,r9 | ||
| 201 | ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR) | ||
| 202 | mtspr SPRN_MAS3,r9 | ||
| 203 | tlbwe | ||
| 204 | addi r11, r11, 1 | ||
| 205 | bdnz+ next_tlb_setup | ||
| 206 | |||
| 207 | /* 7. Jump to our 1:1 mapping */ | ||
| 208 | li r6, 0 | ||
| 209 | |||
| 210 | #else | ||
| 211 | #error You need to specify the mapping or not use this at all. | ||
| 212 | #endif | ||
| 213 | |||
| 214 | lis r7,MSR_KERNEL@h | ||
| 215 | ori r7,r7,MSR_KERNEL@l | ||
| 216 | bl 1f /* Find our address */ | ||
| 217 | 1: mflr r9 | ||
| 218 | rlwimi r6,r9,0,20,31 | ||
| 219 | addi r6,r6,(2f - 1b) | ||
| 220 | add r6, r6, r25 | ||
| 221 | mtspr SPRN_SRR0,r6 | ||
| 222 | mtspr SPRN_SRR1,r7 | ||
| 223 | rfi /* start execution out of TLB1[0] entry */ | ||
| 224 | |||
| 225 | /* 8. Clear out the temp mapping */ | ||
| 226 | 2: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 227 | rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */ | ||
| 228 | mtspr SPRN_MAS0,r7 | ||
| 229 | tlbre | ||
| 230 | mfspr r8,SPRN_MAS1 | ||
| 231 | rlwinm r8,r8,0,2,0 /* clear IPROT */ | ||
| 232 | mtspr SPRN_MAS1,r8 | ||
| 233 | tlbwe | ||
| 234 | /* Invalidate TLB1 */ | ||
| 235 | li r9,0x0c | ||
| 236 | tlbivax 0,r9 | ||
| 237 | TLBSYNC | ||
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index edd4a57fd29e..4faeba247854 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
| @@ -94,204 +94,10 @@ _ENTRY(_start); | |||
| 94 | */ | 94 | */ |
| 95 | 95 | ||
| 96 | _ENTRY(__early_start) | 96 | _ENTRY(__early_start) |
| 97 | /* 1. Find the index of the entry we're executing in */ | ||
| 98 | bl invstr /* Find our address */ | ||
| 99 | invstr: mflr r6 /* Make it accessible */ | ||
| 100 | mfmsr r7 | ||
| 101 | rlwinm r4,r7,27,31,31 /* extract MSR[IS] */ | ||
| 102 | mfspr r7, SPRN_PID0 | ||
| 103 | slwi r7,r7,16 | ||
| 104 | or r7,r7,r4 | ||
| 105 | mtspr SPRN_MAS6,r7 | ||
| 106 | tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */ | ||
| 107 | mfspr r7,SPRN_MAS1 | ||
| 108 | andis. r7,r7,MAS1_VALID@h | ||
| 109 | bne match_TLB | ||
| 110 | |||
| 111 | mfspr r7,SPRN_MMUCFG | ||
| 112 | rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */ | ||
| 113 | cmpwi r7,3 | ||
| 114 | bne match_TLB /* skip if NPIDS != 3 */ | ||
| 115 | |||
| 116 | mfspr r7,SPRN_PID1 | ||
| 117 | slwi r7,r7,16 | ||
| 118 | or r7,r7,r4 | ||
| 119 | mtspr SPRN_MAS6,r7 | ||
| 120 | tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */ | ||
| 121 | mfspr r7,SPRN_MAS1 | ||
| 122 | andis. r7,r7,MAS1_VALID@h | ||
| 123 | bne match_TLB | ||
| 124 | mfspr r7, SPRN_PID2 | ||
| 125 | slwi r7,r7,16 | ||
| 126 | or r7,r7,r4 | ||
| 127 | mtspr SPRN_MAS6,r7 | ||
| 128 | tlbsx 0,r6 /* Fall through, we had to match */ | ||
| 129 | |||
| 130 | match_TLB: | ||
| 131 | mfspr r7,SPRN_MAS0 | ||
| 132 | rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */ | ||
| 133 | |||
| 134 | mfspr r7,SPRN_MAS1 /* Insure IPROT set */ | ||
| 135 | oris r7,r7,MAS1_IPROT@h | ||
| 136 | mtspr SPRN_MAS1,r7 | ||
| 137 | tlbwe | ||
| 138 | |||
| 139 | /* 2. Invalidate all entries except the entry we're executing in */ | ||
| 140 | mfspr r9,SPRN_TLB1CFG | ||
| 141 | andi. r9,r9,0xfff | ||
| 142 | li r6,0 /* Set Entry counter to 0 */ | ||
| 143 | 1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 144 | rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */ | ||
| 145 | mtspr SPRN_MAS0,r7 | ||
| 146 | tlbre | ||
| 147 | mfspr r7,SPRN_MAS1 | ||
| 148 | rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */ | ||
| 149 | cmpw r3,r6 | ||
| 150 | beq skpinv /* Dont update the current execution TLB */ | ||
| 151 | mtspr SPRN_MAS1,r7 | ||
| 152 | tlbwe | ||
| 153 | isync | ||
| 154 | skpinv: addi r6,r6,1 /* Increment */ | ||
| 155 | cmpw r6,r9 /* Are we done? */ | ||
| 156 | bne 1b /* If not, repeat */ | ||
| 157 | |||
| 158 | /* Invalidate TLB0 */ | ||
| 159 | li r6,0x04 | ||
| 160 | tlbivax 0,r6 | ||
| 161 | TLBSYNC | ||
| 162 | /* Invalidate TLB1 */ | ||
| 163 | li r6,0x0c | ||
| 164 | tlbivax 0,r6 | ||
| 165 | TLBSYNC | ||
| 166 | |||
| 167 | /* 3. Setup a temp mapping and jump to it */ | ||
| 168 | andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */ | ||
| 169 | addi r5, r5, 0x1 | ||
| 170 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 171 | rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ | ||
| 172 | mtspr SPRN_MAS0,r7 | ||
| 173 | tlbre | ||
| 174 | |||
| 175 | /* grab and fixup the RPN */ | ||
| 176 | mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */ | ||
| 177 | rlwinm r6,r6,25,27,31 | ||
| 178 | li r8,-1 | ||
| 179 | addi r6,r6,10 | ||
| 180 | slw r6,r8,r6 /* convert to mask */ | ||
| 181 | |||
| 182 | bl 1f /* Find our address */ | ||
| 183 | 1: mflr r7 | ||
| 184 | |||
| 185 | mfspr r8,SPRN_MAS3 | ||
| 186 | #ifdef CONFIG_PHYS_64BIT | ||
| 187 | mfspr r23,SPRN_MAS7 | ||
| 188 | #endif | ||
| 189 | and r8,r6,r8 | ||
| 190 | subfic r9,r6,-4096 | ||
| 191 | and r9,r9,r7 | ||
| 192 | |||
| 193 | or r25,r8,r9 | ||
| 194 | ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR) | ||
| 195 | |||
| 196 | /* Just modify the entry ID and EPN for the temp mapping */ | ||
| 197 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 198 | rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */ | ||
| 199 | mtspr SPRN_MAS0,r7 | ||
| 200 | xori r6,r4,1 /* Setup TMP mapping in the other Address space */ | ||
| 201 | slwi r6,r6,12 | ||
| 202 | oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h | ||
| 203 | ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l | ||
| 204 | mtspr SPRN_MAS1,r6 | ||
| 205 | mfspr r6,SPRN_MAS2 | ||
| 206 | li r7,0 /* temp EPN = 0 */ | ||
| 207 | rlwimi r7,r6,0,20,31 | ||
| 208 | mtspr SPRN_MAS2,r7 | ||
| 209 | mtspr SPRN_MAS3,r8 | ||
| 210 | tlbwe | ||
| 211 | |||
| 212 | xori r6,r4,1 | ||
| 213 | slwi r6,r6,5 /* setup new context with other address space */ | ||
| 214 | bl 1f /* Find our address */ | ||
| 215 | 1: mflr r9 | ||
| 216 | rlwimi r7,r9,0,20,31 | ||
| 217 | addi r7,r7,(2f - 1b) | ||
| 218 | mtspr SPRN_SRR0,r7 | ||
| 219 | mtspr SPRN_SRR1,r6 | ||
| 220 | rfi | ||
| 221 | 2: | ||
| 222 | /* 4. Clear out PIDs & Search info */ | ||
| 223 | li r6,0 | ||
| 224 | mtspr SPRN_MAS6,r6 | ||
| 225 | mtspr SPRN_PID0,r6 | ||
| 226 | |||
| 227 | mfspr r7,SPRN_MMUCFG | ||
| 228 | rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */ | ||
| 229 | cmpwi r7,3 | ||
| 230 | bne 2f /* skip if NPIDS != 3 */ | ||
| 231 | 97 | ||
| 232 | mtspr SPRN_PID1,r6 | 98 | #define ENTRY_MAPPING_BOOT_SETUP |
| 233 | mtspr SPRN_PID2,r6 | 99 | #include "fsl_booke_entry_mapping.S" |
| 234 | 100 | #undef ENTRY_MAPPING_BOOT_SETUP | |
| 235 | /* 5. Invalidate mapping we started in */ | ||
| 236 | 2: | ||
| 237 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 238 | rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ | ||
| 239 | mtspr SPRN_MAS0,r7 | ||
| 240 | tlbre | ||
| 241 | mfspr r6,SPRN_MAS1 | ||
| 242 | rlwinm r6,r6,0,2,0 /* clear IPROT */ | ||
| 243 | mtspr SPRN_MAS1,r6 | ||
| 244 | tlbwe | ||
| 245 | /* Invalidate TLB1 */ | ||
| 246 | li r9,0x0c | ||
| 247 | tlbivax 0,r9 | ||
| 248 | TLBSYNC | ||
| 249 | |||
| 250 | /* The mapping only needs to be cache-coherent on SMP */ | ||
| 251 | #ifdef CONFIG_SMP | ||
| 252 | #define M_IF_SMP MAS2_M | ||
| 253 | #else | ||
| 254 | #define M_IF_SMP 0 | ||
| 255 | #endif | ||
| 256 | |||
| 257 | /* 6. Setup KERNELBASE mapping in TLB1[0] */ | ||
| 258 | lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */ | ||
| 259 | mtspr SPRN_MAS0,r6 | ||
| 260 | lis r6,(MAS1_VALID|MAS1_IPROT)@h | ||
| 261 | ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l | ||
| 262 | mtspr SPRN_MAS1,r6 | ||
| 263 | lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h | ||
| 264 | ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l | ||
| 265 | mtspr SPRN_MAS2,r6 | ||
| 266 | mtspr SPRN_MAS3,r8 | ||
| 267 | tlbwe | ||
| 268 | |||
| 269 | /* 7. Jump to KERNELBASE mapping */ | ||
| 270 | lis r6,(KERNELBASE & ~0xfff)@h | ||
| 271 | ori r6,r6,(KERNELBASE & ~0xfff)@l | ||
| 272 | lis r7,MSR_KERNEL@h | ||
| 273 | ori r7,r7,MSR_KERNEL@l | ||
| 274 | bl 1f /* Find our address */ | ||
| 275 | 1: mflr r9 | ||
| 276 | rlwimi r6,r9,0,20,31 | ||
| 277 | addi r6,r6,(2f - 1b) | ||
| 278 | mtspr SPRN_SRR0,r6 | ||
| 279 | mtspr SPRN_SRR1,r7 | ||
| 280 | rfi /* start execution out of TLB1[0] entry */ | ||
| 281 | |||
| 282 | /* 8. Clear out the temp mapping */ | ||
| 283 | 2: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | ||
| 284 | rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */ | ||
| 285 | mtspr SPRN_MAS0,r7 | ||
| 286 | tlbre | ||
| 287 | mfspr r8,SPRN_MAS1 | ||
| 288 | rlwinm r8,r8,0,2,0 /* clear IPROT */ | ||
| 289 | mtspr SPRN_MAS1,r8 | ||
| 290 | tlbwe | ||
| 291 | /* Invalidate TLB1 */ | ||
| 292 | li r9,0x0c | ||
| 293 | tlbivax 0,r9 | ||
| 294 | TLBSYNC | ||
| 295 | 101 | ||
| 296 | /* Establish the interrupt vector offsets */ | 102 | /* Establish the interrupt vector offsets */ |
| 297 | SET_IVOR(0, CriticalInput); | 103 | SET_IVOR(0, CriticalInput); |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 8043d1b73cf0..dc66d52dcff5 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
| @@ -711,6 +711,22 @@ relocate_new_kernel: | |||
| 711 | /* r4 = reboot_code_buffer */ | 711 | /* r4 = reboot_code_buffer */ |
| 712 | /* r5 = start_address */ | 712 | /* r5 = start_address */ |
| 713 | 713 | ||
| 714 | #ifdef CONFIG_FSL_BOOKE | ||
| 715 | |||
| 716 | mr r29, r3 | ||
| 717 | mr r30, r4 | ||
| 718 | mr r31, r5 | ||
| 719 | |||
| 720 | #define ENTRY_MAPPING_KEXEC_SETUP | ||
| 721 | #include "fsl_booke_entry_mapping.S" | ||
| 722 | #undef ENTRY_MAPPING_KEXEC_SETUP | ||
| 723 | |||
| 724 | mr r3, r29 | ||
| 725 | mr r4, r30 | ||
| 726 | mr r5, r31 | ||
| 727 | |||
| 728 | li r0, 0 | ||
| 729 | #else | ||
| 714 | li r0, 0 | 730 | li r0, 0 |
| 715 | 731 | ||
| 716 | /* | 732 | /* |
| @@ -727,6 +743,7 @@ relocate_new_kernel: | |||
| 727 | rfi | 743 | rfi |
| 728 | 744 | ||
| 729 | 1: | 745 | 1: |
| 746 | #endif | ||
| 730 | /* from this point address translation is turned off */ | 747 | /* from this point address translation is turned off */ |
| 731 | /* and interrupts are disabled */ | 748 | /* and interrupts are disabled */ |
| 732 | 749 | ||
diff --git a/arch/powerpc/kernel/swsusp_booke.S b/arch/powerpc/kernel/swsusp_booke.S new file mode 100644 index 000000000000..11a39307dd71 --- /dev/null +++ b/arch/powerpc/kernel/swsusp_booke.S | |||
| @@ -0,0 +1,193 @@ | |||
| 1 | /* | ||
| 2 | * Based on swsusp_32.S, modified for FSL BookE by | ||
| 3 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 4 | * Copyright (c) 2009-2010 MontaVista Software, LLC. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/threads.h> | ||
| 8 | #include <asm/processor.h> | ||
| 9 | #include <asm/page.h> | ||
| 10 | #include <asm/cputable.h> | ||
| 11 | #include <asm/thread_info.h> | ||
| 12 | #include <asm/ppc_asm.h> | ||
| 13 | #include <asm/asm-offsets.h> | ||
| 14 | #include <asm/mmu.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * Structure for storing CPU registers on the save area. | ||
| 18 | */ | ||
| 19 | #define SL_SP 0 | ||
| 20 | #define SL_PC 4 | ||
| 21 | #define SL_MSR 8 | ||
| 22 | #define SL_TCR 0xc | ||
| 23 | #define SL_SPRG0 0x10 | ||
| 24 | #define SL_SPRG1 0x14 | ||
| 25 | #define SL_SPRG2 0x18 | ||
| 26 | #define SL_SPRG3 0x1c | ||
| 27 | #define SL_SPRG4 0x20 | ||
| 28 | #define SL_SPRG5 0x24 | ||
| 29 | #define SL_SPRG6 0x28 | ||
| 30 | #define SL_SPRG7 0x2c | ||
| 31 | #define SL_TBU 0x30 | ||
| 32 | #define SL_TBL 0x34 | ||
| 33 | #define SL_R2 0x38 | ||
| 34 | #define SL_CR 0x3c | ||
| 35 | #define SL_LR 0x40 | ||
| 36 | #define SL_R12 0x44 /* r12 to r31 */ | ||
| 37 | #define SL_SIZE (SL_R12 + 80) | ||
| 38 | |||
| 39 | .section .data | ||
| 40 | .align 5 | ||
| 41 | |||
| 42 | _GLOBAL(swsusp_save_area) | ||
| 43 | .space SL_SIZE | ||
| 44 | |||
| 45 | |||
| 46 | .section .text | ||
| 47 | .align 5 | ||
| 48 | |||
| 49 | _GLOBAL(swsusp_arch_suspend) | ||
| 50 | lis r11,swsusp_save_area@h | ||
| 51 | ori r11,r11,swsusp_save_area@l | ||
| 52 | |||
| 53 | mflr r0 | ||
| 54 | stw r0,SL_LR(r11) | ||
| 55 | mfcr r0 | ||
| 56 | stw r0,SL_CR(r11) | ||
| 57 | stw r1,SL_SP(r11) | ||
| 58 | stw r2,SL_R2(r11) | ||
| 59 | stmw r12,SL_R12(r11) | ||
| 60 | |||
| 61 | /* Save MSR & TCR */ | ||
| 62 | mfmsr r4 | ||
| 63 | stw r4,SL_MSR(r11) | ||
| 64 | mfspr r4,SPRN_TCR | ||
| 65 | stw r4,SL_TCR(r11) | ||
| 66 | |||
| 67 | /* Get a stable timebase and save it */ | ||
| 68 | 1: mfspr r4,SPRN_TBRU | ||
| 69 | stw r4,SL_TBU(r11) | ||
| 70 | mfspr r5,SPRN_TBRL | ||
| 71 | stw r5,SL_TBL(r11) | ||
| 72 | mfspr r3,SPRN_TBRU | ||
| 73 | cmpw r3,r4 | ||
| 74 | bne 1b | ||
| 75 | |||
| 76 | /* Save SPRGs */ | ||
| 77 | mfsprg r4,0 | ||
| 78 | stw r4,SL_SPRG0(r11) | ||
| 79 | mfsprg r4,1 | ||
| 80 | stw r4,SL_SPRG1(r11) | ||
| 81 | mfsprg r4,2 | ||
| 82 | stw r4,SL_SPRG2(r11) | ||
| 83 | mfsprg r4,3 | ||
| 84 | stw r4,SL_SPRG3(r11) | ||
| 85 | mfsprg r4,4 | ||
| 86 | stw r4,SL_SPRG4(r11) | ||
| 87 | mfsprg r4,5 | ||
| 88 | stw r4,SL_SPRG5(r11) | ||
| 89 | mfsprg r4,6 | ||
| 90 | stw r4,SL_SPRG6(r11) | ||
| 91 | mfsprg r4,7 | ||
| 92 | stw r4,SL_SPRG7(r11) | ||
| 93 | |||
| 94 | /* Call the low level suspend stuff (we should probably have made | ||
| 95 | * a stackframe... | ||
| 96 | */ | ||
| 97 | bl swsusp_save | ||
| 98 | |||
| 99 | /* Restore LR from the save area */ | ||
| 100 | lis r11,swsusp_save_area@h | ||
| 101 | ori r11,r11,swsusp_save_area@l | ||
| 102 | lwz r0,SL_LR(r11) | ||
| 103 | mtlr r0 | ||
| 104 | |||
| 105 | blr | ||
| 106 | |||
| 107 | _GLOBAL(swsusp_arch_resume) | ||
| 108 | sync | ||
| 109 | |||
| 110 | /* Load ptr the list of pages to copy in r3 */ | ||
| 111 | lis r11,(restore_pblist)@h | ||
| 112 | ori r11,r11,restore_pblist@l | ||
| 113 | lwz r3,0(r11) | ||
| 114 | |||
| 115 | /* Copy the pages. This is a very basic implementation, to | ||
| 116 | * be replaced by something more cache efficient */ | ||
| 117 | 1: | ||
| 118 | li r0,256 | ||
| 119 | mtctr r0 | ||
| 120 | lwz r5,pbe_address(r3) /* source */ | ||
| 121 | lwz r6,pbe_orig_address(r3) /* destination */ | ||
| 122 | 2: | ||
| 123 | lwz r8,0(r5) | ||
| 124 | lwz r9,4(r5) | ||
| 125 | lwz r10,8(r5) | ||
| 126 | lwz r11,12(r5) | ||
| 127 | addi r5,r5,16 | ||
| 128 | stw r8,0(r6) | ||
| 129 | stw r9,4(r6) | ||
| 130 | stw r10,8(r6) | ||
| 131 | stw r11,12(r6) | ||
| 132 | addi r6,r6,16 | ||
| 133 | bdnz 2b | ||
| 134 | lwz r3,pbe_next(r3) | ||
| 135 | cmpwi 0,r3,0 | ||
| 136 | bne 1b | ||
| 137 | |||
| 138 | bl flush_dcache_L1 | ||
| 139 | bl flush_instruction_cache | ||
| 140 | |||
| 141 | lis r11,swsusp_save_area@h | ||
| 142 | ori r11,r11,swsusp_save_area@l | ||
| 143 | |||
| 144 | lwz r4,SL_SPRG0(r11) | ||
| 145 | mtsprg 0,r4 | ||
| 146 | lwz r4,SL_SPRG1(r11) | ||
| 147 | mtsprg 1,r4 | ||
| 148 | lwz r4,SL_SPRG2(r11) | ||
| 149 | mtsprg 2,r4 | ||
| 150 | lwz r4,SL_SPRG3(r11) | ||
| 151 | mtsprg 3,r4 | ||
| 152 | lwz r4,SL_SPRG4(r11) | ||
| 153 | mtsprg 4,r4 | ||
| 154 | lwz r4,SL_SPRG5(r11) | ||
| 155 | mtsprg 5,r4 | ||
| 156 | lwz r4,SL_SPRG6(r11) | ||
| 157 | mtsprg 6,r4 | ||
| 158 | lwz r4,SL_SPRG7(r11) | ||
| 159 | mtsprg 7,r4 | ||
| 160 | |||
| 161 | /* restore the MSR */ | ||
| 162 | lwz r3,SL_MSR(r11) | ||
| 163 | mtmsr r3 | ||
| 164 | |||
| 165 | /* Restore TB */ | ||
| 166 | li r3,0 | ||
| 167 | mtspr SPRN_TBWL,r3 | ||
| 168 | lwz r3,SL_TBU(r11) | ||
| 169 | lwz r4,SL_TBL(r11) | ||
| 170 | mtspr SPRN_TBWU,r3 | ||
| 171 | mtspr SPRN_TBWL,r4 | ||
| 172 | |||
| 173 | /* Restore TCR and clear any pending bits in TSR. */ | ||
| 174 | lwz r4,SL_TCR(r11) | ||
| 175 | mtspr SPRN_TCR,r4 | ||
| 176 | lis r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h | ||
| 177 | mtspr SPRN_TSR,r4 | ||
| 178 | |||
| 179 | /* Kick decrementer */ | ||
| 180 | li r0,1 | ||
| 181 | mtdec r0 | ||
| 182 | |||
| 183 | /* Restore the callee-saved registers and return */ | ||
| 184 | lwz r0,SL_CR(r11) | ||
| 185 | mtcr r0 | ||
| 186 | lwz r2,SL_R2(r11) | ||
| 187 | lmw r12,SL_R12(r11) | ||
| 188 | lwz r1,SL_SP(r11) | ||
| 189 | lwz r0,SL_LR(r11) | ||
| 190 | mtlr r0 | ||
| 191 | |||
| 192 | li r3,0 | ||
| 193 | blr | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 3031fc712ad0..25fc33984c2b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 2 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
| 3 | * Copyright 2007-2010 Freescale Semiconductor, Inc. | ||
| 3 | * | 4 | * |
| 4 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU General Public License | 6 | * modify it under the terms of the GNU General Public License |
| @@ -305,7 +306,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
| 305 | #ifndef CONFIG_FSL_BOOKE | 306 | #ifndef CONFIG_FSL_BOOKE |
| 306 | #define get_mc_reason(regs) ((regs)->dsisr) | 307 | #define get_mc_reason(regs) ((regs)->dsisr) |
| 307 | #else | 308 | #else |
| 308 | #define get_mc_reason(regs) (mfspr(SPRN_MCSR) & MCSR_MASK) | 309 | #define get_mc_reason(regs) (mfspr(SPRN_MCSR)) |
| 309 | #endif | 310 | #endif |
| 310 | #define REASON_FP ESR_FP | 311 | #define REASON_FP ESR_FP |
| 311 | #define REASON_ILLEGAL (ESR_PIL | ESR_PUO) | 312 | #define REASON_ILLEGAL (ESR_PIL | ESR_PUO) |
| @@ -421,6 +422,91 @@ int machine_check_47x(struct pt_regs *regs) | |||
| 421 | return 0; | 422 | return 0; |
| 422 | } | 423 | } |
| 423 | #elif defined(CONFIG_E500) | 424 | #elif defined(CONFIG_E500) |
| 425 | int machine_check_e500mc(struct pt_regs *regs) | ||
| 426 | { | ||
| 427 | unsigned long mcsr = mfspr(SPRN_MCSR); | ||
| 428 | unsigned long reason = mcsr; | ||
| 429 | int recoverable = 1; | ||
| 430 | |||
| 431 | printk("Machine check in kernel mode.\n"); | ||
| 432 | printk("Caused by (from MCSR=%lx): ", reason); | ||
| 433 | |||
| 434 | if (reason & MCSR_MCP) | ||
| 435 | printk("Machine Check Signal\n"); | ||
| 436 | |||
| 437 | if (reason & MCSR_ICPERR) { | ||
| 438 | printk("Instruction Cache Parity Error\n"); | ||
| 439 | |||
| 440 | /* | ||
| 441 | * This is recoverable by invalidating the i-cache. | ||
| 442 | */ | ||
| 443 | mtspr(SPRN_L1CSR1, mfspr(SPRN_L1CSR1) | L1CSR1_ICFI); | ||
| 444 | while (mfspr(SPRN_L1CSR1) & L1CSR1_ICFI) | ||
| 445 | ; | ||
| 446 | |||
| 447 | /* | ||
| 448 | * This will generally be accompanied by an instruction | ||
| 449 | * fetch error report -- only treat MCSR_IF as fatal | ||
| 450 | * if it wasn't due to an L1 parity error. | ||
| 451 | */ | ||
| 452 | reason &= ~MCSR_IF; | ||
| 453 | } | ||
| 454 | |||
| 455 | if (reason & MCSR_DCPERR_MC) { | ||
| 456 | printk("Data Cache Parity Error\n"); | ||
| 457 | recoverable = 0; | ||
| 458 | } | ||
| 459 | |||
| 460 | if (reason & MCSR_L2MMU_MHIT) { | ||
| 461 | printk("Hit on multiple TLB entries\n"); | ||
| 462 | recoverable = 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | if (reason & MCSR_NMI) | ||
| 466 | printk("Non-maskable interrupt\n"); | ||
| 467 | |||
| 468 | if (reason & MCSR_IF) { | ||
| 469 | printk("Instruction Fetch Error Report\n"); | ||
| 470 | recoverable = 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | if (reason & MCSR_LD) { | ||
| 474 | printk("Load Error Report\n"); | ||
| 475 | recoverable = 0; | ||
| 476 | } | ||
| 477 | |||
| 478 | if (reason & MCSR_ST) { | ||
| 479 | printk("Store Error Report\n"); | ||
| 480 | recoverable = 0; | ||
| 481 | } | ||
| 482 | |||
| 483 | if (reason & MCSR_LDG) { | ||
| 484 | printk("Guarded Load Error Report\n"); | ||
| 485 | recoverable = 0; | ||
| 486 | } | ||
| 487 | |||
| 488 | if (reason & MCSR_TLBSYNC) | ||
| 489 | printk("Simultaneous tlbsync operations\n"); | ||
| 490 | |||
| 491 | if (reason & MCSR_BSL2_ERR) { | ||
| 492 | printk("Level 2 Cache Error\n"); | ||
| 493 | recoverable = 0; | ||
| 494 | } | ||
| 495 | |||
| 496 | if (reason & MCSR_MAV) { | ||
| 497 | u64 addr; | ||
| 498 | |||
| 499 | addr = mfspr(SPRN_MCAR); | ||
| 500 | addr |= (u64)mfspr(SPRN_MCARU) << 32; | ||
| 501 | |||
| 502 | printk("Machine Check %s Address: %#llx\n", | ||
| 503 | reason & MCSR_MEA ? "Effective" : "Physical", addr); | ||
| 504 | } | ||
| 505 | |||
| 506 | mtspr(SPRN_MCSR, mcsr); | ||
| 507 | return mfspr(SPRN_MCSR) == 0 && recoverable; | ||
| 508 | } | ||
| 509 | |||
| 424 | int machine_check_e500(struct pt_regs *regs) | 510 | int machine_check_e500(struct pt_regs *regs) |
| 425 | { | 511 | { |
| 426 | unsigned long reason = get_mc_reason(regs); | 512 | unsigned long reason = get_mc_reason(regs); |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index f0684c8ac960..8fe87fc61485 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Freescale Semicondutor, Inc. 2006-2007. All rights reserved. | 2 | * Copyright (C) Freescale Semicondutor, Inc. 2006-2010. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * Author: Andy Fleming <afleming@freescale.com> | 4 | * Author: Andy Fleming <afleming@freescale.com> |
| 5 | * | 5 | * |
| @@ -154,6 +154,10 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev) | |||
| 154 | * Setup the architecture | 154 | * Setup the architecture |
| 155 | * | 155 | * |
| 156 | */ | 156 | */ |
| 157 | #ifdef CONFIG_SMP | ||
| 158 | extern void __init mpc85xx_smp_init(void); | ||
| 159 | #endif | ||
| 160 | |||
| 157 | static void __init mpc85xx_mds_setup_arch(void) | 161 | static void __init mpc85xx_mds_setup_arch(void) |
| 158 | { | 162 | { |
| 159 | struct device_node *np; | 163 | struct device_node *np; |
| @@ -194,6 +198,10 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
| 194 | } | 198 | } |
| 195 | #endif | 199 | #endif |
| 196 | 200 | ||
| 201 | #ifdef CONFIG_SMP | ||
| 202 | mpc85xx_smp_init(); | ||
| 203 | #endif | ||
| 204 | |||
| 197 | #ifdef CONFIG_QUICC_ENGINE | 205 | #ifdef CONFIG_QUICC_ENGINE |
| 198 | np = of_find_compatible_node(NULL, NULL, "fsl,qe"); | 206 | np = of_find_compatible_node(NULL, NULL, "fsl,qe"); |
| 199 | if (!np) { | 207 | if (!np) { |
| @@ -271,9 +279,49 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
| 271 | BCSR_UCC_RGMII, BCSR_UCC_RTBI); | 279 | BCSR_UCC_RGMII, BCSR_UCC_RTBI); |
| 272 | } | 280 | } |
| 273 | 281 | ||
| 282 | } else if (machine_is(p1021_mds)) { | ||
| 283 | #define BCSR11_ENET_MICRST (0x1 << 5) | ||
| 284 | /* Reset Micrel PHY */ | ||
| 285 | clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST); | ||
| 286 | setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST); | ||
| 274 | } | 287 | } |
| 288 | |||
| 275 | iounmap(bcsr_regs); | 289 | iounmap(bcsr_regs); |
| 276 | } | 290 | } |
| 291 | |||
| 292 | if (machine_is(p1021_mds)) { | ||
| 293 | #define MPC85xx_PMUXCR_OFFSET 0x60 | ||
| 294 | #define MPC85xx_PMUXCR_QE0 0x00008000 | ||
| 295 | #define MPC85xx_PMUXCR_QE3 0x00001000 | ||
| 296 | #define MPC85xx_PMUXCR_QE9 0x00000040 | ||
| 297 | #define MPC85xx_PMUXCR_QE12 0x00000008 | ||
| 298 | static __be32 __iomem *pmuxcr; | ||
| 299 | |||
| 300 | np = of_find_node_by_name(NULL, "global-utilities"); | ||
| 301 | |||
| 302 | if (np) { | ||
| 303 | pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET; | ||
| 304 | |||
| 305 | if (!pmuxcr) | ||
| 306 | printk(KERN_EMERG "Error: Alternate function" | ||
| 307 | " signal multiplex control register not" | ||
| 308 | " mapped!\n"); | ||
| 309 | else | ||
| 310 | /* P1021 has pins muxed for QE and other functions. To | ||
| 311 | * enable QE UEC mode, we need to set bit QE0 for UCC1 | ||
| 312 | * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9 | ||
| 313 | * and QE12 for QE MII management singals in PMUXCR | ||
| 314 | * register. | ||
| 315 | */ | ||
| 316 | setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 | | ||
| 317 | MPC85xx_PMUXCR_QE3 | | ||
| 318 | MPC85xx_PMUXCR_QE9 | | ||
| 319 | MPC85xx_PMUXCR_QE12); | ||
| 320 | |||
| 321 | of_node_put(np); | ||
| 322 | } | ||
| 323 | |||
| 324 | } | ||
| 277 | #endif /* CONFIG_QUICC_ENGINE */ | 325 | #endif /* CONFIG_QUICC_ENGINE */ |
| 278 | 326 | ||
| 279 | #ifdef CONFIG_SWIOTLB | 327 | #ifdef CONFIG_SWIOTLB |
| @@ -330,6 +378,16 @@ static struct of_device_id mpc85xx_ids[] = { | |||
| 330 | {}, | 378 | {}, |
| 331 | }; | 379 | }; |
| 332 | 380 | ||
| 381 | static struct of_device_id p1021_ids[] = { | ||
| 382 | { .type = "soc", }, | ||
| 383 | { .compatible = "soc", }, | ||
| 384 | { .compatible = "simple-bus", }, | ||
| 385 | { .type = "qe", }, | ||
| 386 | { .compatible = "fsl,qe", }, | ||
| 387 | { .compatible = "gianfar", }, | ||
| 388 | {}, | ||
| 389 | }; | ||
| 390 | |||
| 333 | static int __init mpc85xx_publish_devices(void) | 391 | static int __init mpc85xx_publish_devices(void) |
| 334 | { | 392 | { |
| 335 | if (machine_is(mpc8568_mds)) | 393 | if (machine_is(mpc8568_mds)) |
| @@ -342,11 +400,22 @@ static int __init mpc85xx_publish_devices(void) | |||
| 342 | 400 | ||
| 343 | return 0; | 401 | return 0; |
| 344 | } | 402 | } |
| 403 | |||
| 404 | static int __init p1021_publish_devices(void) | ||
| 405 | { | ||
| 406 | /* Publish the QE devices */ | ||
| 407 | of_platform_bus_probe(NULL, p1021_ids, NULL); | ||
| 408 | |||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | |||
| 345 | machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices); | 412 | machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices); |
| 346 | machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices); | 413 | machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices); |
| 414 | machine_device_initcall(p1021_mds, p1021_publish_devices); | ||
| 347 | 415 | ||
| 348 | machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier); | 416 | machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier); |
| 349 | machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier); | 417 | machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier); |
| 418 | machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier); | ||
| 350 | 419 | ||
| 351 | static void __init mpc85xx_mds_pic_init(void) | 420 | static void __init mpc85xx_mds_pic_init(void) |
| 352 | { | 421 | { |
| @@ -366,7 +435,7 @@ static void __init mpc85xx_mds_pic_init(void) | |||
| 366 | 435 | ||
| 367 | mpic = mpic_alloc(np, r.start, | 436 | mpic = mpic_alloc(np, r.start, |
| 368 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | | 437 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | |
| 369 | MPIC_BROKEN_FRR_NIRQS, | 438 | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU, |
| 370 | 0, 256, " OpenPIC "); | 439 | 0, 256, " OpenPIC "); |
| 371 | BUG_ON(mpic == NULL); | 440 | BUG_ON(mpic == NULL); |
| 372 | of_node_put(np); | 441 | of_node_put(np); |
| @@ -380,7 +449,11 @@ static void __init mpc85xx_mds_pic_init(void) | |||
| 380 | if (!np) | 449 | if (!np) |
| 381 | return; | 450 | return; |
| 382 | } | 451 | } |
| 383 | qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL); | 452 | if (machine_is(p1021_mds)) |
| 453 | qe_ic_init(np, 0, qe_ic_cascade_low_mpic, | ||
| 454 | qe_ic_cascade_high_mpic); | ||
| 455 | else | ||
| 456 | qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL); | ||
| 384 | of_node_put(np); | 457 | of_node_put(np); |
| 385 | #endif /* CONFIG_QUICC_ENGINE */ | 458 | #endif /* CONFIG_QUICC_ENGINE */ |
| 386 | } | 459 | } |
| @@ -426,3 +499,26 @@ define_machine(mpc8569_mds) { | |||
| 426 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | 499 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, |
| 427 | #endif | 500 | #endif |
| 428 | }; | 501 | }; |
| 502 | |||
| 503 | static int __init p1021_mds_probe(void) | ||
| 504 | { | ||
| 505 | unsigned long root = of_get_flat_dt_root(); | ||
| 506 | |||
| 507 | return of_flat_dt_is_compatible(root, "fsl,P1021MDS"); | ||
| 508 | |||
| 509 | } | ||
| 510 | |||
| 511 | define_machine(p1021_mds) { | ||
| 512 | .name = "P1021 MDS", | ||
| 513 | .probe = p1021_mds_probe, | ||
| 514 | .setup_arch = mpc85xx_mds_setup_arch, | ||
| 515 | .init_IRQ = mpc85xx_mds_pic_init, | ||
| 516 | .get_irq = mpic_get_irq, | ||
| 517 | .restart = fsl_rstcr_restart, | ||
| 518 | .calibrate_decr = generic_calibrate_decr, | ||
| 519 | .progress = udbg_progress, | ||
| 520 | #ifdef CONFIG_PCI | ||
| 521 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
| 522 | #endif | ||
| 523 | }; | ||
| 524 | |||
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index a7be144f5874..0f5bee90ee4e 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved. | 2 | * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. |
| 3 | * | 3 | * |
| 4 | * Author: Tony Li <tony.li@freescale.com> | 4 | * Author: Tony Li <tony.li@freescale.com> |
| 5 | * Jason Jin <Jason.jin@freescale.com> | 5 | * Jason Jin <Jason.jin@freescale.com> |
| @@ -22,14 +22,20 @@ | |||
| 22 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
| 23 | #include <asm/hw_irq.h> | 23 | #include <asm/hw_irq.h> |
| 24 | #include <asm/ppc-pci.h> | 24 | #include <asm/ppc-pci.h> |
| 25 | #include <asm/mpic.h> | ||
| 25 | #include "fsl_msi.h" | 26 | #include "fsl_msi.h" |
| 26 | 27 | ||
| 28 | LIST_HEAD(msi_head); | ||
| 29 | |||
| 27 | struct fsl_msi_feature { | 30 | struct fsl_msi_feature { |
| 28 | u32 fsl_pic_ip; | 31 | u32 fsl_pic_ip; |
| 29 | u32 msiir_offset; | 32 | u32 msiir_offset; |
| 30 | }; | 33 | }; |
| 31 | 34 | ||
| 32 | static struct fsl_msi *fsl_msi; | 35 | struct fsl_msi_cascade_data { |
| 36 | struct fsl_msi *msi_data; | ||
| 37 | int index; | ||
| 38 | }; | ||
| 33 | 39 | ||
| 34 | static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) | 40 | static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) |
| 35 | { | 41 | { |
| @@ -54,10 +60,12 @@ static struct irq_chip fsl_msi_chip = { | |||
| 54 | static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, | 60 | static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, |
| 55 | irq_hw_number_t hw) | 61 | irq_hw_number_t hw) |
| 56 | { | 62 | { |
| 63 | struct fsl_msi *msi_data = h->host_data; | ||
| 57 | struct irq_chip *chip = &fsl_msi_chip; | 64 | struct irq_chip *chip = &fsl_msi_chip; |
| 58 | 65 | ||
| 59 | irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; | 66 | irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; |
| 60 | 67 | ||
| 68 | set_irq_chip_data(virq, msi_data); | ||
| 61 | set_irq_chip_and_handler(virq, chip, handle_edge_irq); | 69 | set_irq_chip_and_handler(virq, chip, handle_edge_irq); |
| 62 | 70 | ||
| 63 | return 0; | 71 | return 0; |
| @@ -96,11 +104,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) | |||
| 96 | static void fsl_teardown_msi_irqs(struct pci_dev *pdev) | 104 | static void fsl_teardown_msi_irqs(struct pci_dev *pdev) |
| 97 | { | 105 | { |
| 98 | struct msi_desc *entry; | 106 | struct msi_desc *entry; |
| 99 | struct fsl_msi *msi_data = fsl_msi; | 107 | struct fsl_msi *msi_data; |
| 100 | 108 | ||
| 101 | list_for_each_entry(entry, &pdev->msi_list, list) { | 109 | list_for_each_entry(entry, &pdev->msi_list, list) { |
| 102 | if (entry->irq == NO_IRQ) | 110 | if (entry->irq == NO_IRQ) |
| 103 | continue; | 111 | continue; |
| 112 | msi_data = get_irq_data(entry->irq); | ||
| 104 | set_irq_msi(entry->irq, NULL); | 113 | set_irq_msi(entry->irq, NULL); |
| 105 | msi_bitmap_free_hwirqs(&msi_data->bitmap, | 114 | msi_bitmap_free_hwirqs(&msi_data->bitmap, |
| 106 | virq_to_hw(entry->irq), 1); | 115 | virq_to_hw(entry->irq), 1); |
| @@ -111,9 +120,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev) | |||
| 111 | } | 120 | } |
| 112 | 121 | ||
| 113 | static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | 122 | static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, |
| 114 | struct msi_msg *msg) | 123 | struct msi_msg *msg, |
| 124 | struct fsl_msi *fsl_msi_data) | ||
| 115 | { | 125 | { |
| 116 | struct fsl_msi *msi_data = fsl_msi; | 126 | struct fsl_msi *msi_data = fsl_msi_data; |
| 117 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | 127 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
| 118 | u32 base = 0; | 128 | u32 base = 0; |
| 119 | 129 | ||
| @@ -130,14 +140,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | |||
| 130 | 140 | ||
| 131 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 141 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
| 132 | { | 142 | { |
| 133 | int rc, hwirq; | 143 | int rc, hwirq = -ENOMEM; |
| 134 | unsigned int virq; | 144 | unsigned int virq; |
| 135 | struct msi_desc *entry; | 145 | struct msi_desc *entry; |
| 136 | struct msi_msg msg; | 146 | struct msi_msg msg; |
| 137 | struct fsl_msi *msi_data = fsl_msi; | 147 | struct fsl_msi *msi_data; |
| 138 | 148 | ||
| 139 | list_for_each_entry(entry, &pdev->msi_list, list) { | 149 | list_for_each_entry(entry, &pdev->msi_list, list) { |
| 140 | hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); | 150 | list_for_each_entry(msi_data, &msi_head, list) { |
| 151 | hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); | ||
| 152 | if (hwirq >= 0) | ||
| 153 | break; | ||
| 154 | } | ||
| 155 | |||
| 141 | if (hwirq < 0) { | 156 | if (hwirq < 0) { |
| 142 | rc = hwirq; | 157 | rc = hwirq; |
| 143 | pr_debug("%s: fail allocating msi interrupt\n", | 158 | pr_debug("%s: fail allocating msi interrupt\n", |
| @@ -154,25 +169,31 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
| 154 | rc = -ENOSPC; | 169 | rc = -ENOSPC; |
| 155 | goto out_free; | 170 | goto out_free; |
| 156 | } | 171 | } |
| 172 | set_irq_data(virq, msi_data); | ||
| 157 | set_irq_msi(virq, entry); | 173 | set_irq_msi(virq, entry); |
| 158 | 174 | ||
| 159 | fsl_compose_msi_msg(pdev, hwirq, &msg); | 175 | fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data); |
| 160 | write_msi_msg(virq, &msg); | 176 | write_msi_msg(virq, &msg); |
| 161 | } | 177 | } |
| 162 | return 0; | 178 | return 0; |
| 163 | 179 | ||
| 164 | out_free: | 180 | out_free: |
| 181 | /* free by the caller of this function */ | ||
| 165 | return rc; | 182 | return rc; |
| 166 | } | 183 | } |
| 167 | 184 | ||
| 168 | static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | 185 | static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) |
| 169 | { | 186 | { |
| 170 | unsigned int cascade_irq; | 187 | unsigned int cascade_irq; |
| 171 | struct fsl_msi *msi_data = fsl_msi; | 188 | struct fsl_msi *msi_data; |
| 172 | int msir_index = -1; | 189 | int msir_index = -1; |
| 173 | u32 msir_value = 0; | 190 | u32 msir_value = 0; |
| 174 | u32 intr_index; | 191 | u32 intr_index; |
| 175 | u32 have_shift = 0; | 192 | u32 have_shift = 0; |
| 193 | struct fsl_msi_cascade_data *cascade_data; | ||
| 194 | |||
| 195 | cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq); | ||
| 196 | msi_data = cascade_data->msi_data; | ||
| 176 | 197 | ||
| 177 | raw_spin_lock(&desc->lock); | 198 | raw_spin_lock(&desc->lock); |
| 178 | if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { | 199 | if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { |
| @@ -187,13 +208,13 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
| 187 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 208 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
| 188 | goto unlock; | 209 | goto unlock; |
| 189 | 210 | ||
| 190 | msir_index = (int)desc->handler_data; | 211 | msir_index = cascade_data->index; |
| 191 | 212 | ||
| 192 | if (msir_index >= NR_MSI_REG) | 213 | if (msir_index >= NR_MSI_REG) |
| 193 | cascade_irq = NO_IRQ; | 214 | cascade_irq = NO_IRQ; |
| 194 | 215 | ||
| 195 | desc->status |= IRQ_INPROGRESS; | 216 | desc->status |= IRQ_INPROGRESS; |
| 196 | switch (fsl_msi->feature & FSL_PIC_IP_MASK) { | 217 | switch (msi_data->feature & FSL_PIC_IP_MASK) { |
| 197 | case FSL_PIC_IP_MPIC: | 218 | case FSL_PIC_IP_MPIC: |
| 198 | msir_value = fsl_msi_read(msi_data->msi_regs, | 219 | msir_value = fsl_msi_read(msi_data->msi_regs, |
| 199 | msir_index * 0x10); | 220 | msir_index * 0x10); |
| @@ -229,6 +250,30 @@ unlock: | |||
| 229 | raw_spin_unlock(&desc->lock); | 250 | raw_spin_unlock(&desc->lock); |
| 230 | } | 251 | } |
| 231 | 252 | ||
| 253 | static int fsl_of_msi_remove(struct of_device *ofdev) | ||
| 254 | { | ||
| 255 | struct fsl_msi *msi = ofdev->dev.platform_data; | ||
| 256 | int virq, i; | ||
| 257 | struct fsl_msi_cascade_data *cascade_data; | ||
| 258 | |||
| 259 | if (msi->list.prev != NULL) | ||
| 260 | list_del(&msi->list); | ||
| 261 | for (i = 0; i < NR_MSI_REG; i++) { | ||
| 262 | virq = msi->msi_virqs[i]; | ||
| 263 | if (virq != NO_IRQ) { | ||
| 264 | cascade_data = get_irq_data(virq); | ||
| 265 | kfree(cascade_data); | ||
| 266 | irq_dispose_mapping(virq); | ||
| 267 | } | ||
| 268 | } | ||
| 269 | if (msi->bitmap.bitmap) | ||
| 270 | msi_bitmap_free(&msi->bitmap); | ||
| 271 | iounmap(msi->msi_regs); | ||
| 272 | kfree(msi); | ||
| 273 | |||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 232 | static int __devinit fsl_of_msi_probe(struct of_device *dev, | 277 | static int __devinit fsl_of_msi_probe(struct of_device *dev, |
| 233 | const struct of_device_id *match) | 278 | const struct of_device_id *match) |
| 234 | { | 279 | { |
| @@ -239,15 +284,18 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, | |||
| 239 | int virt_msir; | 284 | int virt_msir; |
| 240 | const u32 *p; | 285 | const u32 *p; |
| 241 | struct fsl_msi_feature *features = match->data; | 286 | struct fsl_msi_feature *features = match->data; |
| 287 | struct fsl_msi_cascade_data *cascade_data = NULL; | ||
| 288 | int len; | ||
| 289 | u32 offset; | ||
| 242 | 290 | ||
| 243 | printk(KERN_DEBUG "Setting up Freescale MSI support\n"); | 291 | printk(KERN_DEBUG "Setting up Freescale MSI support\n"); |
| 244 | 292 | ||
| 245 | msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); | 293 | msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); |
| 246 | if (!msi) { | 294 | if (!msi) { |
| 247 | dev_err(&dev->dev, "No memory for MSI structure\n"); | 295 | dev_err(&dev->dev, "No memory for MSI structure\n"); |
| 248 | err = -ENOMEM; | 296 | return -ENOMEM; |
| 249 | goto error_out; | ||
| 250 | } | 297 | } |
| 298 | dev->dev.platform_data = msi; | ||
| 251 | 299 | ||
| 252 | msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR, | 300 | msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR, |
| 253 | NR_MSI_IRQS, &fsl_msi_host_ops, 0); | 301 | NR_MSI_IRQS, &fsl_msi_host_ops, 0); |
| @@ -298,27 +346,47 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, | |||
| 298 | err = -EINVAL; | 346 | err = -EINVAL; |
| 299 | goto error_out; | 347 | goto error_out; |
| 300 | } | 348 | } |
| 349 | offset = 0; | ||
| 350 | p = of_get_property(dev->node, "msi-available-ranges", &len); | ||
| 351 | if (p) | ||
| 352 | offset = *p / IRQS_PER_MSI_REG; | ||
| 301 | 353 | ||
| 302 | count /= sizeof(u32); | 354 | count /= sizeof(u32); |
| 303 | for (i = 0; i < count / 2; i++) { | 355 | for (i = 0; i < min(count / 2, NR_MSI_REG); i++) { |
| 304 | if (i > NR_MSI_REG) | ||
| 305 | break; | ||
| 306 | virt_msir = irq_of_parse_and_map(dev->dev.of_node, i); | 356 | virt_msir = irq_of_parse_and_map(dev->dev.of_node, i); |
| 307 | if (virt_msir != NO_IRQ) { | 357 | if (virt_msir != NO_IRQ) { |
| 308 | set_irq_data(virt_msir, (void *)i); | 358 | cascade_data = kzalloc( |
| 359 | sizeof(struct fsl_msi_cascade_data), | ||
| 360 | GFP_KERNEL); | ||
| 361 | if (!cascade_data) { | ||
| 362 | dev_err(&dev->dev, | ||
| 363 | "No memory for MSI cascade data\n"); | ||
| 364 | err = -ENOMEM; | ||
| 365 | goto error_out; | ||
| 366 | } | ||
| 367 | msi->msi_virqs[i] = virt_msir; | ||
| 368 | cascade_data->index = i + offset; | ||
| 369 | cascade_data->msi_data = msi; | ||
| 370 | set_irq_data(virt_msir, (void *)cascade_data); | ||
| 309 | set_irq_chained_handler(virt_msir, fsl_msi_cascade); | 371 | set_irq_chained_handler(virt_msir, fsl_msi_cascade); |
| 310 | } | 372 | } |
| 311 | } | 373 | } |
| 312 | 374 | ||
| 313 | fsl_msi = msi; | 375 | list_add_tail(&msi->list, &msi_head); |
| 314 | 376 | ||
| 315 | WARN_ON(ppc_md.setup_msi_irqs); | 377 | /* The multiple setting ppc_md.setup_msi_irqs will not harm things */ |
| 316 | ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; | 378 | if (!ppc_md.setup_msi_irqs) { |
| 317 | ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; | 379 | ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; |
| 318 | ppc_md.msi_check_device = fsl_msi_check_device; | 380 | ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; |
| 381 | ppc_md.msi_check_device = fsl_msi_check_device; | ||
| 382 | } else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) { | ||
| 383 | dev_err(&dev->dev, "Different MSI driver already installed!\n"); | ||
| 384 | err = -ENODEV; | ||
| 385 | goto error_out; | ||
| 386 | } | ||
| 319 | return 0; | 387 | return 0; |
| 320 | error_out: | 388 | error_out: |
| 321 | kfree(msi); | 389 | fsl_of_msi_remove(dev); |
| 322 | return err; | 390 | return err; |
| 323 | } | 391 | } |
| 324 | 392 | ||
| @@ -351,6 +419,7 @@ static struct of_platform_driver fsl_of_msi_driver = { | |||
| 351 | .of_match_table = fsl_of_msi_ids, | 419 | .of_match_table = fsl_of_msi_ids, |
| 352 | }, | 420 | }, |
| 353 | .probe = fsl_of_msi_probe, | 421 | .probe = fsl_of_msi_probe, |
| 422 | .remove = fsl_of_msi_remove, | ||
| 354 | }; | 423 | }; |
| 355 | 424 | ||
| 356 | static __init int fsl_of_msi_init(void) | 425 | static __init int fsl_of_msi_init(void) |
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 331c7e7025b7..624580c252d7 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h | |||
| @@ -32,8 +32,11 @@ struct fsl_msi { | |||
| 32 | u32 msi_addr_hi; | 32 | u32 msi_addr_hi; |
| 33 | void __iomem *msi_regs; | 33 | void __iomem *msi_regs; |
| 34 | u32 feature; | 34 | u32 feature; |
| 35 | int msi_virqs[NR_MSI_REG]; | ||
| 35 | 36 | ||
| 36 | struct msi_bitmap bitmap; | 37 | struct msi_bitmap bitmap; |
| 38 | |||
| 39 | struct list_head list; /* support multiple MSI banks */ | ||
| 37 | }; | 40 | }; |
| 38 | 41 | ||
| 39 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ | 42 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ |
