diff options
author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-04 22:22:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-04 22:22:33 -0500 |
commit | 15a4cb9c25df05a5d4844e80a1aea83d66165868 (patch) | |
tree | bcb4f7c6e84f501ee6ce8c7a740cc7c4ec92447d | |
parent | ff51a98799931256b555446b2f5675db08de6229 (diff) | |
parent | d8594d639135b500bf6010f981ea854092d54030 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc
* master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc: (194 commits)
[POWERPC] Add missing EXPORTS for mpc52xx support
[POWERPC] Remove obsolete PPC_52xx and update CLASSIC32 comment
[POWERPC] ps3: add a default zImage target
[POWERPC] Add of_platform_bus support to mpc52xx psc uart driver
[POWERPC] typo fix and whitespace cleanup on mpc52xx-uart driver
[POWERPC] Fix debug printks for 32-bit resources in the PCI code
[POWERPC] Replace kmalloc+memset with kzalloc
[POWERPC] Linkstation / kurobox support
[POWERPC] Add the e300c3 core to the CPU table.
[POWERPC] ppc: m48t35 add missing bracket
[POWERPC] iSeries: don't build head_64.o unnecessarily
[POWERPC] iSeries: stop dt_mod.o being rebuilt unnecessarily
[POWERPC] Fix cputable.h for combined build
[POWERPC] Allow CONFIG_BOOTX_TEXT on iSeries
[POWERPC] Allow xmon to build on legacy iSeries
[POWERPC] Change ppc64_defconfig to use AUTOFS_V4 not V3
[POWERPC] Tell firmware we can handle POWER6 compatible mode
[POWERPC] Clean images in arch/powerpc/boot
[POWERPC] Fix OF pci flags parsing
[POWERPC] defconfig for lite5200 board
...
298 files changed, 25464 insertions, 5051 deletions
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 4ac2d641fcb..b3bd36668db 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
@@ -6,6 +6,8 @@ | |||
6 | IBM Corp. | 6 | IBM Corp. |
7 | (c) 2005 Becky Bruce <becky.bruce at freescale.com>, | 7 | (c) 2005 Becky Bruce <becky.bruce at freescale.com>, |
8 | Freescale Semiconductor, FSL SOC and 32-bit additions | 8 | Freescale Semiconductor, FSL SOC and 32-bit additions |
9 | (c) 2006 MontaVista Software, Inc. | ||
10 | Flash chip node definition | ||
9 | 11 | ||
10 | May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet. | 12 | May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet. |
11 | 13 | ||
@@ -1693,6 +1695,43 @@ platforms are moved over to use the flattened-device-tree model. | |||
1693 | }; | 1695 | }; |
1694 | }; | 1696 | }; |
1695 | 1697 | ||
1698 | g) Flash chip nodes | ||
1699 | |||
1700 | Flash chips (Memory Technology Devices) are often used for solid state | ||
1701 | file systems on embedded devices. | ||
1702 | |||
1703 | Required properties: | ||
1704 | |||
1705 | - device_type : has to be "rom" | ||
1706 | - compatible : Should specify what this ROM device is compatible with | ||
1707 | (i.e. "onenand"). Currently, this is most likely to be "direct-mapped" | ||
1708 | (which corresponds to the MTD physmap mapping driver). | ||
1709 | - regs : Offset and length of the register set (or memory mapping) for | ||
1710 | the device. | ||
1711 | |||
1712 | Recommended properties : | ||
1713 | |||
1714 | - bank-width : Width of the flash data bus in bytes. Required | ||
1715 | for the NOR flashes (compatible == "direct-mapped" and others) ONLY. | ||
1716 | - partitions : Several pairs of 32-bit values where the first value is | ||
1717 | partition's offset from the start of the device and the second one is | ||
1718 | partition size in bytes with LSB used to signify a read only | ||
1719 | partititon (so, the parition size should always be an even number). | ||
1720 | - partition-names : The list of concatenated zero terminated strings | ||
1721 | representing the partition names. | ||
1722 | |||
1723 | Example: | ||
1724 | |||
1725 | flash@ff000000 { | ||
1726 | device_type = "rom"; | ||
1727 | compatible = "direct-mapped"; | ||
1728 | regs = <ff000000 01000000>; | ||
1729 | bank-width = <4>; | ||
1730 | partitions = <00000000 00f80000 | ||
1731 | 00f80000 00080001>; | ||
1732 | partition-names = "fs\0firmware"; | ||
1733 | }; | ||
1734 | |||
1696 | More devices will be defined as this spec matures. | 1735 | More devices will be defined as this spec matures. |
1697 | 1736 | ||
1698 | 1737 | ||
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt new file mode 100644 index 00000000000..d077d764f82 --- /dev/null +++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt | |||
@@ -0,0 +1,189 @@ | |||
1 | MPC52xx Device Tree Bindings | ||
2 | ---------------------------- | ||
3 | |||
4 | (c) 2006 Secret Lab Technologies Ltd | ||
5 | Grant Likely <grant.likely at secretlab.ca> | ||
6 | |||
7 | I - Introduction | ||
8 | ================ | ||
9 | Boards supported by the arch/powerpc architecture require device tree be | ||
10 | passed by the boot loader to the kernel at boot time. The device tree | ||
11 | describes what devices are present on the board and how they are | ||
12 | connected. The device tree can either be passed as a binary blob (as | ||
13 | described in Documentation/powerpc/booting-without-of.txt), or passed | ||
14 | by Open Firmare (IEEE 1275) compatible firmware using an OF compatible | ||
15 | client interface API. | ||
16 | |||
17 | This document specifies the requirements on the device-tree for mpc52xx | ||
18 | based boards. These requirements are above and beyond the details | ||
19 | specified in either the OpenFirmware spec or booting-without-of.txt | ||
20 | |||
21 | All new mpc52xx-based boards are expected to match this document. In | ||
22 | cases where this document is not sufficient to support a new board port, | ||
23 | this document should be updated as part of adding the new board support. | ||
24 | |||
25 | II - Philosophy | ||
26 | =============== | ||
27 | The core of this document is naming convention. The whole point of | ||
28 | defining this convention is to reduce or eliminate the number of | ||
29 | special cases required to support a 52xx board. If all 52xx boards | ||
30 | follow the same convention, then generic 52xx support code will work | ||
31 | rather than coding special cases for each new board. | ||
32 | |||
33 | This section tries to capture the thought process behind why the naming | ||
34 | convention is what it is. | ||
35 | |||
36 | 1. Node names | ||
37 | ------------- | ||
38 | There is strong convention/requirements already established for children | ||
39 | of the root node. 'cpus' describes the processor cores, 'memory' | ||
40 | describes memory, and 'chosen' provides boot configuration. Other nodes | ||
41 | are added to describe devices attached to the processor local bus. | ||
42 | Following convention already established with other system-on-chip | ||
43 | processors, MPC52xx boards must have an 'soc5200' node as a child of the | ||
44 | root node. | ||
45 | |||
46 | The soc5200 node holds child nodes for all on chip devices. Child nodes | ||
47 | are typically named after the configured function. ie. the FEC node is | ||
48 | named 'ethernet', and a PSC in uart mode is named 'serial'. | ||
49 | |||
50 | 2. device_type property | ||
51 | ----------------------- | ||
52 | similar to the node name convention above; the device_type reflects the | ||
53 | configured function of a device. ie. 'serial' for a uart and 'spi' for | ||
54 | an spi controller. However, while node names *should* reflect the | ||
55 | configured function, device_type *must* match the configured function | ||
56 | exactly. | ||
57 | |||
58 | 3. compatible property | ||
59 | ---------------------- | ||
60 | Since device_type isn't enough to match devices to drivers, there also | ||
61 | needs to be a naming convention for the compatible property. Compatible | ||
62 | is an list of device descriptions sorted from specific to generic. For | ||
63 | the mpc52xx, the required format for each compatible value is | ||
64 | <chip>-<device>[-<mode>]. At the minimum, the list shall contain two | ||
65 | items; the first specifying the exact chip, and the second specifying | ||
66 | mpc52xx for the chip. | ||
67 | |||
68 | ie. ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc52xx-ethernet" | ||
69 | |||
70 | The idea here is that most drivers will match to the most generic field | ||
71 | in the compatible list (mpc52xx-*), but can also test the more specific | ||
72 | field for enabling bug fixes or extra features. | ||
73 | |||
74 | Modal devices, like PSCs, also append the configured function to the | ||
75 | end of the compatible field. ie. A PSC in i2s mode would specify | ||
76 | "mpc52xx-psc-i2s", not "mpc52xx-i2s". This convention is chosen to | ||
77 | avoid naming conflicts with non-psc devices providing the same | ||
78 | function. For example, "mpc52xx-spi" and "mpc52xx-psc-spi" describe | ||
79 | the mpc5200 simple spi device and a PSC spi mode respectively. | ||
80 | |||
81 | If the soc device is more generic and present on other SOCs, the | ||
82 | compatible property can specify the more generic device type also. | ||
83 | |||
84 | ie. mscan: compatible = "mpc5200-mscan\0mpc52xx-mscan\0fsl,mscan"; | ||
85 | |||
86 | At the time of writing, exact chip may be either 'mpc5200' or | ||
87 | 'mpc5200b'. | ||
88 | |||
89 | Device drivers should always try to match as generically as possible. | ||
90 | |||
91 | III - Structure | ||
92 | =============== | ||
93 | The device tree for an mpc52xx board follows the structure defined in | ||
94 | booting-without-of.txt with the following additional notes: | ||
95 | |||
96 | 0) the root node | ||
97 | ---------------- | ||
98 | Typical root description node; see booting-without-of | ||
99 | |||
100 | 1) The cpus node | ||
101 | ---------------- | ||
102 | The cpus node follows the basic layout described in booting-without-of. | ||
103 | The bus-frequency property holds the XLB bus frequency | ||
104 | The clock-frequency property holds the core frequency | ||
105 | |||
106 | 2) The memory node | ||
107 | ------------------ | ||
108 | Typical memory description node; see booting-without-of. | ||
109 | |||
110 | 3) The soc5200 node | ||
111 | ------------------- | ||
112 | This node describes the on chip SOC peripherals. Every mpc52xx based | ||
113 | board will have this node, and as such there is a common naming | ||
114 | convention for SOC devices. | ||
115 | |||
116 | Required properties: | ||
117 | name type description | ||
118 | ---- ---- ----------- | ||
119 | device_type string must be "soc" | ||
120 | ranges int should be <0 baseaddr baseaddr+10000> | ||
121 | reg int must be <baseaddr 10000> | ||
122 | |||
123 | Recommended properties: | ||
124 | name type description | ||
125 | ---- ---- ----------- | ||
126 | compatible string should be "<chip>-soc\0mpc52xx-soc" | ||
127 | ie. "mpc5200b-soc\0mpc52xx-soc" | ||
128 | #interrupt-cells int must be <3>. If it is not defined | ||
129 | here then it must be defined in every | ||
130 | soc device node. | ||
131 | bus-frequency int IPB bus frequency in HZ. Clock rate | ||
132 | used by most of the soc devices. | ||
133 | Defining it here avoids needing it | ||
134 | added to every device node. | ||
135 | |||
136 | 4) soc5200 child nodes | ||
137 | ---------------------- | ||
138 | Any on chip SOC devices available to Linux must appear as soc5200 child nodes. | ||
139 | |||
140 | Note: in the tables below, '*' matches all <chip> values. ie. | ||
141 | *-pic would translate to "mpc5200-pic\0mpc52xx-pic" | ||
142 | |||
143 | Required soc5200 child nodes: | ||
144 | name device_type compatible Description | ||
145 | ---- ----------- ---------- ----------- | ||
146 | cdm@<addr> cdm *-cmd Clock Distribution | ||
147 | pic@<addr> interrupt-controller *-pic need an interrupt | ||
148 | controller to boot | ||
149 | bestcomm@<addr> dma-controller *-bestcomm 52xx pic also requires | ||
150 | the bestcomm device | ||
151 | |||
152 | Recommended soc5200 child nodes; populate as needed for your board | ||
153 | name device_type compatible Description | ||
154 | ---- ----------- ---------- ----------- | ||
155 | gpt@<addr> gpt *-gpt General purpose timers | ||
156 | rtc@<addr> rtc *-rtc Real time clock | ||
157 | mscan@<addr> mscan *-mscan CAN bus controller | ||
158 | pci@<addr> pci *-pci PCI bridge | ||
159 | serial@<addr> serial *-psc-uart PSC in serial mode | ||
160 | i2s@<addr> i2s *-psc-i2s PSC in i2s mode | ||
161 | ac97@<addr> ac97 *-psc-ac97 PSC in ac97 mode | ||
162 | spi@<addr> spi *-psc-spi PSC in spi mode | ||
163 | irda@<addr> irda *-psc-irda PSC in IrDA mode | ||
164 | spi@<addr> spi *-spi MPC52xx spi device | ||
165 | ethernet@<addr> network *-fec MPC52xx ethernet device | ||
166 | ata@<addr> ata *-ata IDE ATA interface | ||
167 | i2c@<addr> i2c *-i2c I2C controller | ||
168 | usb@<addr> usb-ohci-be *-ohci,ohci-be USB controller | ||
169 | xlb@<addr> xlb *-xlb XLB arbritrator | ||
170 | |||
171 | IV - Extra Notes | ||
172 | ================ | ||
173 | |||
174 | 1. Interrupt mapping | ||
175 | -------------------- | ||
176 | The mpc52xx pic driver splits hardware IRQ numbers into two levels. The | ||
177 | split reflects the layout of the PIC hardware itself, which groups | ||
178 | interrupts into one of three groups; CRIT, MAIN or PERP. Also, the | ||
179 | Bestcomm dma engine has it's own set of interrupt sources which are | ||
180 | cascaded off of peripheral interrupt 0, which the driver interprets as a | ||
181 | fourth group, SDMA. | ||
182 | |||
183 | The interrupts property for device nodes using the mpc52xx pic consists | ||
184 | of three cells; <L1 L2 level> | ||
185 | |||
186 | L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3] | ||
187 | L2 := interrupt number; directly mapped from the value in the | ||
188 | "ICTL PerStat, MainStat, CritStat Encoded Register" | ||
189 | level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3] | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 8385a69138a..5dff26814a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2438,6 +2438,13 @@ M: promise@pnd-pc.demon.co.uk | |||
2438 | W: http://www.pnd-pc.demon.co.uk/promise/ | 2438 | W: http://www.pnd-pc.demon.co.uk/promise/ |
2439 | S: Maintained | 2439 | S: Maintained |
2440 | 2440 | ||
2441 | PS3 PLATFORM SUPPORT | ||
2442 | P: Geoff Levand | ||
2443 | M: geoffrey.levand@am.sony.com | ||
2444 | L: linuxppc-dev@ozlabs.org | ||
2445 | L: cbe-oss-dev@ozlabs.org | ||
2446 | S: Supported | ||
2447 | |||
2441 | PVRUSB2 VIDEO4LINUX DRIVER | 2448 | PVRUSB2 VIDEO4LINUX DRIVER |
2442 | P: Mike Isely | 2449 | P: Mike Isely |
2443 | M: isely@pobox.com | 2450 | M: isely@pobox.com |
diff --git a/arch/powerpc/.gitignore b/arch/powerpc/.gitignore new file mode 100644 index 00000000000..a1a869c8c84 --- /dev/null +++ b/arch/powerpc/.gitignore | |||
@@ -0,0 +1 @@ | |||
include | |||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 116d7d3683e..291c95ac4b3 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -112,7 +112,7 @@ choice | |||
112 | default 6xx | 112 | default 6xx |
113 | 113 | ||
114 | config CLASSIC32 | 114 | config CLASSIC32 |
115 | bool "6xx/7xx/74xx" | 115 | bool "52xx/6xx/7xx/74xx" |
116 | select PPC_FPU | 116 | select PPC_FPU |
117 | select 6xx | 117 | select 6xx |
118 | help | 118 | help |
@@ -121,16 +121,18 @@ config CLASSIC32 | |||
121 | versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC | 121 | versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC |
122 | embedded versions (403 and 405) and the high end 64 bit Power | 122 | embedded versions (403 and 405) and the high end 64 bit Power |
123 | processors (POWER 3, POWER4, and IBM PPC970 also known as G5). | 123 | processors (POWER 3, POWER4, and IBM PPC970 also known as G5). |
124 | |||
125 | This option is the catch-all for 6xx types, including some of the | ||
126 | embedded versions. Unless there is see an option for the specific | ||
127 | chip family you are using, you want this option. | ||
128 | |||
129 | You do not want this if you are building a kernel for a 64 bit | ||
130 | IBM RS/6000 or an Apple G5, choose 6xx. | ||
131 | |||
132 | If unsure, select this option | ||
124 | 133 | ||
125 | Unless you are building a kernel for one of the embedded processor | ||
126 | systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx. | ||
127 | Note that the kernel runs in 32-bit mode even on 64-bit chips. | 134 | Note that the kernel runs in 32-bit mode even on 64-bit chips. |
128 | 135 | ||
129 | config PPC_52xx | ||
130 | bool "Freescale 52xx" | ||
131 | select 6xx | ||
132 | select PPC_FPU | ||
133 | |||
134 | config PPC_82xx | 136 | config PPC_82xx |
135 | bool "Freescale 82xx" | 137 | bool "Freescale 82xx" |
136 | select 6xx | 138 | select 6xx |
@@ -160,9 +162,11 @@ config PPC_86xx | |||
160 | 162 | ||
161 | config 40x | 163 | config 40x |
162 | bool "AMCC 40x" | 164 | bool "AMCC 40x" |
165 | select PPC_DCR_NATIVE | ||
163 | 166 | ||
164 | config 44x | 167 | config 44x |
165 | bool "AMCC 44x" | 168 | bool "AMCC 44x" |
169 | select PPC_DCR_NATIVE | ||
166 | 170 | ||
167 | config 8xx | 171 | config 8xx |
168 | bool "Freescale 8xx" | 172 | bool "Freescale 8xx" |
@@ -208,6 +212,24 @@ config PPC_FPU | |||
208 | bool | 212 | bool |
209 | default y if PPC64 | 213 | default y if PPC64 |
210 | 214 | ||
215 | config PPC_DCR_NATIVE | ||
216 | bool | ||
217 | default n | ||
218 | |||
219 | config PPC_DCR_MMIO | ||
220 | bool | ||
221 | default n | ||
222 | |||
223 | config PPC_DCR | ||
224 | bool | ||
225 | depends on PPC_DCR_NATIVE || PPC_DCR_MMIO | ||
226 | default y | ||
227 | |||
228 | config PPC_OF_PLATFORM_PCI | ||
229 | bool | ||
230 | depends on PPC64 # not supported on 32 bits yet | ||
231 | default n | ||
232 | |||
211 | config BOOKE | 233 | config BOOKE |
212 | bool | 234 | bool |
213 | depends on E200 || E500 | 235 | depends on E200 || E500 |
@@ -227,6 +249,7 @@ config PTE_64BIT | |||
227 | config PHYS_64BIT | 249 | config PHYS_64BIT |
228 | bool 'Large physical address support' if E500 | 250 | bool 'Large physical address support' if E500 |
229 | depends on 44x || E500 | 251 | depends on 44x || E500 |
252 | select RESOURCES_64BIT | ||
230 | default y if 44x | 253 | default y if 44x |
231 | ---help--- | 254 | ---help--- |
232 | This option enables kernel support for larger than 32-bit physical | 255 | This option enables kernel support for larger than 32-bit physical |
@@ -369,11 +392,13 @@ config PPC_PSERIES | |||
369 | select PPC_RTAS | 392 | select PPC_RTAS |
370 | select RTAS_ERROR_LOGGING | 393 | select RTAS_ERROR_LOGGING |
371 | select PPC_UDBG_16550 | 394 | select PPC_UDBG_16550 |
395 | select PPC_NATIVE | ||
372 | default y | 396 | default y |
373 | 397 | ||
374 | config PPC_ISERIES | 398 | config PPC_ISERIES |
375 | bool "IBM Legacy iSeries" | 399 | bool "IBM Legacy iSeries" |
376 | depends on PPC_MULTIPLATFORM && PPC64 | 400 | depends on PPC_MULTIPLATFORM && PPC64 |
401 | select PPC_INDIRECT_IO | ||
377 | 402 | ||
378 | config PPC_CHRP | 403 | config PPC_CHRP |
379 | bool "Common Hardware Reference Platform (CHRP) based machines" | 404 | bool "Common Hardware Reference Platform (CHRP) based machines" |
@@ -384,14 +409,35 @@ config PPC_CHRP | |||
384 | select PPC_RTAS | 409 | select PPC_RTAS |
385 | select PPC_MPC106 | 410 | select PPC_MPC106 |
386 | select PPC_UDBG_16550 | 411 | select PPC_UDBG_16550 |
412 | select PPC_NATIVE | ||
413 | default y | ||
414 | |||
415 | config PPC_MPC52xx | ||
416 | bool | ||
417 | default n | ||
418 | |||
419 | config PPC_EFIKA | ||
420 | bool "bPlan Efika 5k2. MPC5200B based computer" | ||
421 | depends on PPC_MULTIPLATFORM && PPC32 | ||
422 | select PPC_RTAS | ||
423 | select RTAS_PROC | ||
424 | select PPC_MPC52xx | ||
425 | select PPC_NATIVE | ||
387 | default y | 426 | default y |
388 | 427 | ||
428 | config PPC_LITE5200 | ||
429 | bool "Freescale Lite5200 Eval Board" | ||
430 | depends on PPC_MULTIPLATFORM && PPC32 | ||
431 | select PPC_MPC52xx | ||
432 | default n | ||
433 | |||
389 | config PPC_PMAC | 434 | config PPC_PMAC |
390 | bool "Apple PowerMac based machines" | 435 | bool "Apple PowerMac based machines" |
391 | depends on PPC_MULTIPLATFORM | 436 | depends on PPC_MULTIPLATFORM |
392 | select MPIC | 437 | select MPIC |
393 | select PPC_INDIRECT_PCI if PPC32 | 438 | select PPC_INDIRECT_PCI if PPC32 |
394 | select PPC_MPC106 if PPC32 | 439 | select PPC_MPC106 if PPC32 |
440 | select PPC_NATIVE | ||
395 | default y | 441 | default y |
396 | 442 | ||
397 | config PPC_PMAC64 | 443 | config PPC_PMAC64 |
@@ -411,6 +457,7 @@ config PPC_PREP | |||
411 | select PPC_I8259 | 457 | select PPC_I8259 |
412 | select PPC_INDIRECT_PCI | 458 | select PPC_INDIRECT_PCI |
413 | select PPC_UDBG_16550 | 459 | select PPC_UDBG_16550 |
460 | select PPC_NATIVE | ||
414 | default y | 461 | default y |
415 | 462 | ||
416 | config PPC_MAPLE | 463 | config PPC_MAPLE |
@@ -422,6 +469,7 @@ config PPC_MAPLE | |||
422 | select GENERIC_TBSYNC | 469 | select GENERIC_TBSYNC |
423 | select PPC_UDBG_16550 | 470 | select PPC_UDBG_16550 |
424 | select PPC_970_NAP | 471 | select PPC_970_NAP |
472 | select PPC_NATIVE | ||
425 | default n | 473 | default n |
426 | help | 474 | help |
427 | This option enables support for the Maple 970FX Evaluation Board. | 475 | This option enables support for the Maple 970FX Evaluation Board. |
@@ -434,6 +482,7 @@ config PPC_PASEMI | |||
434 | select MPIC | 482 | select MPIC |
435 | select PPC_UDBG_16550 | 483 | select PPC_UDBG_16550 |
436 | select GENERIC_TBSYNC | 484 | select GENERIC_TBSYNC |
485 | select PPC_NATIVE | ||
437 | help | 486 | help |
438 | This option enables support for PA Semi's PWRficient line | 487 | This option enables support for PA Semi's PWRficient line |
439 | of SoC processors, including PA6T-1682M | 488 | of SoC processors, including PA6T-1682M |
@@ -445,6 +494,11 @@ config PPC_CELL | |||
445 | config PPC_CELL_NATIVE | 494 | config PPC_CELL_NATIVE |
446 | bool | 495 | bool |
447 | select PPC_CELL | 496 | select PPC_CELL |
497 | select PPC_DCR_MMIO | ||
498 | select PPC_OF_PLATFORM_PCI | ||
499 | select PPC_INDIRECT_IO | ||
500 | select PPC_NATIVE | ||
501 | select MPIC | ||
448 | default n | 502 | default n |
449 | 503 | ||
450 | config PPC_IBM_CELL_BLADE | 504 | config PPC_IBM_CELL_BLADE |
@@ -456,6 +510,22 @@ config PPC_IBM_CELL_BLADE | |||
456 | select PPC_UDBG_16550 | 510 | select PPC_UDBG_16550 |
457 | select UDBG_RTAS_CONSOLE | 511 | select UDBG_RTAS_CONSOLE |
458 | 512 | ||
513 | config PPC_PS3 | ||
514 | bool "Sony PS3" | ||
515 | depends on PPC_MULTIPLATFORM && PPC64 | ||
516 | select PPC_CELL | ||
517 | help | ||
518 | This option enables support for the Sony PS3 game console | ||
519 | and other platforms using the PS3 hypervisor. | ||
520 | |||
521 | config PPC_NATIVE | ||
522 | bool | ||
523 | depends on PPC_MULTIPLATFORM | ||
524 | help | ||
525 | Support for running natively on the hardware, i.e. without | ||
526 | a hypervisor. This option is not user-selectable but should | ||
527 | be selected by all platforms that need it. | ||
528 | |||
459 | config UDBG_RTAS_CONSOLE | 529 | config UDBG_RTAS_CONSOLE |
460 | bool "RTAS based debug console" | 530 | bool "RTAS based debug console" |
461 | depends on PPC_RTAS | 531 | depends on PPC_RTAS |
@@ -517,6 +587,15 @@ config PPC_970_NAP | |||
517 | bool | 587 | bool |
518 | default n | 588 | default n |
519 | 589 | ||
590 | config PPC_INDIRECT_IO | ||
591 | bool | ||
592 | select GENERIC_IOMAP | ||
593 | default n | ||
594 | |||
595 | config GENERIC_IOMAP | ||
596 | bool | ||
597 | default n | ||
598 | |||
520 | source "drivers/cpufreq/Kconfig" | 599 | source "drivers/cpufreq/Kconfig" |
521 | 600 | ||
522 | config CPU_FREQ_PMAC | 601 | config CPU_FREQ_PMAC |
@@ -594,12 +673,6 @@ config TAU_AVERAGE | |||
594 | 673 | ||
595 | If in doubt, say N here. | 674 | If in doubt, say N here. |
596 | 675 | ||
597 | config PPC_TODC | ||
598 | depends on EMBEDDED6xx | ||
599 | bool "Generic Time-of-day Clock (TODC) support" | ||
600 | ---help--- | ||
601 | This adds support for many TODC/RTC chips. | ||
602 | |||
603 | endmenu | 676 | endmenu |
604 | 677 | ||
605 | source arch/powerpc/platforms/embedded6xx/Kconfig | 678 | source arch/powerpc/platforms/embedded6xx/Kconfig |
@@ -610,6 +683,7 @@ source arch/powerpc/platforms/85xx/Kconfig | |||
610 | source arch/powerpc/platforms/86xx/Kconfig | 683 | source arch/powerpc/platforms/86xx/Kconfig |
611 | source arch/powerpc/platforms/8xx/Kconfig | 684 | source arch/powerpc/platforms/8xx/Kconfig |
612 | source arch/powerpc/platforms/cell/Kconfig | 685 | source arch/powerpc/platforms/cell/Kconfig |
686 | source arch/powerpc/platforms/ps3/Kconfig | ||
613 | 687 | ||
614 | menu "Kernel options" | 688 | menu "Kernel options" |
615 | 689 | ||
@@ -790,7 +864,6 @@ source "arch/powerpc/platforms/prep/Kconfig" | |||
790 | 864 | ||
791 | config CMDLINE_BOOL | 865 | config CMDLINE_BOOL |
792 | bool "Default bootloader kernel arguments" | 866 | bool "Default bootloader kernel arguments" |
793 | depends on !PPC_ISERIES | ||
794 | 867 | ||
795 | config CMDLINE | 868 | config CMDLINE |
796 | string "Initial kernel command string" | 869 | string "Initial kernel command string" |
@@ -880,7 +953,7 @@ config MCA | |||
880 | 953 | ||
881 | config PCI | 954 | config PCI |
882 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ | 955 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ |
883 | || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 | 956 | || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3 |
884 | default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ | 957 | default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ |
885 | && !PPC_85xx && !PPC_86xx | 958 | && !PPC_85xx && !PPC_86xx |
886 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS | 959 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 5ad149b47e3..f0e51edde02 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
@@ -77,7 +77,7 @@ config KGDB_CONSOLE | |||
77 | 77 | ||
78 | config XMON | 78 | config XMON |
79 | bool "Include xmon kernel debugger" | 79 | bool "Include xmon kernel debugger" |
80 | depends on DEBUGGER && !PPC_ISERIES | 80 | depends on DEBUGGER |
81 | help | 81 | help |
82 | Include in-kernel hooks for the xmon kernel monitor/debugger. | 82 | Include in-kernel hooks for the xmon kernel monitor/debugger. |
83 | Unless you are intending to debug the kernel, say N here. | 83 | Unless you are intending to debug the kernel, say N here. |
@@ -98,6 +98,15 @@ config XMON_DEFAULT | |||
98 | xmon is normally disabled unless booted with 'xmon=on'. | 98 | xmon is normally disabled unless booted with 'xmon=on'. |
99 | Use 'xmon=off' to disable xmon init during runtime. | 99 | Use 'xmon=off' to disable xmon init during runtime. |
100 | 100 | ||
101 | config XMON_DISASSEMBLY | ||
102 | bool "Include disassembly support in xmon" | ||
103 | depends on XMON | ||
104 | default y | ||
105 | help | ||
106 | Include support for disassembling in xmon. You probably want | ||
107 | to say Y here, unless you're building for a memory-constrained | ||
108 | system. | ||
109 | |||
101 | config IRQSTACKS | 110 | config IRQSTACKS |
102 | bool "Use separate kernel stacks when processing interrupts" | 111 | bool "Use separate kernel stacks when processing interrupts" |
103 | depends on PPC64 | 112 | depends on PPC64 |
@@ -116,7 +125,7 @@ config BDI_SWITCH | |||
116 | 125 | ||
117 | config BOOTX_TEXT | 126 | config BOOTX_TEXT |
118 | bool "Support for early boot text console (BootX or OpenFirmware only)" | 127 | bool "Support for early boot text console (BootX or OpenFirmware only)" |
119 | depends PPC_OF && !PPC_ISERIES | 128 | depends PPC_OF |
120 | help | 129 | help |
121 | Say Y here to see progress messages from the boot firmware in text | 130 | Say Y here to see progress messages from the boot firmware in text |
122 | mode. Requires either BootX or Open Firmware. | 131 | mode. Requires either BootX or Open Firmware. |
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 45c9ad23526..0734b2fc1d9 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore | |||
@@ -1,19 +1,32 @@ | |||
1 | addnote | 1 | addnote |
2 | empty.c | ||
3 | hack-coff | ||
2 | infblock.c | 4 | infblock.c |
3 | infblock.h | 5 | infblock.h |
4 | infcodes.c | 6 | infcodes.c |
5 | infcodes.h | 7 | infcodes.h |
6 | inffast.c | 8 | inffast.c |
7 | inffast.h | 9 | inffast.h |
10 | inffixed.h | ||
8 | inflate.c | 11 | inflate.c |
12 | inflate.h | ||
9 | inftrees.c | 13 | inftrees.c |
10 | inftrees.h | 14 | inftrees.h |
11 | infutil.c | 15 | infutil.c |
12 | infutil.h | 16 | infutil.h |
13 | kernel-vmlinux.strip.c | 17 | kernel-vmlinux.strip.c |
14 | kernel-vmlinux.strip.gz | 18 | kernel-vmlinux.strip.gz |
19 | mktree | ||
15 | uImage | 20 | uImage |
16 | zImage | 21 | zImage |
22 | zImage.chrp | ||
23 | zImage.coff | ||
24 | zImage.coff.lds | ||
25 | zImage.lds | ||
26 | zImage.miboot | ||
27 | zImage.pmac | ||
28 | zImage.pseries | ||
29 | zImage.sandpoint | ||
17 | zImage.vmode | 30 | zImage.vmode |
18 | zconf.h | 31 | zconf.h |
19 | zlib.h | 32 | zlib.h |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 4b2be611f77..343dbcfdf08 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h | |||
40 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ | 40 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ |
41 | $(addprefix $(obj)/,$(zlibheader)) | 41 | $(addprefix $(obj)/,$(zlibheader)) |
42 | 42 | ||
43 | src-wlib := string.S stdio.c main.c div64.S $(zlib) | 43 | src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ |
44 | ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib) | ||
44 | src-plat := of.c | 45 | src-plat := of.c |
45 | src-boot := crt0.S $(src-wlib) $(src-plat) empty.c | 46 | src-boot := crt0.S $(src-wlib) $(src-plat) empty.c |
46 | 47 | ||
@@ -74,7 +75,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S | |||
74 | @cp $< $@ | 75 | @cp $< $@ |
75 | 76 | ||
76 | clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ | 77 | clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ |
77 | $(obj)/empty.c | 78 | empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint |
78 | 79 | ||
79 | quiet_cmd_bootcc = BOOTCC $@ | 80 | quiet_cmd_bootcc = BOOTCC $@ |
80 | cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< | 81 | cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< |
@@ -93,13 +94,13 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S | |||
93 | $(obj)/wrapper.a: $(obj-wlib) | 94 | $(obj)/wrapper.a: $(obj-wlib) |
94 | $(call cmd,bootar) | 95 | $(call cmd,bootar) |
95 | 96 | ||
96 | hostprogs-y := addnote addRamDisk hack-coff | 97 | hostprogs-y := addnote addRamDisk hack-coff mktree |
97 | 98 | ||
98 | extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ | 99 | extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ |
99 | $(obj)/zImage.lds $(obj)/zImage.coff.lds | 100 | $(obj)/zImage.lds $(obj)/zImage.coff.lds |
100 | 101 | ||
101 | wrapper :=$(srctree)/$(src)/wrapper | 102 | wrapper :=$(srctree)/$(src)/wrapper |
102 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff) | 103 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) |
103 | 104 | ||
104 | ############# | 105 | ############# |
105 | # Bits for building various flavours of zImage | 106 | # Bits for building various flavours of zImage |
@@ -148,13 +149,18 @@ $(obj)/zImage.miboot: vmlinux $(wrapperbits) | |||
148 | $(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits) | 149 | $(obj)/zImage.initrd.miboot: vmlinux $(wrapperbits) |
149 | $(call cmd,wrap_initrd,miboot) | 150 | $(call cmd,wrap_initrd,miboot) |
150 | 151 | ||
152 | $(obj)/zImage.ps3: vmlinux | ||
153 | $(STRIP) -s -R .comment $< -o $@ | ||
154 | |||
151 | $(obj)/uImage: vmlinux $(wrapperbits) | 155 | $(obj)/uImage: vmlinux $(wrapperbits) |
152 | $(call cmd,wrap,uboot) | 156 | $(call cmd,wrap,uboot) |
153 | 157 | ||
154 | image-$(CONFIG_PPC_PSERIES) += zImage.pseries | 158 | image-$(CONFIG_PPC_PSERIES) += zImage.pseries |
155 | image-$(CONFIG_PPC_MAPLE) += zImage.pseries | 159 | image-$(CONFIG_PPC_MAPLE) += zImage.pseries |
156 | image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries | 160 | image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries |
161 | image-$(CONFIG_PPC_PS3) += zImage.ps3 | ||
157 | image-$(CONFIG_PPC_CHRP) += zImage.chrp | 162 | image-$(CONFIG_PPC_CHRP) += zImage.chrp |
163 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp | ||
158 | image-$(CONFIG_PPC_PMAC) += zImage.pmac | 164 | image-$(CONFIG_PPC_PMAC) += zImage.pmac |
159 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage | 165 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage |
160 | 166 | ||
@@ -176,3 +182,4 @@ install: $(CONFIGURE) $(image-y) | |||
176 | 182 | ||
177 | clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz) | 183 | clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz) |
178 | clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz) | 184 | clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz) |
185 | clean-files += $(image-) | ||
diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts new file mode 100644 index 00000000000..d06b0b01889 --- /dev/null +++ b/arch/powerpc/boot/dts/kuroboxHG.dts | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Device Tree Souce for Buffalo KuroboxHG | ||
3 | * | ||
4 | * Choose CONFIG_LINKSTATION to build a kernel for KuroboxHG, or use | ||
5 | * the default configuration linkstation_defconfig. | ||
6 | * | ||
7 | * Based on sandpoint.dts | ||
8 | * | ||
9 | * 2006 (c) G. Liakhovetski <g.liakhovetski@gmx.de> | ||
10 | * | ||
11 | * This file is licensed under | ||
12 | * the terms of the GNU General Public License version 2. This program | ||
13 | * is licensed "as is" without any warranty of any kind, whether express | ||
14 | * or implied. | ||
15 | |||
16 | XXXX add flash parts, rtc, ?? | ||
17 | |||
18 | build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts" | ||
19 | |||
20 | |||
21 | */ | ||
22 | |||
23 | / { | ||
24 | linux,phandle = <1000>; | ||
25 | model = "KuroboxHG"; | ||
26 | compatible = "linkstation"; | ||
27 | #address-cells = <1>; | ||
28 | #size-cells = <1>; | ||
29 | |||
30 | cpus { | ||
31 | linux,phandle = <2000>; | ||
32 | #cpus = <1>; | ||
33 | #address-cells = <1>; | ||
34 | #size-cells = <0>; | ||
35 | |||
36 | PowerPC,603e { /* Really 8241 */ | ||
37 | linux,phandle = <2100>; | ||
38 | linux,boot-cpu; | ||
39 | device_type = "cpu"; | ||
40 | reg = <0>; | ||
41 | clock-frequency = <fdad680>; /* Fixed by bootwrapper */ | ||
42 | timebase-frequency = <1F04000>; /* Fixed by bootwrapper */ | ||
43 | bus-frequency = <0>; /* From bootloader */ | ||
44 | /* Following required by dtc but not used */ | ||
45 | i-cache-line-size = <0>; | ||
46 | d-cache-line-size = <0>; | ||
47 | i-cache-size = <4000>; | ||
48 | d-cache-size = <4000>; | ||
49 | }; | ||
50 | }; | ||
51 | |||
52 | memory { | ||
53 | linux,phandle = <3000>; | ||
54 | device_type = "memory"; | ||
55 | reg = <00000000 08000000>; | ||
56 | }; | ||
57 | |||
58 | soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */ | ||
59 | linux,phandle = <4000>; | ||
60 | #address-cells = <1>; | ||
61 | #size-cells = <1>; | ||
62 | #interrupt-cells = <2>; | ||
63 | device_type = "soc"; | ||
64 | compatible = "mpc10x"; | ||
65 | store-gathering = <0>; /* 0 == off, !0 == on */ | ||
66 | reg = <80000000 00100000>; | ||
67 | ranges = <80000000 80000000 70000000 /* pci mem space */ | ||
68 | fc000000 fc000000 00100000 /* EUMB */ | ||
69 | fe000000 fe000000 00c00000 /* pci i/o space */ | ||
70 | fec00000 fec00000 00300000 /* pci cfg regs */ | ||
71 | fef00000 fef00000 00100000>; /* pci iack */ | ||
72 | |||
73 | i2c@80003000 { | ||
74 | linux,phandle = <4300>; | ||
75 | device_type = "i2c"; | ||
76 | compatible = "fsl-i2c"; | ||
77 | reg = <80003000 1000>; | ||
78 | interrupts = <5 2>; | ||
79 | interrupt-parent = <4400>; | ||
80 | }; | ||
81 | |||
82 | serial@80004500 { | ||
83 | linux,phandle = <4511>; | ||
84 | device_type = "serial"; | ||
85 | compatible = "ns16550"; | ||
86 | reg = <80004500 8>; | ||
87 | clock-frequency = <7c044a8>; | ||
88 | current-speed = <2580>; | ||
89 | interrupts = <9 2>; | ||
90 | interrupt-parent = <4400>; | ||
91 | }; | ||
92 | |||
93 | serial@80004600 { | ||
94 | linux,phandle = <4512>; | ||
95 | device_type = "serial"; | ||
96 | compatible = "ns16550"; | ||
97 | reg = <80004600 8>; | ||
98 | clock-frequency = <7c044a8>; | ||
99 | current-speed = <e100>; | ||
100 | interrupts = <a 0>; | ||
101 | interrupt-parent = <4400>; | ||
102 | }; | ||
103 | |||
104 | pic@80040000 { | ||
105 | linux,phandle = <4400>; | ||
106 | #interrupt-cells = <2>; | ||
107 | #address-cells = <0>; | ||
108 | device_type = "open-pic"; | ||
109 | compatible = "chrp,open-pic"; | ||
110 | interrupt-controller; | ||
111 | reg = <80040000 40000>; | ||
112 | built-in; | ||
113 | }; | ||
114 | |||
115 | pci@fec00000 { | ||
116 | linux,phandle = <4500>; | ||
117 | #address-cells = <3>; | ||
118 | #size-cells = <2>; | ||
119 | #interrupt-cells = <1>; | ||
120 | device_type = "pci"; | ||
121 | compatible = "mpc10x-pci"; | ||
122 | reg = <fec00000 400000>; | ||
123 | ranges = <01000000 0 0 fe000000 0 00c00000 | ||
124 | 02000000 0 80000000 80000000 0 70000000>; | ||
125 | bus-range = <0 ff>; | ||
126 | clock-frequency = <7f28155>; | ||
127 | interrupt-parent = <4400>; | ||
128 | interrupt-map-mask = <f800 0 0 7>; | ||
129 | interrupt-map = < | ||
130 | /* IDSEL 0x11 - IRQ0 ETH */ | ||
131 | 5800 0 0 1 4400 0 1 | ||
132 | 5800 0 0 2 4400 1 1 | ||
133 | 5800 0 0 3 4400 2 1 | ||
134 | 5800 0 0 4 4400 3 1 | ||
135 | /* IDSEL 0x12 - IRQ1 IDE0 */ | ||
136 | 6000 0 0 1 4400 1 1 | ||
137 | 6000 0 0 2 4400 2 1 | ||
138 | 6000 0 0 3 4400 3 1 | ||
139 | 6000 0 0 4 4400 0 1 | ||
140 | /* IDSEL 0x14 - IRQ3 USB2.0 */ | ||
141 | 7000 0 0 1 4400 3 1 | ||
142 | 7000 0 0 2 4400 3 1 | ||
143 | 7000 0 0 3 4400 3 1 | ||
144 | 7000 0 0 4 4400 3 1 | ||
145 | >; | ||
146 | }; | ||
147 | }; | ||
148 | }; | ||
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts new file mode 100644 index 00000000000..8bc0d259796 --- /dev/null +++ b/arch/powerpc/boot/dts/lite5200.dts | |||
@@ -0,0 +1,313 @@ | |||
1 | /* | ||
2 | * Lite5200 board Device Tree Source | ||
3 | * | ||
4 | * Copyright 2006 Secret Lab Technologies Ltd. | ||
5 | * Grant Likely <grant.likely@secretlab.ca> | ||
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 | / { | ||
14 | model = "Lite5200"; | ||
15 | compatible = "lite5200\0lite52xx\0mpc5200\0mpc52xx"; | ||
16 | #address-cells = <1>; | ||
17 | #size-cells = <1>; | ||
18 | |||
19 | cpus { | ||
20 | #cpus = <1>; | ||
21 | #address-cells = <1>; | ||
22 | #size-cells = <0>; | ||
23 | |||
24 | PowerPC,5200@0 { | ||
25 | device_type = "cpu"; | ||
26 | reg = <0>; | ||
27 | d-cache-line-size = <20>; | ||
28 | i-cache-line-size = <20>; | ||
29 | d-cache-size = <4000>; // L1, 16K | ||
30 | i-cache-size = <4000>; // L1, 16K | ||
31 | timebase-frequency = <0>; // from bootloader | ||
32 | bus-frequency = <0>; // from bootloader | ||
33 | clock-frequency = <0>; // from bootloader | ||
34 | 32-bit; | ||
35 | }; | ||
36 | }; | ||
37 | |||
38 | memory { | ||
39 | device_type = "memory"; | ||
40 | reg = <00000000 04000000>; // 64MB | ||
41 | }; | ||
42 | |||
43 | soc5200@f0000000 { | ||
44 | #interrupt-cells = <3>; | ||
45 | device_type = "soc"; | ||
46 | ranges = <0 f0000000 f0010000>; | ||
47 | reg = <f0000000 00010000>; | ||
48 | bus-frequency = <0>; // from bootloader | ||
49 | |||
50 | cdm@200 { | ||
51 | compatible = "mpc5200-cdm\0mpc52xx-cdm"; | ||
52 | reg = <200 38>; | ||
53 | }; | ||
54 | |||
55 | pic@500 { | ||
56 | // 5200 interrupts are encoded into two levels; | ||
57 | linux,phandle = <500>; | ||
58 | interrupt-controller; | ||
59 | #interrupt-cells = <3>; | ||
60 | device_type = "interrupt-controller"; | ||
61 | compatible = "mpc5200-pic\0mpc52xx-pic"; | ||
62 | reg = <500 80>; | ||
63 | built-in; | ||
64 | }; | ||
65 | |||
66 | gpt@600 { // General Purpose Timer | ||
67 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
68 | device_type = "gpt"; | ||
69 | reg = <600 10>; | ||
70 | interrupts = <1 9 0>; | ||
71 | interrupt-parent = <500>; | ||
72 | }; | ||
73 | |||
74 | gpt@610 { // General Purpose Timer | ||
75 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
76 | device_type = "gpt"; | ||
77 | reg = <610 10>; | ||
78 | interrupts = <1 a 0>; | ||
79 | interrupt-parent = <500>; | ||
80 | }; | ||
81 | |||
82 | gpt@620 { // General Purpose Timer | ||
83 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
84 | device_type = "gpt"; | ||
85 | reg = <620 10>; | ||
86 | interrupts = <1 b 0>; | ||
87 | interrupt-parent = <500>; | ||
88 | }; | ||
89 | |||
90 | gpt@630 { // General Purpose Timer | ||
91 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
92 | device_type = "gpt"; | ||
93 | reg = <630 10>; | ||
94 | interrupts = <1 c 0>; | ||
95 | interrupt-parent = <500>; | ||
96 | }; | ||
97 | |||
98 | gpt@640 { // General Purpose Timer | ||
99 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
100 | device_type = "gpt"; | ||
101 | reg = <640 10>; | ||
102 | interrupts = <1 d 0>; | ||
103 | interrupt-parent = <500>; | ||
104 | }; | ||
105 | |||
106 | gpt@650 { // General Purpose Timer | ||
107 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
108 | device_type = "gpt"; | ||
109 | reg = <650 10>; | ||
110 | interrupts = <1 e 0>; | ||
111 | interrupt-parent = <500>; | ||
112 | }; | ||
113 | |||
114 | gpt@660 { // General Purpose Timer | ||
115 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
116 | device_type = "gpt"; | ||
117 | reg = <660 10>; | ||
118 | interrupts = <1 f 0>; | ||
119 | interrupt-parent = <500>; | ||
120 | }; | ||
121 | |||
122 | gpt@670 { // General Purpose Timer | ||
123 | compatible = "mpc5200-gpt\0mpc52xx-gpt"; | ||
124 | device_type = "gpt"; | ||
125 | reg = <670 10>; | ||
126 | interrupts = <1 10 0>; | ||
127 | interrupt-parent = <500>; | ||
128 | }; | ||
129 | |||
130 | rtc@800 { // Real time clock | ||
131 | compatible = "mpc5200-rtc\0mpc52xx-rtc"; | ||
132 | device_type = "rtc"; | ||
133 | reg = <800 100>; | ||
134 | interrupts = <1 5 0 1 6 0>; | ||
135 | interrupt-parent = <500>; | ||
136 | }; | ||
137 | |||
138 | mscan@900 { | ||
139 | device_type = "mscan"; | ||
140 | compatible = "mpc5200-mscan\0mpc52xx-mscan"; | ||
141 | interrupts = <2 11 0>; | ||
142 | interrupt-parent = <500>; | ||
143 | reg = <900 80>; | ||
144 | }; | ||
145 | |||
146 | mscan@980 { | ||
147 | device_type = "mscan"; | ||
148 | compatible = "mpc5200-mscan\0mpc52xx-mscan"; | ||
149 | interrupts = <1 12 0>; | ||
150 | interrupt-parent = <500>; | ||
151 | reg = <980 80>; | ||
152 | }; | ||
153 | |||
154 | gpio@b00 { | ||
155 | compatible = "mpc5200-gpio\0mpc52xx-gpio"; | ||
156 | reg = <b00 40>; | ||
157 | interrupts = <1 7 0>; | ||
158 | interrupt-parent = <500>; | ||
159 | }; | ||
160 | |||
161 | gpio-wkup@b00 { | ||
162 | compatible = "mpc5200-gpio-wkup\0mpc52xx-gpio-wkup"; | ||
163 | reg = <c00 40>; | ||
164 | interrupts = <1 8 0 0 3 0>; | ||
165 | interrupt-parent = <500>; | ||
166 | }; | ||
167 | |||
168 | pci@0d00 { | ||
169 | #interrupt-cells = <1>; | ||
170 | #size-cells = <2>; | ||
171 | #address-cells = <3>; | ||
172 | device_type = "pci"; | ||
173 | compatible = "mpc5200-pci\0mpc52xx-pci"; | ||
174 | reg = <d00 100>; | ||
175 | interrupt-map-mask = <f800 0 0 7>; | ||
176 | interrupt-map = <c000 0 0 1 500 0 0 3 | ||
177 | c000 0 0 2 500 0 0 3 | ||
178 | c000 0 0 3 500 0 0 3 | ||
179 | c000 0 0 4 500 0 0 3>; | ||
180 | clock-frequency = <0>; // From boot loader | ||
181 | interrupts = <2 8 0 2 9 0 2 a 0>; | ||
182 | interrupt-parent = <500>; | ||
183 | bus-range = <0 0>; | ||
184 | ranges = <42000000 0 80000000 80000000 0 20000000 | ||
185 | 02000000 0 a0000000 a0000000 0 10000000 | ||
186 | 01000000 0 00000000 b0000000 0 01000000>; | ||
187 | }; | ||
188 | |||
189 | spi@f00 { | ||
190 | device_type = "spi"; | ||
191 | compatible = "mpc5200-spi\0mpc52xx-spi"; | ||
192 | reg = <f00 20>; | ||
193 | interrupts = <2 d 0 2 e 0>; | ||
194 | interrupt-parent = <500>; | ||
195 | }; | ||
196 | |||
197 | usb@1000 { | ||
198 | device_type = "usb-ohci-be"; | ||
199 | compatible = "mpc5200-ohci\0mpc52xx-ohci\0ohci-be"; | ||
200 | reg = <1000 ff>; | ||
201 | interrupts = <2 6 0>; | ||
202 | interrupt-parent = <500>; | ||
203 | }; | ||
204 | |||
205 | bestcomm@1200 { | ||
206 | device_type = "dma-controller"; | ||
207 | compatible = "mpc5200-bestcomm\0mpc52xx-bestcomm"; | ||
208 | reg = <1200 80>; | ||
209 | interrupts = <3 0 0 3 1 0 3 2 0 3 3 0 | ||
210 | 3 4 0 3 5 0 3 6 0 3 7 0 | ||
211 | 3 8 0 3 9 0 3 a 0 3 b 0 | ||
212 | 3 c 0 3 d 0 3 e 0 3 f 0>; | ||
213 | interrupt-parent = <500>; | ||
214 | }; | ||
215 | |||
216 | xlb@1f00 { | ||
217 | compatible = "mpc5200-xlb\0mpc52xx-xlb"; | ||
218 | reg = <1f00 100>; | ||
219 | }; | ||
220 | |||
221 | serial@2000 { // PSC1 | ||
222 | device_type = "serial"; | ||
223 | compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart"; | ||
224 | port-number = <0>; // Logical port assignment | ||
225 | reg = <2000 100>; | ||
226 | interrupts = <2 1 0>; | ||
227 | interrupt-parent = <500>; | ||
228 | }; | ||
229 | |||
230 | // PSC2 in spi mode example | ||
231 | spi@2200 { // PSC2 | ||
232 | device_type = "spi"; | ||
233 | compatible = "mpc5200-psc-spi\0mpc52xx-psc-spi"; | ||
234 | reg = <2200 100>; | ||
235 | interrupts = <2 2 0>; | ||
236 | interrupt-parent = <500>; | ||
237 | }; | ||
238 | |||
239 | // PSC3 in CODEC mode example | ||
240 | i2s@2400 { // PSC3 | ||
241 | device_type = "i2s"; | ||
242 | compatible = "mpc5200-psc-i2s\0mpc52xx-psc-i2s"; | ||
243 | reg = <2400 100>; | ||
244 | interrupts = <2 3 0>; | ||
245 | interrupt-parent = <500>; | ||
246 | }; | ||
247 | |||
248 | // PSC4 unconfigured | ||
249 | //serial@2600 { // PSC4 | ||
250 | // device_type = "serial"; | ||
251 | // compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart"; | ||
252 | // reg = <2600 100>; | ||
253 | // interrupts = <2 b 0>; | ||
254 | // interrupt-parent = <500>; | ||
255 | //}; | ||
256 | |||
257 | // PSC5 unconfigured | ||
258 | //serial@2800 { // PSC5 | ||
259 | // device_type = "serial"; | ||
260 | // compatible = "mpc5200-psc-uart\0mpc52xx-psc-uart"; | ||
261 | // reg = <2800 100>; | ||
262 | // interrupts = <2 c 0>; | ||
263 | // interrupt-parent = <500>; | ||
264 | //}; | ||
265 | |||
266 | // PSC6 in AC97 mode example | ||
267 | ac97@2c00 { // PSC6 | ||
268 | device_type = "ac97"; | ||
269 | compatible = "mpc5200-psc-ac97\0mpc52xx-psc-ac97"; | ||
270 | reg = <2c00 100>; | ||
271 | interrupts = <2 4 0>; | ||
272 | interrupt-parent = <500>; | ||
273 | }; | ||
274 | |||
275 | ethernet@3000 { | ||
276 | device_type = "network"; | ||
277 | compatible = "mpc5200-fec\0mpc52xx-fec"; | ||
278 | reg = <3000 800>; | ||
279 | mac-address = [ 02 03 04 05 06 07 ]; // Bad! | ||
280 | interrupts = <2 5 0>; | ||
281 | interrupt-parent = <500>; | ||
282 | }; | ||
283 | |||
284 | ata@3a00 { | ||
285 | device_type = "ata"; | ||
286 | compatible = "mpc5200-ata\0mpc52xx-ata"; | ||
287 | reg = <3a00 100>; | ||
288 | interrupts = <2 7 0>; | ||
289 | interrupt-parent = <500>; | ||
290 | }; | ||
291 | |||
292 | i2c@3d00 { | ||
293 | device_type = "i2c"; | ||
294 | compatible = "mpc5200-i2c\0mpc52xx-i2c"; | ||
295 | reg = <3d00 40>; | ||
296 | interrupts = <2 f 0>; | ||
297 | interrupt-parent = <500>; | ||
298 | }; | ||
299 | |||
300 | i2c@3d40 { | ||
301 | device_type = "i2c"; | ||
302 | compatible = "mpc5200-i2c\0mpc52xx-i2c"; | ||
303 | reg = <3d40 40>; | ||
304 | interrupts = <2 10 0>; | ||
305 | interrupt-parent = <500>; | ||
306 | }; | ||
307 | sram@8000 { | ||
308 | device_type = "sram"; | ||
309 | compatible = "mpc5200-sram\0mpc52xx-sram\0sram"; | ||
310 | reg = <8000 4000>; | ||
311 | }; | ||
312 | }; | ||
313 | }; | ||
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts new file mode 100644 index 00000000000..81cb76418a7 --- /dev/null +++ b/arch/powerpc/boot/dts/lite5200b.dts | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * Lite5200B board Device Tree Source | ||
3 | * | ||
4 | * Copyright 2006 Secret Lab Technologies Ltd. | ||
5 | * Grant Likely <grant.likely@secretlab.ca> | ||
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 | / { | ||
14 | model = "Lite5200b"; | ||
15 | compatible = "lite5200b\0lite52xx\0mpc5200b\0mpc52xx"; | ||
16 | #address-cells = <1>; | ||
17 | #size-cells = <1>; | ||
18 | |||
19 | cpus { | ||
20 | #cpus = <1>; | ||
21 | #address-cells = <1>; | ||
22 | #size-cells = <0>; | ||
23 | |||
24 | PowerPC,5200@0 { | ||
25 | device_type = "cpu"; | ||
26 | reg = <0>; | ||
27 | d-cache-line-size = <20>; | ||
28 | i-cache-line-size = <20>; | ||
29 | d-cache-size = <4000>; // L1, 16K | ||
30 | i-cache-size = <4000>; // L1, 16K | ||
31 | timebase-frequency = <0>; // from bootloader | ||
32 | bus-frequency = <0>; // from bootloader | ||
33 | clock-frequency = <0>; // from bootloader | ||
34 | 32-bit; | ||
35 | }; | ||
36 | }; | ||
37 | |||
38 | memory { | ||
39 | device_type = "memory"; | ||
40 | reg = <00000000 10000000>; // 256MB | ||
41 | }; | ||
42 | |||
43 | soc5200@f0000000 { | ||
44 | #interrupt-cells = <3>; | ||
45 | device_type = "soc"; | ||
46 | ranges = <0 f0000000 f0010000>; | ||
47 | reg = <f0000000 00010000>; | ||
48 | bus-frequency = <0>; // from bootloader | ||
49 | |||
50 | cdm@200 { | ||
51 | compatible = "mpc5200b-cdm\0mpc52xx-cdm"; | ||
52 | reg = <200 38>; | ||
53 | }; | ||
54 | |||
55 | pic@500 { | ||
56 | // 5200 interrupts are encoded into two levels; | ||
57 | linux,phandle = <500>; | ||
58 | interrupt-controller; | ||
59 | #interrupt-cells = <3>; | ||
60 | device_type = "interrupt-controller"; | ||
61 | compatible = "mpc5200b-pic\0mpc52xx-pic"; | ||
62 | reg = <500 80>; | ||
63 | built-in; | ||
64 | }; | ||
65 | |||
66 | gpt@600 { // General Purpose Timer | ||
67 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
68 | device_type = "gpt"; | ||
69 | reg = <600 10>; | ||
70 | interrupts = <1 9 0>; | ||
71 | interrupt-parent = <500>; | ||
72 | }; | ||
73 | |||
74 | gpt@610 { // General Purpose Timer | ||
75 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
76 | device_type = "gpt"; | ||
77 | reg = <610 10>; | ||
78 | interrupts = <1 a 0>; | ||
79 | interrupt-parent = <500>; | ||
80 | }; | ||
81 | |||
82 | gpt@620 { // General Purpose Timer | ||
83 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
84 | device_type = "gpt"; | ||
85 | reg = <620 10>; | ||
86 | interrupts = <1 b 0>; | ||
87 | interrupt-parent = <500>; | ||
88 | }; | ||
89 | |||
90 | gpt@630 { // General Purpose Timer | ||
91 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
92 | device_type = "gpt"; | ||
93 | reg = <630 10>; | ||
94 | interrupts = <1 c 0>; | ||
95 | interrupt-parent = <500>; | ||
96 | }; | ||
97 | |||
98 | gpt@640 { // General Purpose Timer | ||
99 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
100 | device_type = "gpt"; | ||
101 | reg = <640 10>; | ||
102 | interrupts = <1 d 0>; | ||
103 | interrupt-parent = <500>; | ||
104 | }; | ||
105 | |||
106 | gpt@650 { // General Purpose Timer | ||
107 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
108 | device_type = "gpt"; | ||
109 | reg = <650 10>; | ||
110 | interrupts = <1 e 0>; | ||
111 | interrupt-parent = <500>; | ||
112 | }; | ||
113 | |||
114 | gpt@660 { // General Purpose Timer | ||
115 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
116 | device_type = "gpt"; | ||
117 | reg = <660 10>; | ||
118 | interrupts = <1 f 0>; | ||
119 | interrupt-parent = <500>; | ||
120 | }; | ||
121 | |||
122 | gpt@670 { // General Purpose Timer | ||
123 | compatible = "mpc5200b-gpt\0mpc52xx-gpt"; | ||
124 | device_type = "gpt"; | ||
125 | reg = <670 10>; | ||
126 | interrupts = <1 10 0>; | ||
127 | interrupt-parent = <500>; | ||
128 | }; | ||
129 | |||
130 | rtc@800 { // Real time clock | ||
131 | compatible = "mpc5200b-rtc\0mpc52xx-rtc"; | ||
132 | device_type = "rtc"; | ||
133 | reg = <800 100>; | ||
134 | interrupts = <1 5 0 1 6 0>; | ||
135 | interrupt-parent = <500>; | ||
136 | }; | ||
137 | |||
138 | mscan@900 { | ||
139 | device_type = "mscan"; | ||
140 | compatible = "mpc5200b-mscan\0mpc52xx-mscan"; | ||
141 | interrupts = <2 11 0>; | ||
142 | interrupt-parent = <500>; | ||
143 | reg = <900 80>; | ||
144 | }; | ||
145 | |||
146 | mscan@980 { | ||
147 | device_type = "mscan"; | ||
148 | compatible = "mpc5200b-mscan\0mpc52xx-mscan"; | ||
149 | interrupts = <1 12 0>; | ||
150 | interrupt-parent = <500>; | ||
151 | reg = <980 80>; | ||
152 | }; | ||
153 | |||
154 | gpio@b00 { | ||
155 | compatible = "mpc5200b-gpio\0mpc52xx-gpio"; | ||
156 | reg = <b00 40>; | ||
157 | interrupts = <1 7 0>; | ||
158 | interrupt-parent = <500>; | ||
159 | }; | ||
160 | |||
161 | gpio-wkup@b00 { | ||
162 | compatible = "mpc5200b-gpio-wkup\0mpc52xx-gpio-wkup"; | ||
163 | reg = <c00 40>; | ||
164 | interrupts = <1 8 0 0 3 0>; | ||
165 | interrupt-parent = <500>; | ||
166 | }; | ||
167 | |||
168 | pci@0d00 { | ||
169 | #interrupt-cells = <1>; | ||
170 | #size-cells = <2>; | ||
171 | #address-cells = <3>; | ||
172 | device_type = "pci"; | ||
173 | compatible = "mpc5200b-pci\0mpc52xx-pci"; | ||
174 | reg = <d00 100>; | ||
175 | interrupt-map-mask = <f800 0 0 7>; | ||
176 | interrupt-map = <c000 0 0 1 500 0 0 3 // 1st slot | ||
177 | c000 0 0 2 500 1 1 3 | ||
178 | c000 0 0 3 500 1 2 3 | ||
179 | c000 0 0 4 500 1 3 3 | ||
180 | |||
181 | c800 0 0 1 500 1 1 3 // 2nd slot | ||
182 | c800 0 0 2 500 1 2 3 | ||
183 | c800 0 0 3 500 1 3 3 | ||
184 | c800 0 0 4 500 0 0 3>; | ||
185 | clock-frequency = <0>; // From boot loader | ||
186 | interrupts = <2 8 0 2 9 0 2 a 0>; | ||
187 | interrupt-parent = <500>; | ||
188 | bus-range = <0 0>; | ||
189 | ranges = <42000000 0 80000000 80000000 0 20000000 | ||
190 | 02000000 0 a0000000 a0000000 0 10000000 | ||
191 | 01000000 0 00000000 b0000000 0 01000000>; | ||
192 | }; | ||
193 | |||
194 | spi@f00 { | ||
195 | device_type = "spi"; | ||
196 | compatible = "mpc5200b-spi\0mpc52xx-spi"; | ||
197 | reg = <f00 20>; | ||
198 | interrupts = <2 d 0 2 e 0>; | ||
199 | interrupt-parent = <500>; | ||
200 | }; | ||
201 | |||
202 | usb@1000 { | ||
203 | device_type = "usb-ohci-be"; | ||
204 | compatible = "mpc5200b-ohci\0mpc52xx-ohci\0ohci-be"; | ||
205 | reg = <1000 ff>; | ||
206 | interrupts = <2 6 0>; | ||
207 | interrupt-parent = <500>; | ||
208 | }; | ||
209 | |||
210 | bestcomm@1200 { | ||
211 | device_type = "dma-controller"; | ||
212 | compatible = "mpc5200b-bestcomm\0mpc52xx-bestcomm"; | ||
213 | reg = <1200 80>; | ||
214 | interrupts = <3 0 0 3 1 0 3 2 0 3 3 0 | ||
215 | 3 4 0 3 5 0 3 6 0 3 7 0 | ||
216 | 3 8 0 3 9 0 3 a 0 3 b 0 | ||
217 | 3 c 0 3 d 0 3 e 0 3 f 0>; | ||
218 | interrupt-parent = <500>; | ||
219 | }; | ||
220 | |||
221 | xlb@1f00 { | ||
222 | compatible = "mpc5200b-xlb\0mpc52xx-xlb"; | ||
223 | reg = <1f00 100>; | ||
224 | }; | ||
225 | |||
226 | serial@2000 { // PSC1 | ||
227 | device_type = "serial"; | ||
228 | compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart"; | ||
229 | port-number = <0>; // Logical port assignment | ||
230 | reg = <2000 100>; | ||
231 | interrupts = <2 1 0>; | ||
232 | interrupt-parent = <500>; | ||
233 | }; | ||
234 | |||
235 | // PSC2 in spi mode example | ||
236 | spi@2200 { // PSC2 | ||
237 | device_type = "spi"; | ||
238 | compatible = "mpc5200b-psc-spi\0mpc52xx-psc-spi"; | ||
239 | reg = <2200 100>; | ||
240 | interrupts = <2 2 0>; | ||
241 | interrupt-parent = <500>; | ||
242 | }; | ||
243 | |||
244 | // PSC3 in CODEC mode example | ||
245 | i2s@2400 { // PSC3 | ||
246 | device_type = "i2s"; | ||
247 | compatible = "mpc5200b-psc-i2s\0mpc52xx-psc-i2s"; | ||
248 | reg = <2400 100>; | ||
249 | interrupts = <2 3 0>; | ||
250 | interrupt-parent = <500>; | ||
251 | }; | ||
252 | |||
253 | // PSC4 unconfigured | ||
254 | //serial@2600 { // PSC4 | ||
255 | // device_type = "serial"; | ||
256 | // compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart"; | ||
257 | // reg = <2600 100>; | ||
258 | // interrupts = <2 b 0>; | ||
259 | // interrupt-parent = <500>; | ||
260 | //}; | ||
261 | |||
262 | // PSC5 unconfigured | ||
263 | //serial@2800 { // PSC5 | ||
264 | // device_type = "serial"; | ||
265 | // compatible = "mpc5200b-psc-uart\0mpc52xx-psc-uart"; | ||
266 | // reg = <2800 100>; | ||
267 | // interrupts = <2 c 0>; | ||
268 | // interrupt-parent = <500>; | ||
269 | //}; | ||
270 | |||
271 | // PSC6 in AC97 mode example | ||
272 | ac97@2c00 { // PSC6 | ||
273 | device_type = "ac97"; | ||
274 | compatible = "mpc5200b-psc-ac97\0mpc52xx-psc-ac97"; | ||
275 | reg = <2c00 100>; | ||
276 | interrupts = <2 4 0>; | ||
277 | interrupt-parent = <500>; | ||
278 | }; | ||
279 | |||
280 | ethernet@3000 { | ||
281 | device_type = "network"; | ||
282 | compatible = "mpc5200b-fec\0mpc52xx-fec"; | ||
283 | reg = <3000 800>; | ||
284 | mac-address = [ 02 03 04 05 06 07 ]; // Bad! | ||
285 | interrupts = <2 5 0>; | ||
286 | interrupt-parent = <500>; | ||
287 | }; | ||
288 | |||
289 | ata@3a00 { | ||
290 | device_type = "ata"; | ||
291 | compatible = "mpc5200b-ata\0mpc52xx-ata"; | ||
292 | reg = <3a00 100>; | ||
293 | interrupts = <2 7 0>; | ||
294 | interrupt-parent = <500>; | ||
295 | }; | ||
296 | |||
297 | i2c@3d00 { | ||
298 | device_type = "i2c"; | ||
299 | compatible = "mpc5200b-i2c\0mpc52xx-i2c"; | ||
300 | reg = <3d00 40>; | ||
301 | interrupts = <2 f 0>; | ||
302 | interrupt-parent = <500>; | ||
303 | }; | ||
304 | |||
305 | i2c@3d40 { | ||
306 | device_type = "i2c"; | ||
307 | compatible = "mpc5200b-i2c\0mpc52xx-i2c"; | ||
308 | reg = <3d40 40>; | ||
309 | interrupts = <2 10 0>; | ||
310 | interrupt-parent = <500>; | ||
311 | }; | ||
312 | sram@8000 { | ||
313 | device_type = "sram"; | ||
314 | compatible = "mpc5200b-sram\0mpc52xx-sram\0sram"; | ||
315 | reg = <8000 4000>; | ||
316 | }; | ||
317 | }; | ||
318 | }; | ||
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts index d7b985e6bd2..c4d9562cbaa 100644 --- a/arch/powerpc/boot/dts/mpc7448hpc2.dts +++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts | |||
@@ -161,29 +161,41 @@ | |||
161 | interrupt-map = < | 161 | interrupt-map = < |
162 | 162 | ||
163 | /* IDSEL 0x11 */ | 163 | /* IDSEL 0x11 */ |
164 | 0800 0 0 1 7400 24 0 | 164 | 0800 0 0 1 1180 24 0 |
165 | 0800 0 0 2 7400 25 0 | 165 | 0800 0 0 2 1180 25 0 |
166 | 0800 0 0 3 7400 26 0 | 166 | 0800 0 0 3 1180 26 0 |
167 | 0800 0 0 4 7400 27 0 | 167 | 0800 0 0 4 1180 27 0 |
168 | 168 | ||
169 | /* IDSEL 0x12 */ | 169 | /* IDSEL 0x12 */ |
170 | 1000 0 0 1 7400 25 0 | 170 | 1000 0 0 1 1180 25 0 |
171 | 1000 0 0 2 7400 26 0 | 171 | 1000 0 0 2 1180 26 0 |
172 | 1000 0 0 3 7400 27 0 | 172 | 1000 0 0 3 1180 27 0 |
173 | 1000 0 0 4 7400 24 0 | 173 | 1000 0 0 4 1180 24 0 |
174 | 174 | ||
175 | /* IDSEL 0x13 */ | 175 | /* IDSEL 0x13 */ |
176 | 1800 0 0 1 7400 26 0 | 176 | 1800 0 0 1 1180 26 0 |
177 | 1800 0 0 2 7400 27 0 | 177 | 1800 0 0 2 1180 27 0 |
178 | 1800 0 0 3 7400 24 0 | 178 | 1800 0 0 3 1180 24 0 |
179 | 1800 0 0 4 7400 25 0 | 179 | 1800 0 0 4 1180 25 0 |
180 | 180 | ||
181 | /* IDSEL 0x14 */ | 181 | /* IDSEL 0x14 */ |
182 | 2000 0 0 1 7400 27 0 | 182 | 2000 0 0 1 1180 27 0 |
183 | 2000 0 0 2 7400 24 0 | 183 | 2000 0 0 2 1180 24 0 |
184 | 2000 0 0 3 7400 25 0 | 184 | 2000 0 0 3 1180 25 0 |
185 | 2000 0 0 4 7400 26 0 | 185 | 2000 0 0 4 1180 26 0 |
186 | >; | 186 | >; |
187 | router@1180 { | ||
188 | linux,phandle = <1180>; | ||
189 | clock-frequency = <0>; | ||
190 | interrupt-controller; | ||
191 | device_type = "pic-router"; | ||
192 | #address-cells = <0>; | ||
193 | #interrupt-cells = <2>; | ||
194 | built-in; | ||
195 | big-endian; | ||
196 | interrupts = <17 2>; | ||
197 | interrupt-parent = <7400>; | ||
198 | }; | ||
187 | }; | 199 | }; |
188 | }; | 200 | }; |
189 | 201 | ||
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c new file mode 100644 index 00000000000..c76c194715b --- /dev/null +++ b/arch/powerpc/boot/flatdevtree.c | |||
@@ -0,0 +1,880 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
15 | * | ||
16 | * Copyright Pantelis Antoniou 2006 | ||
17 | * Copyright (C) IBM Corporation 2006 | ||
18 | * | ||
19 | * Authors: Pantelis Antoniou <pantelis@embeddedalley.com> | ||
20 | * Hollis Blanchard <hollisb@us.ibm.com> | ||
21 | * Mark A. Greer <mgreer@mvista.com> | ||
22 | * Paul Mackerras <paulus@samba.org> | ||
23 | */ | ||
24 | |||
25 | #include <string.h> | ||
26 | #include <stddef.h> | ||
27 | #include "flatdevtree.h" | ||
28 | #include "flatdevtree_env.h" | ||
29 | |||
30 | #define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1)) | ||
31 | |||
32 | /* Routines for keeping node ptrs returned by ft_find_device current */ | ||
33 | /* First entry not used b/c it would return 0 and be taken as NULL/error */ | ||
34 | static void *ft_node_add(struct ft_cxt *cxt, char *node) | ||
35 | { | ||
36 | unsigned int i; | ||
37 | |||
38 | for (i = 1; i < cxt->nodes_used; i++) /* already there? */ | ||
39 | if (cxt->node_tbl[i] == node) | ||
40 | return (void *)i; | ||
41 | |||
42 | if (cxt->nodes_used < cxt->node_max) { | ||
43 | cxt->node_tbl[cxt->nodes_used] = node; | ||
44 | return (void *)cxt->nodes_used++; | ||
45 | } | ||
46 | |||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle) | ||
51 | { | ||
52 | unsigned int i = (unsigned int)phandle; | ||
53 | |||
54 | if (i < cxt->nodes_used) | ||
55 | return cxt->node_tbl[i]; | ||
56 | return NULL; | ||
57 | } | ||
58 | |||
59 | static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift) | ||
60 | { | ||
61 | unsigned int i; | ||
62 | |||
63 | if (shift == 0) | ||
64 | return; | ||
65 | |||
66 | for (i = 1; i < cxt->nodes_used; i++) | ||
67 | if (cxt->node_tbl[i] < addr) | ||
68 | cxt->node_tbl[i] += shift; | ||
69 | } | ||
70 | |||
71 | static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift) | ||
72 | { | ||
73 | unsigned int i; | ||
74 | |||
75 | if (shift == 0) | ||
76 | return; | ||
77 | |||
78 | for (i = 1; i < cxt->nodes_used; i++) | ||
79 | if (cxt->node_tbl[i] >= addr) | ||
80 | cxt->node_tbl[i] += shift; | ||
81 | } | ||
82 | |||
83 | /* Struct used to return info from ft_next() */ | ||
84 | struct ft_atom { | ||
85 | u32 tag; | ||
86 | const char *name; | ||
87 | void *data; | ||
88 | u32 size; | ||
89 | }; | ||
90 | |||
91 | /* Set ptrs to current one's info; return addr of next one */ | ||
92 | static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret) | ||
93 | { | ||
94 | u32 sz; | ||
95 | |||
96 | if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size) | ||
97 | return NULL; | ||
98 | |||
99 | ret->tag = be32_to_cpu(*(u32 *) p); | ||
100 | p += 4; | ||
101 | |||
102 | switch (ret->tag) { /* Tag */ | ||
103 | case OF_DT_BEGIN_NODE: | ||
104 | ret->name = p; | ||
105 | ret->data = (void *)(p - 4); /* start of node */ | ||
106 | p += _ALIGN(strlen(p) + 1, 4); | ||
107 | break; | ||
108 | case OF_DT_PROP: | ||
109 | ret->size = sz = be32_to_cpu(*(u32 *) p); | ||
110 | ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4)); | ||
111 | ret->data = (void *)(p + 8); | ||
112 | p += 8 + _ALIGN(sz, 4); | ||
113 | break; | ||
114 | case OF_DT_END_NODE: | ||
115 | case OF_DT_NOP: | ||
116 | break; | ||
117 | case OF_DT_END: | ||
118 | default: | ||
119 | p = NULL; | ||
120 | break; | ||
121 | } | ||
122 | |||
123 | return p; | ||
124 | } | ||
125 | |||
126 | #define HDR_SIZE _ALIGN(sizeof(struct boot_param_header), 8) | ||
127 | #define EXPAND_INCR 1024 /* alloc this much extra when expanding */ | ||
128 | |||
129 | /* See if the regions are in the standard order and non-overlapping */ | ||
130 | static int ft_ordered(struct ft_cxt *cxt) | ||
131 | { | ||
132 | char *p = (char *)cxt->bph + HDR_SIZE; | ||
133 | enum ft_rgn_id r; | ||
134 | |||
135 | for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) { | ||
136 | if (p > cxt->rgn[r].start) | ||
137 | return 0; | ||
138 | p = cxt->rgn[r].start + cxt->rgn[r].size; | ||
139 | } | ||
140 | return p <= (char *)cxt->bph + cxt->max_size; | ||
141 | } | ||
142 | |||
143 | /* Copy the tree to a newly-allocated region and put things in order */ | ||
144 | static int ft_reorder(struct ft_cxt *cxt, int nextra) | ||
145 | { | ||
146 | unsigned long tot; | ||
147 | enum ft_rgn_id r; | ||
148 | char *p, *pend; | ||
149 | int stroff; | ||
150 | |||
151 | tot = HDR_SIZE + EXPAND_INCR; | ||
152 | for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) | ||
153 | tot += cxt->rgn[r].size; | ||
154 | if (nextra > 0) | ||
155 | tot += nextra; | ||
156 | tot = _ALIGN(tot, 8); | ||
157 | |||
158 | if (!cxt->realloc) | ||
159 | return 0; | ||
160 | p = cxt->realloc(NULL, tot); | ||
161 | if (!p) | ||
162 | return 0; | ||
163 | |||
164 | memcpy(p, cxt->bph, sizeof(struct boot_param_header)); | ||
165 | /* offsets get fixed up later */ | ||
166 | |||
167 | cxt->bph = (struct boot_param_header *)p; | ||
168 | cxt->max_size = tot; | ||
169 | pend = p + tot; | ||
170 | p += HDR_SIZE; | ||
171 | |||
172 | memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size); | ||
173 | cxt->rgn[FT_RSVMAP].start = p; | ||
174 | p += cxt->rgn[FT_RSVMAP].size; | ||
175 | |||
176 | memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size); | ||
177 | ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, | ||
178 | p - cxt->rgn[FT_STRUCT].start); | ||
179 | cxt->p += p - cxt->rgn[FT_STRUCT].start; | ||
180 | cxt->rgn[FT_STRUCT].start = p; | ||
181 | |||
182 | p = pend - cxt->rgn[FT_STRINGS].size; | ||
183 | memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size); | ||
184 | stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start; | ||
185 | cxt->rgn[FT_STRINGS].start = p; | ||
186 | cxt->str_anchor = p + stroff; | ||
187 | |||
188 | cxt->isordered = 1; | ||
189 | return 1; | ||
190 | } | ||
191 | |||
192 | static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r) | ||
193 | { | ||
194 | if (r > FT_RSVMAP) | ||
195 | return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size; | ||
196 | return (char *)cxt->bph + HDR_SIZE; | ||
197 | } | ||
198 | |||
199 | static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r) | ||
200 | { | ||
201 | if (r < FT_STRINGS) | ||
202 | return cxt->rgn[r + 1].start; | ||
203 | return (char *)cxt->bph + cxt->max_size; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * See if we can expand region rgn by nextra bytes by using up | ||
208 | * free space after or before the region. | ||
209 | */ | ||
210 | static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, | ||
211 | int nextra) | ||
212 | { | ||
213 | char *p = *pp; | ||
214 | char *rgn_start, *rgn_end; | ||
215 | |||
216 | rgn_start = cxt->rgn[rgn].start; | ||
217 | rgn_end = rgn_start + cxt->rgn[rgn].size; | ||
218 | if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) { | ||
219 | /* move following stuff */ | ||
220 | if (p < rgn_end) { | ||
221 | if (nextra < 0) | ||
222 | memmove(p, p - nextra, rgn_end - p + nextra); | ||
223 | else | ||
224 | memmove(p + nextra, p, rgn_end - p); | ||
225 | if (rgn == FT_STRUCT) | ||
226 | ft_node_update_after(cxt, p, nextra); | ||
227 | } | ||
228 | cxt->rgn[rgn].size += nextra; | ||
229 | if (rgn == FT_STRINGS) | ||
230 | /* assumes strings only added at beginning */ | ||
231 | cxt->str_anchor += nextra; | ||
232 | return 1; | ||
233 | } | ||
234 | if (prev_end(cxt, rgn) <= rgn_start - nextra) { | ||
235 | /* move preceding stuff */ | ||
236 | if (p > rgn_start) { | ||
237 | memmove(rgn_start - nextra, rgn_start, p - rgn_start); | ||
238 | if (rgn == FT_STRUCT) | ||
239 | ft_node_update_before(cxt, p, -nextra); | ||
240 | } | ||
241 | *p -= nextra; | ||
242 | cxt->rgn[rgn].start -= nextra; | ||
243 | cxt->rgn[rgn].size += nextra; | ||
244 | return 1; | ||
245 | } | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn, | ||
250 | int nextra) | ||
251 | { | ||
252 | unsigned long size, ssize, tot; | ||
253 | char *str, *next; | ||
254 | enum ft_rgn_id r; | ||
255 | |||
256 | if (!cxt->isordered && !ft_reorder(cxt, nextra)) | ||
257 | return 0; | ||
258 | if (ft_shuffle(cxt, pp, rgn, nextra)) | ||
259 | return 1; | ||
260 | |||
261 | /* See if there is space after the strings section */ | ||
262 | ssize = cxt->rgn[FT_STRINGS].size; | ||
263 | if (cxt->rgn[FT_STRINGS].start + ssize | ||
264 | < (char *)cxt->bph + cxt->max_size) { | ||
265 | /* move strings up as far as possible */ | ||
266 | str = (char *)cxt->bph + cxt->max_size - ssize; | ||
267 | cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start; | ||
268 | memmove(str, cxt->rgn[FT_STRINGS].start, ssize); | ||
269 | cxt->rgn[FT_STRINGS].start = str; | ||
270 | /* enough space now? */ | ||
271 | if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra)) | ||
272 | return 1; | ||
273 | } | ||
274 | |||
275 | /* how much total free space is there following this region? */ | ||
276 | tot = 0; | ||
277 | for (r = rgn; r < FT_STRINGS; ++r) { | ||
278 | char *r_end = cxt->rgn[r].start + cxt->rgn[r].size; | ||
279 | tot += next_start(cxt, rgn) - r_end; | ||
280 | } | ||
281 | |||
282 | /* cast is to shut gcc up; we know nextra >= 0 */ | ||
283 | if (tot < (unsigned int)nextra) { | ||
284 | /* have to reallocate */ | ||
285 | char *newp, *new_start; | ||
286 | int shift; | ||
287 | |||
288 | if (!cxt->realloc) | ||
289 | return 0; | ||
290 | size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8); | ||
291 | newp = cxt->realloc(cxt->bph, size); | ||
292 | if (!newp) | ||
293 | return 0; | ||
294 | cxt->max_size = size; | ||
295 | shift = newp - (char *)cxt->bph; | ||
296 | |||
297 | if (shift) { /* realloc can return same addr */ | ||
298 | cxt->bph = (struct boot_param_header *)newp; | ||
299 | ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, | ||
300 | shift); | ||
301 | for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) { | ||
302 | new_start = cxt->rgn[r].start + shift; | ||
303 | cxt->rgn[r].start = new_start; | ||
304 | } | ||
305 | *pp += shift; | ||
306 | cxt->str_anchor += shift; | ||
307 | } | ||
308 | |||
309 | /* move strings up to the end */ | ||
310 | str = newp + size - ssize; | ||
311 | cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start; | ||
312 | memmove(str, cxt->rgn[FT_STRINGS].start, ssize); | ||
313 | cxt->rgn[FT_STRINGS].start = str; | ||
314 | |||
315 | if (ft_shuffle(cxt, pp, rgn, nextra)) | ||
316 | return 1; | ||
317 | } | ||
318 | |||
319 | /* must be FT_RSVMAP and we need to move FT_STRUCT up */ | ||
320 | if (rgn == FT_RSVMAP) { | ||
321 | next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size | ||
322 | + nextra; | ||
323 | ssize = cxt->rgn[FT_STRUCT].size; | ||
324 | if (next + ssize >= cxt->rgn[FT_STRINGS].start) | ||
325 | return 0; /* "can't happen" */ | ||
326 | memmove(next, cxt->rgn[FT_STRUCT].start, ssize); | ||
327 | ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra); | ||
328 | cxt->rgn[FT_STRUCT].start = next; | ||
329 | |||
330 | if (ft_shuffle(cxt, pp, rgn, nextra)) | ||
331 | return 1; | ||
332 | } | ||
333 | |||
334 | return 0; /* "can't happen" */ | ||
335 | } | ||
336 | |||
337 | static void ft_put_word(struct ft_cxt *cxt, u32 v) | ||
338 | { | ||
339 | *(u32 *) cxt->p = cpu_to_be32(v); | ||
340 | cxt->p += 4; | ||
341 | } | ||
342 | |||
343 | static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz) | ||
344 | { | ||
345 | unsigned long sza = _ALIGN(sz, 4); | ||
346 | |||
347 | /* zero out the alignment gap if necessary */ | ||
348 | if (sz < sza) | ||
349 | *(u32 *) (cxt->p + sza - 4) = 0; | ||
350 | |||
351 | /* copy in the data */ | ||
352 | memcpy(cxt->p, data, sz); | ||
353 | |||
354 | cxt->p += sza; | ||
355 | } | ||
356 | |||
357 | int ft_begin_node(struct ft_cxt *cxt, const char *name) | ||
358 | { | ||
359 | unsigned long nlen = strlen(name) + 1; | ||
360 | unsigned long len = 8 + _ALIGN(nlen, 4); | ||
361 | |||
362 | if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) | ||
363 | return -1; | ||
364 | ft_put_word(cxt, OF_DT_BEGIN_NODE); | ||
365 | ft_put_bin(cxt, name, strlen(name) + 1); | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | void ft_end_node(struct ft_cxt *cxt) | ||
370 | { | ||
371 | ft_put_word(cxt, OF_DT_END_NODE); | ||
372 | } | ||
373 | |||
374 | void ft_nop(struct ft_cxt *cxt) | ||
375 | { | ||
376 | if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4)) | ||
377 | ft_put_word(cxt, OF_DT_NOP); | ||
378 | } | ||
379 | |||
380 | #define NO_STRING 0x7fffffff | ||
381 | |||
382 | static int lookup_string(struct ft_cxt *cxt, const char *name) | ||
383 | { | ||
384 | char *p, *end; | ||
385 | |||
386 | p = cxt->rgn[FT_STRINGS].start; | ||
387 | end = p + cxt->rgn[FT_STRINGS].size; | ||
388 | while (p < end) { | ||
389 | if (strcmp(p, (char *)name) == 0) | ||
390 | return p - cxt->str_anchor; | ||
391 | p += strlen(p) + 1; | ||
392 | } | ||
393 | |||
394 | return NO_STRING; | ||
395 | } | ||
396 | |||
397 | /* lookup string and insert if not found */ | ||
398 | static int map_string(struct ft_cxt *cxt, const char *name) | ||
399 | { | ||
400 | int off; | ||
401 | char *p; | ||
402 | |||
403 | off = lookup_string(cxt, name); | ||
404 | if (off != NO_STRING) | ||
405 | return off; | ||
406 | p = cxt->rgn[FT_STRINGS].start; | ||
407 | if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1)) | ||
408 | return NO_STRING; | ||
409 | strcpy(p, name); | ||
410 | return p - cxt->str_anchor; | ||
411 | } | ||
412 | |||
413 | int ft_prop(struct ft_cxt *cxt, const char *name, const void *data, | ||
414 | unsigned int sz) | ||
415 | { | ||
416 | int off, len; | ||
417 | |||
418 | off = lookup_string(cxt, name); | ||
419 | if (off == NO_STRING) | ||
420 | return -1; | ||
421 | |||
422 | len = 12 + _ALIGN(sz, 4); | ||
423 | if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) | ||
424 | return -1; | ||
425 | |||
426 | ft_put_word(cxt, OF_DT_PROP); | ||
427 | ft_put_word(cxt, sz); | ||
428 | ft_put_word(cxt, off); | ||
429 | ft_put_bin(cxt, data, sz); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str) | ||
434 | { | ||
435 | return ft_prop(cxt, name, str, strlen(str) + 1); | ||
436 | } | ||
437 | |||
438 | int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val) | ||
439 | { | ||
440 | u32 v = cpu_to_be32((u32) val); | ||
441 | |||
442 | return ft_prop(cxt, name, &v, 4); | ||
443 | } | ||
444 | |||
445 | /* Calculate the size of the reserved map */ | ||
446 | static unsigned long rsvmap_size(struct ft_cxt *cxt) | ||
447 | { | ||
448 | struct ft_reserve *res; | ||
449 | |||
450 | res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start; | ||
451 | while (res->start || res->len) | ||
452 | ++res; | ||
453 | return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start; | ||
454 | } | ||
455 | |||
456 | /* Calculate the size of the struct region by stepping through it */ | ||
457 | static unsigned long struct_size(struct ft_cxt *cxt) | ||
458 | { | ||
459 | char *p = cxt->rgn[FT_STRUCT].start; | ||
460 | char *next; | ||
461 | struct ft_atom atom; | ||
462 | |||
463 | /* make check in ft_next happy */ | ||
464 | if (cxt->rgn[FT_STRUCT].size == 0) | ||
465 | cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p; | ||
466 | |||
467 | while ((next = ft_next(cxt, p, &atom)) != NULL) | ||
468 | p = next; | ||
469 | return p + 4 - cxt->rgn[FT_STRUCT].start; | ||
470 | } | ||
471 | |||
472 | /* add `adj' on to all string offset values in the struct area */ | ||
473 | static void adjust_string_offsets(struct ft_cxt *cxt, int adj) | ||
474 | { | ||
475 | char *p = cxt->rgn[FT_STRUCT].start; | ||
476 | char *next; | ||
477 | struct ft_atom atom; | ||
478 | int off; | ||
479 | |||
480 | while ((next = ft_next(cxt, p, &atom)) != NULL) { | ||
481 | if (atom.tag == OF_DT_PROP) { | ||
482 | off = be32_to_cpu(*(u32 *) (p + 8)); | ||
483 | *(u32 *) (p + 8) = cpu_to_be32(off + adj); | ||
484 | } | ||
485 | p = next; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | /* start construction of the flat OF tree from scratch */ | ||
490 | void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size, | ||
491 | void *(*realloc_fn) (void *, unsigned long)) | ||
492 | { | ||
493 | struct boot_param_header *bph = blob; | ||
494 | char *p; | ||
495 | struct ft_reserve *pres; | ||
496 | |||
497 | /* clear the cxt */ | ||
498 | memset(cxt, 0, sizeof(*cxt)); | ||
499 | |||
500 | cxt->bph = bph; | ||
501 | cxt->max_size = max_size; | ||
502 | cxt->realloc = realloc_fn; | ||
503 | cxt->isordered = 1; | ||
504 | |||
505 | /* zero everything in the header area */ | ||
506 | memset(bph, 0, sizeof(*bph)); | ||
507 | |||
508 | bph->magic = cpu_to_be32(OF_DT_HEADER); | ||
509 | bph->version = cpu_to_be32(0x10); | ||
510 | bph->last_comp_version = cpu_to_be32(0x10); | ||
511 | |||
512 | /* start pointers */ | ||
513 | cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE; | ||
514 | cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve); | ||
515 | pres = (struct ft_reserve *)p; | ||
516 | cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve); | ||
517 | cxt->rgn[FT_STRUCT].size = 4; | ||
518 | cxt->rgn[FT_STRINGS].start = blob + max_size; | ||
519 | cxt->rgn[FT_STRINGS].size = 0; | ||
520 | |||
521 | /* init rsvmap and struct */ | ||
522 | pres->start = 0; | ||
523 | pres->len = 0; | ||
524 | *(u32 *) p = cpu_to_be32(OF_DT_END); | ||
525 | |||
526 | cxt->str_anchor = blob; | ||
527 | } | ||
528 | |||
529 | /* open up an existing blob to be examined or modified */ | ||
530 | int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size, | ||
531 | unsigned int max_find_device, | ||
532 | void *(*realloc_fn) (void *, unsigned long)) | ||
533 | { | ||
534 | struct boot_param_header *bph = blob; | ||
535 | |||
536 | /* can't cope with version < 16 */ | ||
537 | if (be32_to_cpu(bph->version) < 16) | ||
538 | return -1; | ||
539 | |||
540 | /* clear the cxt */ | ||
541 | memset(cxt, 0, sizeof(*cxt)); | ||
542 | |||
543 | /* alloc node_tbl to track node ptrs returned by ft_find_device */ | ||
544 | ++max_find_device; | ||
545 | cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *)); | ||
546 | if (!cxt->node_tbl) | ||
547 | return -1; | ||
548 | memset(cxt->node_tbl, 0, max_find_device * sizeof(char *)); | ||
549 | cxt->node_max = max_find_device; | ||
550 | cxt->nodes_used = 1; /* don't use idx 0 b/c looks like NULL */ | ||
551 | |||
552 | cxt->bph = bph; | ||
553 | cxt->max_size = max_size; | ||
554 | cxt->realloc = realloc_fn; | ||
555 | |||
556 | cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap); | ||
557 | cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt); | ||
558 | cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct); | ||
559 | cxt->rgn[FT_STRUCT].size = struct_size(cxt); | ||
560 | cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings); | ||
561 | cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size); | ||
562 | /* Leave as '0' to force first ft_make_space call to do a ft_reorder | ||
563 | * and move dt to an area allocated by realloc. | ||
564 | cxt->isordered = ft_ordered(cxt); | ||
565 | */ | ||
566 | |||
567 | cxt->p = cxt->rgn[FT_STRUCT].start; | ||
568 | cxt->str_anchor = cxt->rgn[FT_STRINGS].start; | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | /* add a reserver physical area to the rsvmap */ | ||
574 | int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size) | ||
575 | { | ||
576 | char *p; | ||
577 | struct ft_reserve *pres; | ||
578 | |||
579 | p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size | ||
580 | - sizeof(struct ft_reserve); | ||
581 | if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve))) | ||
582 | return -1; | ||
583 | |||
584 | pres = (struct ft_reserve *)p; | ||
585 | pres->start = cpu_to_be64(physaddr); | ||
586 | pres->len = cpu_to_be64(size); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | void ft_begin_tree(struct ft_cxt *cxt) | ||
592 | { | ||
593 | cxt->p = cxt->rgn[FT_STRUCT].start; | ||
594 | } | ||
595 | |||
596 | void ft_end_tree(struct ft_cxt *cxt) | ||
597 | { | ||
598 | struct boot_param_header *bph = cxt->bph; | ||
599 | char *p, *oldstr, *str, *endp; | ||
600 | unsigned long ssize; | ||
601 | int adj; | ||
602 | |||
603 | if (!cxt->isordered) | ||
604 | return; /* we haven't touched anything */ | ||
605 | |||
606 | /* adjust string offsets */ | ||
607 | oldstr = cxt->rgn[FT_STRINGS].start; | ||
608 | adj = cxt->str_anchor - oldstr; | ||
609 | if (adj) | ||
610 | adjust_string_offsets(cxt, adj); | ||
611 | |||
612 | /* make strings end on 8-byte boundary */ | ||
613 | ssize = cxt->rgn[FT_STRINGS].size; | ||
614 | endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start | ||
615 | + cxt->rgn[FT_STRUCT].size + ssize, 8); | ||
616 | str = endp - ssize; | ||
617 | |||
618 | /* move strings down to end of structs */ | ||
619 | memmove(str, oldstr, ssize); | ||
620 | cxt->str_anchor = str; | ||
621 | cxt->rgn[FT_STRINGS].start = str; | ||
622 | |||
623 | /* fill in header fields */ | ||
624 | p = (char *)bph; | ||
625 | bph->totalsize = cpu_to_be32(endp - p); | ||
626 | bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p); | ||
627 | bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p); | ||
628 | bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p); | ||
629 | bph->dt_strings_size = cpu_to_be32(ssize); | ||
630 | } | ||
631 | |||
632 | void *ft_find_device(struct ft_cxt *cxt, const char *srch_path) | ||
633 | { | ||
634 | char *node; | ||
635 | |||
636 | /* require absolute path */ | ||
637 | if (srch_path[0] != '/') | ||
638 | return NULL; | ||
639 | node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path); | ||
640 | return ft_node_add(cxt, node); | ||
641 | } | ||
642 | |||
643 | void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path) | ||
644 | { | ||
645 | struct ft_atom atom; | ||
646 | char *p; | ||
647 | const char *cp, *q; | ||
648 | int cl; | ||
649 | int depth = -1; | ||
650 | int dmatch = 0; | ||
651 | const char *path_comp[FT_MAX_DEPTH]; | ||
652 | |||
653 | cp = srch_path; | ||
654 | cl = 0; | ||
655 | p = top; | ||
656 | |||
657 | while ((p = ft_next(cxt, p, &atom)) != NULL) { | ||
658 | switch (atom.tag) { | ||
659 | case OF_DT_BEGIN_NODE: | ||
660 | ++depth; | ||
661 | if (depth != dmatch) | ||
662 | break; | ||
663 | cxt->genealogy[depth] = atom.data; | ||
664 | cxt->genealogy[depth + 1] = NULL; | ||
665 | if (depth && !(strncmp(atom.name, cp, cl) == 0 | ||
666 | && (atom.name[cl] == '/' | ||
667 | || atom.name[cl] == '\0' | ||
668 | || atom.name[cl] == '@'))) | ||
669 | break; | ||
670 | path_comp[dmatch] = cp; | ||
671 | /* it matches so far, advance to next path component */ | ||
672 | cp += cl; | ||
673 | /* skip slashes */ | ||
674 | while (*cp == '/') | ||
675 | ++cp; | ||
676 | /* we're done if this is the end of the string */ | ||
677 | if (*cp == 0) | ||
678 | return atom.data; | ||
679 | /* look for end of this component */ | ||
680 | q = strchr(cp, '/'); | ||
681 | if (q) | ||
682 | cl = q - cp; | ||
683 | else | ||
684 | cl = strlen(cp); | ||
685 | ++dmatch; | ||
686 | break; | ||
687 | case OF_DT_END_NODE: | ||
688 | if (depth == 0) | ||
689 | return NULL; | ||
690 | if (dmatch > depth) { | ||
691 | --dmatch; | ||
692 | cl = cp - path_comp[dmatch] - 1; | ||
693 | cp = path_comp[dmatch]; | ||
694 | while (cl > 0 && cp[cl - 1] == '/') | ||
695 | --cl; | ||
696 | } | ||
697 | --depth; | ||
698 | break; | ||
699 | } | ||
700 | } | ||
701 | return NULL; | ||
702 | } | ||
703 | |||
704 | void *ft_get_parent(struct ft_cxt *cxt, const void *phandle) | ||
705 | { | ||
706 | void *node; | ||
707 | int d; | ||
708 | struct ft_atom atom; | ||
709 | char *p; | ||
710 | |||
711 | node = ft_node_ph2node(cxt, phandle); | ||
712 | if (node == NULL) | ||
713 | return NULL; | ||
714 | |||
715 | for (d = 0; cxt->genealogy[d] != NULL; ++d) | ||
716 | if (cxt->genealogy[d] == node) | ||
717 | return cxt->genealogy[d > 0 ? d - 1 : 0]; | ||
718 | |||
719 | /* have to do it the hard way... */ | ||
720 | p = cxt->rgn[FT_STRUCT].start; | ||
721 | d = 0; | ||
722 | while ((p = ft_next(cxt, p, &atom)) != NULL) { | ||
723 | switch (atom.tag) { | ||
724 | case OF_DT_BEGIN_NODE: | ||
725 | cxt->genealogy[d] = atom.data; | ||
726 | if (node == atom.data) { | ||
727 | /* found it */ | ||
728 | cxt->genealogy[d + 1] = NULL; | ||
729 | return d > 0 ? cxt->genealogy[d - 1] : node; | ||
730 | } | ||
731 | ++d; | ||
732 | break; | ||
733 | case OF_DT_END_NODE: | ||
734 | --d; | ||
735 | break; | ||
736 | } | ||
737 | } | ||
738 | return NULL; | ||
739 | } | ||
740 | |||
741 | int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | ||
742 | void *buf, const unsigned int buflen) | ||
743 | { | ||
744 | struct ft_atom atom; | ||
745 | void *node; | ||
746 | char *p; | ||
747 | int depth; | ||
748 | unsigned int size; | ||
749 | |||
750 | node = ft_node_ph2node(cxt, phandle); | ||
751 | if (node == NULL) | ||
752 | return -1; | ||
753 | |||
754 | depth = 0; | ||
755 | p = (char *)node; | ||
756 | |||
757 | while ((p = ft_next(cxt, p, &atom)) != NULL) { | ||
758 | switch (atom.tag) { | ||
759 | case OF_DT_BEGIN_NODE: | ||
760 | ++depth; | ||
761 | break; | ||
762 | case OF_DT_PROP: | ||
763 | if ((depth != 1) || strcmp(atom.name, propname)) | ||
764 | break; | ||
765 | size = min(atom.size, buflen); | ||
766 | memcpy(buf, atom.data, size); | ||
767 | return atom.size; | ||
768 | case OF_DT_END_NODE: | ||
769 | if (--depth <= 0) | ||
770 | return -1; | ||
771 | } | ||
772 | } | ||
773 | return -1; | ||
774 | } | ||
775 | |||
776 | int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | ||
777 | const void *buf, const unsigned int buflen) | ||
778 | { | ||
779 | struct ft_atom atom; | ||
780 | void *node; | ||
781 | char *p, *next; | ||
782 | int nextra, depth; | ||
783 | |||
784 | node = ft_node_ph2node(cxt, phandle); | ||
785 | if (node == NULL) | ||
786 | return -1; | ||
787 | |||
788 | depth = 0; | ||
789 | p = node; | ||
790 | |||
791 | while ((next = ft_next(cxt, p, &atom)) != NULL) { | ||
792 | switch (atom.tag) { | ||
793 | case OF_DT_BEGIN_NODE: | ||
794 | ++depth; | ||
795 | break; | ||
796 | case OF_DT_END_NODE: | ||
797 | if (--depth > 0) | ||
798 | break; | ||
799 | /* haven't found the property, insert here */ | ||
800 | cxt->p = p; | ||
801 | return ft_prop(cxt, propname, buf, buflen); | ||
802 | case OF_DT_PROP: | ||
803 | if ((depth != 1) || strcmp(atom.name, propname)) | ||
804 | break; | ||
805 | /* found an existing property, overwrite it */ | ||
806 | nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4); | ||
807 | cxt->p = atom.data; | ||
808 | if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT, | ||
809 | nextra)) | ||
810 | return -1; | ||
811 | *(u32 *) (cxt->p - 8) = cpu_to_be32(buflen); | ||
812 | ft_put_bin(cxt, buf, buflen); | ||
813 | return 0; | ||
814 | } | ||
815 | p = next; | ||
816 | } | ||
817 | return -1; | ||
818 | } | ||
819 | |||
820 | int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname) | ||
821 | { | ||
822 | struct ft_atom atom; | ||
823 | void *node; | ||
824 | char *p, *next; | ||
825 | int size; | ||
826 | |||
827 | node = ft_node_ph2node(cxt, phandle); | ||
828 | if (node == NULL) | ||
829 | return -1; | ||
830 | |||
831 | p = node; | ||
832 | while ((next = ft_next(cxt, p, &atom)) != NULL) { | ||
833 | switch (atom.tag) { | ||
834 | case OF_DT_BEGIN_NODE: | ||
835 | case OF_DT_END_NODE: | ||
836 | return -1; | ||
837 | case OF_DT_PROP: | ||
838 | if (strcmp(atom.name, propname)) | ||
839 | break; | ||
840 | /* found the property, remove it */ | ||
841 | size = 12 + -_ALIGN(atom.size, 4); | ||
842 | cxt->p = p; | ||
843 | if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size)) | ||
844 | return -1; | ||
845 | return 0; | ||
846 | } | ||
847 | p = next; | ||
848 | } | ||
849 | return -1; | ||
850 | } | ||
851 | |||
852 | void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path) | ||
853 | { | ||
854 | struct ft_atom atom; | ||
855 | char *p, *next; | ||
856 | int depth = 0; | ||
857 | |||
858 | p = cxt->rgn[FT_STRUCT].start; | ||
859 | while ((next = ft_next(cxt, p, &atom)) != NULL) { | ||
860 | switch (atom.tag) { | ||
861 | case OF_DT_BEGIN_NODE: | ||
862 | ++depth; | ||
863 | if (depth == 1 && strcmp(atom.name, path) == 0) | ||
864 | /* duplicate node path, return error */ | ||
865 | return NULL; | ||
866 | break; | ||
867 | case OF_DT_END_NODE: | ||
868 | --depth; | ||
869 | if (depth > 0) | ||
870 | break; | ||
871 | /* end of node, insert here */ | ||
872 | cxt->p = p; | ||
873 | ft_begin_node(cxt, path); | ||
874 | ft_end_node(cxt); | ||
875 | return p; | ||
876 | } | ||
877 | p = next; | ||
878 | } | ||
879 | return NULL; | ||
880 | } | ||
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h index 761c8dc8400..b9cd9f61f35 100644 --- a/arch/powerpc/boot/flatdevtree.h +++ b/arch/powerpc/boot/flatdevtree.h | |||
@@ -17,7 +17,7 @@ | |||
17 | #ifndef FLATDEVTREE_H | 17 | #ifndef FLATDEVTREE_H |
18 | #define FLATDEVTREE_H | 18 | #define FLATDEVTREE_H |
19 | 19 | ||
20 | #include "types.h" | 20 | #include "flatdevtree_env.h" |
21 | 21 | ||
22 | /* Definitions used by the flattened device tree */ | 22 | /* Definitions used by the flattened device tree */ |
23 | #define OF_DT_HEADER 0xd00dfeed /* marker */ | 23 | #define OF_DT_HEADER 0xd00dfeed /* marker */ |
@@ -43,4 +43,64 @@ struct boot_param_header { | |||
43 | u32 dt_strings_size; /* size of the DT strings block */ | 43 | u32 dt_strings_size; /* size of the DT strings block */ |
44 | }; | 44 | }; |
45 | 45 | ||
46 | struct ft_reserve { | ||
47 | u64 start; | ||
48 | u64 len; | ||
49 | }; | ||
50 | |||
51 | struct ft_region { | ||
52 | char *start; | ||
53 | unsigned long size; | ||
54 | }; | ||
55 | |||
56 | enum ft_rgn_id { | ||
57 | FT_RSVMAP, | ||
58 | FT_STRUCT, | ||
59 | FT_STRINGS, | ||
60 | FT_N_REGION | ||
61 | }; | ||
62 | |||
63 | #define FT_MAX_DEPTH 50 | ||
64 | |||
65 | struct ft_cxt { | ||
66 | struct boot_param_header *bph; | ||
67 | int max_size; /* maximum size of tree */ | ||
68 | int isordered; /* everything in standard order */ | ||
69 | void *(*realloc)(void *, unsigned long); | ||
70 | char *str_anchor; | ||
71 | char *p; /* current insertion point in structs */ | ||
72 | struct ft_region rgn[FT_N_REGION]; | ||
73 | void *genealogy[FT_MAX_DEPTH+1]; | ||
74 | char **node_tbl; | ||
75 | unsigned int node_max; | ||
76 | unsigned int nodes_used; | ||
77 | }; | ||
78 | |||
79 | int ft_begin_node(struct ft_cxt *cxt, const char *name); | ||
80 | void ft_end_node(struct ft_cxt *cxt); | ||
81 | |||
82 | void ft_begin_tree(struct ft_cxt *cxt); | ||
83 | void ft_end_tree(struct ft_cxt *cxt); | ||
84 | |||
85 | void ft_nop(struct ft_cxt *cxt); | ||
86 | int ft_prop(struct ft_cxt *cxt, const char *name, | ||
87 | const void *data, unsigned int sz); | ||
88 | int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str); | ||
89 | int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val); | ||
90 | void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size, | ||
91 | void *(*realloc_fn)(void *, unsigned long)); | ||
92 | int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size, | ||
93 | unsigned int max_find_device, | ||
94 | void *(*realloc_fn)(void *, unsigned long)); | ||
95 | int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size); | ||
96 | |||
97 | void ft_dump_blob(const void *bphp); | ||
98 | void ft_merge_blob(struct ft_cxt *cxt, void *blob); | ||
99 | void *ft_find_device(struct ft_cxt *cxt, const char *srch_path); | ||
100 | void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path); | ||
101 | int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | ||
102 | void *buf, const unsigned int buflen); | ||
103 | int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, | ||
104 | const void *buf, const unsigned int buflen); | ||
105 | |||
46 | #endif /* FLATDEVTREE_H */ | 106 | #endif /* FLATDEVTREE_H */ |
diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h new file mode 100644 index 00000000000..83bc1c71883 --- /dev/null +++ b/arch/powerpc/boot/flatdevtree_env.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * This file adds the header file glue so that the shared files | ||
3 | * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper. | ||
4 | * | ||
5 | * strncmp & strchr copied from <file:lib/strings.c> | ||
6 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
7 | * | ||
8 | * Maintained by: Mark A. Greer <mgreer@mvista.com> | ||
9 | */ | ||
10 | #ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_ | ||
11 | #define _PPC_BOOT_FLATDEVTREE_ENV_H_ | ||
12 | |||
13 | #include <stdarg.h> | ||
14 | #include <stddef.h> | ||
15 | #include "types.h" | ||
16 | #include "string.h" | ||
17 | #include "stdio.h" | ||
18 | #include "ops.h" | ||
19 | |||
20 | #define be16_to_cpu(x) (x) | ||
21 | #define cpu_to_be16(x) (x) | ||
22 | #define be32_to_cpu(x) (x) | ||
23 | #define cpu_to_be32(x) (x) | ||
24 | #define be64_to_cpu(x) (x) | ||
25 | #define cpu_to_be64(x) (x) | ||
26 | |||
27 | static inline int strncmp(const char *cs, const char *ct, size_t count) | ||
28 | { | ||
29 | signed char __res = 0; | ||
30 | |||
31 | while (count) { | ||
32 | if ((__res = *cs - *ct++) != 0 || !*cs++) | ||
33 | break; | ||
34 | count--; | ||
35 | } | ||
36 | return __res; | ||
37 | } | ||
38 | |||
39 | static inline char *strchr(const char *s, int c) | ||
40 | { | ||
41 | for (; *s != (char)c; ++s) | ||
42 | if (*s == '\0') | ||
43 | return NULL; | ||
44 | return (char *)s; | ||
45 | } | ||
46 | |||
47 | #endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */ | ||
diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c new file mode 100644 index 00000000000..04da38fa477 --- /dev/null +++ b/arch/powerpc/boot/flatdevtree_misc.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * This file does the necessary interface mapping between the bootwrapper | ||
3 | * device tree operations and the interface provided by shared source | ||
4 | * files flatdevicetree.[ch]. | ||
5 | * | ||
6 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
7 | * | ||
8 | * 2006 (c) MontaVista Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | #include <stddef.h> | ||
14 | #include "flatdevtree.h" | ||
15 | #include "ops.h" | ||
16 | |||
17 | static struct ft_cxt cxt; | ||
18 | |||
19 | static void *ft_finddevice(const char *name) | ||
20 | { | ||
21 | return ft_find_device(&cxt, name); | ||
22 | } | ||
23 | |||
24 | static int ft_getprop(const void *phandle, const char *propname, void *buf, | ||
25 | const int buflen) | ||
26 | { | ||
27 | return ft_get_prop(&cxt, phandle, propname, buf, buflen); | ||
28 | } | ||
29 | |||
30 | static int ft_setprop(const void *phandle, const char *propname, | ||
31 | const void *buf, const int buflen) | ||
32 | { | ||
33 | return ft_set_prop(&cxt, phandle, propname, buf, buflen); | ||
34 | } | ||
35 | |||
36 | static unsigned long ft_finalize(void) | ||
37 | { | ||
38 | ft_end_tree(&cxt); | ||
39 | return (unsigned long)cxt.bph; | ||
40 | } | ||
41 | |||
42 | int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) | ||
43 | { | ||
44 | dt_ops.finddevice = ft_finddevice; | ||
45 | dt_ops.getprop = ft_getprop; | ||
46 | dt_ops.setprop = ft_setprop; | ||
47 | dt_ops.finalize = ft_finalize; | ||
48 | |||
49 | return ft_open(&cxt, dt_blob, max_size, max_find_device, | ||
50 | platform_ops.realloc); | ||
51 | } | ||
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h new file mode 100644 index 00000000000..32974ed49e0 --- /dev/null +++ b/arch/powerpc/boot/io.h | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifndef _IO_H | ||
2 | #define __IO_H | ||
3 | /* | ||
4 | * Low-level I/O routines. | ||
5 | * | ||
6 | * Copied from <file:include/asm-powerpc/io.h> (which has no copyright) | ||
7 | */ | ||
8 | static inline int in_8(const volatile unsigned char *addr) | ||
9 | { | ||
10 | int ret; | ||
11 | |||
12 | __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync" | ||
13 | : "=r" (ret) : "m" (*addr)); | ||
14 | return ret; | ||
15 | } | ||
16 | |||
17 | static inline void out_8(volatile unsigned char *addr, int val) | ||
18 | { | ||
19 | __asm__ __volatile__("stb%U0%X0 %1,%0; sync" | ||
20 | : "=m" (*addr) : "r" (val)); | ||
21 | } | ||
22 | |||
23 | static inline unsigned in_le32(const volatile unsigned *addr) | ||
24 | { | ||
25 | unsigned ret; | ||
26 | |||
27 | __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync" | ||
28 | : "=r" (ret) : "r" (addr), "m" (*addr)); | ||
29 | return ret; | ||
30 | } | ||
31 | |||
32 | static inline unsigned in_be32(const volatile unsigned *addr) | ||
33 | { | ||
34 | unsigned ret; | ||
35 | |||
36 | __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync" | ||
37 | : "=r" (ret) : "m" (*addr)); | ||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | static inline void out_le32(volatile unsigned *addr, int val) | ||
42 | { | ||
43 | __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr) | ||
44 | : "r" (val), "r" (addr)); | ||
45 | } | ||
46 | |||
47 | static inline void out_be32(volatile unsigned *addr, int val) | ||
48 | { | ||
49 | __asm__ __volatile__("stw%U0%X0 %1,%0; sync" | ||
50 | : "=m" (*addr) : "r" (val)); | ||
51 | } | ||
52 | |||
53 | #endif /* _IO_H */ | ||
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index d719bb9333d..6f6b50d238b 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
@@ -27,6 +27,8 @@ extern char _vmlinux_start[]; | |||
27 | extern char _vmlinux_end[]; | 27 | extern char _vmlinux_end[]; |
28 | extern char _initrd_start[]; | 28 | extern char _initrd_start[]; |
29 | extern char _initrd_end[]; | 29 | extern char _initrd_end[]; |
30 | extern char _dtb_start[]; | ||
31 | extern char _dtb_end[]; | ||
30 | 32 | ||
31 | struct addr_range { | 33 | struct addr_range { |
32 | unsigned long addr; | 34 | unsigned long addr; |
@@ -167,7 +169,7 @@ static int is_elf32(void *hdr) | |||
167 | return 1; | 169 | return 1; |
168 | } | 170 | } |
169 | 171 | ||
170 | static void prep_kernel(unsigned long *a1, unsigned long *a2) | 172 | static void prep_kernel(unsigned long a1, unsigned long a2) |
171 | { | 173 | { |
172 | int len; | 174 | int len; |
173 | 175 | ||
@@ -203,11 +205,14 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2) | |||
203 | } | 205 | } |
204 | 206 | ||
205 | /* | 207 | /* |
206 | * Now we try to alloc memory for the initrd (and copy it there) | 208 | * Now find the initrd |
209 | * | ||
210 | * First see if we have an image attached to us. If so | ||
211 | * allocate memory for it and copy it there. | ||
207 | */ | 212 | */ |
208 | initrd.size = (unsigned long)(_initrd_end - _initrd_start); | 213 | initrd.size = (unsigned long)(_initrd_end - _initrd_start); |
209 | initrd.memsize = initrd.size; | 214 | initrd.memsize = initrd.size; |
210 | if ( initrd.size > 0 ) { | 215 | if (initrd.size > 0) { |
211 | printf("Allocating 0x%lx bytes for initrd ...\n\r", | 216 | printf("Allocating 0x%lx bytes for initrd ...\n\r", |
212 | initrd.size); | 217 | initrd.size); |
213 | initrd.addr = (unsigned long)malloc((u32)initrd.size); | 218 | initrd.addr = (unsigned long)malloc((u32)initrd.size); |
@@ -216,8 +221,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2) | |||
216 | "ramdisk !\n\r"); | 221 | "ramdisk !\n\r"); |
217 | exit(); | 222 | exit(); |
218 | } | 223 | } |
219 | *a1 = initrd.addr; | ||
220 | *a2 = initrd.size; | ||
221 | printf("initial ramdisk moving 0x%lx <- 0x%lx " | 224 | printf("initial ramdisk moving 0x%lx <- 0x%lx " |
222 | "(0x%lx bytes)\n\r", initrd.addr, | 225 | "(0x%lx bytes)\n\r", initrd.addr, |
223 | (unsigned long)_initrd_start, initrd.size); | 226 | (unsigned long)_initrd_start, initrd.size); |
@@ -225,6 +228,12 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2) | |||
225 | initrd.size); | 228 | initrd.size); |
226 | printf("initrd head: 0x%lx\n\r", | 229 | printf("initrd head: 0x%lx\n\r", |
227 | *((unsigned long *)initrd.addr)); | 230 | *((unsigned long *)initrd.addr)); |
231 | } else if (a2 != 0) { | ||
232 | /* Otherwise, see if yaboot or another loader gave us an initrd */ | ||
233 | initrd.addr = a1; | ||
234 | initrd.memsize = initrd.size = a2; | ||
235 | printf("Using loader supplied initrd at 0x%lx (0x%lx bytes)\n\r", | ||
236 | initrd.addr, initrd.size); | ||
228 | } | 237 | } |
229 | 238 | ||
230 | /* Eventually gunzip the kernel */ | 239 | /* Eventually gunzip the kernel */ |
@@ -250,10 +259,6 @@ static void prep_kernel(unsigned long *a1, unsigned long *a2) | |||
250 | flush_cache((void *)vmlinux.addr, vmlinux.size); | 259 | flush_cache((void *)vmlinux.addr, vmlinux.size); |
251 | } | 260 | } |
252 | 261 | ||
253 | void __attribute__ ((weak)) ft_init(void *dt_blob) | ||
254 | { | ||
255 | } | ||
256 | |||
257 | /* A buffer that may be edited by tools operating on a zImage binary so as to | 262 | /* A buffer that may be edited by tools operating on a zImage binary so as to |
258 | * edit the command line passed to vmlinux (by setting /chosen/bootargs). | 263 | * edit the command line passed to vmlinux (by setting /chosen/bootargs). |
259 | * The buffer is put in it's own section so that tools may locate it easier. | 264 | * The buffer is put in it's own section so that tools may locate it easier. |
@@ -285,36 +290,22 @@ static void set_cmdline(char *buf) | |||
285 | setprop(devp, "bootargs", buf, strlen(buf) + 1); | 290 | setprop(devp, "bootargs", buf, strlen(buf) + 1); |
286 | } | 291 | } |
287 | 292 | ||
288 | /* Section where ft can be tacked on after zImage is built */ | ||
289 | union blobspace { | ||
290 | struct boot_param_header hdr; | ||
291 | char space[8*1024]; | ||
292 | } dt_blob __attribute__((__section__("__builtin_ft"))); | ||
293 | |||
294 | struct platform_ops platform_ops; | 293 | struct platform_ops platform_ops; |
295 | struct dt_ops dt_ops; | 294 | struct dt_ops dt_ops; |
296 | struct console_ops console_ops; | 295 | struct console_ops console_ops; |
297 | 296 | ||
298 | void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | 297 | void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) |
299 | { | 298 | { |
300 | int have_dt = 0; | ||
301 | kernel_entry_t kentry; | 299 | kernel_entry_t kentry; |
302 | char cmdline[COMMAND_LINE_SIZE]; | 300 | char cmdline[COMMAND_LINE_SIZE]; |
301 | unsigned long ft_addr = 0; | ||
303 | 302 | ||
304 | memset(__bss_start, 0, _end - __bss_start); | 303 | memset(__bss_start, 0, _end - __bss_start); |
305 | memset(&platform_ops, 0, sizeof(platform_ops)); | 304 | memset(&platform_ops, 0, sizeof(platform_ops)); |
306 | memset(&dt_ops, 0, sizeof(dt_ops)); | 305 | memset(&dt_ops, 0, sizeof(dt_ops)); |
307 | memset(&console_ops, 0, sizeof(console_ops)); | 306 | memset(&console_ops, 0, sizeof(console_ops)); |
308 | 307 | ||
309 | /* Override the dt_ops and device tree if there was an flat dev | 308 | if (platform_init(promptr, _dtb_start, _dtb_end)) |
310 | * tree attached to the zImage. | ||
311 | */ | ||
312 | if (dt_blob.hdr.magic == OF_DT_HEADER) { | ||
313 | have_dt = 1; | ||
314 | ft_init(&dt_blob); | ||
315 | } | ||
316 | |||
317 | if (platform_init(promptr)) | ||
318 | exit(); | 309 | exit(); |
319 | if (console_ops.open && (console_ops.open() < 0)) | 310 | if (console_ops.open && (console_ops.open() < 0)) |
320 | exit(); | 311 | exit(); |
@@ -324,7 +315,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | |||
324 | printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", | 315 | printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", |
325 | _start, sp); | 316 | _start, sp); |
326 | 317 | ||
327 | prep_kernel(&a1, &a2); | 318 | prep_kernel(a1, a2); |
328 | 319 | ||
329 | /* If cmdline came from zimage wrapper or if we can edit the one | 320 | /* If cmdline came from zimage wrapper or if we can edit the one |
330 | * in the dt, print it out and edit it, if possible. | 321 | * in the dt, print it out and edit it, if possible. |
@@ -338,15 +329,23 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) | |||
338 | set_cmdline(cmdline); | 329 | set_cmdline(cmdline); |
339 | } | 330 | } |
340 | 331 | ||
332 | printf("Finalizing device tree..."); | ||
333 | if (dt_ops.finalize) | ||
334 | ft_addr = dt_ops.finalize(); | ||
335 | if (ft_addr) | ||
336 | printf(" flat tree at 0x%lx\n\r", ft_addr); | ||
337 | else | ||
338 | printf(" using OF tree (promptr=%p)\n\r", promptr); | ||
339 | |||
341 | if (console_ops.close) | 340 | if (console_ops.close) |
342 | console_ops.close(); | 341 | console_ops.close(); |
343 | 342 | ||
344 | kentry = (kernel_entry_t) vmlinux.addr; | 343 | kentry = (kernel_entry_t) vmlinux.addr; |
345 | if (have_dt) | 344 | if (ft_addr) |
346 | kentry(dt_ops.ft_addr(), 0, NULL); | 345 | kentry(ft_addr, 0, NULL); |
347 | else | 346 | else |
348 | /* XXX initrd addr/size should be passed in properties */ | 347 | /* XXX initrd addr/size should be passed in properties */ |
349 | kentry(a1, a2, promptr); | 348 | kentry(initrd.addr, initrd.size, promptr); |
350 | 349 | ||
351 | /* console closed so printf below may not work */ | 350 | /* console closed so printf below may not work */ |
352 | printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); | 351 | printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); |
diff --git a/arch/powerpc/boot/mktree.c b/arch/powerpc/boot/mktree.c new file mode 100644 index 00000000000..4cb89299365 --- /dev/null +++ b/arch/powerpc/boot/mktree.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Makes a tree bootable image for IBM Evaluation boards. | ||
3 | * Basically, just take a zImage, skip the ELF header, and stuff | ||
4 | * a 32 byte header on the front. | ||
5 | * | ||
6 | * We use htonl, which is a network macro, to make sure we're doing | ||
7 | * The Right Thing on an LE machine. It's non-obvious, but it should | ||
8 | * work on anything BSD'ish. | ||
9 | */ | ||
10 | |||
11 | #include <fcntl.h> | ||
12 | #include <stdio.h> | ||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <sys/stat.h> | ||
16 | #include <unistd.h> | ||
17 | #include <netinet/in.h> | ||
18 | #ifdef __sun__ | ||
19 | #include <inttypes.h> | ||
20 | #else | ||
21 | #include <stdint.h> | ||
22 | #endif | ||
23 | |||
24 | /* This gets tacked on the front of the image. There are also a few | ||
25 | * bytes allocated after the _start label used by the boot rom (see | ||
26 | * head.S for details). | ||
27 | */ | ||
28 | typedef struct boot_block { | ||
29 | uint32_t bb_magic; /* 0x0052504F */ | ||
30 | uint32_t bb_dest; /* Target address of the image */ | ||
31 | uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */ | ||
32 | uint32_t bb_debug_flag; /* Run debugger or image after load */ | ||
33 | uint32_t bb_entry_point; /* The image address to start */ | ||
34 | uint32_t bb_checksum; /* 32 bit checksum including header */ | ||
35 | uint32_t reserved[2]; | ||
36 | } boot_block_t; | ||
37 | |||
38 | #define IMGBLK 512 | ||
39 | char tmpbuf[IMGBLK]; | ||
40 | |||
41 | int main(int argc, char *argv[]) | ||
42 | { | ||
43 | int in_fd, out_fd; | ||
44 | int nblks, i; | ||
45 | uint cksum, *cp; | ||
46 | struct stat st; | ||
47 | boot_block_t bt; | ||
48 | |||
49 | if (argc < 3) { | ||
50 | fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]); | ||
51 | exit(1); | ||
52 | } | ||
53 | |||
54 | if (stat(argv[1], &st) < 0) { | ||
55 | perror("stat"); | ||
56 | exit(2); | ||
57 | } | ||
58 | |||
59 | nblks = (st.st_size + IMGBLK) / IMGBLK; | ||
60 | |||
61 | bt.bb_magic = htonl(0x0052504F); | ||
62 | |||
63 | /* If we have the optional entry point parameter, use it */ | ||
64 | if (argc == 4) | ||
65 | bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0)); | ||
66 | else | ||
67 | bt.bb_dest = bt.bb_entry_point = htonl(0x500000); | ||
68 | |||
69 | /* We know these from the linker command. | ||
70 | * ...and then move it up into memory a little more so the | ||
71 | * relocation can happen. | ||
72 | */ | ||
73 | bt.bb_num_512blocks = htonl(nblks); | ||
74 | bt.bb_debug_flag = 0; | ||
75 | |||
76 | bt.bb_checksum = 0; | ||
77 | |||
78 | /* To be neat and tidy :-). | ||
79 | */ | ||
80 | bt.reserved[0] = 0; | ||
81 | bt.reserved[1] = 0; | ||
82 | |||
83 | if ((in_fd = open(argv[1], O_RDONLY)) < 0) { | ||
84 | perror("zImage open"); | ||
85 | exit(3); | ||
86 | } | ||
87 | |||
88 | if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { | ||
89 | perror("bootfile open"); | ||
90 | exit(3); | ||
91 | } | ||
92 | |||
93 | cksum = 0; | ||
94 | cp = (void *)&bt; | ||
95 | for (i=0; i<sizeof(bt)/sizeof(uint); i++) | ||
96 | cksum += *cp++; | ||
97 | |||
98 | /* Assume zImage is an ELF file, and skip the 64K header. | ||
99 | */ | ||
100 | if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) { | ||
101 | fprintf(stderr, "%s is too small to be an ELF image\n", | ||
102 | argv[1]); | ||
103 | exit(4); | ||
104 | } | ||
105 | |||
106 | if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) { | ||
107 | fprintf(stderr, "%s is not an ELF image\n", argv[1]); | ||
108 | exit(4); | ||
109 | } | ||
110 | |||
111 | if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) { | ||
112 | fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]); | ||
113 | exit(4); | ||
114 | } | ||
115 | |||
116 | nblks -= (64 * 1024) / IMGBLK; | ||
117 | |||
118 | /* And away we go...... | ||
119 | */ | ||
120 | if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { | ||
121 | perror("boot-image write"); | ||
122 | exit(5); | ||
123 | } | ||
124 | |||
125 | while (nblks-- > 0) { | ||
126 | if (read(in_fd, tmpbuf, IMGBLK) < 0) { | ||
127 | perror("zImage read"); | ||
128 | exit(5); | ||
129 | } | ||
130 | cp = (uint *)tmpbuf; | ||
131 | for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++) | ||
132 | cksum += *cp++; | ||
133 | if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) { | ||
134 | perror("boot-image write"); | ||
135 | exit(5); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | /* rewrite the header with the computed checksum. | ||
140 | */ | ||
141 | bt.bb_checksum = htonl(cksum); | ||
142 | if (lseek(out_fd, 0, SEEK_SET) < 0) { | ||
143 | perror("rewrite seek"); | ||
144 | exit(1); | ||
145 | } | ||
146 | if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { | ||
147 | perror("boot-image rewrite"); | ||
148 | exit(1); | ||
149 | } | ||
150 | |||
151 | exit(0); | ||
152 | } | ||
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c new file mode 100644 index 00000000000..1ffe72e35cd --- /dev/null +++ b/arch/powerpc/boot/ns16550.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * 16550 serial console support. | ||
3 | * | ||
4 | * Original copied from <file:arch/ppc/boot/common/ns16550.c> | ||
5 | * (which had no copyright) | ||
6 | * Modifications: 2006 (c) MontaVista Software, Inc. | ||
7 | * | ||
8 | * Modified by: Mark A. Greer <mgreer@mvista.com> | ||
9 | */ | ||
10 | #include <stdarg.h> | ||
11 | #include <stddef.h> | ||
12 | #include "types.h" | ||
13 | #include "string.h" | ||
14 | #include "stdio.h" | ||
15 | #include "io.h" | ||
16 | #include "ops.h" | ||
17 | |||
18 | #define UART_DLL 0 /* Out: Divisor Latch Low */ | ||
19 | #define UART_DLM 1 /* Out: Divisor Latch High */ | ||
20 | #define UART_FCR 2 /* Out: FIFO Control Register */ | ||
21 | #define UART_LCR 3 /* Out: Line Control Register */ | ||
22 | #define UART_MCR 4 /* Out: Modem Control Register */ | ||
23 | #define UART_LSR 5 /* In: Line Status Register */ | ||
24 | #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ | ||
25 | #define UART_LSR_DR 0x01 /* Receiver data ready */ | ||
26 | #define UART_MSR 6 /* In: Modem Status Register */ | ||
27 | #define UART_SCR 7 /* I/O: Scratch Register */ | ||
28 | |||
29 | static unsigned char *reg_base; | ||
30 | static u32 reg_shift; | ||
31 | |||
32 | static int ns16550_open(void) | ||
33 | { | ||
34 | out_8(reg_base + (UART_FCR << reg_shift), 0x06); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static void ns16550_putc(unsigned char c) | ||
39 | { | ||
40 | while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0); | ||
41 | out_8(reg_base, c); | ||
42 | } | ||
43 | |||
44 | static unsigned char ns16550_getc(void) | ||
45 | { | ||
46 | while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0); | ||
47 | return in_8(reg_base); | ||
48 | } | ||
49 | |||
50 | static u8 ns16550_tstc(void) | ||
51 | { | ||
52 | return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0); | ||
53 | } | ||
54 | |||
55 | int ns16550_console_init(void *devp, struct serial_console_data *scdp) | ||
56 | { | ||
57 | int n; | ||
58 | |||
59 | n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base)); | ||
60 | if (n != sizeof(reg_base)) | ||
61 | return -1; | ||
62 | |||
63 | n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); | ||
64 | if (n != sizeof(reg_shift)) | ||
65 | reg_shift = 0; | ||
66 | |||
67 | scdp->open = ns16550_open; | ||
68 | scdp->putc = ns16550_putc; | ||
69 | scdp->getc = ns16550_getc; | ||
70 | scdp->tstc = ns16550_tstc; | ||
71 | scdp->close = NULL; | ||
72 | |||
73 | return 0; | ||
74 | } | ||
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index 3a71845afc6..0182f384f3e 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c | |||
@@ -256,24 +256,18 @@ static void of_console_write(char *buf, int len) | |||
256 | call_prom("write", 3, 1, of_stdout_handle, buf, len); | 256 | call_prom("write", 3, 1, of_stdout_handle, buf, len); |
257 | } | 257 | } |
258 | 258 | ||
259 | int platform_init(void *promptr) | 259 | int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) |
260 | { | 260 | { |
261 | platform_ops.fixups = NULL; | ||
262 | platform_ops.image_hdr = of_image_hdr; | 261 | platform_ops.image_hdr = of_image_hdr; |
263 | platform_ops.malloc = of_try_claim; | 262 | platform_ops.malloc = of_try_claim; |
264 | platform_ops.free = NULL; | ||
265 | platform_ops.exit = of_exit; | 263 | platform_ops.exit = of_exit; |
266 | 264 | ||
267 | dt_ops.finddevice = of_finddevice; | 265 | dt_ops.finddevice = of_finddevice; |
268 | dt_ops.getprop = of_getprop; | 266 | dt_ops.getprop = of_getprop; |
269 | dt_ops.setprop = of_setprop; | 267 | dt_ops.setprop = of_setprop; |
270 | dt_ops.translate_addr = NULL; | ||
271 | 268 | ||
272 | console_ops.open = of_console_open; | 269 | console_ops.open = of_console_open; |
273 | console_ops.write = of_console_write; | 270 | console_ops.write = of_console_write; |
274 | console_ops.edit_cmdline = NULL; | ||
275 | console_ops.close = NULL; | ||
276 | console_ops.data = NULL; | ||
277 | 271 | ||
278 | prom = (int (*)(void *))promptr; | 272 | prom = (int (*)(void *))promptr; |
279 | return 0; | 273 | return 0; |
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 135eb4bb03b..8abb6516bb7 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h | |||
@@ -22,7 +22,8 @@ struct platform_ops { | |||
22 | void (*fixups)(void); | 22 | void (*fixups)(void); |
23 | void (*image_hdr)(const void *); | 23 | void (*image_hdr)(const void *); |
24 | void * (*malloc)(u32 size); | 24 | void * (*malloc)(u32 size); |
25 | void (*free)(void *ptr, u32 size); | 25 | void (*free)(void *ptr); |
26 | void * (*realloc)(void *ptr, unsigned long size); | ||
26 | void (*exit)(void); | 27 | void (*exit)(void); |
27 | }; | 28 | }; |
28 | extern struct platform_ops platform_ops; | 29 | extern struct platform_ops platform_ops; |
@@ -30,13 +31,11 @@ extern struct platform_ops platform_ops; | |||
30 | /* Device Tree operations */ | 31 | /* Device Tree operations */ |
31 | struct dt_ops { | 32 | struct dt_ops { |
32 | void * (*finddevice)(const char *name); | 33 | void * (*finddevice)(const char *name); |
33 | int (*getprop)(const void *node, const char *name, void *buf, | 34 | int (*getprop)(const void *phandle, const char *name, void *buf, |
34 | const int buflen); | 35 | const int buflen); |
35 | int (*setprop)(const void *node, const char *name, | 36 | int (*setprop)(const void *phandle, const char *name, |
36 | const void *buf, const int buflen); | 37 | const void *buf, const int buflen); |
37 | u64 (*translate_addr)(const char *path, const u32 *in_addr, | 38 | unsigned long (*finalize)(void); |
38 | const u32 addr_len); | ||
39 | unsigned long (*ft_addr)(void); | ||
40 | }; | 39 | }; |
41 | extern struct dt_ops dt_ops; | 40 | extern struct dt_ops dt_ops; |
42 | 41 | ||
@@ -59,10 +58,13 @@ struct serial_console_data { | |||
59 | void (*close)(void); | 58 | void (*close)(void); |
60 | }; | 59 | }; |
61 | 60 | ||
62 | extern int platform_init(void *promptr); | 61 | int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); |
63 | extern void simple_alloc_init(void); | 62 | int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); |
64 | extern void ft_init(void *dt_blob); | 63 | int serial_console_init(void); |
65 | extern int serial_console_init(void); | 64 | int ns16550_console_init(void *devp, struct serial_console_data *scdp); |
65 | void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, | ||
66 | u32 max_allocs); | ||
67 | |||
66 | 68 | ||
67 | static inline void *finddevice(const char *name) | 69 | static inline void *finddevice(const char *name) |
68 | { | 70 | { |
@@ -84,10 +86,10 @@ static inline void *malloc(u32 size) | |||
84 | return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; | 86 | return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; |
85 | } | 87 | } |
86 | 88 | ||
87 | static inline void free(void *ptr, u32 size) | 89 | static inline void free(void *ptr) |
88 | { | 90 | { |
89 | if (platform_ops.free) | 91 | if (platform_ops.free) |
90 | platform_ops.free(ptr, size); | 92 | platform_ops.free(ptr); |
91 | } | 93 | } |
92 | 94 | ||
93 | static inline void exit(void) | 95 | static inline void exit(void) |
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c new file mode 100644 index 00000000000..e8de4cf59be --- /dev/null +++ b/arch/powerpc/boot/serial.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Generic serial console support | ||
3 | * | ||
4 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
5 | * | ||
6 | * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c> | ||
7 | * and was written by Matt Porter <mporter@kernel.crashing.org>. | ||
8 | * | ||
9 | * 2001,2006 (c) MontaVista Software, Inc. This file is licensed under | ||
10 | * the terms of the GNU General Public License version 2. This program | ||
11 | * is licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | #include <stdarg.h> | ||
15 | #include <stddef.h> | ||
16 | #include "types.h" | ||
17 | #include "string.h" | ||
18 | #include "stdio.h" | ||
19 | #include "io.h" | ||
20 | #include "ops.h" | ||
21 | |||
22 | extern void udelay(long delay); | ||
23 | |||
24 | static int serial_open(void) | ||
25 | { | ||
26 | struct serial_console_data *scdp = console_ops.data; | ||
27 | return scdp->open(); | ||
28 | } | ||
29 | |||
30 | static void serial_write(char *buf, int len) | ||
31 | { | ||
32 | struct serial_console_data *scdp = console_ops.data; | ||
33 | |||
34 | while (*buf != '\0') | ||
35 | scdp->putc(*buf++); | ||
36 | } | ||
37 | |||
38 | static void serial_edit_cmdline(char *buf, int len) | ||
39 | { | ||
40 | int timer = 0, count; | ||
41 | char ch, *cp; | ||
42 | struct serial_console_data *scdp = console_ops.data; | ||
43 | |||
44 | cp = buf; | ||
45 | count = strlen(buf); | ||
46 | cp = &buf[count]; | ||
47 | count++; | ||
48 | |||
49 | while (timer++ < 5*1000) { | ||
50 | if (scdp->tstc()) { | ||
51 | while (((ch = scdp->getc()) != '\n') && (ch != '\r')) { | ||
52 | /* Test for backspace/delete */ | ||
53 | if ((ch == '\b') || (ch == '\177')) { | ||
54 | if (cp != buf) { | ||
55 | cp--; | ||
56 | count--; | ||
57 | printf("\b \b"); | ||
58 | } | ||
59 | /* Test for ^x/^u (and wipe the line) */ | ||
60 | } else if ((ch == '\030') || (ch == '\025')) { | ||
61 | while (cp != buf) { | ||
62 | cp--; | ||
63 | count--; | ||
64 | printf("\b \b"); | ||
65 | } | ||
66 | } else if (count < len) { | ||
67 | *cp++ = ch; | ||
68 | count++; | ||
69 | scdp->putc(ch); | ||
70 | } | ||
71 | } | ||
72 | break; /* Exit 'timer' loop */ | ||
73 | } | ||
74 | udelay(1000); /* 1 msec */ | ||
75 | } | ||
76 | *cp = 0; | ||
77 | } | ||
78 | |||
79 | static void serial_close(void) | ||
80 | { | ||
81 | struct serial_console_data *scdp = console_ops.data; | ||
82 | |||
83 | if (scdp->close) | ||
84 | scdp->close(); | ||
85 | } | ||
86 | |||
87 | static void *serial_get_stdout_devp(void) | ||
88 | { | ||
89 | void *devp; | ||
90 | char devtype[MAX_PROP_LEN]; | ||
91 | char path[MAX_PATH_LEN]; | ||
92 | |||
93 | devp = finddevice("/chosen"); | ||
94 | if (devp == NULL) | ||
95 | goto err_out; | ||
96 | |||
97 | if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) { | ||
98 | devp = finddevice(path); | ||
99 | if (devp == NULL) | ||
100 | goto err_out; | ||
101 | |||
102 | if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0) | ||
103 | && !strcmp(devtype, "serial")) | ||
104 | return devp; | ||
105 | } | ||
106 | err_out: | ||
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | static struct serial_console_data serial_cd; | ||
111 | |||
112 | /* Node's "compatible" property determines which serial driver to use */ | ||
113 | int serial_console_init(void) | ||
114 | { | ||
115 | void *devp; | ||
116 | int rc = -1; | ||
117 | char compat[MAX_PROP_LEN]; | ||
118 | |||
119 | devp = serial_get_stdout_devp(); | ||
120 | if (devp == NULL) | ||
121 | goto err_out; | ||
122 | |||
123 | if (getprop(devp, "compatible", compat, sizeof(compat)) < 0) | ||
124 | goto err_out; | ||
125 | |||
126 | if (!strcmp(compat, "ns16550")) | ||
127 | rc = ns16550_console_init(devp, &serial_cd); | ||
128 | |||
129 | /* Add other serial console driver calls here */ | ||
130 | |||
131 | if (!rc) { | ||
132 | console_ops.open = serial_open; | ||
133 | console_ops.write = serial_write; | ||
134 | console_ops.edit_cmdline = serial_edit_cmdline; | ||
135 | console_ops.close = serial_close; | ||
136 | console_ops.data = &serial_cd; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | err_out: | ||
141 | return -1; | ||
142 | } | ||
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c new file mode 100644 index 00000000000..cfe3a7505ba --- /dev/null +++ b/arch/powerpc/boot/simple_alloc.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * Implement primitive realloc(3) functionality. | ||
3 | * | ||
4 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
5 | * | ||
6 | * 2006 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <stddef.h> | ||
13 | #include "types.h" | ||
14 | #include "page.h" | ||
15 | #include "string.h" | ||
16 | #include "ops.h" | ||
17 | |||
18 | #define ENTRY_BEEN_USED 0x01 | ||
19 | #define ENTRY_IN_USE 0x02 | ||
20 | |||
21 | static struct alloc_info { | ||
22 | u32 flags; | ||
23 | u32 base; | ||
24 | u32 size; | ||
25 | } *alloc_tbl; | ||
26 | |||
27 | static u32 tbl_entries; | ||
28 | static u32 alloc_min; | ||
29 | static u32 next_base; | ||
30 | static u32 space_left; | ||
31 | |||
32 | /* | ||
33 | * First time an entry is used, its base and size are set. | ||
34 | * An entry can be freed and re-malloc'd but its base & size don't change. | ||
35 | * Should be smart enough for needs of bootwrapper. | ||
36 | */ | ||
37 | static void *simple_malloc(u32 size) | ||
38 | { | ||
39 | u32 i; | ||
40 | struct alloc_info *p = alloc_tbl; | ||
41 | |||
42 | if (size == 0) | ||
43 | goto err_out; | ||
44 | |||
45 | size = _ALIGN_UP(size, alloc_min); | ||
46 | |||
47 | for (i=0; i<tbl_entries; i++, p++) | ||
48 | if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */ | ||
49 | if (size <= space_left) { | ||
50 | p->base = next_base; | ||
51 | p->size = size; | ||
52 | p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE; | ||
53 | next_base += size; | ||
54 | space_left -= size; | ||
55 | return (void *)p->base; | ||
56 | } | ||
57 | goto err_out; /* not enough space left */ | ||
58 | } | ||
59 | /* reuse an entry keeping same base & size */ | ||
60 | else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) { | ||
61 | p->flags |= ENTRY_IN_USE; | ||
62 | return (void *)p->base; | ||
63 | } | ||
64 | err_out: | ||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | static struct alloc_info *simple_find_entry(void *ptr) | ||
69 | { | ||
70 | u32 i; | ||
71 | struct alloc_info *p = alloc_tbl; | ||
72 | |||
73 | for (i=0; i<tbl_entries; i++,p++) { | ||
74 | if (!(p->flags & ENTRY_BEEN_USED)) | ||
75 | break; | ||
76 | if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr)) | ||
77 | return p; | ||
78 | } | ||
79 | return NULL; | ||
80 | } | ||
81 | |||
82 | static void simple_free(void *ptr) | ||
83 | { | ||
84 | struct alloc_info *p = simple_find_entry(ptr); | ||
85 | |||
86 | if (p != NULL) | ||
87 | p->flags &= ~ENTRY_IN_USE; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * Change size of area pointed to by 'ptr' to 'size'. | ||
92 | * If 'ptr' is NULL, then its a malloc(). If 'size' is 0, then its a free(). | ||
93 | * 'ptr' must be NULL or a pointer to a non-freed area previously returned by | ||
94 | * simple_realloc() or simple_malloc(). | ||
95 | */ | ||
96 | static void *simple_realloc(void *ptr, unsigned long size) | ||
97 | { | ||
98 | struct alloc_info *p; | ||
99 | void *new; | ||
100 | |||
101 | if (size == 0) { | ||
102 | simple_free(ptr); | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
106 | if (ptr == NULL) | ||
107 | return simple_malloc(size); | ||
108 | |||
109 | p = simple_find_entry(ptr); | ||
110 | if (p == NULL) /* ptr not from simple_malloc/simple_realloc */ | ||
111 | return NULL; | ||
112 | if (size <= p->size) /* fits in current block */ | ||
113 | return ptr; | ||
114 | |||
115 | new = simple_malloc(size); | ||
116 | memcpy(new, ptr, p->size); | ||
117 | simple_free(ptr); | ||
118 | return new; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Returns addr of first byte after heap so caller can see if it took | ||
123 | * too much space. If so, change args & try again. | ||
124 | */ | ||
125 | void *simple_alloc_init(char *base, u32 heap_size, u32 granularity, | ||
126 | u32 max_allocs) | ||
127 | { | ||
128 | u32 heap_base, tbl_size; | ||
129 | |||
130 | heap_size = _ALIGN_UP(heap_size, granularity); | ||
131 | alloc_min = granularity; | ||
132 | tbl_entries = max_allocs; | ||
133 | |||
134 | tbl_size = tbl_entries * sizeof(struct alloc_info); | ||
135 | |||
136 | alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8); | ||
137 | memset(alloc_tbl, 0, tbl_size); | ||
138 | |||
139 | heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min); | ||
140 | |||
141 | next_base = heap_base; | ||
142 | space_left = heap_size; | ||
143 | |||
144 | platform_ops.malloc = simple_malloc; | ||
145 | platform_ops.free = simple_free; | ||
146 | platform_ops.realloc = simple_realloc; | ||
147 | |||
148 | return (void *)(heap_base + heap_size); | ||
149 | } | ||
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c index 6d5f6382e1c..0a9feeb9834 100644 --- a/arch/powerpc/boot/stdio.c +++ b/arch/powerpc/boot/stdio.c | |||
@@ -320,6 +320,7 @@ printf(const char *fmt, ...) | |||
320 | va_start(args, fmt); | 320 | va_start(args, fmt); |
321 | n = vsprintf(sprint_buf, fmt, args); | 321 | n = vsprintf(sprint_buf, fmt, args); |
322 | va_end(args); | 322 | va_end(args); |
323 | console_ops.write(sprint_buf, n); | 323 | if (console_ops.write) |
324 | console_ops.write(sprint_buf, n); | ||
324 | return n; | 325 | return n; |
325 | } | 326 | } |
diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S new file mode 100644 index 00000000000..427ddfc1199 --- /dev/null +++ b/arch/powerpc/boot/util.S | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copied from <file:arch/powerpc/kernel/misc_32.S> | ||
3 | * | ||
4 | * This file contains miscellaneous low-level functions. | ||
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
6 | * | ||
7 | * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) | ||
8 | * and Paul Mackerras. | ||
9 | * | ||
10 | * kexec bits: | ||
11 | * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> | ||
12 | * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version | ||
17 | * 2 of the License, or (at your option) any later version. | ||
18 | * | ||
19 | */ | ||
20 | #include "ppc_asm.h" | ||
21 | |||
22 | #define SPRN_PVR 0x11F /* Processor Version Register */ | ||
23 | |||
24 | .text | ||
25 | |||
26 | /* udelay (on non-601 processors) needs to know the period of the | ||
27 | * timebase in nanoseconds. This used to be hardcoded to be 60ns | ||
28 | * (period of 66MHz/4). Now a variable is used that is initialized to | ||
29 | * 60 for backward compatibility, but it can be overridden as necessary | ||
30 | * with code something like this: | ||
31 | * extern unsigned long timebase_period_ns; | ||
32 | * timebase_period_ns = 1000000000 / bd->bi_tbfreq; | ||
33 | */ | ||
34 | .data | ||
35 | .globl timebase_period_ns | ||
36 | timebase_period_ns: | ||
37 | .long 60 | ||
38 | |||
39 | .text | ||
40 | /* | ||
41 | * Delay for a number of microseconds | ||
42 | */ | ||
43 | .globl udelay | ||
44 | udelay: | ||
45 | mfspr r4,SPRN_PVR | ||
46 | srwi r4,r4,16 | ||
47 | cmpwi 0,r4,1 /* 601 ? */ | ||
48 | bne .udelay_not_601 | ||
49 | 00: li r0,86 /* Instructions / microsecond? */ | ||
50 | mtctr r0 | ||
51 | 10: addi r0,r0,0 /* NOP */ | ||
52 | bdnz 10b | ||
53 | subic. r3,r3,1 | ||
54 | bne 00b | ||
55 | blr | ||
56 | |||
57 | .udelay_not_601: | ||
58 | mulli r4,r3,1000 /* nanoseconds */ | ||
59 | /* Change r4 to be the number of ticks using: | ||
60 | * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns | ||
61 | * timebase_period_ns defaults to 60 (16.6MHz) */ | ||
62 | mflr r5 | ||
63 | bl 0f | ||
64 | 0: mflr r6 | ||
65 | mtlr r5 | ||
66 | lis r5,0b@ha | ||
67 | addi r5,r5,0b@l | ||
68 | subf r5,r5,r6 /* In case we're relocated */ | ||
69 | addis r5,r5,timebase_period_ns@ha | ||
70 | lwz r5,timebase_period_ns@l(r5) | ||
71 | add r4,r4,r5 | ||
72 | addi r4,r4,-1 | ||
73 | divw r4,r4,r5 /* BUS ticks */ | ||
74 | 1: mftbu r5 | ||
75 | mftb r6 | ||
76 | mftbu r7 | ||
77 | cmpw 0,r5,r7 | ||
78 | bne 1b /* Get [synced] base time */ | ||
79 | addc r9,r6,r4 /* Compute end time */ | ||
80 | addze r8,r5 | ||
81 | 2: mftbu r5 | ||
82 | cmpw 0,r5,r8 | ||
83 | blt 2b | ||
84 | bgt 3f | ||
85 | mftb r6 | ||
86 | cmpw 0,r6,r9 | ||
87 | blt 2b | ||
88 | 3: blr | ||
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index b5fb1fee76f..024e4d425c5 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper | |||
@@ -184,6 +184,9 @@ fi | |||
184 | 184 | ||
185 | if [ -n "$dtb" ]; then | 185 | if [ -n "$dtb" ]; then |
186 | addsec $tmp "$dtb" .kernel:dtb | 186 | addsec $tmp "$dtb" .kernel:dtb |
187 | if [ -n "$dts" ]; then | ||
188 | rm $dtb | ||
189 | fi | ||
187 | fi | 190 | fi |
188 | 191 | ||
189 | if [ "$platform" != "miboot" ]; then | 192 | if [ "$platform" != "miboot" ]; then |
diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S index 05f32388b95..a360905e542 100644 --- a/arch/powerpc/boot/zImage.coff.lds.S +++ b/arch/powerpc/boot/zImage.coff.lds.S | |||
@@ -21,6 +21,10 @@ SECTIONS | |||
21 | *(.got2) | 21 | *(.got2) |
22 | __got2_end = .; | 22 | __got2_end = .; |
23 | 23 | ||
24 | _dtb_start = .; | ||
25 | *(.kernel:dtb) | ||
26 | _dtb_end = .; | ||
27 | |||
24 | _vmlinux_start = .; | 28 | _vmlinux_start = .; |
25 | *(.kernel:vmlinux.strip) | 29 | *(.kernel:vmlinux.strip) |
26 | _vmlinux_end = .; | 30 | _vmlinux_end = .; |
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 0aba06d7d2e..a98c982c73a 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.18 | 3 | # Linux kernel version: 2.6.19-rc6 |
4 | # Wed Oct 4 15:30:50 2006 | 4 | # Wed Nov 22 15:33:04 2006 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | 6 | CONFIG_PPC64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -32,6 +32,10 @@ CONFIG_AUDIT_ARCH=y | |||
32 | CONFIG_POWER3=y | 32 | CONFIG_POWER3=y |
33 | CONFIG_POWER4=y | 33 | CONFIG_POWER4=y |
34 | CONFIG_PPC_FPU=y | 34 | CONFIG_PPC_FPU=y |
35 | # CONFIG_PPC_DCR_NATIVE is not set | ||
36 | CONFIG_PPC_DCR_MMIO=y | ||
37 | CONFIG_PPC_DCR=y | ||
38 | CONFIG_PPC_OF_PLATFORM_PCI=y | ||
35 | CONFIG_ALTIVEC=y | 39 | CONFIG_ALTIVEC=y |
36 | CONFIG_PPC_STD_MMU=y | 40 | CONFIG_PPC_STD_MMU=y |
37 | CONFIG_VIRT_CPU_ACCOUNTING=y | 41 | CONFIG_VIRT_CPU_ACCOUNTING=y |
@@ -67,7 +71,7 @@ CONFIG_INITRAMFS_SOURCE="" | |||
67 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 71 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
68 | CONFIG_SYSCTL=y | 72 | CONFIG_SYSCTL=y |
69 | # CONFIG_EMBEDDED is not set | 73 | # CONFIG_EMBEDDED is not set |
70 | # CONFIG_SYSCTL_SYSCALL is not set | 74 | CONFIG_SYSCTL_SYSCALL=y |
71 | CONFIG_KALLSYMS=y | 75 | CONFIG_KALLSYMS=y |
72 | # CONFIG_KALLSYMS_ALL is not set | 76 | # CONFIG_KALLSYMS_ALL is not set |
73 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | 77 | # CONFIG_KALLSYMS_EXTRA_PASS is not set |
@@ -131,6 +135,7 @@ CONFIG_PPC_CELL=y | |||
131 | CONFIG_PPC_CELL_NATIVE=y | 135 | CONFIG_PPC_CELL_NATIVE=y |
132 | CONFIG_PPC_IBM_CELL_BLADE=y | 136 | CONFIG_PPC_IBM_CELL_BLADE=y |
133 | CONFIG_UDBG_RTAS_CONSOLE=y | 137 | CONFIG_UDBG_RTAS_CONSOLE=y |
138 | CONFIG_PPC_PS3=y | ||
134 | # CONFIG_U3_DART is not set | 139 | # CONFIG_U3_DART is not set |
135 | CONFIG_PPC_RTAS=y | 140 | CONFIG_PPC_RTAS=y |
136 | # CONFIG_RTAS_ERROR_LOGGING is not set | 141 | # CONFIG_RTAS_ERROR_LOGGING is not set |
@@ -139,9 +144,23 @@ CONFIG_RTAS_FLASH=y | |||
139 | CONFIG_MMIO_NVRAM=y | 144 | CONFIG_MMIO_NVRAM=y |
140 | # CONFIG_PPC_MPC106 is not set | 145 | # CONFIG_PPC_MPC106 is not set |
141 | # CONFIG_PPC_970_NAP is not set | 146 | # CONFIG_PPC_970_NAP is not set |
142 | # CONFIG_CPU_FREQ is not set | 147 | CONFIG_PPC_INDIRECT_IO=y |
148 | CONFIG_GENERIC_IOMAP=y | ||
149 | CONFIG_CPU_FREQ=y | ||
150 | CONFIG_CPU_FREQ_TABLE=y | ||
151 | CONFIG_CPU_FREQ_DEBUG=y | ||
152 | CONFIG_CPU_FREQ_STAT=y | ||
153 | # CONFIG_CPU_FREQ_STAT_DETAILS is not set | ||
154 | CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y | ||
155 | # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set | ||
156 | CONFIG_CPU_FREQ_GOV_PERFORMANCE=y | ||
157 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | ||
158 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | ||
159 | CONFIG_CPU_FREQ_GOV_ONDEMAND=y | ||
160 | CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y | ||
161 | # CONFIG_CPU_FREQ_PMAC64 is not set | ||
143 | # CONFIG_WANT_EARLY_SERIAL is not set | 162 | # CONFIG_WANT_EARLY_SERIAL is not set |
144 | # CONFIG_MPIC is not set | 163 | CONFIG_MPIC=y |
145 | 164 | ||
146 | # | 165 | # |
147 | # Cell Broadband Engine options | 166 | # Cell Broadband Engine options |
@@ -149,6 +168,15 @@ CONFIG_MMIO_NVRAM=y | |||
149 | CONFIG_SPU_FS=m | 168 | CONFIG_SPU_FS=m |
150 | CONFIG_SPU_BASE=y | 169 | CONFIG_SPU_BASE=y |
151 | CONFIG_CBE_RAS=y | 170 | CONFIG_CBE_RAS=y |
171 | CONFIG_CBE_THERM=m | ||
172 | CONFIG_CBE_CPUFREQ=m | ||
173 | |||
174 | # | ||
175 | # PS3 Platform Options | ||
176 | # | ||
177 | CONFIG_PS3_HTAB_SIZE=20 | ||
178 | # CONFIG_PS3_DYNAMIC_DMA is not set | ||
179 | CONFIG_PS3_USE_LPAR_ADDR=y | ||
152 | 180 | ||
153 | # | 181 | # |
154 | # Kernel options | 182 | # Kernel options |
@@ -166,13 +194,14 @@ CONFIG_BINFMT_MISC=m | |||
166 | CONFIG_FORCE_MAX_ZONEORDER=9 | 194 | CONFIG_FORCE_MAX_ZONEORDER=9 |
167 | # CONFIG_IOMMU_VMERGE is not set | 195 | # CONFIG_IOMMU_VMERGE is not set |
168 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | 196 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y |
169 | CONFIG_KEXEC=y | 197 | # CONFIG_KEXEC is not set |
170 | # CONFIG_CRASH_DUMP is not set | 198 | # CONFIG_CRASH_DUMP is not set |
171 | CONFIG_IRQ_ALL_CPUS=y | 199 | CONFIG_IRQ_ALL_CPUS=y |
172 | CONFIG_NUMA=y | 200 | CONFIG_NUMA=y |
173 | CONFIG_NODES_SHIFT=4 | 201 | CONFIG_NODES_SHIFT=4 |
174 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y | 202 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y |
175 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | 203 | CONFIG_ARCH_SPARSEMEM_ENABLE=y |
204 | CONFIG_ARCH_SPARSEMEM_DEFAULT=y | ||
176 | CONFIG_ARCH_POPULATES_NODE_MAP=y | 205 | CONFIG_ARCH_POPULATES_NODE_MAP=y |
177 | CONFIG_SELECT_MEMORY_MODEL=y | 206 | CONFIG_SELECT_MEMORY_MODEL=y |
178 | # CONFIG_FLATMEM_MANUAL is not set | 207 | # CONFIG_FLATMEM_MANUAL is not set |
@@ -189,6 +218,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 | |||
189 | CONFIG_MIGRATION=y | 218 | CONFIG_MIGRATION=y |
190 | CONFIG_RESOURCES_64BIT=y | 219 | CONFIG_RESOURCES_64BIT=y |
191 | CONFIG_ARCH_MEMORY_PROBE=y | 220 | CONFIG_ARCH_MEMORY_PROBE=y |
221 | CONFIG_NODES_SPAN_OTHER_NODES=y | ||
192 | CONFIG_PPC_64K_PAGES=y | 222 | CONFIG_PPC_64K_PAGES=y |
193 | CONFIG_SCHED_SMT=y | 223 | CONFIG_SCHED_SMT=y |
194 | CONFIG_PROC_DEVICETREE=y | 224 | CONFIG_PROC_DEVICETREE=y |
@@ -207,7 +237,6 @@ CONFIG_GENERIC_ISA_DMA=y | |||
207 | CONFIG_PCI=y | 237 | CONFIG_PCI=y |
208 | CONFIG_PCI_DOMAINS=y | 238 | CONFIG_PCI_DOMAINS=y |
209 | CONFIG_PCIEPORTBUS=y | 239 | CONFIG_PCIEPORTBUS=y |
210 | # CONFIG_PCI_MULTITHREAD_PROBE is not set | ||
211 | # CONFIG_PCI_DEBUG is not set | 240 | # CONFIG_PCI_DEBUG is not set |
212 | 241 | ||
213 | # | 242 | # |
@@ -280,7 +309,6 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y | |||
280 | # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set | 309 | # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set |
281 | # CONFIG_IPV6_SIT is not set | 310 | # CONFIG_IPV6_SIT is not set |
282 | CONFIG_IPV6_TUNNEL=m | 311 | CONFIG_IPV6_TUNNEL=m |
283 | # CONFIG_IPV6_SUBTREES is not set | ||
284 | # CONFIG_IPV6_MULTIPLE_TABLES is not set | 312 | # CONFIG_IPV6_MULTIPLE_TABLES is not set |
285 | # CONFIG_NETWORK_SECMARK is not set | 313 | # CONFIG_NETWORK_SECMARK is not set |
286 | CONFIG_NETFILTER=y | 314 | CONFIG_NETFILTER=y |
@@ -1107,7 +1135,8 @@ CONFIG_PLIST=y | |||
1107 | # | 1135 | # |
1108 | # Instrumentation Support | 1136 | # Instrumentation Support |
1109 | # | 1137 | # |
1110 | # CONFIG_PROFILING is not set | 1138 | CONFIG_PROFILING=y |
1139 | CONFIG_OPROFILE=y | ||
1111 | # CONFIG_KPROBES is not set | 1140 | # CONFIG_KPROBES is not set |
1112 | 1141 | ||
1113 | # | 1142 | # |
@@ -1142,6 +1171,7 @@ CONFIG_DEBUG_FS=y | |||
1142 | CONFIG_DEBUGGER=y | 1171 | CONFIG_DEBUGGER=y |
1143 | CONFIG_XMON=y | 1172 | CONFIG_XMON=y |
1144 | CONFIG_XMON_DEFAULT=y | 1173 | CONFIG_XMON_DEFAULT=y |
1174 | CONFIG_XMON_DISASSEMBLY=y | ||
1145 | CONFIG_IRQSTACKS=y | 1175 | CONFIG_IRQSTACKS=y |
1146 | # CONFIG_BOOTX_TEXT is not set | 1176 | # CONFIG_BOOTX_TEXT is not set |
1147 | # CONFIG_PPC_EARLY_DEBUG is not set | 1177 | # CONFIG_PPC_EARLY_DEBUG is not set |
@@ -1159,7 +1189,7 @@ CONFIG_CRYPTO=y | |||
1159 | CONFIG_CRYPTO_ALGAPI=y | 1189 | CONFIG_CRYPTO_ALGAPI=y |
1160 | CONFIG_CRYPTO_BLKCIPHER=m | 1190 | CONFIG_CRYPTO_BLKCIPHER=m |
1161 | CONFIG_CRYPTO_HASH=y | 1191 | CONFIG_CRYPTO_HASH=y |
1162 | # CONFIG_CRYPTO_MANAGER is not set | 1192 | CONFIG_CRYPTO_MANAGER=y |
1163 | CONFIG_CRYPTO_HMAC=y | 1193 | CONFIG_CRYPTO_HMAC=y |
1164 | # CONFIG_CRYPTO_NULL is not set | 1194 | # CONFIG_CRYPTO_NULL is not set |
1165 | # CONFIG_CRYPTO_MD4 is not set | 1195 | # CONFIG_CRYPTO_MD4 is not set |
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig new file mode 100644 index 00000000000..23fd210eb56 --- /dev/null +++ b/arch/powerpc/configs/linkstation_defconfig | |||
@@ -0,0 +1,1583 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.19-rc4 | ||
4 | # Wed Nov 15 20:36:30 2006 | ||
5 | # | ||
6 | # CONFIG_PPC64 is not set | ||
7 | CONFIG_PPC32=y | ||
8 | CONFIG_PPC_MERGE=y | ||
9 | CONFIG_MMU=y | ||
10 | CONFIG_GENERIC_HARDIRQS=y | ||
11 | CONFIG_IRQ_PER_CPU=y | ||
12 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||
13 | CONFIG_GENERIC_HWEIGHT=y | ||
14 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
15 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
16 | CONFIG_PPC=y | ||
17 | CONFIG_EARLY_PRINTK=y | ||
18 | CONFIG_GENERIC_NVRAM=y | ||
19 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | ||
20 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | ||
21 | CONFIG_PPC_OF=y | ||
22 | CONFIG_PPC_UDBG_16550=y | ||
23 | # CONFIG_GENERIC_TBSYNC is not set | ||
24 | CONFIG_AUDIT_ARCH=y | ||
25 | # CONFIG_DEFAULT_UIMAGE is not set | ||
26 | |||
27 | # | ||
28 | # Processor support | ||
29 | # | ||
30 | CONFIG_CLASSIC32=y | ||
31 | # CONFIG_PPC_52xx is not set | ||
32 | # CONFIG_PPC_82xx is not set | ||
33 | # CONFIG_PPC_83xx is not set | ||
34 | # CONFIG_PPC_85xx is not set | ||
35 | # CONFIG_PPC_86xx is not set | ||
36 | # CONFIG_40x is not set | ||
37 | # CONFIG_44x is not set | ||
38 | # CONFIG_8xx is not set | ||
39 | # CONFIG_E200 is not set | ||
40 | CONFIG_6xx=y | ||
41 | CONFIG_PPC_FPU=y | ||
42 | # CONFIG_PPC_DCR_NATIVE is not set | ||
43 | # CONFIG_PPC_DCR_MMIO is not set | ||
44 | # CONFIG_ALTIVEC is not set | ||
45 | CONFIG_PPC_STD_MMU=y | ||
46 | CONFIG_PPC_STD_MMU_32=y | ||
47 | # CONFIG_SMP is not set | ||
48 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
49 | |||
50 | # | ||
51 | # Code maturity level options | ||
52 | # | ||
53 | CONFIG_EXPERIMENTAL=y | ||
54 | CONFIG_BROKEN_ON_SMP=y | ||
55 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
56 | |||
57 | # | ||
58 | # General setup | ||
59 | # | ||
60 | CONFIG_LOCALVERSION="-kuroboxHG" | ||
61 | CONFIG_LOCALVERSION_AUTO=y | ||
62 | CONFIG_SWAP=y | ||
63 | CONFIG_SYSVIPC=y | ||
64 | # CONFIG_IPC_NS is not set | ||
65 | CONFIG_POSIX_MQUEUE=y | ||
66 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
67 | # CONFIG_TASKSTATS is not set | ||
68 | # CONFIG_UTS_NS is not set | ||
69 | # CONFIG_AUDIT is not set | ||
70 | CONFIG_IKCONFIG=y | ||
71 | CONFIG_IKCONFIG_PROC=y | ||
72 | # CONFIG_RELAY is not set | ||
73 | CONFIG_INITRAMFS_SOURCE="" | ||
74 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
75 | CONFIG_SYSCTL=y | ||
76 | # CONFIG_EMBEDDED is not set | ||
77 | # CONFIG_SYSCTL_SYSCALL is not set | ||
78 | CONFIG_KALLSYMS=y | ||
79 | # CONFIG_KALLSYMS_ALL is not set | ||
80 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
81 | CONFIG_HOTPLUG=y | ||
82 | CONFIG_PRINTK=y | ||
83 | CONFIG_BUG=y | ||
84 | CONFIG_ELF_CORE=y | ||
85 | CONFIG_BASE_FULL=y | ||
86 | CONFIG_FUTEX=y | ||
87 | CONFIG_EPOLL=y | ||
88 | CONFIG_SHMEM=y | ||
89 | CONFIG_SLAB=y | ||
90 | CONFIG_VM_EVENT_COUNTERS=y | ||
91 | CONFIG_RT_MUTEXES=y | ||
92 | # CONFIG_TINY_SHMEM is not set | ||
93 | CONFIG_BASE_SMALL=0 | ||
94 | # CONFIG_SLOB is not set | ||
95 | |||
96 | # | ||
97 | # Loadable module support | ||
98 | # | ||
99 | CONFIG_MODULES=y | ||
100 | CONFIG_MODULE_UNLOAD=y | ||
101 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
102 | # CONFIG_MODVERSIONS is not set | ||
103 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
104 | CONFIG_KMOD=y | ||
105 | |||
106 | # | ||
107 | # Block layer | ||
108 | # | ||
109 | CONFIG_BLOCK=y | ||
110 | # CONFIG_LBD is not set | ||
111 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
112 | # CONFIG_LSF is not set | ||
113 | |||
114 | # | ||
115 | # IO Schedulers | ||
116 | # | ||
117 | CONFIG_IOSCHED_NOOP=y | ||
118 | CONFIG_IOSCHED_AS=y | ||
119 | CONFIG_IOSCHED_DEADLINE=y | ||
120 | CONFIG_IOSCHED_CFQ=y | ||
121 | CONFIG_DEFAULT_AS=y | ||
122 | # CONFIG_DEFAULT_DEADLINE is not set | ||
123 | # CONFIG_DEFAULT_CFQ is not set | ||
124 | # CONFIG_DEFAULT_NOOP is not set | ||
125 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
126 | |||
127 | # | ||
128 | # Platform support | ||
129 | # | ||
130 | # CONFIG_PPC_MULTIPLATFORM is not set | ||
131 | CONFIG_EMBEDDED6xx=y | ||
132 | # CONFIG_APUS is not set | ||
133 | # CONFIG_PPC_CELL is not set | ||
134 | # CONFIG_PPC_CELL_NATIVE is not set | ||
135 | # CONFIG_PPC_RTAS is not set | ||
136 | # CONFIG_MMIO_NVRAM is not set | ||
137 | # CONFIG_PPC_MPC106 is not set | ||
138 | # CONFIG_PPC_970_NAP is not set | ||
139 | # CONFIG_PPC_INDIRECT_IO is not set | ||
140 | # CONFIG_GENERIC_IOMAP is not set | ||
141 | # CONFIG_CPU_FREQ is not set | ||
142 | # CONFIG_TAU is not set | ||
143 | # CONFIG_KATANA is not set | ||
144 | # CONFIG_WILLOW is not set | ||
145 | # CONFIG_CPCI690 is not set | ||
146 | # CONFIG_POWERPMC250 is not set | ||
147 | # CONFIG_CHESTNUT is not set | ||
148 | # CONFIG_SPRUCE is not set | ||
149 | # CONFIG_HDPU is not set | ||
150 | # CONFIG_EV64260 is not set | ||
151 | # CONFIG_LOPEC is not set | ||
152 | # CONFIG_MVME5100 is not set | ||
153 | # CONFIG_PPLUS is not set | ||
154 | # CONFIG_PRPMC750 is not set | ||
155 | # CONFIG_PRPMC800 is not set | ||
156 | # CONFIG_SANDPOINT is not set | ||
157 | CONFIG_LINKSTATION=y | ||
158 | # CONFIG_MPC7448HPC2 is not set | ||
159 | # CONFIG_RADSTONE_PPC7D is not set | ||
160 | # CONFIG_PAL4 is not set | ||
161 | # CONFIG_GEMINI is not set | ||
162 | # CONFIG_EST8260 is not set | ||
163 | # CONFIG_SBC82xx is not set | ||
164 | # CONFIG_SBS8260 is not set | ||
165 | # CONFIG_RPX8260 is not set | ||
166 | # CONFIG_TQM8260 is not set | ||
167 | # CONFIG_ADS8272 is not set | ||
168 | # CONFIG_PQ2FADS is not set | ||
169 | # CONFIG_LITE5200 is not set | ||
170 | # CONFIG_EV64360 is not set | ||
171 | CONFIG_PPC_GEN550=y | ||
172 | CONFIG_MPC10X_BRIDGE=y | ||
173 | CONFIG_MPC10X_OPENPIC=y | ||
174 | # CONFIG_MPC10X_STORE_GATHERING is not set | ||
175 | # CONFIG_WANT_EARLY_SERIAL is not set | ||
176 | CONFIG_MPIC=y | ||
177 | |||
178 | # | ||
179 | # Kernel options | ||
180 | # | ||
181 | # CONFIG_HIGHMEM is not set | ||
182 | CONFIG_HZ_100=y | ||
183 | # CONFIG_HZ_250 is not set | ||
184 | # CONFIG_HZ_1000 is not set | ||
185 | CONFIG_HZ=100 | ||
186 | CONFIG_PREEMPT_NONE=y | ||
187 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
188 | # CONFIG_PREEMPT is not set | ||
189 | CONFIG_BINFMT_ELF=y | ||
190 | # CONFIG_BINFMT_MISC is not set | ||
191 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | ||
192 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
193 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
194 | CONFIG_SELECT_MEMORY_MODEL=y | ||
195 | CONFIG_FLATMEM_MANUAL=y | ||
196 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
197 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
198 | CONFIG_FLATMEM=y | ||
199 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
200 | # CONFIG_SPARSEMEM_STATIC is not set | ||
201 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
202 | # CONFIG_RESOURCES_64BIT is not set | ||
203 | CONFIG_PROC_DEVICETREE=y | ||
204 | # CONFIG_CMDLINE_BOOL is not set | ||
205 | # CONFIG_PM is not set | ||
206 | # CONFIG_SECCOMP is not set | ||
207 | CONFIG_ISA_DMA_API=y | ||
208 | |||
209 | # | ||
210 | # Bus options | ||
211 | # | ||
212 | CONFIG_GENERIC_ISA_DMA=y | ||
213 | # CONFIG_MPIC_WEIRD is not set | ||
214 | # CONFIG_PPC_I8259 is not set | ||
215 | CONFIG_PPC_INDIRECT_PCI=y | ||
216 | CONFIG_FSL_SOC=y | ||
217 | CONFIG_PCI=y | ||
218 | CONFIG_PCI_DOMAINS=y | ||
219 | # CONFIG_PCIEPORTBUS is not set | ||
220 | # CONFIG_PCI_MULTITHREAD_PROBE is not set | ||
221 | # CONFIG_PCI_DEBUG is not set | ||
222 | |||
223 | # | ||
224 | # PCCARD (PCMCIA/CardBus) support | ||
225 | # | ||
226 | # CONFIG_PCCARD is not set | ||
227 | |||
228 | # | ||
229 | # PCI Hotplug Support | ||
230 | # | ||
231 | # CONFIG_HOTPLUG_PCI is not set | ||
232 | |||
233 | # | ||
234 | # Advanced setup | ||
235 | # | ||
236 | # CONFIG_ADVANCED_OPTIONS is not set | ||
237 | |||
238 | # | ||
239 | # Default settings for advanced configuration options are used | ||
240 | # | ||
241 | CONFIG_HIGHMEM_START=0xfe000000 | ||
242 | CONFIG_LOWMEM_SIZE=0x30000000 | ||
243 | CONFIG_KERNEL_START=0xc0000000 | ||
244 | CONFIG_TASK_SIZE=0x80000000 | ||
245 | CONFIG_BOOT_LOAD=0x00800000 | ||
246 | |||
247 | # | ||
248 | # Networking | ||
249 | # | ||
250 | CONFIG_NET=y | ||
251 | |||
252 | # | ||
253 | # Networking options | ||
254 | # | ||
255 | # CONFIG_NETDEBUG is not set | ||
256 | CONFIG_PACKET=y | ||
257 | CONFIG_PACKET_MMAP=y | ||
258 | CONFIG_UNIX=y | ||
259 | CONFIG_XFRM=y | ||
260 | # CONFIG_XFRM_USER is not set | ||
261 | # CONFIG_XFRM_SUB_POLICY is not set | ||
262 | # CONFIG_NET_KEY is not set | ||
263 | CONFIG_INET=y | ||
264 | CONFIG_IP_MULTICAST=y | ||
265 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
266 | CONFIG_IP_FIB_HASH=y | ||
267 | CONFIG_IP_PNP=y | ||
268 | CONFIG_IP_PNP_DHCP=y | ||
269 | CONFIG_IP_PNP_BOOTP=y | ||
270 | # CONFIG_IP_PNP_RARP is not set | ||
271 | # CONFIG_NET_IPIP is not set | ||
272 | # CONFIG_NET_IPGRE is not set | ||
273 | # CONFIG_IP_MROUTE is not set | ||
274 | # CONFIG_ARPD is not set | ||
275 | # CONFIG_SYN_COOKIES is not set | ||
276 | # CONFIG_INET_AH is not set | ||
277 | # CONFIG_INET_ESP is not set | ||
278 | # CONFIG_INET_IPCOMP is not set | ||
279 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
280 | # CONFIG_INET_TUNNEL is not set | ||
281 | CONFIG_INET_XFRM_MODE_TRANSPORT=y | ||
282 | CONFIG_INET_XFRM_MODE_TUNNEL=y | ||
283 | CONFIG_INET_XFRM_MODE_BEET=y | ||
284 | CONFIG_INET_DIAG=y | ||
285 | CONFIG_INET_TCP_DIAG=y | ||
286 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
287 | CONFIG_TCP_CONG_CUBIC=y | ||
288 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
289 | |||
290 | # | ||
291 | # IP: Virtual Server Configuration | ||
292 | # | ||
293 | # CONFIG_IP_VS is not set | ||
294 | # CONFIG_IPV6 is not set | ||
295 | # CONFIG_INET6_XFRM_TUNNEL is not set | ||
296 | # CONFIG_INET6_TUNNEL is not set | ||
297 | # CONFIG_NETWORK_SECMARK is not set | ||
298 | CONFIG_NETFILTER=y | ||
299 | # CONFIG_NETFILTER_DEBUG is not set | ||
300 | |||
301 | # | ||
302 | # Core Netfilter Configuration | ||
303 | # | ||
304 | # CONFIG_NETFILTER_NETLINK is not set | ||
305 | CONFIG_NETFILTER_XTABLES=m | ||
306 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
307 | # CONFIG_NETFILTER_XT_TARGET_DSCP is not set | ||
308 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
309 | # CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set | ||
310 | # CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set | ||
311 | # CONFIG_NETFILTER_XT_MATCH_COMMENT is not set | ||
312 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
313 | # CONFIG_NETFILTER_XT_MATCH_DCCP is not set | ||
314 | # CONFIG_NETFILTER_XT_MATCH_DSCP is not set | ||
315 | CONFIG_NETFILTER_XT_MATCH_ESP=m | ||
316 | # CONFIG_NETFILTER_XT_MATCH_HELPER is not set | ||
317 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
318 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
319 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
320 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
321 | # CONFIG_NETFILTER_XT_MATCH_POLICY is not set | ||
322 | CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m | ||
323 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
324 | # CONFIG_NETFILTER_XT_MATCH_QUOTA is not set | ||
325 | # CONFIG_NETFILTER_XT_MATCH_REALM is not set | ||
326 | # CONFIG_NETFILTER_XT_MATCH_SCTP is not set | ||
327 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
328 | # CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set | ||
329 | # CONFIG_NETFILTER_XT_MATCH_STRING is not set | ||
330 | # CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set | ||
331 | |||
332 | # | ||
333 | # IP: Netfilter Configuration | ||
334 | # | ||
335 | CONFIG_IP_NF_CONNTRACK=m | ||
336 | # CONFIG_IP_NF_CT_ACCT is not set | ||
337 | # CONFIG_IP_NF_CONNTRACK_MARK is not set | ||
338 | # CONFIG_IP_NF_CONNTRACK_EVENTS is not set | ||
339 | # CONFIG_IP_NF_CT_PROTO_SCTP is not set | ||
340 | CONFIG_IP_NF_FTP=m | ||
341 | CONFIG_IP_NF_IRC=m | ||
342 | # CONFIG_IP_NF_NETBIOS_NS is not set | ||
343 | CONFIG_IP_NF_TFTP=m | ||
344 | # CONFIG_IP_NF_AMANDA is not set | ||
345 | # CONFIG_IP_NF_PPTP is not set | ||
346 | # CONFIG_IP_NF_H323 is not set | ||
347 | # CONFIG_IP_NF_SIP is not set | ||
348 | # CONFIG_IP_NF_QUEUE is not set | ||
349 | CONFIG_IP_NF_IPTABLES=m | ||
350 | CONFIG_IP_NF_MATCH_IPRANGE=m | ||
351 | # CONFIG_IP_NF_MATCH_TOS is not set | ||
352 | # CONFIG_IP_NF_MATCH_RECENT is not set | ||
353 | # CONFIG_IP_NF_MATCH_ECN is not set | ||
354 | # CONFIG_IP_NF_MATCH_AH is not set | ||
355 | # CONFIG_IP_NF_MATCH_TTL is not set | ||
356 | # CONFIG_IP_NF_MATCH_OWNER is not set | ||
357 | # CONFIG_IP_NF_MATCH_ADDRTYPE is not set | ||
358 | # CONFIG_IP_NF_MATCH_HASHLIMIT is not set | ||
359 | CONFIG_IP_NF_FILTER=m | ||
360 | CONFIG_IP_NF_TARGET_REJECT=m | ||
361 | # CONFIG_IP_NF_TARGET_LOG is not set | ||
362 | # CONFIG_IP_NF_TARGET_ULOG is not set | ||
363 | # CONFIG_IP_NF_TARGET_TCPMSS is not set | ||
364 | CONFIG_IP_NF_NAT=m | ||
365 | CONFIG_IP_NF_NAT_NEEDED=y | ||
366 | CONFIG_IP_NF_TARGET_MASQUERADE=m | ||
367 | CONFIG_IP_NF_TARGET_REDIRECT=m | ||
368 | CONFIG_IP_NF_TARGET_NETMAP=m | ||
369 | CONFIG_IP_NF_TARGET_SAME=m | ||
370 | # CONFIG_IP_NF_NAT_SNMP_BASIC is not set | ||
371 | CONFIG_IP_NF_NAT_IRC=m | ||
372 | CONFIG_IP_NF_NAT_FTP=m | ||
373 | CONFIG_IP_NF_NAT_TFTP=m | ||
374 | CONFIG_IP_NF_MANGLE=m | ||
375 | CONFIG_IP_NF_TARGET_TOS=m | ||
376 | CONFIG_IP_NF_TARGET_ECN=m | ||
377 | CONFIG_IP_NF_TARGET_TTL=m | ||
378 | CONFIG_IP_NF_RAW=m | ||
379 | CONFIG_IP_NF_ARPTABLES=m | ||
380 | CONFIG_IP_NF_ARPFILTER=m | ||
381 | CONFIG_IP_NF_ARP_MANGLE=m | ||
382 | |||
383 | # | ||
384 | # DCCP Configuration (EXPERIMENTAL) | ||
385 | # | ||
386 | # CONFIG_IP_DCCP is not set | ||
387 | |||
388 | # | ||
389 | # SCTP Configuration (EXPERIMENTAL) | ||
390 | # | ||
391 | # CONFIG_IP_SCTP is not set | ||
392 | |||
393 | # | ||
394 | # TIPC Configuration (EXPERIMENTAL) | ||
395 | # | ||
396 | # CONFIG_TIPC is not set | ||
397 | # CONFIG_ATM is not set | ||
398 | # CONFIG_BRIDGE is not set | ||
399 | # CONFIG_VLAN_8021Q is not set | ||
400 | # CONFIG_DECNET is not set | ||
401 | # CONFIG_LLC2 is not set | ||
402 | # CONFIG_IPX is not set | ||
403 | # CONFIG_ATALK is not set | ||
404 | # CONFIG_X25 is not set | ||
405 | # CONFIG_LAPB is not set | ||
406 | # CONFIG_ECONET is not set | ||
407 | # CONFIG_WAN_ROUTER is not set | ||
408 | |||
409 | # | ||
410 | # QoS and/or fair queueing | ||
411 | # | ||
412 | # CONFIG_NET_SCHED is not set | ||
413 | |||
414 | # | ||
415 | # Network testing | ||
416 | # | ||
417 | # CONFIG_NET_PKTGEN is not set | ||
418 | # CONFIG_HAMRADIO is not set | ||
419 | # CONFIG_IRDA is not set | ||
420 | # CONFIG_BT is not set | ||
421 | CONFIG_IEEE80211=m | ||
422 | CONFIG_IEEE80211_DEBUG=y | ||
423 | CONFIG_IEEE80211_CRYPT_WEP=m | ||
424 | CONFIG_IEEE80211_CRYPT_CCMP=m | ||
425 | CONFIG_IEEE80211_CRYPT_TKIP=m | ||
426 | CONFIG_IEEE80211_SOFTMAC=m | ||
427 | CONFIG_IEEE80211_SOFTMAC_DEBUG=y | ||
428 | CONFIG_WIRELESS_EXT=y | ||
429 | |||
430 | # | ||
431 | # Device Drivers | ||
432 | # | ||
433 | |||
434 | # | ||
435 | # Generic Driver Options | ||
436 | # | ||
437 | CONFIG_STANDALONE=y | ||
438 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
439 | CONFIG_FW_LOADER=m | ||
440 | # CONFIG_DEBUG_DRIVER is not set | ||
441 | # CONFIG_SYS_HYPERVISOR is not set | ||
442 | |||
443 | # | ||
444 | # Connector - unified userspace <-> kernelspace linker | ||
445 | # | ||
446 | # CONFIG_CONNECTOR is not set | ||
447 | |||
448 | # | ||
449 | # Memory Technology Devices (MTD) | ||
450 | # | ||
451 | CONFIG_MTD=y | ||
452 | # CONFIG_MTD_DEBUG is not set | ||
453 | CONFIG_MTD_CONCAT=y | ||
454 | CONFIG_MTD_PARTITIONS=y | ||
455 | # CONFIG_MTD_REDBOOT_PARTS is not set | ||
456 | # CONFIG_MTD_CMDLINE_PARTS is not set | ||
457 | |||
458 | # | ||
459 | # User Modules And Translation Layers | ||
460 | # | ||
461 | CONFIG_MTD_CHAR=y | ||
462 | CONFIG_MTD_BLOCK=y | ||
463 | # CONFIG_FTL is not set | ||
464 | # CONFIG_NFTL is not set | ||
465 | # CONFIG_INFTL is not set | ||
466 | # CONFIG_RFD_FTL is not set | ||
467 | # CONFIG_SSFDC is not set | ||
468 | |||
469 | # | ||
470 | # RAM/ROM/Flash chip drivers | ||
471 | # | ||
472 | CONFIG_MTD_CFI=y | ||
473 | CONFIG_MTD_JEDECPROBE=y | ||
474 | CONFIG_MTD_GEN_PROBE=y | ||
475 | CONFIG_MTD_CFI_ADV_OPTIONS=y | ||
476 | CONFIG_MTD_CFI_NOSWAP=y | ||
477 | # CONFIG_MTD_CFI_BE_BYTE_SWAP is not set | ||
478 | # CONFIG_MTD_CFI_LE_BYTE_SWAP is not set | ||
479 | CONFIG_MTD_CFI_GEOMETRY=y | ||
480 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
481 | # CONFIG_MTD_MAP_BANK_WIDTH_2 is not set | ||
482 | # CONFIG_MTD_MAP_BANK_WIDTH_4 is not set | ||
483 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
484 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
485 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
486 | CONFIG_MTD_CFI_I1=y | ||
487 | # CONFIG_MTD_CFI_I2 is not set | ||
488 | # CONFIG_MTD_CFI_I4 is not set | ||
489 | # CONFIG_MTD_CFI_I8 is not set | ||
490 | # CONFIG_MTD_OTP is not set | ||
491 | # CONFIG_MTD_CFI_INTELEXT is not set | ||
492 | CONFIG_MTD_CFI_AMDSTD=y | ||
493 | # CONFIG_MTD_CFI_STAA is not set | ||
494 | CONFIG_MTD_CFI_UTIL=y | ||
495 | # CONFIG_MTD_RAM is not set | ||
496 | # CONFIG_MTD_ROM is not set | ||
497 | # CONFIG_MTD_ABSENT is not set | ||
498 | # CONFIG_MTD_OBSOLETE_CHIPS is not set | ||
499 | |||
500 | # | ||
501 | # Mapping drivers for chip access | ||
502 | # | ||
503 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | ||
504 | CONFIG_MTD_PHYSMAP=y | ||
505 | CONFIG_MTD_PHYSMAP_START=0xffc00000 | ||
506 | CONFIG_MTD_PHYSMAP_LEN=0x400000 | ||
507 | CONFIG_MTD_PHYSMAP_BANKWIDTH=1 | ||
508 | # CONFIG_MTD_PLATRAM is not set | ||
509 | |||
510 | # | ||
511 | # Self-contained MTD device drivers | ||
512 | # | ||
513 | # CONFIG_MTD_PMC551 is not set | ||
514 | # CONFIG_MTD_SLRAM is not set | ||
515 | # CONFIG_MTD_PHRAM is not set | ||
516 | # CONFIG_MTD_MTDRAM is not set | ||
517 | # CONFIG_MTD_BLOCK2MTD is not set | ||
518 | |||
519 | # | ||
520 | # Disk-On-Chip Device Drivers | ||
521 | # | ||
522 | # CONFIG_MTD_DOC2000 is not set | ||
523 | # CONFIG_MTD_DOC2001 is not set | ||
524 | # CONFIG_MTD_DOC2001PLUS is not set | ||
525 | |||
526 | # | ||
527 | # NAND Flash Device Drivers | ||
528 | # | ||
529 | # CONFIG_MTD_NAND is not set | ||
530 | |||
531 | # | ||
532 | # OneNAND Flash Device Drivers | ||
533 | # | ||
534 | # CONFIG_MTD_ONENAND is not set | ||
535 | |||
536 | # | ||
537 | # Parallel port support | ||
538 | # | ||
539 | # CONFIG_PARPORT is not set | ||
540 | |||
541 | # | ||
542 | # Plug and Play support | ||
543 | # | ||
544 | |||
545 | # | ||
546 | # Block devices | ||
547 | # | ||
548 | # CONFIG_BLK_DEV_FD is not set | ||
549 | # CONFIG_BLK_CPQ_DA is not set | ||
550 | # CONFIG_BLK_CPQ_CISS_DA is not set | ||
551 | # CONFIG_BLK_DEV_DAC960 is not set | ||
552 | # CONFIG_BLK_DEV_UMEM is not set | ||
553 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
554 | CONFIG_BLK_DEV_LOOP=y | ||
555 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
556 | # CONFIG_BLK_DEV_NBD is not set | ||
557 | # CONFIG_BLK_DEV_SX8 is not set | ||
558 | # CONFIG_BLK_DEV_UB is not set | ||
559 | CONFIG_BLK_DEV_RAM=y | ||
560 | CONFIG_BLK_DEV_RAM_COUNT=2 | ||
561 | CONFIG_BLK_DEV_RAM_SIZE=8192 | ||
562 | CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 | ||
563 | CONFIG_BLK_DEV_INITRD=y | ||
564 | # CONFIG_CDROM_PKTCDVD is not set | ||
565 | # CONFIG_ATA_OVER_ETH is not set | ||
566 | |||
567 | # | ||
568 | # Misc devices | ||
569 | # | ||
570 | # CONFIG_SGI_IOC4 is not set | ||
571 | # CONFIG_TIFM_CORE is not set | ||
572 | |||
573 | # | ||
574 | # ATA/ATAPI/MFM/RLL support | ||
575 | # | ||
576 | # CONFIG_IDE is not set | ||
577 | |||
578 | # | ||
579 | # SCSI device support | ||
580 | # | ||
581 | # CONFIG_RAID_ATTRS is not set | ||
582 | CONFIG_SCSI=y | ||
583 | # CONFIG_SCSI_NETLINK is not set | ||
584 | CONFIG_SCSI_PROC_FS=y | ||
585 | |||
586 | # | ||
587 | # SCSI support type (disk, tape, CD-ROM) | ||
588 | # | ||
589 | CONFIG_BLK_DEV_SD=y | ||
590 | # CONFIG_CHR_DEV_ST is not set | ||
591 | # CONFIG_CHR_DEV_OSST is not set | ||
592 | # CONFIG_BLK_DEV_SR is not set | ||
593 | CONFIG_CHR_DEV_SG=y | ||
594 | # CONFIG_CHR_DEV_SCH is not set | ||
595 | |||
596 | # | ||
597 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | ||
598 | # | ||
599 | CONFIG_SCSI_MULTI_LUN=y | ||
600 | # CONFIG_SCSI_CONSTANTS is not set | ||
601 | # CONFIG_SCSI_LOGGING is not set | ||
602 | |||
603 | # | ||
604 | # SCSI Transports | ||
605 | # | ||
606 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
607 | # CONFIG_SCSI_FC_ATTRS is not set | ||
608 | # CONFIG_SCSI_ISCSI_ATTRS is not set | ||
609 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
610 | # CONFIG_SCSI_SAS_LIBSAS is not set | ||
611 | |||
612 | # | ||
613 | # SCSI low-level drivers | ||
614 | # | ||
615 | # CONFIG_ISCSI_TCP is not set | ||
616 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set | ||
617 | # CONFIG_SCSI_3W_9XXX is not set | ||
618 | # CONFIG_SCSI_ACARD is not set | ||
619 | # CONFIG_SCSI_AACRAID is not set | ||
620 | # CONFIG_SCSI_AIC7XXX is not set | ||
621 | # CONFIG_SCSI_AIC7XXX_OLD is not set | ||
622 | # CONFIG_SCSI_AIC79XX is not set | ||
623 | # CONFIG_SCSI_AIC94XX is not set | ||
624 | # CONFIG_SCSI_DPT_I2O is not set | ||
625 | # CONFIG_SCSI_ARCMSR is not set | ||
626 | # CONFIG_MEGARAID_NEWGEN is not set | ||
627 | # CONFIG_MEGARAID_LEGACY is not set | ||
628 | # CONFIG_MEGARAID_SAS is not set | ||
629 | # CONFIG_SCSI_HPTIOP is not set | ||
630 | # CONFIG_SCSI_BUSLOGIC is not set | ||
631 | # CONFIG_SCSI_DMX3191D is not set | ||
632 | # CONFIG_SCSI_EATA is not set | ||
633 | # CONFIG_SCSI_FUTURE_DOMAIN is not set | ||
634 | # CONFIG_SCSI_GDTH is not set | ||
635 | # CONFIG_SCSI_IPS is not set | ||
636 | # CONFIG_SCSI_INITIO is not set | ||
637 | # CONFIG_SCSI_INIA100 is not set | ||
638 | # CONFIG_SCSI_STEX is not set | ||
639 | # CONFIG_SCSI_SYM53C8XX_2 is not set | ||
640 | # CONFIG_SCSI_IPR is not set | ||
641 | # CONFIG_SCSI_QLOGIC_1280 is not set | ||
642 | # CONFIG_SCSI_QLA_FC is not set | ||
643 | # CONFIG_SCSI_QLA_ISCSI is not set | ||
644 | # CONFIG_SCSI_LPFC is not set | ||
645 | # CONFIG_SCSI_DC395x is not set | ||
646 | # CONFIG_SCSI_DC390T is not set | ||
647 | # CONFIG_SCSI_NSP32 is not set | ||
648 | # CONFIG_SCSI_DEBUG is not set | ||
649 | |||
650 | # | ||
651 | # Serial ATA (prod) and Parallel ATA (experimental) drivers | ||
652 | # | ||
653 | CONFIG_ATA=y | ||
654 | # CONFIG_SATA_AHCI is not set | ||
655 | # CONFIG_SATA_SVW is not set | ||
656 | # CONFIG_ATA_PIIX is not set | ||
657 | # CONFIG_SATA_MV is not set | ||
658 | # CONFIG_SATA_NV is not set | ||
659 | # CONFIG_PDC_ADMA is not set | ||
660 | # CONFIG_SATA_QSTOR is not set | ||
661 | # CONFIG_SATA_PROMISE is not set | ||
662 | # CONFIG_SATA_SX4 is not set | ||
663 | # CONFIG_SATA_SIL is not set | ||
664 | # CONFIG_SATA_SIL24 is not set | ||
665 | # CONFIG_SATA_SIS is not set | ||
666 | # CONFIG_SATA_ULI is not set | ||
667 | # CONFIG_SATA_VIA is not set | ||
668 | # CONFIG_SATA_VITESSE is not set | ||
669 | # CONFIG_PATA_ALI is not set | ||
670 | # CONFIG_PATA_AMD is not set | ||
671 | # CONFIG_PATA_ARTOP is not set | ||
672 | # CONFIG_PATA_ATIIXP is not set | ||
673 | # CONFIG_PATA_CMD64X is not set | ||
674 | # CONFIG_PATA_CS5520 is not set | ||
675 | # CONFIG_PATA_CS5530 is not set | ||
676 | # CONFIG_PATA_CYPRESS is not set | ||
677 | # CONFIG_PATA_EFAR is not set | ||
678 | # CONFIG_ATA_GENERIC is not set | ||
679 | # CONFIG_PATA_HPT366 is not set | ||
680 | # CONFIG_PATA_HPT37X is not set | ||
681 | # CONFIG_PATA_HPT3X2N is not set | ||
682 | # CONFIG_PATA_HPT3X3 is not set | ||
683 | # CONFIG_PATA_IT821X is not set | ||
684 | # CONFIG_PATA_JMICRON is not set | ||
685 | # CONFIG_PATA_TRIFLEX is not set | ||
686 | # CONFIG_PATA_MPIIX is not set | ||
687 | # CONFIG_PATA_OLDPIIX is not set | ||
688 | # CONFIG_PATA_NETCELL is not set | ||
689 | # CONFIG_PATA_NS87410 is not set | ||
690 | # CONFIG_PATA_OPTI is not set | ||
691 | # CONFIG_PATA_OPTIDMA is not set | ||
692 | # CONFIG_PATA_PDC_OLD is not set | ||
693 | # CONFIG_PATA_RADISYS is not set | ||
694 | # CONFIG_PATA_RZ1000 is not set | ||
695 | # CONFIG_PATA_SC1200 is not set | ||
696 | # CONFIG_PATA_SERVERWORKS is not set | ||
697 | # CONFIG_PATA_PDC2027X is not set | ||
698 | CONFIG_PATA_SIL680=y | ||
699 | # CONFIG_PATA_SIS is not set | ||
700 | # CONFIG_PATA_VIA is not set | ||
701 | # CONFIG_PATA_WINBOND is not set | ||
702 | |||
703 | # | ||
704 | # Multi-device support (RAID and LVM) | ||
705 | # | ||
706 | # CONFIG_MD is not set | ||
707 | |||
708 | # | ||
709 | # Fusion MPT device support | ||
710 | # | ||
711 | # CONFIG_FUSION is not set | ||
712 | # CONFIG_FUSION_SPI is not set | ||
713 | # CONFIG_FUSION_FC is not set | ||
714 | # CONFIG_FUSION_SAS is not set | ||
715 | |||
716 | # | ||
717 | # IEEE 1394 (FireWire) support | ||
718 | # | ||
719 | # CONFIG_IEEE1394 is not set | ||
720 | |||
721 | # | ||
722 | # I2O device support | ||
723 | # | ||
724 | # CONFIG_I2O is not set | ||
725 | |||
726 | # | ||
727 | # Macintosh device drivers | ||
728 | # | ||
729 | # CONFIG_WINDFARM is not set | ||
730 | |||
731 | # | ||
732 | # Network device support | ||
733 | # | ||
734 | CONFIG_NETDEVICES=y | ||
735 | # CONFIG_DUMMY is not set | ||
736 | # CONFIG_BONDING is not set | ||
737 | # CONFIG_EQUALIZER is not set | ||
738 | CONFIG_TUN=m | ||
739 | |||
740 | # | ||
741 | # ARCnet devices | ||
742 | # | ||
743 | # CONFIG_ARCNET is not set | ||
744 | |||
745 | # | ||
746 | # PHY device support | ||
747 | # | ||
748 | |||
749 | # | ||
750 | # Ethernet (10 or 100Mbit) | ||
751 | # | ||
752 | # CONFIG_NET_ETHERNET is not set | ||
753 | |||
754 | # | ||
755 | # Ethernet (1000 Mbit) | ||
756 | # | ||
757 | # CONFIG_ACENIC is not set | ||
758 | # CONFIG_DL2K is not set | ||
759 | # CONFIG_E1000 is not set | ||
760 | # CONFIG_NS83820 is not set | ||
761 | # CONFIG_HAMACHI is not set | ||
762 | # CONFIG_YELLOWFIN is not set | ||
763 | CONFIG_R8169=y | ||
764 | # CONFIG_R8169_NAPI is not set | ||
765 | # CONFIG_SIS190 is not set | ||
766 | # CONFIG_SKGE is not set | ||
767 | # CONFIG_SKY2 is not set | ||
768 | # CONFIG_SK98LIN is not set | ||
769 | # CONFIG_TIGON3 is not set | ||
770 | # CONFIG_BNX2 is not set | ||
771 | # CONFIG_QLA3XXX is not set | ||
772 | |||
773 | # | ||
774 | # Ethernet (10000 Mbit) | ||
775 | # | ||
776 | # CONFIG_CHELSIO_T1 is not set | ||
777 | # CONFIG_IXGB is not set | ||
778 | # CONFIG_S2IO is not set | ||
779 | # CONFIG_MYRI10GE is not set | ||
780 | |||
781 | # | ||
782 | # Token Ring devices | ||
783 | # | ||
784 | # CONFIG_TR is not set | ||
785 | |||
786 | # | ||
787 | # Wireless LAN (non-hamradio) | ||
788 | # | ||
789 | CONFIG_NET_RADIO=y | ||
790 | # CONFIG_NET_WIRELESS_RTNETLINK is not set | ||
791 | |||
792 | # | ||
793 | # Obsolete Wireless cards support (pre-802.11) | ||
794 | # | ||
795 | # CONFIG_STRIP is not set | ||
796 | |||
797 | # | ||
798 | # Wireless 802.11b ISA/PCI cards support | ||
799 | # | ||
800 | # CONFIG_IPW2100 is not set | ||
801 | # CONFIG_IPW2200 is not set | ||
802 | # CONFIG_AIRO is not set | ||
803 | # CONFIG_HERMES is not set | ||
804 | # CONFIG_ATMEL is not set | ||
805 | |||
806 | # | ||
807 | # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support | ||
808 | # | ||
809 | # CONFIG_PRISM54 is not set | ||
810 | # CONFIG_USB_ZD1201 is not set | ||
811 | # CONFIG_HOSTAP is not set | ||
812 | # CONFIG_BCM43XX is not set | ||
813 | # CONFIG_ZD1211RW is not set | ||
814 | CONFIG_NET_WIRELESS=y | ||
815 | |||
816 | # | ||
817 | # Wan interfaces | ||
818 | # | ||
819 | # CONFIG_WAN is not set | ||
820 | # CONFIG_FDDI is not set | ||
821 | # CONFIG_HIPPI is not set | ||
822 | # CONFIG_PPP is not set | ||
823 | # CONFIG_SLIP is not set | ||
824 | # CONFIG_NET_FC is not set | ||
825 | # CONFIG_SHAPER is not set | ||
826 | CONFIG_NETCONSOLE=y | ||
827 | CONFIG_NETPOLL=y | ||
828 | # CONFIG_NETPOLL_RX is not set | ||
829 | # CONFIG_NETPOLL_TRAP is not set | ||
830 | CONFIG_NET_POLL_CONTROLLER=y | ||
831 | |||
832 | # | ||
833 | # ISDN subsystem | ||
834 | # | ||
835 | # CONFIG_ISDN is not set | ||
836 | |||
837 | # | ||
838 | # Telephony Support | ||
839 | # | ||
840 | # CONFIG_PHONE is not set | ||
841 | |||
842 | # | ||
843 | # Input device support | ||
844 | # | ||
845 | CONFIG_INPUT=y | ||
846 | # CONFIG_INPUT_FF_MEMLESS is not set | ||
847 | |||
848 | # | ||
849 | # Userland interfaces | ||
850 | # | ||
851 | CONFIG_INPUT_MOUSEDEV=y | ||
852 | # CONFIG_INPUT_MOUSEDEV_PSAUX is not set | ||
853 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 | ||
854 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | ||
855 | # CONFIG_INPUT_JOYDEV is not set | ||
856 | # CONFIG_INPUT_TSDEV is not set | ||
857 | CONFIG_INPUT_EVDEV=m | ||
858 | # CONFIG_INPUT_EVBUG is not set | ||
859 | |||
860 | # | ||
861 | # Input Device Drivers | ||
862 | # | ||
863 | # CONFIG_INPUT_KEYBOARD is not set | ||
864 | # CONFIG_INPUT_MOUSE is not set | ||
865 | # CONFIG_INPUT_JOYSTICK is not set | ||
866 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
867 | CONFIG_INPUT_MISC=y | ||
868 | CONFIG_INPUT_UINPUT=m | ||
869 | |||
870 | # | ||
871 | # Hardware I/O ports | ||
872 | # | ||
873 | CONFIG_SERIO=y | ||
874 | # CONFIG_SERIO_I8042 is not set | ||
875 | CONFIG_SERIO_SERPORT=y | ||
876 | # CONFIG_SERIO_PCIPS2 is not set | ||
877 | # CONFIG_SERIO_RAW is not set | ||
878 | # CONFIG_GAMEPORT is not set | ||
879 | |||
880 | # | ||
881 | # Character devices | ||
882 | # | ||
883 | CONFIG_VT=y | ||
884 | CONFIG_VT_CONSOLE=y | ||
885 | CONFIG_HW_CONSOLE=y | ||
886 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | ||
887 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
888 | |||
889 | # | ||
890 | # Serial drivers | ||
891 | # | ||
892 | CONFIG_SERIAL_8250=y | ||
893 | CONFIG_SERIAL_8250_CONSOLE=y | ||
894 | CONFIG_SERIAL_8250_PCI=y | ||
895 | CONFIG_SERIAL_8250_NR_UARTS=4 | ||
896 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
897 | # CONFIG_SERIAL_8250_EXTENDED is not set | ||
898 | |||
899 | # | ||
900 | # Non-8250 serial port support | ||
901 | # | ||
902 | CONFIG_SERIAL_CORE=y | ||
903 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
904 | # CONFIG_SERIAL_JSM is not set | ||
905 | CONFIG_UNIX98_PTYS=y | ||
906 | CONFIG_LEGACY_PTYS=y | ||
907 | CONFIG_LEGACY_PTY_COUNT=256 | ||
908 | |||
909 | # | ||
910 | # IPMI | ||
911 | # | ||
912 | # CONFIG_IPMI_HANDLER is not set | ||
913 | |||
914 | # | ||
915 | # Watchdog Cards | ||
916 | # | ||
917 | # CONFIG_WATCHDOG is not set | ||
918 | CONFIG_HW_RANDOM=y | ||
919 | # CONFIG_NVRAM is not set | ||
920 | # CONFIG_GEN_RTC is not set | ||
921 | # CONFIG_DTLK is not set | ||
922 | # CONFIG_R3964 is not set | ||
923 | # CONFIG_APPLICOM is not set | ||
924 | |||
925 | # | ||
926 | # Ftape, the floppy tape device driver | ||
927 | # | ||
928 | # CONFIG_AGP is not set | ||
929 | # CONFIG_DRM is not set | ||
930 | # CONFIG_RAW_DRIVER is not set | ||
931 | |||
932 | # | ||
933 | # TPM devices | ||
934 | # | ||
935 | # CONFIG_TCG_TPM is not set | ||
936 | |||
937 | # | ||
938 | # I2C support | ||
939 | # | ||
940 | CONFIG_I2C=y | ||
941 | CONFIG_I2C_CHARDEV=y | ||
942 | |||
943 | # | ||
944 | # I2C Algorithms | ||
945 | # | ||
946 | # CONFIG_I2C_ALGOBIT is not set | ||
947 | # CONFIG_I2C_ALGOPCF is not set | ||
948 | # CONFIG_I2C_ALGOPCA is not set | ||
949 | |||
950 | # | ||
951 | # I2C Hardware Bus support | ||
952 | # | ||
953 | # CONFIG_I2C_ALI1535 is not set | ||
954 | # CONFIG_I2C_ALI1563 is not set | ||
955 | # CONFIG_I2C_ALI15X3 is not set | ||
956 | # CONFIG_I2C_AMD756 is not set | ||
957 | # CONFIG_I2C_AMD8111 is not set | ||
958 | # CONFIG_I2C_I801 is not set | ||
959 | # CONFIG_I2C_I810 is not set | ||
960 | # CONFIG_I2C_PIIX4 is not set | ||
961 | CONFIG_I2C_MPC=y | ||
962 | # CONFIG_I2C_NFORCE2 is not set | ||
963 | # CONFIG_I2C_OCORES is not set | ||
964 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
965 | # CONFIG_I2C_PROSAVAGE is not set | ||
966 | # CONFIG_I2C_SAVAGE4 is not set | ||
967 | # CONFIG_I2C_SIS5595 is not set | ||
968 | # CONFIG_I2C_SIS630 is not set | ||
969 | # CONFIG_I2C_SIS96X is not set | ||
970 | # CONFIG_I2C_STUB is not set | ||
971 | # CONFIG_I2C_VIA is not set | ||
972 | # CONFIG_I2C_VIAPRO is not set | ||
973 | # CONFIG_I2C_VOODOO3 is not set | ||
974 | # CONFIG_I2C_PCA_ISA is not set | ||
975 | |||
976 | # | ||
977 | # Miscellaneous I2C Chip support | ||
978 | # | ||
979 | # CONFIG_SENSORS_DS1337 is not set | ||
980 | # CONFIG_SENSORS_DS1374 is not set | ||
981 | CONFIG_SENSORS_EEPROM=m | ||
982 | # CONFIG_SENSORS_PCF8574 is not set | ||
983 | # CONFIG_SENSORS_PCA9539 is not set | ||
984 | # CONFIG_SENSORS_PCF8591 is not set | ||
985 | # CONFIG_SENSORS_M41T00 is not set | ||
986 | # CONFIG_SENSORS_MAX6875 is not set | ||
987 | # CONFIG_I2C_DEBUG_CORE is not set | ||
988 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
989 | # CONFIG_I2C_DEBUG_BUS is not set | ||
990 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
991 | |||
992 | # | ||
993 | # SPI support | ||
994 | # | ||
995 | # CONFIG_SPI is not set | ||
996 | # CONFIG_SPI_MASTER is not set | ||
997 | |||
998 | # | ||
999 | # Dallas's 1-wire bus | ||
1000 | # | ||
1001 | # CONFIG_W1 is not set | ||
1002 | |||
1003 | # | ||
1004 | # Hardware Monitoring support | ||
1005 | # | ||
1006 | CONFIG_HWMON=y | ||
1007 | # CONFIG_HWMON_VID is not set | ||
1008 | # CONFIG_SENSORS_ABITUGURU is not set | ||
1009 | # CONFIG_SENSORS_ADM1021 is not set | ||
1010 | # CONFIG_SENSORS_ADM1025 is not set | ||
1011 | # CONFIG_SENSORS_ADM1026 is not set | ||
1012 | # CONFIG_SENSORS_ADM1031 is not set | ||
1013 | # CONFIG_SENSORS_ADM9240 is not set | ||
1014 | # CONFIG_SENSORS_ASB100 is not set | ||
1015 | # CONFIG_SENSORS_ATXP1 is not set | ||
1016 | # CONFIG_SENSORS_DS1621 is not set | ||
1017 | # CONFIG_SENSORS_F71805F is not set | ||
1018 | # CONFIG_SENSORS_FSCHER is not set | ||
1019 | # CONFIG_SENSORS_FSCPOS is not set | ||
1020 | # CONFIG_SENSORS_GL518SM is not set | ||
1021 | # CONFIG_SENSORS_GL520SM is not set | ||
1022 | # CONFIG_SENSORS_IT87 is not set | ||
1023 | # CONFIG_SENSORS_LM63 is not set | ||
1024 | # CONFIG_SENSORS_LM75 is not set | ||
1025 | # CONFIG_SENSORS_LM77 is not set | ||
1026 | # CONFIG_SENSORS_LM78 is not set | ||
1027 | # CONFIG_SENSORS_LM80 is not set | ||
1028 | # CONFIG_SENSORS_LM83 is not set | ||
1029 | # CONFIG_SENSORS_LM85 is not set | ||
1030 | # CONFIG_SENSORS_LM87 is not set | ||
1031 | # CONFIG_SENSORS_LM90 is not set | ||
1032 | # CONFIG_SENSORS_LM92 is not set | ||
1033 | # CONFIG_SENSORS_MAX1619 is not set | ||
1034 | # CONFIG_SENSORS_PC87360 is not set | ||
1035 | # CONFIG_SENSORS_SIS5595 is not set | ||
1036 | # CONFIG_SENSORS_SMSC47M1 is not set | ||
1037 | # CONFIG_SENSORS_SMSC47M192 is not set | ||
1038 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
1039 | # CONFIG_SENSORS_VIA686A is not set | ||
1040 | # CONFIG_SENSORS_VT1211 is not set | ||
1041 | # CONFIG_SENSORS_VT8231 is not set | ||
1042 | # CONFIG_SENSORS_W83781D is not set | ||
1043 | # CONFIG_SENSORS_W83791D is not set | ||
1044 | # CONFIG_SENSORS_W83792D is not set | ||
1045 | # CONFIG_SENSORS_W83L785TS is not set | ||
1046 | # CONFIG_SENSORS_W83627HF is not set | ||
1047 | # CONFIG_SENSORS_W83627EHF is not set | ||
1048 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
1049 | |||
1050 | # | ||
1051 | # Multimedia devices | ||
1052 | # | ||
1053 | # CONFIG_VIDEO_DEV is not set | ||
1054 | |||
1055 | # | ||
1056 | # Digital Video Broadcasting Devices | ||
1057 | # | ||
1058 | # CONFIG_DVB is not set | ||
1059 | # CONFIG_USB_DABUSB is not set | ||
1060 | |||
1061 | # | ||
1062 | # Graphics support | ||
1063 | # | ||
1064 | CONFIG_FIRMWARE_EDID=y | ||
1065 | # CONFIG_FB is not set | ||
1066 | |||
1067 | # | ||
1068 | # Console display driver support | ||
1069 | # | ||
1070 | # CONFIG_VGA_CONSOLE is not set | ||
1071 | CONFIG_DUMMY_CONSOLE=y | ||
1072 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
1073 | |||
1074 | # | ||
1075 | # Sound | ||
1076 | # | ||
1077 | # CONFIG_SOUND is not set | ||
1078 | |||
1079 | # | ||
1080 | # USB support | ||
1081 | # | ||
1082 | CONFIG_USB_ARCH_HAS_HCD=y | ||
1083 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
1084 | CONFIG_USB_ARCH_HAS_EHCI=y | ||
1085 | CONFIG_USB=y | ||
1086 | # CONFIG_USB_DEBUG is not set | ||
1087 | |||
1088 | # | ||
1089 | # Miscellaneous USB options | ||
1090 | # | ||
1091 | CONFIG_USB_DEVICEFS=y | ||
1092 | # CONFIG_USB_BANDWIDTH is not set | ||
1093 | # CONFIG_USB_DYNAMIC_MINORS is not set | ||
1094 | # CONFIG_USB_OTG is not set | ||
1095 | |||
1096 | # | ||
1097 | # USB Host Controller Drivers | ||
1098 | # | ||
1099 | CONFIG_USB_EHCI_HCD=y | ||
1100 | # CONFIG_USB_EHCI_SPLIT_ISO is not set | ||
1101 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set | ||
1102 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set | ||
1103 | # CONFIG_USB_ISP116X_HCD is not set | ||
1104 | CONFIG_USB_OHCI_HCD=y | ||
1105 | # CONFIG_USB_OHCI_BIG_ENDIAN is not set | ||
1106 | CONFIG_USB_OHCI_LITTLE_ENDIAN=y | ||
1107 | # CONFIG_USB_UHCI_HCD is not set | ||
1108 | # CONFIG_USB_SL811_HCD is not set | ||
1109 | |||
1110 | # | ||
1111 | # USB Device Class drivers | ||
1112 | # | ||
1113 | # CONFIG_USB_ACM is not set | ||
1114 | # CONFIG_USB_PRINTER is not set | ||
1115 | |||
1116 | # | ||
1117 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
1118 | # | ||
1119 | |||
1120 | # | ||
1121 | # may also be needed; see USB_STORAGE Help for more information | ||
1122 | # | ||
1123 | CONFIG_USB_STORAGE=m | ||
1124 | # CONFIG_USB_STORAGE_DEBUG is not set | ||
1125 | # CONFIG_USB_STORAGE_DATAFAB is not set | ||
1126 | # CONFIG_USB_STORAGE_FREECOM is not set | ||
1127 | # CONFIG_USB_STORAGE_DPCM is not set | ||
1128 | # CONFIG_USB_STORAGE_USBAT is not set | ||
1129 | # CONFIG_USB_STORAGE_SDDR09 is not set | ||
1130 | # CONFIG_USB_STORAGE_SDDR55 is not set | ||
1131 | # CONFIG_USB_STORAGE_JUMPSHOT is not set | ||
1132 | # CONFIG_USB_STORAGE_ALAUDA is not set | ||
1133 | # CONFIG_USB_STORAGE_ONETOUCH is not set | ||
1134 | # CONFIG_USB_STORAGE_KARMA is not set | ||
1135 | # CONFIG_USB_LIBUSUAL is not set | ||
1136 | |||
1137 | # | ||
1138 | # USB Input Devices | ||
1139 | # | ||
1140 | # CONFIG_USB_HID is not set | ||
1141 | |||
1142 | # | ||
1143 | # USB HID Boot Protocol drivers | ||
1144 | # | ||
1145 | # CONFIG_USB_KBD is not set | ||
1146 | # CONFIG_USB_MOUSE is not set | ||
1147 | # CONFIG_USB_AIPTEK is not set | ||
1148 | # CONFIG_USB_WACOM is not set | ||
1149 | # CONFIG_USB_ACECAD is not set | ||
1150 | # CONFIG_USB_KBTAB is not set | ||
1151 | # CONFIG_USB_POWERMATE is not set | ||
1152 | # CONFIG_USB_TOUCHSCREEN is not set | ||
1153 | # CONFIG_USB_YEALINK is not set | ||
1154 | # CONFIG_USB_XPAD is not set | ||
1155 | # CONFIG_USB_ATI_REMOTE is not set | ||
1156 | # CONFIG_USB_ATI_REMOTE2 is not set | ||
1157 | # CONFIG_USB_KEYSPAN_REMOTE is not set | ||
1158 | # CONFIG_USB_APPLETOUCH is not set | ||
1159 | |||
1160 | # | ||
1161 | # USB Imaging devices | ||
1162 | # | ||
1163 | # CONFIG_USB_MDC800 is not set | ||
1164 | # CONFIG_USB_MICROTEK is not set | ||
1165 | |||
1166 | # | ||
1167 | # USB Network Adapters | ||
1168 | # | ||
1169 | # CONFIG_USB_CATC is not set | ||
1170 | # CONFIG_USB_KAWETH is not set | ||
1171 | # CONFIG_USB_PEGASUS is not set | ||
1172 | # CONFIG_USB_RTL8150 is not set | ||
1173 | # CONFIG_USB_USBNET is not set | ||
1174 | CONFIG_USB_MON=y | ||
1175 | |||
1176 | # | ||
1177 | # USB port drivers | ||
1178 | # | ||
1179 | |||
1180 | # | ||
1181 | # USB Serial Converter support | ||
1182 | # | ||
1183 | CONFIG_USB_SERIAL=y | ||
1184 | CONFIG_USB_SERIAL_CONSOLE=y | ||
1185 | # CONFIG_USB_SERIAL_GENERIC is not set | ||
1186 | # CONFIG_USB_SERIAL_AIRCABLE is not set | ||
1187 | # CONFIG_USB_SERIAL_AIRPRIME is not set | ||
1188 | # CONFIG_USB_SERIAL_ARK3116 is not set | ||
1189 | # CONFIG_USB_SERIAL_BELKIN is not set | ||
1190 | # CONFIG_USB_SERIAL_WHITEHEAT is not set | ||
1191 | # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set | ||
1192 | # CONFIG_USB_SERIAL_CP2101 is not set | ||
1193 | # CONFIG_USB_SERIAL_CYPRESS_M8 is not set | ||
1194 | # CONFIG_USB_SERIAL_EMPEG is not set | ||
1195 | CONFIG_USB_SERIAL_FTDI_SIO=y | ||
1196 | # CONFIG_USB_SERIAL_FUNSOFT is not set | ||
1197 | # CONFIG_USB_SERIAL_VISOR is not set | ||
1198 | # CONFIG_USB_SERIAL_IPAQ is not set | ||
1199 | # CONFIG_USB_SERIAL_IR is not set | ||
1200 | # CONFIG_USB_SERIAL_EDGEPORT is not set | ||
1201 | # CONFIG_USB_SERIAL_EDGEPORT_TI is not set | ||
1202 | # CONFIG_USB_SERIAL_GARMIN is not set | ||
1203 | # CONFIG_USB_SERIAL_IPW is not set | ||
1204 | # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set | ||
1205 | # CONFIG_USB_SERIAL_KEYSPAN is not set | ||
1206 | # CONFIG_USB_SERIAL_KLSI is not set | ||
1207 | # CONFIG_USB_SERIAL_KOBIL_SCT is not set | ||
1208 | # CONFIG_USB_SERIAL_MCT_U232 is not set | ||
1209 | # CONFIG_USB_SERIAL_MOS7720 is not set | ||
1210 | # CONFIG_USB_SERIAL_MOS7840 is not set | ||
1211 | # CONFIG_USB_SERIAL_NAVMAN is not set | ||
1212 | # CONFIG_USB_SERIAL_PL2303 is not set | ||
1213 | # CONFIG_USB_SERIAL_HP4X is not set | ||
1214 | # CONFIG_USB_SERIAL_SAFE is not set | ||
1215 | # CONFIG_USB_SERIAL_SIERRAWIRELESS is not set | ||
1216 | # CONFIG_USB_SERIAL_TI is not set | ||
1217 | # CONFIG_USB_SERIAL_CYBERJACK is not set | ||
1218 | # CONFIG_USB_SERIAL_XIRCOM is not set | ||
1219 | # CONFIG_USB_SERIAL_OPTION is not set | ||
1220 | # CONFIG_USB_SERIAL_OMNINET is not set | ||
1221 | |||
1222 | # | ||
1223 | # USB Miscellaneous drivers | ||
1224 | # | ||
1225 | # CONFIG_USB_EMI62 is not set | ||
1226 | # CONFIG_USB_EMI26 is not set | ||
1227 | # CONFIG_USB_ADUTUX is not set | ||
1228 | # CONFIG_USB_AUERSWALD is not set | ||
1229 | # CONFIG_USB_RIO500 is not set | ||
1230 | # CONFIG_USB_LEGOTOWER is not set | ||
1231 | # CONFIG_USB_LCD is not set | ||
1232 | # CONFIG_USB_LED is not set | ||
1233 | # CONFIG_USB_CYPRESS_CY7C63 is not set | ||
1234 | # CONFIG_USB_CYTHERM is not set | ||
1235 | # CONFIG_USB_PHIDGET is not set | ||
1236 | # CONFIG_USB_IDMOUSE is not set | ||
1237 | # CONFIG_USB_FTDI_ELAN is not set | ||
1238 | # CONFIG_USB_APPLEDISPLAY is not set | ||
1239 | # CONFIG_USB_SISUSBVGA is not set | ||
1240 | # CONFIG_USB_LD is not set | ||
1241 | # CONFIG_USB_TRANCEVIBRATOR is not set | ||
1242 | # CONFIG_USB_TEST is not set | ||
1243 | |||
1244 | # | ||
1245 | # USB DSL modem support | ||
1246 | # | ||
1247 | |||
1248 | # | ||
1249 | # USB Gadget Support | ||
1250 | # | ||
1251 | # CONFIG_USB_GADGET is not set | ||
1252 | |||
1253 | # | ||
1254 | # MMC/SD Card support | ||
1255 | # | ||
1256 | # CONFIG_MMC is not set | ||
1257 | |||
1258 | # | ||
1259 | # LED devices | ||
1260 | # | ||
1261 | # CONFIG_NEW_LEDS is not set | ||
1262 | |||
1263 | # | ||
1264 | # LED drivers | ||
1265 | # | ||
1266 | |||
1267 | # | ||
1268 | # LED Triggers | ||
1269 | # | ||
1270 | |||
1271 | # | ||
1272 | # InfiniBand support | ||
1273 | # | ||
1274 | # CONFIG_INFINIBAND is not set | ||
1275 | |||
1276 | # | ||
1277 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) | ||
1278 | # | ||
1279 | |||
1280 | # | ||
1281 | # Real Time Clock | ||
1282 | # | ||
1283 | CONFIG_RTC_LIB=y | ||
1284 | CONFIG_RTC_CLASS=y | ||
1285 | CONFIG_RTC_HCTOSYS=y | ||
1286 | CONFIG_RTC_HCTOSYS_DEVICE="rtc0" | ||
1287 | # CONFIG_RTC_DEBUG is not set | ||
1288 | |||
1289 | # | ||
1290 | # RTC interfaces | ||
1291 | # | ||
1292 | CONFIG_RTC_INTF_SYSFS=y | ||
1293 | CONFIG_RTC_INTF_PROC=y | ||
1294 | CONFIG_RTC_INTF_DEV=y | ||
1295 | # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set | ||
1296 | |||
1297 | # | ||
1298 | # RTC drivers | ||
1299 | # | ||
1300 | # CONFIG_RTC_DRV_X1205 is not set | ||
1301 | # CONFIG_RTC_DRV_DS1307 is not set | ||
1302 | # CONFIG_RTC_DRV_DS1553 is not set | ||
1303 | # CONFIG_RTC_DRV_ISL1208 is not set | ||
1304 | # CONFIG_RTC_DRV_DS1672 is not set | ||
1305 | # CONFIG_RTC_DRV_DS1742 is not set | ||
1306 | # CONFIG_RTC_DRV_PCF8563 is not set | ||
1307 | # CONFIG_RTC_DRV_PCF8583 is not set | ||
1308 | CONFIG_RTC_DRV_RS5C372=y | ||
1309 | # CONFIG_RTC_DRV_M48T86 is not set | ||
1310 | # CONFIG_RTC_DRV_TEST is not set | ||
1311 | # CONFIG_RTC_DRV_V3020 is not set | ||
1312 | |||
1313 | # | ||
1314 | # DMA Engine support | ||
1315 | # | ||
1316 | # CONFIG_DMA_ENGINE is not set | ||
1317 | |||
1318 | # | ||
1319 | # DMA Clients | ||
1320 | # | ||
1321 | |||
1322 | # | ||
1323 | # DMA Devices | ||
1324 | # | ||
1325 | |||
1326 | # | ||
1327 | # File systems | ||
1328 | # | ||
1329 | CONFIG_EXT2_FS=y | ||
1330 | # CONFIG_EXT2_FS_XATTR is not set | ||
1331 | # CONFIG_EXT2_FS_XIP is not set | ||
1332 | CONFIG_EXT3_FS=y | ||
1333 | CONFIG_EXT3_FS_XATTR=y | ||
1334 | # CONFIG_EXT3_FS_POSIX_ACL is not set | ||
1335 | # CONFIG_EXT3_FS_SECURITY is not set | ||
1336 | # CONFIG_EXT4DEV_FS is not set | ||
1337 | CONFIG_JBD=y | ||
1338 | # CONFIG_JBD_DEBUG is not set | ||
1339 | CONFIG_FS_MBCACHE=y | ||
1340 | # CONFIG_REISERFS_FS is not set | ||
1341 | # CONFIG_JFS_FS is not set | ||
1342 | CONFIG_FS_POSIX_ACL=y | ||
1343 | # CONFIG_XFS_FS is not set | ||
1344 | # CONFIG_GFS2_FS is not set | ||
1345 | # CONFIG_OCFS2_FS is not set | ||
1346 | # CONFIG_MINIX_FS is not set | ||
1347 | # CONFIG_ROMFS_FS is not set | ||
1348 | CONFIG_INOTIFY=y | ||
1349 | CONFIG_INOTIFY_USER=y | ||
1350 | # CONFIG_QUOTA is not set | ||
1351 | CONFIG_DNOTIFY=y | ||
1352 | # CONFIG_AUTOFS_FS is not set | ||
1353 | # CONFIG_AUTOFS4_FS is not set | ||
1354 | # CONFIG_FUSE_FS is not set | ||
1355 | |||
1356 | # | ||
1357 | # CD-ROM/DVD Filesystems | ||
1358 | # | ||
1359 | CONFIG_ISO9660_FS=m | ||
1360 | CONFIG_JOLIET=y | ||
1361 | CONFIG_ZISOFS=y | ||
1362 | CONFIG_ZISOFS_FS=m | ||
1363 | CONFIG_UDF_FS=m | ||
1364 | CONFIG_UDF_NLS=y | ||
1365 | |||
1366 | # | ||
1367 | # DOS/FAT/NT Filesystems | ||
1368 | # | ||
1369 | CONFIG_FAT_FS=m | ||
1370 | CONFIG_MSDOS_FS=m | ||
1371 | CONFIG_VFAT_FS=m | ||
1372 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
1373 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
1374 | CONFIG_NTFS_FS=m | ||
1375 | # CONFIG_NTFS_DEBUG is not set | ||
1376 | # CONFIG_NTFS_RW is not set | ||
1377 | |||
1378 | # | ||
1379 | # Pseudo filesystems | ||
1380 | # | ||
1381 | CONFIG_PROC_FS=y | ||
1382 | CONFIG_PROC_KCORE=y | ||
1383 | CONFIG_PROC_SYSCTL=y | ||
1384 | CONFIG_SYSFS=y | ||
1385 | CONFIG_TMPFS=y | ||
1386 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
1387 | # CONFIG_HUGETLB_PAGE is not set | ||
1388 | CONFIG_RAMFS=y | ||
1389 | # CONFIG_CONFIGFS_FS is not set | ||
1390 | |||
1391 | # | ||
1392 | # Miscellaneous filesystems | ||
1393 | # | ||
1394 | # CONFIG_ADFS_FS is not set | ||
1395 | # CONFIG_AFFS_FS is not set | ||
1396 | # CONFIG_HFS_FS is not set | ||
1397 | # CONFIG_HFSPLUS_FS is not set | ||
1398 | # CONFIG_BEFS_FS is not set | ||
1399 | # CONFIG_BFS_FS is not set | ||
1400 | # CONFIG_EFS_FS is not set | ||
1401 | # CONFIG_JFFS_FS is not set | ||
1402 | # CONFIG_JFFS2_FS is not set | ||
1403 | # CONFIG_CRAMFS is not set | ||
1404 | # CONFIG_VXFS_FS is not set | ||
1405 | # CONFIG_HPFS_FS is not set | ||
1406 | # CONFIG_QNX4FS_FS is not set | ||
1407 | # CONFIG_SYSV_FS is not set | ||
1408 | # CONFIG_UFS_FS is not set | ||
1409 | |||
1410 | # | ||
1411 | # Network File Systems | ||
1412 | # | ||
1413 | CONFIG_NFS_FS=y | ||
1414 | CONFIG_NFS_V3=y | ||
1415 | CONFIG_NFS_V3_ACL=y | ||
1416 | CONFIG_NFS_V4=y | ||
1417 | # CONFIG_NFS_DIRECTIO is not set | ||
1418 | CONFIG_NFSD=m | ||
1419 | CONFIG_NFSD_V3=y | ||
1420 | # CONFIG_NFSD_V3_ACL is not set | ||
1421 | # CONFIG_NFSD_V4 is not set | ||
1422 | CONFIG_NFSD_TCP=y | ||
1423 | CONFIG_ROOT_NFS=y | ||
1424 | CONFIG_LOCKD=y | ||
1425 | CONFIG_LOCKD_V4=y | ||
1426 | CONFIG_EXPORTFS=m | ||
1427 | CONFIG_NFS_ACL_SUPPORT=y | ||
1428 | CONFIG_NFS_COMMON=y | ||
1429 | CONFIG_SUNRPC=y | ||
1430 | CONFIG_SUNRPC_GSS=y | ||
1431 | CONFIG_RPCSEC_GSS_KRB5=y | ||
1432 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
1433 | # CONFIG_SMB_FS is not set | ||
1434 | # CONFIG_CIFS is not set | ||
1435 | # CONFIG_NCP_FS is not set | ||
1436 | # CONFIG_CODA_FS is not set | ||
1437 | # CONFIG_AFS_FS is not set | ||
1438 | # CONFIG_9P_FS is not set | ||
1439 | |||
1440 | # | ||
1441 | # Partition Types | ||
1442 | # | ||
1443 | # CONFIG_PARTITION_ADVANCED is not set | ||
1444 | CONFIG_MSDOS_PARTITION=y | ||
1445 | |||
1446 | # | ||
1447 | # Native Language Support | ||
1448 | # | ||
1449 | CONFIG_NLS=m | ||
1450 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
1451 | CONFIG_NLS_CODEPAGE_437=m | ||
1452 | # CONFIG_NLS_CODEPAGE_737 is not set | ||
1453 | # CONFIG_NLS_CODEPAGE_775 is not set | ||
1454 | # CONFIG_NLS_CODEPAGE_850 is not set | ||
1455 | # CONFIG_NLS_CODEPAGE_852 is not set | ||
1456 | # CONFIG_NLS_CODEPAGE_855 is not set | ||
1457 | # CONFIG_NLS_CODEPAGE_857 is not set | ||
1458 | # CONFIG_NLS_CODEPAGE_860 is not set | ||
1459 | # CONFIG_NLS_CODEPAGE_861 is not set | ||
1460 | # CONFIG_NLS_CODEPAGE_862 is not set | ||
1461 | # CONFIG_NLS_CODEPAGE_863 is not set | ||
1462 | # CONFIG_NLS_CODEPAGE_864 is not set | ||
1463 | # CONFIG_NLS_CODEPAGE_865 is not set | ||
1464 | # CONFIG_NLS_CODEPAGE_866 is not set | ||
1465 | # CONFIG_NLS_CODEPAGE_869 is not set | ||
1466 | # CONFIG_NLS_CODEPAGE_936 is not set | ||
1467 | # CONFIG_NLS_CODEPAGE_950 is not set | ||
1468 | # CONFIG_NLS_CODEPAGE_932 is not set | ||
1469 | # CONFIG_NLS_CODEPAGE_949 is not set | ||
1470 | # CONFIG_NLS_CODEPAGE_874 is not set | ||
1471 | # CONFIG_NLS_ISO8859_8 is not set | ||
1472 | # CONFIG_NLS_CODEPAGE_1250 is not set | ||
1473 | # CONFIG_NLS_CODEPAGE_1251 is not set | ||
1474 | # CONFIG_NLS_ASCII is not set | ||
1475 | CONFIG_NLS_ISO8859_1=m | ||
1476 | # CONFIG_NLS_ISO8859_2 is not set | ||
1477 | # CONFIG_NLS_ISO8859_3 is not set | ||
1478 | # CONFIG_NLS_ISO8859_4 is not set | ||
1479 | # CONFIG_NLS_ISO8859_5 is not set | ||
1480 | # CONFIG_NLS_ISO8859_6 is not set | ||
1481 | # CONFIG_NLS_ISO8859_7 is not set | ||
1482 | # CONFIG_NLS_ISO8859_9 is not set | ||
1483 | # CONFIG_NLS_ISO8859_13 is not set | ||
1484 | # CONFIG_NLS_ISO8859_14 is not set | ||
1485 | # CONFIG_NLS_ISO8859_15 is not set | ||
1486 | # CONFIG_NLS_KOI8_R is not set | ||
1487 | # CONFIG_NLS_KOI8_U is not set | ||
1488 | CONFIG_NLS_UTF8=m | ||
1489 | |||
1490 | # | ||
1491 | # Library routines | ||
1492 | # | ||
1493 | # CONFIG_CRC_CCITT is not set | ||
1494 | # CONFIG_CRC16 is not set | ||
1495 | CONFIG_CRC32=y | ||
1496 | CONFIG_LIBCRC32C=m | ||
1497 | CONFIG_ZLIB_INFLATE=m | ||
1498 | CONFIG_ZLIB_DEFLATE=m | ||
1499 | CONFIG_PLIST=y | ||
1500 | |||
1501 | # | ||
1502 | # Instrumentation Support | ||
1503 | # | ||
1504 | CONFIG_PROFILING=y | ||
1505 | CONFIG_OPROFILE=m | ||
1506 | |||
1507 | # | ||
1508 | # Kernel hacking | ||
1509 | # | ||
1510 | # CONFIG_PRINTK_TIME is not set | ||
1511 | CONFIG_ENABLE_MUST_CHECK=y | ||
1512 | CONFIG_MAGIC_SYSRQ=y | ||
1513 | # CONFIG_UNUSED_SYMBOLS is not set | ||
1514 | CONFIG_DEBUG_KERNEL=y | ||
1515 | CONFIG_LOG_BUF_SHIFT=14 | ||
1516 | CONFIG_DETECT_SOFTLOCKUP=y | ||
1517 | # CONFIG_SCHEDSTATS is not set | ||
1518 | # CONFIG_DEBUG_SLAB is not set | ||
1519 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
1520 | # CONFIG_RT_MUTEX_TESTER is not set | ||
1521 | # CONFIG_DEBUG_SPINLOCK is not set | ||
1522 | # CONFIG_DEBUG_MUTEXES is not set | ||
1523 | # CONFIG_DEBUG_RWSEMS is not set | ||
1524 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
1525 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
1526 | # CONFIG_DEBUG_KOBJECT is not set | ||
1527 | # CONFIG_DEBUG_INFO is not set | ||
1528 | # CONFIG_DEBUG_FS is not set | ||
1529 | # CONFIG_DEBUG_VM is not set | ||
1530 | # CONFIG_DEBUG_LIST is not set | ||
1531 | CONFIG_FORCED_INLINING=y | ||
1532 | # CONFIG_HEADERS_CHECK is not set | ||
1533 | # CONFIG_RCU_TORTURE_TEST is not set | ||
1534 | # CONFIG_DEBUGGER is not set | ||
1535 | # CONFIG_BDI_SWITCH is not set | ||
1536 | # CONFIG_BOOTX_TEXT is not set | ||
1537 | # CONFIG_SERIAL_TEXT_DEBUG is not set | ||
1538 | # CONFIG_PPC_EARLY_DEBUG is not set | ||
1539 | |||
1540 | # | ||
1541 | # Security options | ||
1542 | # | ||
1543 | # CONFIG_KEYS is not set | ||
1544 | # CONFIG_SECURITY is not set | ||
1545 | |||
1546 | # | ||
1547 | # Cryptographic options | ||
1548 | # | ||
1549 | CONFIG_CRYPTO=y | ||
1550 | CONFIG_CRYPTO_ALGAPI=y | ||
1551 | CONFIG_CRYPTO_BLKCIPHER=y | ||
1552 | CONFIG_CRYPTO_MANAGER=y | ||
1553 | # CONFIG_CRYPTO_HMAC is not set | ||
1554 | # CONFIG_CRYPTO_NULL is not set | ||
1555 | CONFIG_CRYPTO_MD4=m | ||
1556 | CONFIG_CRYPTO_MD5=y | ||
1557 | CONFIG_CRYPTO_SHA1=m | ||
1558 | # CONFIG_CRYPTO_SHA256 is not set | ||
1559 | # CONFIG_CRYPTO_SHA512 is not set | ||
1560 | # CONFIG_CRYPTO_WP512 is not set | ||
1561 | # CONFIG_CRYPTO_TGR192 is not set | ||
1562 | CONFIG_CRYPTO_ECB=m | ||
1563 | CONFIG_CRYPTO_CBC=y | ||
1564 | CONFIG_CRYPTO_DES=y | ||
1565 | CONFIG_CRYPTO_BLOWFISH=m | ||
1566 | CONFIG_CRYPTO_TWOFISH=m | ||
1567 | CONFIG_CRYPTO_TWOFISH_COMMON=m | ||
1568 | CONFIG_CRYPTO_SERPENT=m | ||
1569 | CONFIG_CRYPTO_AES=m | ||
1570 | # CONFIG_CRYPTO_CAST5 is not set | ||
1571 | # CONFIG_CRYPTO_CAST6 is not set | ||
1572 | # CONFIG_CRYPTO_TEA is not set | ||
1573 | CONFIG_CRYPTO_ARC4=m | ||
1574 | # CONFIG_CRYPTO_KHAZAD is not set | ||
1575 | # CONFIG_CRYPTO_ANUBIS is not set | ||
1576 | CONFIG_CRYPTO_DEFLATE=m | ||
1577 | CONFIG_CRYPTO_MICHAEL_MIC=m | ||
1578 | CONFIG_CRYPTO_CRC32C=m | ||
1579 | # CONFIG_CRYPTO_TEST is not set | ||
1580 | |||
1581 | # | ||
1582 | # Hardware crypto devices | ||
1583 | # | ||
diff --git a/arch/powerpc/configs/lite5200_defconfig b/arch/powerpc/configs/lite5200_defconfig new file mode 100644 index 00000000000..ee7655776d4 --- /dev/null +++ b/arch/powerpc/configs/lite5200_defconfig | |||
@@ -0,0 +1,931 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.19-rc6 | ||
4 | # Mon Nov 27 11:08:20 2006 | ||
5 | # | ||
6 | # CONFIG_PPC64 is not set | ||
7 | CONFIG_PPC32=y | ||
8 | CONFIG_PPC_MERGE=y | ||
9 | CONFIG_MMU=y | ||
10 | CONFIG_GENERIC_HARDIRQS=y | ||
11 | CONFIG_IRQ_PER_CPU=y | ||
12 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||
13 | CONFIG_GENERIC_HWEIGHT=y | ||
14 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
15 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
16 | CONFIG_PPC=y | ||
17 | CONFIG_EARLY_PRINTK=y | ||
18 | CONFIG_GENERIC_NVRAM=y | ||
19 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | ||
20 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | ||
21 | CONFIG_PPC_OF=y | ||
22 | # CONFIG_PPC_UDBG_16550 is not set | ||
23 | # CONFIG_GENERIC_TBSYNC is not set | ||
24 | CONFIG_AUDIT_ARCH=y | ||
25 | # CONFIG_DEFAULT_UIMAGE is not set | ||
26 | |||
27 | # | ||
28 | # Processor support | ||
29 | # | ||
30 | CONFIG_CLASSIC32=y | ||
31 | # CONFIG_PPC_52xx is not set | ||
32 | # CONFIG_PPC_82xx is not set | ||
33 | # CONFIG_PPC_83xx is not set | ||
34 | # CONFIG_PPC_85xx is not set | ||
35 | # CONFIG_PPC_86xx is not set | ||
36 | # CONFIG_40x is not set | ||
37 | # CONFIG_44x is not set | ||
38 | # CONFIG_8xx is not set | ||
39 | # CONFIG_E200 is not set | ||
40 | CONFIG_6xx=y | ||
41 | CONFIG_PPC_FPU=y | ||
42 | # CONFIG_PPC_DCR_NATIVE is not set | ||
43 | # CONFIG_PPC_DCR_MMIO is not set | ||
44 | # CONFIG_ALTIVEC is not set | ||
45 | CONFIG_PPC_STD_MMU=y | ||
46 | CONFIG_PPC_STD_MMU_32=y | ||
47 | # CONFIG_SMP is not set | ||
48 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
49 | |||
50 | # | ||
51 | # Code maturity level options | ||
52 | # | ||
53 | CONFIG_EXPERIMENTAL=y | ||
54 | CONFIG_BROKEN_ON_SMP=y | ||
55 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
56 | |||
57 | # | ||
58 | # General setup | ||
59 | # | ||
60 | CONFIG_LOCALVERSION="" | ||
61 | CONFIG_LOCALVERSION_AUTO=y | ||
62 | CONFIG_SWAP=y | ||
63 | CONFIG_SYSVIPC=y | ||
64 | # CONFIG_IPC_NS is not set | ||
65 | # CONFIG_POSIX_MQUEUE is not set | ||
66 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
67 | # CONFIG_TASKSTATS is not set | ||
68 | # CONFIG_UTS_NS is not set | ||
69 | # CONFIG_AUDIT is not set | ||
70 | # CONFIG_IKCONFIG is not set | ||
71 | # CONFIG_RELAY is not set | ||
72 | CONFIG_INITRAMFS_SOURCE="" | ||
73 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
74 | CONFIG_SYSCTL=y | ||
75 | CONFIG_EMBEDDED=y | ||
76 | # CONFIG_SYSCTL_SYSCALL is not set | ||
77 | # CONFIG_KALLSYMS is not set | ||
78 | CONFIG_HOTPLUG=y | ||
79 | CONFIG_PRINTK=y | ||
80 | CONFIG_BUG=y | ||
81 | CONFIG_ELF_CORE=y | ||
82 | CONFIG_BASE_FULL=y | ||
83 | CONFIG_FUTEX=y | ||
84 | # CONFIG_EPOLL is not set | ||
85 | CONFIG_SHMEM=y | ||
86 | CONFIG_SLAB=y | ||
87 | CONFIG_VM_EVENT_COUNTERS=y | ||
88 | CONFIG_RT_MUTEXES=y | ||
89 | # CONFIG_TINY_SHMEM is not set | ||
90 | CONFIG_BASE_SMALL=0 | ||
91 | # CONFIG_SLOB is not set | ||
92 | |||
93 | # | ||
94 | # Loadable module support | ||
95 | # | ||
96 | CONFIG_MODULES=y | ||
97 | CONFIG_MODULE_UNLOAD=y | ||
98 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
99 | # CONFIG_MODVERSIONS is not set | ||
100 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
101 | # CONFIG_KMOD is not set | ||
102 | |||
103 | # | ||
104 | # Block layer | ||
105 | # | ||
106 | CONFIG_BLOCK=y | ||
107 | # CONFIG_LBD is not set | ||
108 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
109 | # CONFIG_LSF is not set | ||
110 | |||
111 | # | ||
112 | # IO Schedulers | ||
113 | # | ||
114 | CONFIG_IOSCHED_NOOP=y | ||
115 | CONFIG_IOSCHED_AS=y | ||
116 | CONFIG_IOSCHED_DEADLINE=y | ||
117 | CONFIG_IOSCHED_CFQ=y | ||
118 | CONFIG_DEFAULT_AS=y | ||
119 | # CONFIG_DEFAULT_DEADLINE is not set | ||
120 | # CONFIG_DEFAULT_CFQ is not set | ||
121 | # CONFIG_DEFAULT_NOOP is not set | ||
122 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
123 | |||
124 | # | ||
125 | # Platform support | ||
126 | # | ||
127 | CONFIG_PPC_MULTIPLATFORM=y | ||
128 | # CONFIG_EMBEDDED6xx is not set | ||
129 | # CONFIG_APUS is not set | ||
130 | # CONFIG_PPC_CHRP is not set | ||
131 | CONFIG_PPC_MPC52xx=y | ||
132 | # CONFIG_PPC_EFIKA is not set | ||
133 | CONFIG_PPC_LITE5200=y | ||
134 | # CONFIG_PPC_PMAC is not set | ||
135 | # CONFIG_PPC_CELL is not set | ||
136 | # CONFIG_PPC_CELL_NATIVE is not set | ||
137 | # CONFIG_PPC_RTAS is not set | ||
138 | # CONFIG_MMIO_NVRAM is not set | ||
139 | # CONFIG_PPC_MPC106 is not set | ||
140 | # CONFIG_PPC_970_NAP is not set | ||
141 | # CONFIG_PPC_INDIRECT_IO is not set | ||
142 | # CONFIG_GENERIC_IOMAP is not set | ||
143 | # CONFIG_CPU_FREQ is not set | ||
144 | # CONFIG_TAU is not set | ||
145 | # CONFIG_WANT_EARLY_SERIAL is not set | ||
146 | # CONFIG_MPIC is not set | ||
147 | |||
148 | # | ||
149 | # Kernel options | ||
150 | # | ||
151 | # CONFIG_HIGHMEM is not set | ||
152 | # CONFIG_HZ_100 is not set | ||
153 | CONFIG_HZ_250=y | ||
154 | # CONFIG_HZ_1000 is not set | ||
155 | CONFIG_HZ=250 | ||
156 | CONFIG_PREEMPT_NONE=y | ||
157 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
158 | # CONFIG_PREEMPT is not set | ||
159 | CONFIG_BINFMT_ELF=y | ||
160 | # CONFIG_BINFMT_MISC is not set | ||
161 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | ||
162 | # CONFIG_KEXEC is not set | ||
163 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
164 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
165 | CONFIG_SELECT_MEMORY_MODEL=y | ||
166 | CONFIG_FLATMEM_MANUAL=y | ||
167 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
168 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
169 | CONFIG_FLATMEM=y | ||
170 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
171 | # CONFIG_SPARSEMEM_STATIC is not set | ||
172 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
173 | # CONFIG_RESOURCES_64BIT is not set | ||
174 | CONFIG_PROC_DEVICETREE=y | ||
175 | # CONFIG_CMDLINE_BOOL is not set | ||
176 | CONFIG_PM=y | ||
177 | # CONFIG_PM_LEGACY is not set | ||
178 | # CONFIG_PM_DEBUG is not set | ||
179 | # CONFIG_PM_SYSFS_DEPRECATED is not set | ||
180 | # CONFIG_SOFTWARE_SUSPEND is not set | ||
181 | CONFIG_SECCOMP=y | ||
182 | CONFIG_ISA_DMA_API=y | ||
183 | |||
184 | # | ||
185 | # Bus options | ||
186 | # | ||
187 | CONFIG_GENERIC_ISA_DMA=y | ||
188 | # CONFIG_MPIC_WEIRD is not set | ||
189 | # CONFIG_PPC_I8259 is not set | ||
190 | # CONFIG_PPC_INDIRECT_PCI is not set | ||
191 | CONFIG_PCI=y | ||
192 | CONFIG_PCI_DOMAINS=y | ||
193 | # CONFIG_PCIEPORTBUS is not set | ||
194 | # CONFIG_PCI_DEBUG is not set | ||
195 | |||
196 | # | ||
197 | # PCCARD (PCMCIA/CardBus) support | ||
198 | # | ||
199 | # CONFIG_PCCARD is not set | ||
200 | |||
201 | # | ||
202 | # PCI Hotplug Support | ||
203 | # | ||
204 | # CONFIG_HOTPLUG_PCI is not set | ||
205 | |||
206 | # | ||
207 | # Advanced setup | ||
208 | # | ||
209 | # CONFIG_ADVANCED_OPTIONS is not set | ||
210 | |||
211 | # | ||
212 | # Default settings for advanced configuration options are used | ||
213 | # | ||
214 | CONFIG_HIGHMEM_START=0xfe000000 | ||
215 | CONFIG_LOWMEM_SIZE=0x30000000 | ||
216 | CONFIG_KERNEL_START=0xc0000000 | ||
217 | CONFIG_TASK_SIZE=0x80000000 | ||
218 | CONFIG_BOOT_LOAD=0x00800000 | ||
219 | |||
220 | # | ||
221 | # Networking | ||
222 | # | ||
223 | CONFIG_NET=y | ||
224 | |||
225 | # | ||
226 | # Networking options | ||
227 | # | ||
228 | # CONFIG_NETDEBUG is not set | ||
229 | CONFIG_PACKET=y | ||
230 | # CONFIG_PACKET_MMAP is not set | ||
231 | CONFIG_UNIX=y | ||
232 | CONFIG_XFRM=y | ||
233 | CONFIG_XFRM_USER=m | ||
234 | # CONFIG_XFRM_SUB_POLICY is not set | ||
235 | # CONFIG_NET_KEY is not set | ||
236 | CONFIG_INET=y | ||
237 | CONFIG_IP_MULTICAST=y | ||
238 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
239 | CONFIG_IP_FIB_HASH=y | ||
240 | CONFIG_IP_PNP=y | ||
241 | CONFIG_IP_PNP_DHCP=y | ||
242 | CONFIG_IP_PNP_BOOTP=y | ||
243 | # CONFIG_IP_PNP_RARP is not set | ||
244 | # CONFIG_NET_IPIP is not set | ||
245 | # CONFIG_NET_IPGRE is not set | ||
246 | # CONFIG_IP_MROUTE is not set | ||
247 | # CONFIG_ARPD is not set | ||
248 | CONFIG_SYN_COOKIES=y | ||
249 | # CONFIG_INET_AH is not set | ||
250 | # CONFIG_INET_ESP is not set | ||
251 | # CONFIG_INET_IPCOMP is not set | ||
252 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
253 | # CONFIG_INET_TUNNEL is not set | ||
254 | CONFIG_INET_XFRM_MODE_TRANSPORT=y | ||
255 | CONFIG_INET_XFRM_MODE_TUNNEL=y | ||
256 | CONFIG_INET_XFRM_MODE_BEET=y | ||
257 | CONFIG_INET_DIAG=y | ||
258 | CONFIG_INET_TCP_DIAG=y | ||
259 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
260 | CONFIG_TCP_CONG_CUBIC=y | ||
261 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
262 | # CONFIG_IPV6 is not set | ||
263 | # CONFIG_INET6_XFRM_TUNNEL is not set | ||
264 | # CONFIG_INET6_TUNNEL is not set | ||
265 | # CONFIG_NETWORK_SECMARK is not set | ||
266 | # CONFIG_NETFILTER is not set | ||
267 | |||
268 | # | ||
269 | # DCCP Configuration (EXPERIMENTAL) | ||
270 | # | ||
271 | # CONFIG_IP_DCCP is not set | ||
272 | |||
273 | # | ||
274 | # SCTP Configuration (EXPERIMENTAL) | ||
275 | # | ||
276 | # CONFIG_IP_SCTP is not set | ||
277 | |||
278 | # | ||
279 | # TIPC Configuration (EXPERIMENTAL) | ||
280 | # | ||
281 | # CONFIG_TIPC is not set | ||
282 | # CONFIG_ATM is not set | ||
283 | # CONFIG_BRIDGE is not set | ||
284 | # CONFIG_VLAN_8021Q is not set | ||
285 | # CONFIG_DECNET is not set | ||
286 | # CONFIG_LLC2 is not set | ||
287 | # CONFIG_IPX is not set | ||
288 | # CONFIG_ATALK is not set | ||
289 | # CONFIG_X25 is not set | ||
290 | # CONFIG_LAPB is not set | ||
291 | # CONFIG_ECONET is not set | ||
292 | # CONFIG_WAN_ROUTER is not set | ||
293 | |||
294 | # | ||
295 | # QoS and/or fair queueing | ||
296 | # | ||
297 | # CONFIG_NET_SCHED is not set | ||
298 | |||
299 | # | ||
300 | # Network testing | ||
301 | # | ||
302 | # CONFIG_NET_PKTGEN is not set | ||
303 | # CONFIG_HAMRADIO is not set | ||
304 | # CONFIG_IRDA is not set | ||
305 | # CONFIG_BT is not set | ||
306 | # CONFIG_IEEE80211 is not set | ||
307 | |||
308 | # | ||
309 | # Device Drivers | ||
310 | # | ||
311 | |||
312 | # | ||
313 | # Generic Driver Options | ||
314 | # | ||
315 | CONFIG_STANDALONE=y | ||
316 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
317 | # CONFIG_FW_LOADER is not set | ||
318 | # CONFIG_DEBUG_DRIVER is not set | ||
319 | # CONFIG_SYS_HYPERVISOR is not set | ||
320 | |||
321 | # | ||
322 | # Connector - unified userspace <-> kernelspace linker | ||
323 | # | ||
324 | # CONFIG_CONNECTOR is not set | ||
325 | |||
326 | # | ||
327 | # Memory Technology Devices (MTD) | ||
328 | # | ||
329 | # CONFIG_MTD is not set | ||
330 | |||
331 | # | ||
332 | # Parallel port support | ||
333 | # | ||
334 | # CONFIG_PARPORT is not set | ||
335 | |||
336 | # | ||
337 | # Plug and Play support | ||
338 | # | ||
339 | |||
340 | # | ||
341 | # Block devices | ||
342 | # | ||
343 | # CONFIG_BLK_DEV_FD is not set | ||
344 | # CONFIG_BLK_CPQ_DA is not set | ||
345 | # CONFIG_BLK_CPQ_CISS_DA is not set | ||
346 | # CONFIG_BLK_DEV_DAC960 is not set | ||
347 | # CONFIG_BLK_DEV_UMEM is not set | ||
348 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
349 | CONFIG_BLK_DEV_LOOP=y | ||
350 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
351 | # CONFIG_BLK_DEV_NBD is not set | ||
352 | # CONFIG_BLK_DEV_SX8 is not set | ||
353 | CONFIG_BLK_DEV_RAM=y | ||
354 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
355 | CONFIG_BLK_DEV_RAM_SIZE=32768 | ||
356 | CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 | ||
357 | CONFIG_BLK_DEV_INITRD=y | ||
358 | # CONFIG_CDROM_PKTCDVD is not set | ||
359 | # CONFIG_ATA_OVER_ETH is not set | ||
360 | |||
361 | # | ||
362 | # Misc devices | ||
363 | # | ||
364 | # CONFIG_SGI_IOC4 is not set | ||
365 | # CONFIG_TIFM_CORE is not set | ||
366 | |||
367 | # | ||
368 | # ATA/ATAPI/MFM/RLL support | ||
369 | # | ||
370 | # CONFIG_IDE is not set | ||
371 | |||
372 | # | ||
373 | # SCSI device support | ||
374 | # | ||
375 | # CONFIG_RAID_ATTRS is not set | ||
376 | CONFIG_SCSI=y | ||
377 | # CONFIG_SCSI_NETLINK is not set | ||
378 | # CONFIG_SCSI_PROC_FS is not set | ||
379 | |||
380 | # | ||
381 | # SCSI support type (disk, tape, CD-ROM) | ||
382 | # | ||
383 | # CONFIG_BLK_DEV_SD is not set | ||
384 | # CONFIG_CHR_DEV_ST is not set | ||
385 | # CONFIG_CHR_DEV_OSST is not set | ||
386 | # CONFIG_BLK_DEV_SR is not set | ||
387 | # CONFIG_CHR_DEV_SG is not set | ||
388 | # CONFIG_CHR_DEV_SCH is not set | ||
389 | |||
390 | # | ||
391 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | ||
392 | # | ||
393 | # CONFIG_SCSI_MULTI_LUN is not set | ||
394 | # CONFIG_SCSI_CONSTANTS is not set | ||
395 | # CONFIG_SCSI_LOGGING is not set | ||
396 | |||
397 | # | ||
398 | # SCSI Transports | ||
399 | # | ||
400 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
401 | # CONFIG_SCSI_FC_ATTRS is not set | ||
402 | # CONFIG_SCSI_ISCSI_ATTRS is not set | ||
403 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
404 | # CONFIG_SCSI_SAS_LIBSAS is not set | ||
405 | |||
406 | # | ||
407 | # SCSI low-level drivers | ||
408 | # | ||
409 | # CONFIG_ISCSI_TCP is not set | ||
410 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set | ||
411 | # CONFIG_SCSI_3W_9XXX is not set | ||
412 | # CONFIG_SCSI_ACARD is not set | ||
413 | # CONFIG_SCSI_AACRAID is not set | ||
414 | # CONFIG_SCSI_AIC7XXX is not set | ||
415 | # CONFIG_SCSI_AIC7XXX_OLD is not set | ||
416 | # CONFIG_SCSI_AIC79XX is not set | ||
417 | # CONFIG_SCSI_AIC94XX is not set | ||
418 | # CONFIG_SCSI_DPT_I2O is not set | ||
419 | # CONFIG_SCSI_ARCMSR is not set | ||
420 | # CONFIG_MEGARAID_NEWGEN is not set | ||
421 | # CONFIG_MEGARAID_LEGACY is not set | ||
422 | # CONFIG_MEGARAID_SAS is not set | ||
423 | # CONFIG_SCSI_HPTIOP is not set | ||
424 | # CONFIG_SCSI_BUSLOGIC is not set | ||
425 | # CONFIG_SCSI_DMX3191D is not set | ||
426 | # CONFIG_SCSI_EATA is not set | ||
427 | # CONFIG_SCSI_FUTURE_DOMAIN is not set | ||
428 | # CONFIG_SCSI_GDTH is not set | ||
429 | # CONFIG_SCSI_IPS is not set | ||
430 | # CONFIG_SCSI_INITIO is not set | ||
431 | # CONFIG_SCSI_INIA100 is not set | ||
432 | # CONFIG_SCSI_STEX is not set | ||
433 | # CONFIG_SCSI_SYM53C8XX_2 is not set | ||
434 | # CONFIG_SCSI_IPR is not set | ||
435 | # CONFIG_SCSI_QLOGIC_1280 is not set | ||
436 | # CONFIG_SCSI_QLA_FC is not set | ||
437 | # CONFIG_SCSI_QLA_ISCSI is not set | ||
438 | # CONFIG_SCSI_LPFC is not set | ||
439 | # CONFIG_SCSI_DC395x is not set | ||
440 | # CONFIG_SCSI_DC390T is not set | ||
441 | # CONFIG_SCSI_NSP32 is not set | ||
442 | # CONFIG_SCSI_DEBUG is not set | ||
443 | |||
444 | # | ||
445 | # Serial ATA (prod) and Parallel ATA (experimental) drivers | ||
446 | # | ||
447 | CONFIG_ATA=y | ||
448 | # CONFIG_SATA_AHCI is not set | ||
449 | # CONFIG_SATA_SVW is not set | ||
450 | # CONFIG_ATA_PIIX is not set | ||
451 | # CONFIG_SATA_MV is not set | ||
452 | # CONFIG_SATA_NV is not set | ||
453 | # CONFIG_PDC_ADMA is not set | ||
454 | # CONFIG_SATA_QSTOR is not set | ||
455 | # CONFIG_SATA_PROMISE is not set | ||
456 | # CONFIG_SATA_SX4 is not set | ||
457 | # CONFIG_SATA_SIL is not set | ||
458 | # CONFIG_SATA_SIL24 is not set | ||
459 | # CONFIG_SATA_SIS is not set | ||
460 | # CONFIG_SATA_ULI is not set | ||
461 | # CONFIG_SATA_VIA is not set | ||
462 | # CONFIG_SATA_VITESSE is not set | ||
463 | # CONFIG_PATA_ALI is not set | ||
464 | # CONFIG_PATA_AMD is not set | ||
465 | # CONFIG_PATA_ARTOP is not set | ||
466 | # CONFIG_PATA_ATIIXP is not set | ||
467 | # CONFIG_PATA_CMD64X is not set | ||
468 | # CONFIG_PATA_CS5520 is not set | ||
469 | # CONFIG_PATA_CS5530 is not set | ||
470 | # CONFIG_PATA_CYPRESS is not set | ||
471 | # CONFIG_PATA_EFAR is not set | ||
472 | # CONFIG_ATA_GENERIC is not set | ||
473 | # CONFIG_PATA_HPT366 is not set | ||
474 | # CONFIG_PATA_HPT37X is not set | ||
475 | # CONFIG_PATA_HPT3X2N is not set | ||
476 | # CONFIG_PATA_HPT3X3 is not set | ||
477 | # CONFIG_PATA_IT821X is not set | ||
478 | # CONFIG_PATA_JMICRON is not set | ||
479 | # CONFIG_PATA_TRIFLEX is not set | ||
480 | CONFIG_PATA_MPC52xx=y | ||
481 | # CONFIG_PATA_MPIIX is not set | ||
482 | # CONFIG_PATA_OLDPIIX is not set | ||
483 | # CONFIG_PATA_NETCELL is not set | ||
484 | # CONFIG_PATA_NS87410 is not set | ||
485 | # CONFIG_PATA_OPTI is not set | ||
486 | # CONFIG_PATA_OPTIDMA is not set | ||
487 | # CONFIG_PATA_PDC_OLD is not set | ||
488 | # CONFIG_PATA_RADISYS is not set | ||
489 | # CONFIG_PATA_RZ1000 is not set | ||
490 | # CONFIG_PATA_SC1200 is not set | ||
491 | # CONFIG_PATA_SERVERWORKS is not set | ||
492 | # CONFIG_PATA_PDC2027X is not set | ||
493 | # CONFIG_PATA_SIL680 is not set | ||
494 | # CONFIG_PATA_SIS is not set | ||
495 | # CONFIG_PATA_VIA is not set | ||
496 | # CONFIG_PATA_WINBOND is not set | ||
497 | |||
498 | # | ||
499 | # Multi-device support (RAID and LVM) | ||
500 | # | ||
501 | # CONFIG_MD is not set | ||
502 | |||
503 | # | ||
504 | # Fusion MPT device support | ||
505 | # | ||
506 | # CONFIG_FUSION is not set | ||
507 | # CONFIG_FUSION_SPI is not set | ||
508 | # CONFIG_FUSION_FC is not set | ||
509 | # CONFIG_FUSION_SAS is not set | ||
510 | |||
511 | # | ||
512 | # IEEE 1394 (FireWire) support | ||
513 | # | ||
514 | # CONFIG_IEEE1394 is not set | ||
515 | |||
516 | # | ||
517 | # I2O device support | ||
518 | # | ||
519 | # CONFIG_I2O is not set | ||
520 | |||
521 | # | ||
522 | # Macintosh device drivers | ||
523 | # | ||
524 | # CONFIG_WINDFARM is not set | ||
525 | |||
526 | # | ||
527 | # Network device support | ||
528 | # | ||
529 | CONFIG_NETDEVICES=y | ||
530 | # CONFIG_DUMMY is not set | ||
531 | # CONFIG_BONDING is not set | ||
532 | # CONFIG_EQUALIZER is not set | ||
533 | # CONFIG_TUN is not set | ||
534 | |||
535 | # | ||
536 | # ARCnet devices | ||
537 | # | ||
538 | # CONFIG_ARCNET is not set | ||
539 | |||
540 | # | ||
541 | # PHY device support | ||
542 | # | ||
543 | |||
544 | # | ||
545 | # Ethernet (10 or 100Mbit) | ||
546 | # | ||
547 | # CONFIG_NET_ETHERNET is not set | ||
548 | |||
549 | # | ||
550 | # Ethernet (1000 Mbit) | ||
551 | # | ||
552 | # CONFIG_ACENIC is not set | ||
553 | # CONFIG_DL2K is not set | ||
554 | # CONFIG_E1000 is not set | ||
555 | # CONFIG_NS83820 is not set | ||
556 | # CONFIG_HAMACHI is not set | ||
557 | # CONFIG_YELLOWFIN is not set | ||
558 | # CONFIG_R8169 is not set | ||
559 | # CONFIG_SIS190 is not set | ||
560 | # CONFIG_SKGE is not set | ||
561 | # CONFIG_SKY2 is not set | ||
562 | # CONFIG_SK98LIN is not set | ||
563 | # CONFIG_TIGON3 is not set | ||
564 | # CONFIG_BNX2 is not set | ||
565 | # CONFIG_MV643XX_ETH is not set | ||
566 | # CONFIG_QLA3XXX is not set | ||
567 | |||
568 | # | ||
569 | # Ethernet (10000 Mbit) | ||
570 | # | ||
571 | # CONFIG_CHELSIO_T1 is not set | ||
572 | # CONFIG_IXGB is not set | ||
573 | # CONFIG_S2IO is not set | ||
574 | # CONFIG_MYRI10GE is not set | ||
575 | |||
576 | # | ||
577 | # Token Ring devices | ||
578 | # | ||
579 | # CONFIG_TR is not set | ||
580 | |||
581 | # | ||
582 | # Wireless LAN (non-hamradio) | ||
583 | # | ||
584 | # CONFIG_NET_RADIO is not set | ||
585 | |||
586 | # | ||
587 | # Wan interfaces | ||
588 | # | ||
589 | # CONFIG_WAN is not set | ||
590 | # CONFIG_FDDI is not set | ||
591 | # CONFIG_HIPPI is not set | ||
592 | # CONFIG_PPP is not set | ||
593 | # CONFIG_SLIP is not set | ||
594 | # CONFIG_NET_FC is not set | ||
595 | # CONFIG_SHAPER is not set | ||
596 | # CONFIG_NETCONSOLE is not set | ||
597 | # CONFIG_NETPOLL is not set | ||
598 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
599 | |||
600 | # | ||
601 | # ISDN subsystem | ||
602 | # | ||
603 | # CONFIG_ISDN is not set | ||
604 | |||
605 | # | ||
606 | # Telephony Support | ||
607 | # | ||
608 | # CONFIG_PHONE is not set | ||
609 | |||
610 | # | ||
611 | # Input device support | ||
612 | # | ||
613 | # CONFIG_INPUT is not set | ||
614 | |||
615 | # | ||
616 | # Hardware I/O ports | ||
617 | # | ||
618 | # CONFIG_SERIO is not set | ||
619 | # CONFIG_GAMEPORT is not set | ||
620 | |||
621 | # | ||
622 | # Character devices | ||
623 | # | ||
624 | # CONFIG_VT is not set | ||
625 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
626 | |||
627 | # | ||
628 | # Serial drivers | ||
629 | # | ||
630 | # CONFIG_SERIAL_8250 is not set | ||
631 | |||
632 | # | ||
633 | # Non-8250 serial port support | ||
634 | # | ||
635 | CONFIG_SERIAL_CORE=y | ||
636 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
637 | CONFIG_SERIAL_MPC52xx=y | ||
638 | CONFIG_SERIAL_MPC52xx_CONSOLE=y | ||
639 | CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600 | ||
640 | # CONFIG_SERIAL_JSM is not set | ||
641 | CONFIG_UNIX98_PTYS=y | ||
642 | CONFIG_LEGACY_PTYS=y | ||
643 | CONFIG_LEGACY_PTY_COUNT=256 | ||
644 | |||
645 | # | ||
646 | # IPMI | ||
647 | # | ||
648 | # CONFIG_IPMI_HANDLER is not set | ||
649 | |||
650 | # | ||
651 | # Watchdog Cards | ||
652 | # | ||
653 | # CONFIG_WATCHDOG is not set | ||
654 | # CONFIG_HW_RANDOM is not set | ||
655 | # CONFIG_NVRAM is not set | ||
656 | # CONFIG_GEN_RTC is not set | ||
657 | # CONFIG_DTLK is not set | ||
658 | # CONFIG_R3964 is not set | ||
659 | # CONFIG_APPLICOM is not set | ||
660 | |||
661 | # | ||
662 | # Ftape, the floppy tape device driver | ||
663 | # | ||
664 | # CONFIG_AGP is not set | ||
665 | # CONFIG_DRM is not set | ||
666 | # CONFIG_RAW_DRIVER is not set | ||
667 | |||
668 | # | ||
669 | # TPM devices | ||
670 | # | ||
671 | # CONFIG_TCG_TPM is not set | ||
672 | |||
673 | # | ||
674 | # I2C support | ||
675 | # | ||
676 | # CONFIG_I2C is not set | ||
677 | |||
678 | # | ||
679 | # SPI support | ||
680 | # | ||
681 | # CONFIG_SPI is not set | ||
682 | # CONFIG_SPI_MASTER is not set | ||
683 | |||
684 | # | ||
685 | # Dallas's 1-wire bus | ||
686 | # | ||
687 | # CONFIG_W1 is not set | ||
688 | |||
689 | # | ||
690 | # Hardware Monitoring support | ||
691 | # | ||
692 | # CONFIG_HWMON is not set | ||
693 | # CONFIG_HWMON_VID is not set | ||
694 | |||
695 | # | ||
696 | # Multimedia devices | ||
697 | # | ||
698 | # CONFIG_VIDEO_DEV is not set | ||
699 | |||
700 | # | ||
701 | # Digital Video Broadcasting Devices | ||
702 | # | ||
703 | # CONFIG_DVB is not set | ||
704 | |||
705 | # | ||
706 | # Graphics support | ||
707 | # | ||
708 | # CONFIG_FIRMWARE_EDID is not set | ||
709 | # CONFIG_FB is not set | ||
710 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
711 | |||
712 | # | ||
713 | # Sound | ||
714 | # | ||
715 | # CONFIG_SOUND is not set | ||
716 | |||
717 | # | ||
718 | # USB support | ||
719 | # | ||
720 | CONFIG_USB_ARCH_HAS_HCD=y | ||
721 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
722 | CONFIG_USB_ARCH_HAS_EHCI=y | ||
723 | # CONFIG_USB is not set | ||
724 | |||
725 | # | ||
726 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
727 | # | ||
728 | |||
729 | # | ||
730 | # USB Gadget Support | ||
731 | # | ||
732 | # CONFIG_USB_GADGET is not set | ||
733 | |||
734 | # | ||
735 | # MMC/SD Card support | ||
736 | # | ||
737 | # CONFIG_MMC is not set | ||
738 | |||
739 | # | ||
740 | # LED devices | ||
741 | # | ||
742 | # CONFIG_NEW_LEDS is not set | ||
743 | |||
744 | # | ||
745 | # LED drivers | ||
746 | # | ||
747 | |||
748 | # | ||
749 | # LED Triggers | ||
750 | # | ||
751 | |||
752 | # | ||
753 | # InfiniBand support | ||
754 | # | ||
755 | # CONFIG_INFINIBAND is not set | ||
756 | |||
757 | # | ||
758 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) | ||
759 | # | ||
760 | |||
761 | # | ||
762 | # Real Time Clock | ||
763 | # | ||
764 | # CONFIG_RTC_CLASS is not set | ||
765 | |||
766 | # | ||
767 | # DMA Engine support | ||
768 | # | ||
769 | # CONFIG_DMA_ENGINE is not set | ||
770 | |||
771 | # | ||
772 | # DMA Clients | ||
773 | # | ||
774 | |||
775 | # | ||
776 | # DMA Devices | ||
777 | # | ||
778 | |||
779 | # | ||
780 | # File systems | ||
781 | # | ||
782 | CONFIG_EXT2_FS=y | ||
783 | # CONFIG_EXT2_FS_XATTR is not set | ||
784 | # CONFIG_EXT2_FS_XIP is not set | ||
785 | CONFIG_EXT3_FS=y | ||
786 | CONFIG_EXT3_FS_XATTR=y | ||
787 | # CONFIG_EXT3_FS_POSIX_ACL is not set | ||
788 | # CONFIG_EXT3_FS_SECURITY is not set | ||
789 | # CONFIG_EXT4DEV_FS is not set | ||
790 | CONFIG_JBD=y | ||
791 | # CONFIG_JBD_DEBUG is not set | ||
792 | CONFIG_FS_MBCACHE=y | ||
793 | # CONFIG_REISERFS_FS is not set | ||
794 | # CONFIG_JFS_FS is not set | ||
795 | # CONFIG_FS_POSIX_ACL is not set | ||
796 | # CONFIG_XFS_FS is not set | ||
797 | # CONFIG_GFS2_FS is not set | ||
798 | # CONFIG_OCFS2_FS is not set | ||
799 | # CONFIG_MINIX_FS is not set | ||
800 | # CONFIG_ROMFS_FS is not set | ||
801 | CONFIG_INOTIFY=y | ||
802 | CONFIG_INOTIFY_USER=y | ||
803 | # CONFIG_QUOTA is not set | ||
804 | CONFIG_DNOTIFY=y | ||
805 | # CONFIG_AUTOFS_FS is not set | ||
806 | # CONFIG_AUTOFS4_FS is not set | ||
807 | # CONFIG_FUSE_FS is not set | ||
808 | |||
809 | # | ||
810 | # CD-ROM/DVD Filesystems | ||
811 | # | ||
812 | # CONFIG_ISO9660_FS is not set | ||
813 | # CONFIG_UDF_FS is not set | ||
814 | |||
815 | # | ||
816 | # DOS/FAT/NT Filesystems | ||
817 | # | ||
818 | # CONFIG_MSDOS_FS is not set | ||
819 | # CONFIG_VFAT_FS is not set | ||
820 | # CONFIG_NTFS_FS is not set | ||
821 | |||
822 | # | ||
823 | # Pseudo filesystems | ||
824 | # | ||
825 | CONFIG_PROC_FS=y | ||
826 | CONFIG_PROC_KCORE=y | ||
827 | CONFIG_PROC_SYSCTL=y | ||
828 | CONFIG_SYSFS=y | ||
829 | CONFIG_TMPFS=y | ||
830 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
831 | # CONFIG_HUGETLB_PAGE is not set | ||
832 | CONFIG_RAMFS=y | ||
833 | # CONFIG_CONFIGFS_FS is not set | ||
834 | |||
835 | # | ||
836 | # Miscellaneous filesystems | ||
837 | # | ||
838 | # CONFIG_ADFS_FS is not set | ||
839 | # CONFIG_AFFS_FS is not set | ||
840 | # CONFIG_HFS_FS is not set | ||
841 | # CONFIG_HFSPLUS_FS is not set | ||
842 | # CONFIG_BEFS_FS is not set | ||
843 | # CONFIG_BFS_FS is not set | ||
844 | # CONFIG_EFS_FS is not set | ||
845 | # CONFIG_CRAMFS is not set | ||
846 | # CONFIG_VXFS_FS is not set | ||
847 | # CONFIG_HPFS_FS is not set | ||
848 | # CONFIG_QNX4FS_FS is not set | ||
849 | # CONFIG_SYSV_FS is not set | ||
850 | # CONFIG_UFS_FS is not set | ||
851 | |||
852 | # | ||
853 | # Network File Systems | ||
854 | # | ||
855 | # CONFIG_NFS_FS is not set | ||
856 | # CONFIG_NFSD is not set | ||
857 | # CONFIG_SMB_FS is not set | ||
858 | # CONFIG_CIFS is not set | ||
859 | # CONFIG_NCP_FS is not set | ||
860 | # CONFIG_CODA_FS is not set | ||
861 | # CONFIG_AFS_FS is not set | ||
862 | # CONFIG_9P_FS is not set | ||
863 | |||
864 | # | ||
865 | # Partition Types | ||
866 | # | ||
867 | # CONFIG_PARTITION_ADVANCED is not set | ||
868 | CONFIG_MSDOS_PARTITION=y | ||
869 | |||
870 | # | ||
871 | # Native Language Support | ||
872 | # | ||
873 | # CONFIG_NLS is not set | ||
874 | |||
875 | # | ||
876 | # Library routines | ||
877 | # | ||
878 | # CONFIG_CRC_CCITT is not set | ||
879 | # CONFIG_CRC16 is not set | ||
880 | # CONFIG_CRC32 is not set | ||
881 | # CONFIG_LIBCRC32C is not set | ||
882 | CONFIG_PLIST=y | ||
883 | |||
884 | # | ||
885 | # Instrumentation Support | ||
886 | # | ||
887 | # CONFIG_PROFILING is not set | ||
888 | |||
889 | # | ||
890 | # Kernel hacking | ||
891 | # | ||
892 | CONFIG_PRINTK_TIME=y | ||
893 | CONFIG_ENABLE_MUST_CHECK=y | ||
894 | # CONFIG_MAGIC_SYSRQ is not set | ||
895 | # CONFIG_UNUSED_SYMBOLS is not set | ||
896 | CONFIG_DEBUG_KERNEL=y | ||
897 | CONFIG_LOG_BUF_SHIFT=14 | ||
898 | CONFIG_DETECT_SOFTLOCKUP=y | ||
899 | # CONFIG_SCHEDSTATS is not set | ||
900 | # CONFIG_DEBUG_SLAB is not set | ||
901 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
902 | # CONFIG_RT_MUTEX_TESTER is not set | ||
903 | # CONFIG_DEBUG_SPINLOCK is not set | ||
904 | # CONFIG_DEBUG_MUTEXES is not set | ||
905 | # CONFIG_DEBUG_RWSEMS is not set | ||
906 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
907 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
908 | # CONFIG_DEBUG_KOBJECT is not set | ||
909 | CONFIG_DEBUG_INFO=y | ||
910 | # CONFIG_DEBUG_FS is not set | ||
911 | # CONFIG_DEBUG_VM is not set | ||
912 | # CONFIG_DEBUG_LIST is not set | ||
913 | CONFIG_FORCED_INLINING=y | ||
914 | # CONFIG_HEADERS_CHECK is not set | ||
915 | # CONFIG_RCU_TORTURE_TEST is not set | ||
916 | # CONFIG_DEBUGGER is not set | ||
917 | # CONFIG_BDI_SWITCH is not set | ||
918 | # CONFIG_BOOTX_TEXT is not set | ||
919 | # CONFIG_SERIAL_TEXT_DEBUG is not set | ||
920 | # CONFIG_PPC_EARLY_DEBUG is not set | ||
921 | |||
922 | # | ||
923 | # Security options | ||
924 | # | ||
925 | # CONFIG_KEYS is not set | ||
926 | # CONFIG_SECURITY is not set | ||
927 | |||
928 | # | ||
929 | # Cryptographic options | ||
930 | # | ||
931 | # CONFIG_CRYPTO is not set | ||
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index be11df7c11a..1c009651f92 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
@@ -1386,8 +1386,8 @@ CONFIG_INOTIFY=y | |||
1386 | CONFIG_INOTIFY_USER=y | 1386 | CONFIG_INOTIFY_USER=y |
1387 | # CONFIG_QUOTA is not set | 1387 | # CONFIG_QUOTA is not set |
1388 | CONFIG_DNOTIFY=y | 1388 | CONFIG_DNOTIFY=y |
1389 | CONFIG_AUTOFS_FS=y | 1389 | # CONFIG_AUTOFS_FS is not set |
1390 | # CONFIG_AUTOFS4_FS is not set | 1390 | CONFIG_AUTOFS4_FS=m |
1391 | # CONFIG_FUSE_FS is not set | 1391 | # CONFIG_FUSE_FS is not set |
1392 | 1392 | ||
1393 | # | 1393 | # |
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig new file mode 100644 index 00000000000..f2d888e014a --- /dev/null +++ b/arch/powerpc/configs/ps3_defconfig | |||
@@ -0,0 +1,837 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.19-rc6 | ||
4 | # Tue Nov 21 19:38:53 2006 | ||
5 | # | ||
6 | CONFIG_PPC64=y | ||
7 | CONFIG_64BIT=y | ||
8 | CONFIG_PPC_MERGE=y | ||
9 | CONFIG_MMU=y | ||
10 | CONFIG_GENERIC_HARDIRQS=y | ||
11 | CONFIG_IRQ_PER_CPU=y | ||
12 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||
13 | CONFIG_GENERIC_HWEIGHT=y | ||
14 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
15 | CONFIG_GENERIC_FIND_NEXT_BIT=y | ||
16 | CONFIG_PPC=y | ||
17 | CONFIG_EARLY_PRINTK=y | ||
18 | CONFIG_COMPAT=y | ||
19 | CONFIG_SYSVIPC_COMPAT=y | ||
20 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | ||
21 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | ||
22 | CONFIG_PPC_OF=y | ||
23 | # CONFIG_PPC_UDBG_16550 is not set | ||
24 | # CONFIG_GENERIC_TBSYNC is not set | ||
25 | CONFIG_AUDIT_ARCH=y | ||
26 | # CONFIG_DEFAULT_UIMAGE is not set | ||
27 | |||
28 | # | ||
29 | # Processor support | ||
30 | # | ||
31 | # CONFIG_POWER4_ONLY is not set | ||
32 | CONFIG_POWER3=y | ||
33 | CONFIG_POWER4=y | ||
34 | CONFIG_PPC_FPU=y | ||
35 | # CONFIG_PPC_DCR_NATIVE is not set | ||
36 | # CONFIG_PPC_DCR_MMIO is not set | ||
37 | # CONFIG_PPC_OF_PLATFORM_PCI is not set | ||
38 | CONFIG_ALTIVEC=y | ||
39 | CONFIG_PPC_STD_MMU=y | ||
40 | CONFIG_VIRT_CPU_ACCOUNTING=y | ||
41 | CONFIG_SMP=y | ||
42 | CONFIG_NR_CPUS=2 | ||
43 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
44 | |||
45 | # | ||
46 | # Code maturity level options | ||
47 | # | ||
48 | CONFIG_EXPERIMENTAL=y | ||
49 | CONFIG_LOCK_KERNEL=y | ||
50 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
51 | |||
52 | # | ||
53 | # General setup | ||
54 | # | ||
55 | CONFIG_LOCALVERSION="" | ||
56 | CONFIG_LOCALVERSION_AUTO=y | ||
57 | CONFIG_SWAP=y | ||
58 | CONFIG_SYSVIPC=y | ||
59 | # CONFIG_IPC_NS is not set | ||
60 | # CONFIG_POSIX_MQUEUE is not set | ||
61 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
62 | # CONFIG_TASKSTATS is not set | ||
63 | # CONFIG_UTS_NS is not set | ||
64 | # CONFIG_AUDIT is not set | ||
65 | # CONFIG_IKCONFIG is not set | ||
66 | # CONFIG_CPUSETS is not set | ||
67 | # CONFIG_RELAY is not set | ||
68 | CONFIG_INITRAMFS_SOURCE="" | ||
69 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
70 | CONFIG_SYSCTL=y | ||
71 | CONFIG_EMBEDDED=y | ||
72 | # CONFIG_SYSCTL_SYSCALL is not set | ||
73 | CONFIG_KALLSYMS=y | ||
74 | CONFIG_KALLSYMS_ALL=y | ||
75 | CONFIG_KALLSYMS_EXTRA_PASS=y | ||
76 | CONFIG_HOTPLUG=y | ||
77 | CONFIG_PRINTK=y | ||
78 | CONFIG_BUG=y | ||
79 | CONFIG_ELF_CORE=y | ||
80 | CONFIG_BASE_FULL=y | ||
81 | CONFIG_FUTEX=y | ||
82 | CONFIG_EPOLL=y | ||
83 | CONFIG_SHMEM=y | ||
84 | CONFIG_SLAB=y | ||
85 | CONFIG_VM_EVENT_COUNTERS=y | ||
86 | CONFIG_RT_MUTEXES=y | ||
87 | # CONFIG_TINY_SHMEM is not set | ||
88 | CONFIG_BASE_SMALL=0 | ||
89 | # CONFIG_SLOB is not set | ||
90 | |||
91 | # | ||
92 | # Loadable module support | ||
93 | # | ||
94 | CONFIG_MODULES=y | ||
95 | CONFIG_MODULE_UNLOAD=y | ||
96 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
97 | # CONFIG_MODVERSIONS is not set | ||
98 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
99 | CONFIG_KMOD=y | ||
100 | CONFIG_STOP_MACHINE=y | ||
101 | |||
102 | # | ||
103 | # Block layer | ||
104 | # | ||
105 | CONFIG_BLOCK=y | ||
106 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
107 | |||
108 | # | ||
109 | # IO Schedulers | ||
110 | # | ||
111 | CONFIG_IOSCHED_NOOP=y | ||
112 | CONFIG_IOSCHED_AS=y | ||
113 | CONFIG_IOSCHED_DEADLINE=y | ||
114 | CONFIG_IOSCHED_CFQ=y | ||
115 | CONFIG_DEFAULT_AS=y | ||
116 | # CONFIG_DEFAULT_DEADLINE is not set | ||
117 | # CONFIG_DEFAULT_CFQ is not set | ||
118 | # CONFIG_DEFAULT_NOOP is not set | ||
119 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
120 | |||
121 | # | ||
122 | # Platform support | ||
123 | # | ||
124 | CONFIG_PPC_MULTIPLATFORM=y | ||
125 | # CONFIG_EMBEDDED6xx is not set | ||
126 | # CONFIG_APUS is not set | ||
127 | # CONFIG_PPC_PSERIES is not set | ||
128 | # CONFIG_PPC_ISERIES is not set | ||
129 | # CONFIG_PPC_PMAC is not set | ||
130 | # CONFIG_PPC_MAPLE is not set | ||
131 | # CONFIG_PPC_PASEMI is not set | ||
132 | CONFIG_PPC_CELL=y | ||
133 | # CONFIG_PPC_CELL_NATIVE is not set | ||
134 | # CONFIG_PPC_IBM_CELL_BLADE is not set | ||
135 | CONFIG_PPC_PS3=y | ||
136 | # CONFIG_U3_DART is not set | ||
137 | # CONFIG_PPC_RTAS is not set | ||
138 | # CONFIG_MMIO_NVRAM is not set | ||
139 | # CONFIG_PPC_MPC106 is not set | ||
140 | # CONFIG_PPC_970_NAP is not set | ||
141 | # CONFIG_PPC_INDIRECT_IO is not set | ||
142 | # CONFIG_GENERIC_IOMAP is not set | ||
143 | # CONFIG_CPU_FREQ is not set | ||
144 | # CONFIG_WANT_EARLY_SERIAL is not set | ||
145 | # CONFIG_MPIC is not set | ||
146 | |||
147 | # | ||
148 | # Cell Broadband Engine options | ||
149 | # | ||
150 | CONFIG_SPU_FS=y | ||
151 | CONFIG_SPU_BASE=y | ||
152 | # CONFIG_CBE_RAS is not set | ||
153 | |||
154 | # | ||
155 | # PS3 Platform Options | ||
156 | # | ||
157 | CONFIG_PS3_HTAB_SIZE=20 | ||
158 | CONFIG_PS3_DYNAMIC_DMA=y | ||
159 | CONFIG_PS3_USE_LPAR_ADDR=y | ||
160 | |||
161 | # | ||
162 | # Kernel options | ||
163 | # | ||
164 | # CONFIG_HZ_100 is not set | ||
165 | CONFIG_HZ_250=y | ||
166 | # CONFIG_HZ_1000 is not set | ||
167 | CONFIG_HZ=250 | ||
168 | CONFIG_PREEMPT_NONE=y | ||
169 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
170 | # CONFIG_PREEMPT is not set | ||
171 | # CONFIG_PREEMPT_BKL is not set | ||
172 | CONFIG_BINFMT_ELF=y | ||
173 | CONFIG_BINFMT_MISC=y | ||
174 | CONFIG_FORCE_MAX_ZONEORDER=9 | ||
175 | # CONFIG_IOMMU_VMERGE is not set | ||
176 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | ||
177 | # CONFIG_KEXEC is not set | ||
178 | # CONFIG_CRASH_DUMP is not set | ||
179 | # CONFIG_IRQ_ALL_CPUS is not set | ||
180 | # CONFIG_NUMA is not set | ||
181 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y | ||
182 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
183 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | ||
184 | CONFIG_ARCH_SPARSEMEM_DEFAULT=y | ||
185 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
186 | CONFIG_SELECT_MEMORY_MODEL=y | ||
187 | # CONFIG_FLATMEM_MANUAL is not set | ||
188 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
189 | CONFIG_SPARSEMEM_MANUAL=y | ||
190 | CONFIG_SPARSEMEM=y | ||
191 | CONFIG_HAVE_MEMORY_PRESENT=y | ||
192 | # CONFIG_SPARSEMEM_STATIC is not set | ||
193 | CONFIG_SPARSEMEM_EXTREME=y | ||
194 | CONFIG_MEMORY_HOTPLUG=y | ||
195 | CONFIG_MEMORY_HOTPLUG_SPARSE=y | ||
196 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
197 | CONFIG_RESOURCES_64BIT=y | ||
198 | CONFIG_ARCH_MEMORY_PROBE=y | ||
199 | CONFIG_PPC_64K_PAGES=y | ||
200 | # CONFIG_SCHED_SMT is not set | ||
201 | CONFIG_PROC_DEVICETREE=y | ||
202 | CONFIG_CMDLINE_BOOL=y | ||
203 | CONFIG_CMDLINE="root=/dev/nfs rw ip=dhcp" | ||
204 | # CONFIG_PM is not set | ||
205 | # CONFIG_SECCOMP is not set | ||
206 | CONFIG_ISA_DMA_API=y | ||
207 | |||
208 | # | ||
209 | # Bus options | ||
210 | # | ||
211 | CONFIG_GENERIC_ISA_DMA=y | ||
212 | # CONFIG_MPIC_WEIRD is not set | ||
213 | # CONFIG_PPC_I8259 is not set | ||
214 | # CONFIG_PCI is not set | ||
215 | # CONFIG_PCI_DOMAINS is not set | ||
216 | |||
217 | # | ||
218 | # PCCARD (PCMCIA/CardBus) support | ||
219 | # | ||
220 | # CONFIG_PCCARD is not set | ||
221 | |||
222 | # | ||
223 | # PCI Hotplug Support | ||
224 | # | ||
225 | CONFIG_KERNEL_START=0xc000000000000000 | ||
226 | |||
227 | # | ||
228 | # Networking | ||
229 | # | ||
230 | CONFIG_NET=y | ||
231 | |||
232 | # | ||
233 | # Networking options | ||
234 | # | ||
235 | # CONFIG_NETDEBUG is not set | ||
236 | # CONFIG_PACKET is not set | ||
237 | CONFIG_UNIX=y | ||
238 | # CONFIG_NET_KEY is not set | ||
239 | CONFIG_INET=y | ||
240 | # CONFIG_IP_MULTICAST is not set | ||
241 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
242 | CONFIG_IP_FIB_HASH=y | ||
243 | CONFIG_IP_PNP=y | ||
244 | CONFIG_IP_PNP_DHCP=y | ||
245 | # CONFIG_IP_PNP_BOOTP is not set | ||
246 | # CONFIG_IP_PNP_RARP is not set | ||
247 | # CONFIG_NET_IPIP is not set | ||
248 | # CONFIG_NET_IPGRE is not set | ||
249 | # CONFIG_ARPD is not set | ||
250 | # CONFIG_SYN_COOKIES is not set | ||
251 | # CONFIG_INET_AH is not set | ||
252 | # CONFIG_INET_ESP is not set | ||
253 | # CONFIG_INET_IPCOMP is not set | ||
254 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
255 | # CONFIG_INET_TUNNEL is not set | ||
256 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
257 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
258 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
259 | # CONFIG_INET_DIAG is not set | ||
260 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
261 | CONFIG_TCP_CONG_CUBIC=y | ||
262 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
263 | # CONFIG_IPV6 is not set | ||
264 | # CONFIG_INET6_XFRM_TUNNEL is not set | ||
265 | # CONFIG_INET6_TUNNEL is not set | ||
266 | # CONFIG_NETWORK_SECMARK is not set | ||
267 | # CONFIG_NETFILTER is not set | ||
268 | |||
269 | # | ||
270 | # DCCP Configuration (EXPERIMENTAL) | ||
271 | # | ||
272 | # CONFIG_IP_DCCP is not set | ||
273 | |||
274 | # | ||
275 | # SCTP Configuration (EXPERIMENTAL) | ||
276 | # | ||
277 | # CONFIG_IP_SCTP is not set | ||
278 | |||
279 | # | ||
280 | # TIPC Configuration (EXPERIMENTAL) | ||
281 | # | ||
282 | # CONFIG_TIPC is not set | ||
283 | # CONFIG_ATM is not set | ||
284 | # CONFIG_BRIDGE is not set | ||
285 | # CONFIG_VLAN_8021Q is not set | ||
286 | # CONFIG_DECNET is not set | ||
287 | # CONFIG_LLC2 is not set | ||
288 | # CONFIG_IPX is not set | ||
289 | # CONFIG_ATALK is not set | ||
290 | # CONFIG_X25 is not set | ||
291 | # CONFIG_LAPB is not set | ||
292 | # CONFIG_ECONET is not set | ||
293 | # CONFIG_WAN_ROUTER is not set | ||
294 | |||
295 | # | ||
296 | # QoS and/or fair queueing | ||
297 | # | ||
298 | # CONFIG_NET_SCHED is not set | ||
299 | |||
300 | # | ||
301 | # Network testing | ||
302 | # | ||
303 | # CONFIG_NET_PKTGEN is not set | ||
304 | # CONFIG_HAMRADIO is not set | ||
305 | # CONFIG_IRDA is not set | ||
306 | # CONFIG_BT is not set | ||
307 | # CONFIG_IEEE80211 is not set | ||
308 | |||
309 | # | ||
310 | # Device Drivers | ||
311 | # | ||
312 | |||
313 | # | ||
314 | # Generic Driver Options | ||
315 | # | ||
316 | CONFIG_STANDALONE=y | ||
317 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
318 | # CONFIG_FW_LOADER is not set | ||
319 | # CONFIG_DEBUG_DRIVER is not set | ||
320 | # CONFIG_SYS_HYPERVISOR is not set | ||
321 | |||
322 | # | ||
323 | # Connector - unified userspace <-> kernelspace linker | ||
324 | # | ||
325 | # CONFIG_CONNECTOR is not set | ||
326 | |||
327 | # | ||
328 | # Memory Technology Devices (MTD) | ||
329 | # | ||
330 | # CONFIG_MTD is not set | ||
331 | |||
332 | # | ||
333 | # Parallel port support | ||
334 | # | ||
335 | # CONFIG_PARPORT is not set | ||
336 | |||
337 | # | ||
338 | # Plug and Play support | ||
339 | # | ||
340 | |||
341 | # | ||
342 | # Block devices | ||
343 | # | ||
344 | # CONFIG_BLK_DEV_FD is not set | ||
345 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
346 | # CONFIG_BLK_DEV_LOOP is not set | ||
347 | # CONFIG_BLK_DEV_NBD is not set | ||
348 | # CONFIG_BLK_DEV_RAM is not set | ||
349 | # CONFIG_BLK_DEV_INITRD is not set | ||
350 | # CONFIG_CDROM_PKTCDVD is not set | ||
351 | # CONFIG_ATA_OVER_ETH is not set | ||
352 | |||
353 | # | ||
354 | # Misc devices | ||
355 | # | ||
356 | # CONFIG_TIFM_CORE is not set | ||
357 | |||
358 | # | ||
359 | # ATA/ATAPI/MFM/RLL support | ||
360 | # | ||
361 | # CONFIG_IDE is not set | ||
362 | |||
363 | # | ||
364 | # SCSI device support | ||
365 | # | ||
366 | # CONFIG_RAID_ATTRS is not set | ||
367 | CONFIG_SCSI=y | ||
368 | # CONFIG_SCSI_NETLINK is not set | ||
369 | CONFIG_SCSI_PROC_FS=y | ||
370 | |||
371 | # | ||
372 | # SCSI support type (disk, tape, CD-ROM) | ||
373 | # | ||
374 | # CONFIG_BLK_DEV_SD is not set | ||
375 | # CONFIG_CHR_DEV_ST is not set | ||
376 | # CONFIG_CHR_DEV_OSST is not set | ||
377 | # CONFIG_BLK_DEV_SR is not set | ||
378 | # CONFIG_CHR_DEV_SG is not set | ||
379 | # CONFIG_CHR_DEV_SCH is not set | ||
380 | |||
381 | # | ||
382 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | ||
383 | # | ||
384 | # CONFIG_SCSI_MULTI_LUN is not set | ||
385 | # CONFIG_SCSI_CONSTANTS is not set | ||
386 | # CONFIG_SCSI_LOGGING is not set | ||
387 | |||
388 | # | ||
389 | # SCSI Transports | ||
390 | # | ||
391 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
392 | # CONFIG_SCSI_FC_ATTRS is not set | ||
393 | # CONFIG_SCSI_ISCSI_ATTRS is not set | ||
394 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
395 | # CONFIG_SCSI_SAS_LIBSAS is not set | ||
396 | |||
397 | # | ||
398 | # SCSI low-level drivers | ||
399 | # | ||
400 | # CONFIG_ISCSI_TCP is not set | ||
401 | # CONFIG_SCSI_DEBUG is not set | ||
402 | |||
403 | # | ||
404 | # Serial ATA (prod) and Parallel ATA (experimental) drivers | ||
405 | # | ||
406 | # CONFIG_ATA is not set | ||
407 | |||
408 | # | ||
409 | # Multi-device support (RAID and LVM) | ||
410 | # | ||
411 | # CONFIG_MD is not set | ||
412 | |||
413 | # | ||
414 | # Fusion MPT device support | ||
415 | # | ||
416 | # CONFIG_FUSION is not set | ||
417 | |||
418 | # | ||
419 | # IEEE 1394 (FireWire) support | ||
420 | # | ||
421 | |||
422 | # | ||
423 | # I2O device support | ||
424 | # | ||
425 | |||
426 | # | ||
427 | # Macintosh device drivers | ||
428 | # | ||
429 | # CONFIG_WINDFARM is not set | ||
430 | |||
431 | # | ||
432 | # Network device support | ||
433 | # | ||
434 | CONFIG_NETDEVICES=y | ||
435 | # CONFIG_DUMMY is not set | ||
436 | # CONFIG_BONDING is not set | ||
437 | # CONFIG_EQUALIZER is not set | ||
438 | # CONFIG_TUN is not set | ||
439 | |||
440 | # | ||
441 | # PHY device support | ||
442 | # | ||
443 | |||
444 | # | ||
445 | # Ethernet (10 or 100Mbit) | ||
446 | # | ||
447 | # CONFIG_NET_ETHERNET is not set | ||
448 | |||
449 | # | ||
450 | # Ethernet (1000 Mbit) | ||
451 | # | ||
452 | |||
453 | # | ||
454 | # Ethernet (10000 Mbit) | ||
455 | # | ||
456 | |||
457 | # | ||
458 | # Token Ring devices | ||
459 | # | ||
460 | |||
461 | # | ||
462 | # Wireless LAN (non-hamradio) | ||
463 | # | ||
464 | # CONFIG_NET_RADIO is not set | ||
465 | |||
466 | # | ||
467 | # Wan interfaces | ||
468 | # | ||
469 | # CONFIG_WAN is not set | ||
470 | # CONFIG_PPP is not set | ||
471 | # CONFIG_SLIP is not set | ||
472 | # CONFIG_SHAPER is not set | ||
473 | # CONFIG_NETCONSOLE is not set | ||
474 | # CONFIG_NETPOLL is not set | ||
475 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
476 | |||
477 | # | ||
478 | # ISDN subsystem | ||
479 | # | ||
480 | # CONFIG_ISDN is not set | ||
481 | |||
482 | # | ||
483 | # Telephony Support | ||
484 | # | ||
485 | # CONFIG_PHONE is not set | ||
486 | |||
487 | # | ||
488 | # Input device support | ||
489 | # | ||
490 | CONFIG_INPUT=y | ||
491 | # CONFIG_INPUT_FF_MEMLESS is not set | ||
492 | |||
493 | # | ||
494 | # Userland interfaces | ||
495 | # | ||
496 | # CONFIG_INPUT_MOUSEDEV is not set | ||
497 | # CONFIG_INPUT_JOYDEV is not set | ||
498 | # CONFIG_INPUT_TSDEV is not set | ||
499 | CONFIG_INPUT_EVDEV=y | ||
500 | # CONFIG_INPUT_EVBUG is not set | ||
501 | |||
502 | # | ||
503 | # Input Device Drivers | ||
504 | # | ||
505 | # CONFIG_INPUT_KEYBOARD is not set | ||
506 | # CONFIG_INPUT_MOUSE is not set | ||
507 | # CONFIG_INPUT_JOYSTICK is not set | ||
508 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
509 | # CONFIG_INPUT_MISC is not set | ||
510 | |||
511 | # | ||
512 | # Hardware I/O ports | ||
513 | # | ||
514 | # CONFIG_SERIO is not set | ||
515 | # CONFIG_GAMEPORT is not set | ||
516 | |||
517 | # | ||
518 | # Character devices | ||
519 | # | ||
520 | CONFIG_VT=y | ||
521 | CONFIG_VT_CONSOLE=y | ||
522 | CONFIG_HW_CONSOLE=y | ||
523 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | ||
524 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
525 | |||
526 | # | ||
527 | # Serial drivers | ||
528 | # | ||
529 | # CONFIG_SERIAL_8250 is not set | ||
530 | |||
531 | # | ||
532 | # Non-8250 serial port support | ||
533 | # | ||
534 | CONFIG_UNIX98_PTYS=y | ||
535 | # CONFIG_LEGACY_PTYS is not set | ||
536 | |||
537 | # | ||
538 | # IPMI | ||
539 | # | ||
540 | # CONFIG_IPMI_HANDLER is not set | ||
541 | |||
542 | # | ||
543 | # Watchdog Cards | ||
544 | # | ||
545 | # CONFIG_WATCHDOG is not set | ||
546 | # CONFIG_HW_RANDOM is not set | ||
547 | CONFIG_GEN_RTC=y | ||
548 | # CONFIG_GEN_RTC_X is not set | ||
549 | # CONFIG_DTLK is not set | ||
550 | # CONFIG_R3964 is not set | ||
551 | |||
552 | # | ||
553 | # Ftape, the floppy tape device driver | ||
554 | # | ||
555 | # CONFIG_RAW_DRIVER is not set | ||
556 | # CONFIG_HANGCHECK_TIMER is not set | ||
557 | |||
558 | # | ||
559 | # TPM devices | ||
560 | # | ||
561 | # CONFIG_TCG_TPM is not set | ||
562 | |||
563 | # | ||
564 | # I2C support | ||
565 | # | ||
566 | # CONFIG_I2C is not set | ||
567 | |||
568 | # | ||
569 | # SPI support | ||
570 | # | ||
571 | # CONFIG_SPI is not set | ||
572 | # CONFIG_SPI_MASTER is not set | ||
573 | |||
574 | # | ||
575 | # Dallas's 1-wire bus | ||
576 | # | ||
577 | # CONFIG_W1 is not set | ||
578 | |||
579 | # | ||
580 | # Hardware Monitoring support | ||
581 | # | ||
582 | # CONFIG_HWMON is not set | ||
583 | # CONFIG_HWMON_VID is not set | ||
584 | |||
585 | # | ||
586 | # Multimedia devices | ||
587 | # | ||
588 | # CONFIG_VIDEO_DEV is not set | ||
589 | |||
590 | # | ||
591 | # Digital Video Broadcasting Devices | ||
592 | # | ||
593 | # CONFIG_DVB is not set | ||
594 | |||
595 | # | ||
596 | # Graphics support | ||
597 | # | ||
598 | # CONFIG_FIRMWARE_EDID is not set | ||
599 | # CONFIG_FB is not set | ||
600 | |||
601 | # | ||
602 | # Console display driver support | ||
603 | # | ||
604 | # CONFIG_VGA_CONSOLE is not set | ||
605 | CONFIG_DUMMY_CONSOLE=y | ||
606 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
607 | |||
608 | # | ||
609 | # Sound | ||
610 | # | ||
611 | # CONFIG_SOUND is not set | ||
612 | |||
613 | # | ||
614 | # USB support | ||
615 | # | ||
616 | # CONFIG_USB_ARCH_HAS_HCD is not set | ||
617 | # CONFIG_USB_ARCH_HAS_OHCI is not set | ||
618 | # CONFIG_USB_ARCH_HAS_EHCI is not set | ||
619 | |||
620 | # | ||
621 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
622 | # | ||
623 | |||
624 | # | ||
625 | # USB Gadget Support | ||
626 | # | ||
627 | # CONFIG_USB_GADGET is not set | ||
628 | |||
629 | # | ||
630 | # MMC/SD Card support | ||
631 | # | ||
632 | # CONFIG_MMC is not set | ||
633 | |||
634 | # | ||
635 | # LED devices | ||
636 | # | ||
637 | # CONFIG_NEW_LEDS is not set | ||
638 | |||
639 | # | ||
640 | # LED drivers | ||
641 | # | ||
642 | |||
643 | # | ||
644 | # LED Triggers | ||
645 | # | ||
646 | |||
647 | # | ||
648 | # InfiniBand support | ||
649 | # | ||
650 | |||
651 | # | ||
652 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) | ||
653 | # | ||
654 | |||
655 | # | ||
656 | # Real Time Clock | ||
657 | # | ||
658 | # CONFIG_RTC_CLASS is not set | ||
659 | |||
660 | # | ||
661 | # DMA Engine support | ||
662 | # | ||
663 | # CONFIG_DMA_ENGINE is not set | ||
664 | |||
665 | # | ||
666 | # DMA Clients | ||
667 | # | ||
668 | |||
669 | # | ||
670 | # DMA Devices | ||
671 | # | ||
672 | |||
673 | # | ||
674 | # File systems | ||
675 | # | ||
676 | # CONFIG_EXT2_FS is not set | ||
677 | # CONFIG_EXT3_FS is not set | ||
678 | # CONFIG_EXT4DEV_FS is not set | ||
679 | # CONFIG_REISERFS_FS is not set | ||
680 | # CONFIG_JFS_FS is not set | ||
681 | # CONFIG_FS_POSIX_ACL is not set | ||
682 | # CONFIG_XFS_FS is not set | ||
683 | # CONFIG_GFS2_FS is not set | ||
684 | # CONFIG_OCFS2_FS is not set | ||
685 | # CONFIG_MINIX_FS is not set | ||
686 | # CONFIG_ROMFS_FS is not set | ||
687 | CONFIG_INOTIFY=y | ||
688 | CONFIG_INOTIFY_USER=y | ||
689 | # CONFIG_QUOTA is not set | ||
690 | CONFIG_DNOTIFY=y | ||
691 | # CONFIG_AUTOFS_FS is not set | ||
692 | # CONFIG_AUTOFS4_FS is not set | ||
693 | # CONFIG_FUSE_FS is not set | ||
694 | |||
695 | # | ||
696 | # CD-ROM/DVD Filesystems | ||
697 | # | ||
698 | # CONFIG_ISO9660_FS is not set | ||
699 | # CONFIG_UDF_FS is not set | ||
700 | |||
701 | # | ||
702 | # DOS/FAT/NT Filesystems | ||
703 | # | ||
704 | # CONFIG_MSDOS_FS is not set | ||
705 | # CONFIG_VFAT_FS is not set | ||
706 | # CONFIG_NTFS_FS is not set | ||
707 | |||
708 | # | ||
709 | # Pseudo filesystems | ||
710 | # | ||
711 | CONFIG_PROC_FS=y | ||
712 | CONFIG_PROC_KCORE=y | ||
713 | CONFIG_PROC_SYSCTL=y | ||
714 | CONFIG_SYSFS=y | ||
715 | CONFIG_TMPFS=y | ||
716 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
717 | # CONFIG_HUGETLBFS is not set | ||
718 | # CONFIG_HUGETLB_PAGE is not set | ||
719 | CONFIG_RAMFS=y | ||
720 | # CONFIG_CONFIGFS_FS is not set | ||
721 | |||
722 | # | ||
723 | # Miscellaneous filesystems | ||
724 | # | ||
725 | # CONFIG_ADFS_FS is not set | ||
726 | # CONFIG_AFFS_FS is not set | ||
727 | # CONFIG_HFS_FS is not set | ||
728 | # CONFIG_HFSPLUS_FS is not set | ||
729 | # CONFIG_BEFS_FS is not set | ||
730 | # CONFIG_BFS_FS is not set | ||
731 | # CONFIG_EFS_FS is not set | ||
732 | # CONFIG_CRAMFS is not set | ||
733 | # CONFIG_VXFS_FS is not set | ||
734 | # CONFIG_HPFS_FS is not set | ||
735 | # CONFIG_QNX4FS_FS is not set | ||
736 | # CONFIG_SYSV_FS is not set | ||
737 | # CONFIG_UFS_FS is not set | ||
738 | |||
739 | # | ||
740 | # Network File Systems | ||
741 | # | ||
742 | CONFIG_NFS_FS=y | ||
743 | CONFIG_NFS_V3=y | ||
744 | # CONFIG_NFS_V3_ACL is not set | ||
745 | # CONFIG_NFS_V4 is not set | ||
746 | # CONFIG_NFS_DIRECTIO is not set | ||
747 | # CONFIG_NFSD is not set | ||
748 | CONFIG_ROOT_NFS=y | ||
749 | CONFIG_LOCKD=y | ||
750 | CONFIG_LOCKD_V4=y | ||
751 | CONFIG_NFS_COMMON=y | ||
752 | CONFIG_SUNRPC=y | ||
753 | # CONFIG_RPCSEC_GSS_KRB5 is not set | ||
754 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
755 | # CONFIG_SMB_FS is not set | ||
756 | # CONFIG_CIFS is not set | ||
757 | # CONFIG_NCP_FS is not set | ||
758 | # CONFIG_CODA_FS is not set | ||
759 | # CONFIG_AFS_FS is not set | ||
760 | # CONFIG_9P_FS is not set | ||
761 | |||
762 | # | ||
763 | # Partition Types | ||
764 | # | ||
765 | # CONFIG_PARTITION_ADVANCED is not set | ||
766 | CONFIG_MSDOS_PARTITION=y | ||
767 | |||
768 | # | ||
769 | # Native Language Support | ||
770 | # | ||
771 | # CONFIG_NLS is not set | ||
772 | |||
773 | # | ||
774 | # Library routines | ||
775 | # | ||
776 | # CONFIG_CRC_CCITT is not set | ||
777 | # CONFIG_CRC16 is not set | ||
778 | # CONFIG_CRC32 is not set | ||
779 | # CONFIG_LIBCRC32C is not set | ||
780 | CONFIG_PLIST=y | ||
781 | |||
782 | # | ||
783 | # Instrumentation Support | ||
784 | # | ||
785 | # CONFIG_PROFILING is not set | ||
786 | # CONFIG_KPROBES is not set | ||
787 | |||
788 | # | ||
789 | # Kernel hacking | ||
790 | # | ||
791 | # CONFIG_PRINTK_TIME is not set | ||
792 | CONFIG_ENABLE_MUST_CHECK=y | ||
793 | # CONFIG_MAGIC_SYSRQ is not set | ||
794 | # CONFIG_UNUSED_SYMBOLS is not set | ||
795 | CONFIG_DEBUG_KERNEL=y | ||
796 | CONFIG_LOG_BUF_SHIFT=17 | ||
797 | CONFIG_DETECT_SOFTLOCKUP=y | ||
798 | # CONFIG_SCHEDSTATS is not set | ||
799 | # CONFIG_DEBUG_SLAB is not set | ||
800 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
801 | # CONFIG_RT_MUTEX_TESTER is not set | ||
802 | CONFIG_DEBUG_SPINLOCK=y | ||
803 | # CONFIG_DEBUG_MUTEXES is not set | ||
804 | # CONFIG_DEBUG_RWSEMS is not set | ||
805 | CONFIG_DEBUG_SPINLOCK_SLEEP=y | ||
806 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
807 | # CONFIG_DEBUG_KOBJECT is not set | ||
808 | CONFIG_DEBUG_INFO=y | ||
809 | # CONFIG_DEBUG_FS is not set | ||
810 | # CONFIG_DEBUG_VM is not set | ||
811 | CONFIG_DEBUG_LIST=y | ||
812 | CONFIG_FORCED_INLINING=y | ||
813 | # CONFIG_HEADERS_CHECK is not set | ||
814 | # CONFIG_RCU_TORTURE_TEST is not set | ||
815 | # CONFIG_DEBUG_STACKOVERFLOW is not set | ||
816 | # CONFIG_DEBUG_STACK_USAGE is not set | ||
817 | # CONFIG_DEBUGGER is not set | ||
818 | CONFIG_IRQSTACKS=y | ||
819 | # CONFIG_BOOTX_TEXT is not set | ||
820 | CONFIG_PPC_EARLY_DEBUG=y | ||
821 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
822 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
823 | # CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set | ||
824 | # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set | ||
825 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
826 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
827 | |||
828 | # | ||
829 | # Security options | ||
830 | # | ||
831 | # CONFIG_KEYS is not set | ||
832 | # CONFIG_SECURITY is not set | ||
833 | |||
834 | # | ||
835 | # Cryptographic options | ||
836 | # | ||
837 | # CONFIG_CRYPTO is not set | ||
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 7af23c43fd4..4fe53d08ab8 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -17,11 +17,11 @@ obj-y += vdso32/ | |||
17 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 17 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ |
18 | signal_64.o ptrace32.o \ | 18 | signal_64.o ptrace32.o \ |
19 | paca.o cpu_setup_ppc970.o \ | 19 | paca.o cpu_setup_ppc970.o \ |
20 | firmware.o sysfs.o | 20 | firmware.o sysfs.o nvram_64.o |
21 | obj-$(CONFIG_PPC64) += vdso64/ | 21 | obj-$(CONFIG_PPC64) += vdso64/ |
22 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o | 22 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o |
23 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o | 23 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o |
24 | obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o | 24 | obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o |
25 | procfs-$(CONFIG_PPC64) := proc_ppc64.o | 25 | procfs-$(CONFIG_PPC64) := proc_ppc64.o |
26 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | 26 | obj-$(CONFIG_PROC_FS) += $(procfs-y) |
27 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o | 27 | rtaspci-$(CONFIG_PPC64) := rtas_pci.o |
@@ -32,7 +32,6 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o | |||
32 | obj-$(CONFIG_IBMVIO) += vio.o | 32 | obj-$(CONFIG_IBMVIO) += vio.o |
33 | obj-$(CONFIG_IBMEBUS) += ibmebus.o | 33 | obj-$(CONFIG_IBMEBUS) += ibmebus.o |
34 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o | 34 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o |
35 | obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o | ||
36 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 35 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
37 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o | 36 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o |
38 | obj-$(CONFIG_TAU) += tau_6xx.o | 37 | obj-$(CONFIG_TAU) += tau_6xx.o |
@@ -59,11 +58,11 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o | |||
59 | obj-$(CONFIG_SMP) += smp.o | 58 | obj-$(CONFIG_SMP) += smp.o |
60 | obj-$(CONFIG_KPROBES) += kprobes.o | 59 | obj-$(CONFIG_KPROBES) += kprobes.o |
61 | obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o | 60 | obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o |
61 | |||
62 | module-$(CONFIG_PPC64) += module_64.o | 62 | module-$(CONFIG_PPC64) += module_64.o |
63 | obj-$(CONFIG_MODULES) += $(module-y) | 63 | obj-$(CONFIG_MODULES) += $(module-y) |
64 | 64 | ||
65 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ | 65 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o |
66 | pci_direct_iommu.o iomap.o | ||
67 | pci32-$(CONFIG_PPC32) := pci_32.o | 66 | pci32-$(CONFIG_PPC32) := pci_32.o |
68 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | 67 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) |
69 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o | 68 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o |
@@ -72,8 +71,12 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) | |||
72 | obj-$(CONFIG_AUDIT) += audit.o | 71 | obj-$(CONFIG_AUDIT) += audit.o |
73 | obj64-$(CONFIG_AUDIT) += compat_audit.o | 72 | obj64-$(CONFIG_AUDIT) += compat_audit.o |
74 | 73 | ||
74 | ifneq ($(CONFIG_PPC_INDIRECT_IO),y) | ||
75 | obj-y += iomap.o | ||
76 | endif | ||
77 | |||
75 | ifeq ($(CONFIG_PPC_ISERIES),y) | 78 | ifeq ($(CONFIG_PPC_ISERIES),y) |
76 | $(obj)/head_64.o: $(obj)/lparmap.s | 79 | extra-y += lparmap.s |
77 | AFLAGS_head_64.o += -I$(obj) | 80 | AFLAGS_head_64.o += -I$(obj) |
78 | endif | 81 | endif |
79 | 82 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index d06f378597b..e96521530d2 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -118,7 +118,8 @@ int main(void) | |||
118 | DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); | 118 | DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); |
119 | DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); | 119 | DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); |
120 | DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); | 120 | DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); |
121 | DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); | 121 | DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled)); |
122 | DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled)); | ||
122 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | 123 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); |
123 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | 124 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); |
124 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | 125 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); |
diff --git a/arch/powerpc/kernel/cpu_setup_ppc970.S b/arch/powerpc/kernel/cpu_setup_ppc970.S index 652594891d5..bf118c38575 100644 --- a/arch/powerpc/kernel/cpu_setup_ppc970.S +++ b/arch/powerpc/kernel/cpu_setup_ppc970.S | |||
@@ -83,6 +83,22 @@ _GLOBAL(__setup_cpu_ppc970) | |||
83 | rldimi r0,r11,52,8 /* set NAP and DPM */ | 83 | rldimi r0,r11,52,8 /* set NAP and DPM */ |
84 | li r11,0 | 84 | li r11,0 |
85 | rldimi r0,r11,32,31 /* clear EN_ATTN */ | 85 | rldimi r0,r11,32,31 /* clear EN_ATTN */ |
86 | b load_hids /* Jump to shared code */ | ||
87 | |||
88 | |||
89 | _GLOBAL(__setup_cpu_ppc970MP) | ||
90 | /* Do nothing if not running in HV mode */ | ||
91 | mfmsr r0 | ||
92 | rldicl. r0,r0,4,63 | ||
93 | beqlr | ||
94 | |||
95 | mfspr r0,SPRN_HID0 | ||
96 | li r11,0x15 /* clear DOZE and SLEEP */ | ||
97 | rldimi r0,r11,52,6 /* set DEEPNAP, NAP and DPM */ | ||
98 | li r11,0 | ||
99 | rldimi r0,r11,32,31 /* clear EN_ATTN */ | ||
100 | |||
101 | load_hids: | ||
86 | mtspr SPRN_HID0,r0 | 102 | mtspr SPRN_HID0,r0 |
87 | mfspr r0,SPRN_HID0 | 103 | mfspr r0,SPRN_HID0 |
88 | mfspr r0,SPRN_HID0 | 104 | mfspr r0,SPRN_HID0 |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index bfd499ee375..9d1614c3ce6 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -42,6 +42,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec); | |||
42 | #endif /* CONFIG_PPC32 */ | 42 | #endif /* CONFIG_PPC32 */ |
43 | #ifdef CONFIG_PPC64 | 43 | #ifdef CONFIG_PPC64 |
44 | extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); | 44 | extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); |
45 | extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec); | ||
45 | extern void __restore_cpu_ppc970(void); | 46 | extern void __restore_cpu_ppc970(void); |
46 | #endif /* CONFIG_PPC64 */ | 47 | #endif /* CONFIG_PPC64 */ |
47 | 48 | ||
@@ -222,9 +223,9 @@ static struct cpu_spec cpu_specs[] = { | |||
222 | .icache_bsize = 128, | 223 | .icache_bsize = 128, |
223 | .dcache_bsize = 128, | 224 | .dcache_bsize = 128, |
224 | .num_pmcs = 8, | 225 | .num_pmcs = 8, |
225 | .cpu_setup = __setup_cpu_ppc970, | 226 | .cpu_setup = __setup_cpu_ppc970MP, |
226 | .cpu_restore = __restore_cpu_ppc970, | 227 | .cpu_restore = __restore_cpu_ppc970, |
227 | .oprofile_cpu_type = "ppc64/970", | 228 | .oprofile_cpu_type = "ppc64/970MP", |
228 | .oprofile_type = PPC_OPROFILE_POWER4, | 229 | .oprofile_type = PPC_OPROFILE_POWER4, |
229 | .platform = "ppc970", | 230 | .platform = "ppc970", |
230 | }, | 231 | }, |
@@ -276,10 +277,45 @@ static struct cpu_spec cpu_specs[] = { | |||
276 | .oprofile_mmcra_sipr = MMCRA_SIPR, | 277 | .oprofile_mmcra_sipr = MMCRA_SIPR, |
277 | .platform = "power5+", | 278 | .platform = "power5+", |
278 | }, | 279 | }, |
280 | { /* POWER6 in P5+ mode; 2.04-compliant processor */ | ||
281 | .pvr_mask = 0xffffffff, | ||
282 | .pvr_value = 0x0f000001, | ||
283 | .cpu_name = "POWER5+", | ||
284 | .cpu_features = CPU_FTRS_POWER5, | ||
285 | .cpu_user_features = COMMON_USER_POWER5_PLUS, | ||
286 | .icache_bsize = 128, | ||
287 | .dcache_bsize = 128, | ||
288 | .num_pmcs = 6, | ||
289 | .oprofile_cpu_type = "ppc64/power6", | ||
290 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
291 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
292 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
293 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
294 | POWER6_MMCRA_OTHER, | ||
295 | .platform = "power5+", | ||
296 | }, | ||
279 | { /* Power6 */ | 297 | { /* Power6 */ |
280 | .pvr_mask = 0xffff0000, | 298 | .pvr_mask = 0xffff0000, |
281 | .pvr_value = 0x003e0000, | 299 | .pvr_value = 0x003e0000, |
282 | .cpu_name = "POWER6", | 300 | .cpu_name = "POWER6 (raw)", |
301 | .cpu_features = CPU_FTRS_POWER6, | ||
302 | .cpu_user_features = COMMON_USER_POWER6 | | ||
303 | PPC_FEATURE_POWER6_EXT, | ||
304 | .icache_bsize = 128, | ||
305 | .dcache_bsize = 128, | ||
306 | .num_pmcs = 6, | ||
307 | .oprofile_cpu_type = "ppc64/power6", | ||
308 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
309 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
310 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
311 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
312 | POWER6_MMCRA_OTHER, | ||
313 | .platform = "power6x", | ||
314 | }, | ||
315 | { /* 2.05-compliant processor, i.e. Power6 "architected" mode */ | ||
316 | .pvr_mask = 0xffffffff, | ||
317 | .pvr_value = 0x0f000002, | ||
318 | .cpu_name = "POWER6 (architected)", | ||
283 | .cpu_features = CPU_FTRS_POWER6, | 319 | .cpu_features = CPU_FTRS_POWER6, |
284 | .cpu_user_features = COMMON_USER_POWER6, | 320 | .cpu_user_features = COMMON_USER_POWER6, |
285 | .icache_bsize = 128, | 321 | .icache_bsize = 128, |
@@ -303,6 +339,9 @@ static struct cpu_spec cpu_specs[] = { | |||
303 | PPC_FEATURE_SMT, | 339 | PPC_FEATURE_SMT, |
304 | .icache_bsize = 128, | 340 | .icache_bsize = 128, |
305 | .dcache_bsize = 128, | 341 | .dcache_bsize = 128, |
342 | .num_pmcs = 4, | ||
343 | .oprofile_cpu_type = "ppc64/cell-be", | ||
344 | .oprofile_type = PPC_OPROFILE_CELL, | ||
306 | .platform = "ppc-cell-be", | 345 | .platform = "ppc-cell-be", |
307 | }, | 346 | }, |
308 | { /* PA Semi PA6T */ | 347 | { /* PA Semi PA6T */ |
@@ -801,6 +840,17 @@ static struct cpu_spec cpu_specs[] = { | |||
801 | .cpu_setup = __setup_cpu_603, | 840 | .cpu_setup = __setup_cpu_603, |
802 | .platform = "ppc603", | 841 | .platform = "ppc603", |
803 | }, | 842 | }, |
843 | { /* e300c3 on 83xx */ | ||
844 | .pvr_mask = 0x7fff0000, | ||
845 | .pvr_value = 0x00850000, | ||
846 | .cpu_name = "e300c3", | ||
847 | .cpu_features = CPU_FTRS_E300, | ||
848 | .cpu_user_features = COMMON_USER, | ||
849 | .icache_bsize = 32, | ||
850 | .dcache_bsize = 32, | ||
851 | .cpu_setup = __setup_cpu_603, | ||
852 | .platform = "ppc603", | ||
853 | }, | ||
804 | { /* default match, we assume split I/D cache & TB (non-601)... */ | 854 | { /* default match, we assume split I/D cache & TB (non-601)... */ |
805 | .pvr_mask = 0x00000000, | 855 | .pvr_mask = 0x00000000, |
806 | .pvr_value = 0x00000000, | 856 | .pvr_value = 0x00000000, |
@@ -1169,19 +1219,15 @@ static struct cpu_spec cpu_specs[] = { | |||
1169 | #endif /* CONFIG_PPC32 */ | 1219 | #endif /* CONFIG_PPC32 */ |
1170 | }; | 1220 | }; |
1171 | 1221 | ||
1172 | struct cpu_spec *identify_cpu(unsigned long offset) | 1222 | struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr) |
1173 | { | 1223 | { |
1174 | struct cpu_spec *s = cpu_specs; | 1224 | struct cpu_spec *s = cpu_specs; |
1175 | struct cpu_spec **cur = &cur_cpu_spec; | 1225 | struct cpu_spec **cur = &cur_cpu_spec; |
1176 | unsigned int pvr = mfspr(SPRN_PVR); | ||
1177 | int i; | 1226 | int i; |
1178 | 1227 | ||
1179 | s = PTRRELOC(s); | 1228 | s = PTRRELOC(s); |
1180 | cur = PTRRELOC(cur); | 1229 | cur = PTRRELOC(cur); |
1181 | 1230 | ||
1182 | if (*cur != NULL) | ||
1183 | return PTRRELOC(*cur); | ||
1184 | |||
1185 | for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) | 1231 | for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) |
1186 | if ((pvr & s->pvr_mask) == s->pvr_value) { | 1232 | if ((pvr & s->pvr_mask) == s->pvr_value) { |
1187 | *cur = cpu_specs + i; | 1233 | *cur = cpu_specs + i; |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 1af41f7616d..89b03c8da9d 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -111,7 +111,7 @@ void crash_ipi_callback(struct pt_regs *regs) | |||
111 | if (!cpu_online(cpu)) | 111 | if (!cpu_online(cpu)) |
112 | return; | 112 | return; |
113 | 113 | ||
114 | local_irq_disable(); | 114 | hard_irq_disable(); |
115 | if (!cpu_isset(cpu, cpus_in_crash)) | 115 | if (!cpu_isset(cpu, cpus_in_crash)) |
116 | crash_save_this_cpu(regs, cpu); | 116 | crash_save_this_cpu(regs, cpu); |
117 | cpu_set(cpu, cpus_in_crash); | 117 | cpu_set(cpu, cpus_in_crash); |
@@ -289,7 +289,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
289 | * an SMP system. | 289 | * an SMP system. |
290 | * The kernel is broken so disable interrupts. | 290 | * The kernel is broken so disable interrupts. |
291 | */ | 291 | */ |
292 | local_irq_disable(); | 292 | hard_irq_disable(); |
293 | 293 | ||
294 | for_each_irq(irq) { | 294 | for_each_irq(irq) { |
295 | struct irq_desc *desc = irq_desc + irq; | 295 | struct irq_desc *desc = irq_desc + irq; |
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c index 6c168f6ea14..7b0e754383c 100644 --- a/arch/powerpc/kernel/dma_64.c +++ b/arch/powerpc/kernel/dma_64.c | |||
@@ -1,151 +1,194 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 IBM Corporation | 2 | * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation |
3 | * | 3 | * |
4 | * Implements the generic device dma API for ppc64. Handles | 4 | * Provide default implementations of the DMA mapping callbacks for |
5 | * the pci and vio busses | 5 | * directly mapped busses and busses using the iommu infrastructure |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
10 | /* Include the busses we support */ | ||
11 | #include <linux/pci.h> | ||
12 | #include <asm/vio.h> | ||
13 | #include <asm/ibmebus.h> | ||
14 | #include <asm/scatterlist.h> | ||
15 | #include <asm/bug.h> | 10 | #include <asm/bug.h> |
11 | #include <asm/iommu.h> | ||
12 | #include <asm/abs_addr.h> | ||
16 | 13 | ||
17 | static struct dma_mapping_ops *get_dma_ops(struct device *dev) | 14 | /* |
18 | { | 15 | * Generic iommu implementation |
19 | #ifdef CONFIG_PCI | 16 | */ |
20 | if (dev->bus == &pci_bus_type) | ||
21 | return &pci_dma_ops; | ||
22 | #endif | ||
23 | #ifdef CONFIG_IBMVIO | ||
24 | if (dev->bus == &vio_bus_type) | ||
25 | return &vio_dma_ops; | ||
26 | #endif | ||
27 | #ifdef CONFIG_IBMEBUS | ||
28 | if (dev->bus == &ibmebus_bus_type) | ||
29 | return &ibmebus_dma_ops; | ||
30 | #endif | ||
31 | return NULL; | ||
32 | } | ||
33 | 17 | ||
34 | int dma_supported(struct device *dev, u64 mask) | 18 | static inline unsigned long device_to_mask(struct device *dev) |
35 | { | 19 | { |
36 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 20 | if (dev->dma_mask && *dev->dma_mask) |
21 | return *dev->dma_mask; | ||
22 | /* Assume devices without mask can take 32 bit addresses */ | ||
23 | return 0xfffffffful; | ||
24 | } | ||
37 | 25 | ||
38 | BUG_ON(!dma_ops); | ||
39 | 26 | ||
40 | return dma_ops->dma_supported(dev, mask); | 27 | /* Allocates a contiguous real buffer and creates mappings over it. |
28 | * Returns the virtual address of the buffer and sets dma_handle | ||
29 | * to the dma address (mapping) of the first page. | ||
30 | */ | ||
31 | static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, | ||
32 | dma_addr_t *dma_handle, gfp_t flag) | ||
33 | { | ||
34 | return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle, | ||
35 | device_to_mask(dev), flag, | ||
36 | dev->archdata.numa_node); | ||
41 | } | 37 | } |
42 | EXPORT_SYMBOL(dma_supported); | ||
43 | 38 | ||
44 | int dma_set_mask(struct device *dev, u64 dma_mask) | 39 | static void dma_iommu_free_coherent(struct device *dev, size_t size, |
40 | void *vaddr, dma_addr_t dma_handle) | ||
45 | { | 41 | { |
46 | #ifdef CONFIG_PCI | 42 | iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle); |
47 | if (dev->bus == &pci_bus_type) | ||
48 | return pci_set_dma_mask(to_pci_dev(dev), dma_mask); | ||
49 | #endif | ||
50 | #ifdef CONFIG_IBMVIO | ||
51 | if (dev->bus == &vio_bus_type) | ||
52 | return -EIO; | ||
53 | #endif /* CONFIG_IBMVIO */ | ||
54 | #ifdef CONFIG_IBMEBUS | ||
55 | if (dev->bus == &ibmebus_bus_type) | ||
56 | return -EIO; | ||
57 | #endif | ||
58 | BUG(); | ||
59 | return 0; | ||
60 | } | 43 | } |
61 | EXPORT_SYMBOL(dma_set_mask); | ||
62 | 44 | ||
63 | void *dma_alloc_coherent(struct device *dev, size_t size, | 45 | /* Creates TCEs for a user provided buffer. The user buffer must be |
64 | dma_addr_t *dma_handle, gfp_t flag) | 46 | * contiguous real kernel storage (not vmalloc). The address of the buffer |
47 | * passed here is the kernel (virtual) address of the buffer. The buffer | ||
48 | * need not be page aligned, the dma_addr_t returned will point to the same | ||
49 | * byte within the page as vaddr. | ||
50 | */ | ||
51 | static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr, | ||
52 | size_t size, | ||
53 | enum dma_data_direction direction) | ||
65 | { | 54 | { |
66 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 55 | return iommu_map_single(dev->archdata.dma_data, vaddr, size, |
67 | 56 | device_to_mask(dev), direction); | |
68 | BUG_ON(!dma_ops); | ||
69 | |||
70 | return dma_ops->alloc_coherent(dev, size, dma_handle, flag); | ||
71 | } | 57 | } |
72 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
73 | 58 | ||
74 | void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | 59 | |
75 | dma_addr_t dma_handle) | 60 | static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle, |
61 | size_t size, | ||
62 | enum dma_data_direction direction) | ||
76 | { | 63 | { |
77 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 64 | iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction); |
65 | } | ||
78 | 66 | ||
79 | BUG_ON(!dma_ops); | ||
80 | 67 | ||
81 | dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); | 68 | static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist, |
69 | int nelems, enum dma_data_direction direction) | ||
70 | { | ||
71 | return iommu_map_sg(dev->archdata.dma_data, sglist, nelems, | ||
72 | device_to_mask(dev), direction); | ||
82 | } | 73 | } |
83 | EXPORT_SYMBOL(dma_free_coherent); | ||
84 | 74 | ||
85 | dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, | 75 | static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist, |
86 | enum dma_data_direction direction) | 76 | int nelems, enum dma_data_direction direction) |
87 | { | 77 | { |
88 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 78 | iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction); |
89 | |||
90 | BUG_ON(!dma_ops); | ||
91 | |||
92 | return dma_ops->map_single(dev, cpu_addr, size, direction); | ||
93 | } | 79 | } |
94 | EXPORT_SYMBOL(dma_map_single); | ||
95 | 80 | ||
96 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 81 | /* We support DMA to/from any memory page via the iommu */ |
97 | enum dma_data_direction direction) | 82 | static int dma_iommu_dma_supported(struct device *dev, u64 mask) |
98 | { | 83 | { |
99 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 84 | struct iommu_table *tbl = dev->archdata.dma_data; |
100 | 85 | ||
101 | BUG_ON(!dma_ops); | 86 | if (!tbl || tbl->it_offset > mask) { |
102 | 87 | printk(KERN_INFO | |
103 | dma_ops->unmap_single(dev, dma_addr, size, direction); | 88 | "Warning: IOMMU offset too big for device mask\n"); |
89 | if (tbl) | ||
90 | printk(KERN_INFO | ||
91 | "mask: 0x%08lx, table offset: 0x%08lx\n", | ||
92 | mask, tbl->it_offset); | ||
93 | else | ||
94 | printk(KERN_INFO "mask: 0x%08lx, table unavailable\n", | ||
95 | mask); | ||
96 | return 0; | ||
97 | } else | ||
98 | return 1; | ||
104 | } | 99 | } |
105 | EXPORT_SYMBOL(dma_unmap_single); | ||
106 | 100 | ||
107 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | 101 | struct dma_mapping_ops dma_iommu_ops = { |
108 | unsigned long offset, size_t size, | 102 | .alloc_coherent = dma_iommu_alloc_coherent, |
109 | enum dma_data_direction direction) | 103 | .free_coherent = dma_iommu_free_coherent, |
110 | { | 104 | .map_single = dma_iommu_map_single, |
111 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 105 | .unmap_single = dma_iommu_unmap_single, |
106 | .map_sg = dma_iommu_map_sg, | ||
107 | .unmap_sg = dma_iommu_unmap_sg, | ||
108 | .dma_supported = dma_iommu_dma_supported, | ||
109 | }; | ||
110 | EXPORT_SYMBOL(dma_iommu_ops); | ||
112 | 111 | ||
113 | BUG_ON(!dma_ops); | 112 | /* |
113 | * Generic direct DMA implementation | ||
114 | * | ||
115 | * This implementation supports a global offset that can be applied if | ||
116 | * the address at which memory is visible to devices is not 0. | ||
117 | */ | ||
118 | unsigned long dma_direct_offset; | ||
114 | 119 | ||
115 | return dma_ops->map_single(dev, page_address(page) + offset, size, | 120 | static void *dma_direct_alloc_coherent(struct device *dev, size_t size, |
116 | direction); | 121 | dma_addr_t *dma_handle, gfp_t flag) |
122 | { | ||
123 | struct page *page; | ||
124 | void *ret; | ||
125 | int node = dev->archdata.numa_node; | ||
126 | |||
127 | /* TODO: Maybe use the numa node here too ? */ | ||
128 | page = alloc_pages_node(node, flag, get_order(size)); | ||
129 | if (page == NULL) | ||
130 | return NULL; | ||
131 | ret = page_address(page); | ||
132 | memset(ret, 0, size); | ||
133 | *dma_handle = virt_to_abs(ret) | dma_direct_offset; | ||
134 | |||
135 | return ret; | ||
117 | } | 136 | } |
118 | EXPORT_SYMBOL(dma_map_page); | ||
119 | 137 | ||
120 | void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | 138 | static void dma_direct_free_coherent(struct device *dev, size_t size, |
121 | enum dma_data_direction direction) | 139 | void *vaddr, dma_addr_t dma_handle) |
122 | { | 140 | { |
123 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 141 | free_pages((unsigned long)vaddr, get_order(size)); |
142 | } | ||
124 | 143 | ||
125 | BUG_ON(!dma_ops); | 144 | static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr, |
145 | size_t size, | ||
146 | enum dma_data_direction direction) | ||
147 | { | ||
148 | return virt_to_abs(ptr) | dma_direct_offset; | ||
149 | } | ||
126 | 150 | ||
127 | dma_ops->unmap_single(dev, dma_address, size, direction); | 151 | static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, |
152 | size_t size, | ||
153 | enum dma_data_direction direction) | ||
154 | { | ||
128 | } | 155 | } |
129 | EXPORT_SYMBOL(dma_unmap_page); | ||
130 | 156 | ||
131 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 157 | static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg, |
132 | enum dma_data_direction direction) | 158 | int nents, enum dma_data_direction direction) |
133 | { | 159 | { |
134 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 160 | int i; |
135 | 161 | ||
136 | BUG_ON(!dma_ops); | 162 | for (i = 0; i < nents; i++, sg++) { |
163 | sg->dma_address = (page_to_phys(sg->page) + sg->offset) | | ||
164 | dma_direct_offset; | ||
165 | sg->dma_length = sg->length; | ||
166 | } | ||
137 | 167 | ||
138 | return dma_ops->map_sg(dev, sg, nents, direction); | 168 | return nents; |
139 | } | 169 | } |
140 | EXPORT_SYMBOL(dma_map_sg); | ||
141 | 170 | ||
142 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | 171 | static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg, |
143 | enum dma_data_direction direction) | 172 | int nents, enum dma_data_direction direction) |
144 | { | 173 | { |
145 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 174 | } |
146 | |||
147 | BUG_ON(!dma_ops); | ||
148 | 175 | ||
149 | dma_ops->unmap_sg(dev, sg, nhwentries, direction); | 176 | static int dma_direct_dma_supported(struct device *dev, u64 mask) |
177 | { | ||
178 | /* Could be improved to check for memory though it better be | ||
179 | * done via some global so platforms can set the limit in case | ||
180 | * they have limited DMA windows | ||
181 | */ | ||
182 | return mask >= DMA_32BIT_MASK; | ||
150 | } | 183 | } |
151 | EXPORT_SYMBOL(dma_unmap_sg); | 184 | |
185 | struct dma_mapping_ops dma_direct_ops = { | ||
186 | .alloc_coherent = dma_direct_alloc_coherent, | ||
187 | .free_coherent = dma_direct_free_coherent, | ||
188 | .map_single = dma_direct_map_single, | ||
189 | .unmap_single = dma_direct_unmap_single, | ||
190 | .map_sg = dma_direct_map_sg, | ||
191 | .unmap_sg = dma_direct_unmap_sg, | ||
192 | .dma_supported = dma_direct_dma_supported, | ||
193 | }; | ||
194 | EXPORT_SYMBOL(dma_direct_ops); | ||
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 748e74fcf54..1a3d4de197d 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -87,15 +87,19 @@ system_call_common: | |||
87 | addi r9,r1,STACK_FRAME_OVERHEAD | 87 | addi r9,r1,STACK_FRAME_OVERHEAD |
88 | ld r11,exception_marker@toc(r2) | 88 | ld r11,exception_marker@toc(r2) |
89 | std r11,-16(r9) /* "regshere" marker */ | 89 | std r11,-16(r9) /* "regshere" marker */ |
90 | li r10,1 | ||
91 | stb r10,PACASOFTIRQEN(r13) | ||
92 | stb r10,PACAHARDIRQEN(r13) | ||
93 | std r10,SOFTE(r1) | ||
90 | #ifdef CONFIG_PPC_ISERIES | 94 | #ifdef CONFIG_PPC_ISERIES |
91 | BEGIN_FW_FTR_SECTION | 95 | BEGIN_FW_FTR_SECTION |
92 | /* Hack for handling interrupts when soft-enabling on iSeries */ | 96 | /* Hack for handling interrupts when soft-enabling on iSeries */ |
93 | cmpdi cr1,r0,0x5555 /* syscall 0x5555 */ | 97 | cmpdi cr1,r0,0x5555 /* syscall 0x5555 */ |
94 | andi. r10,r12,MSR_PR /* from kernel */ | 98 | andi. r10,r12,MSR_PR /* from kernel */ |
95 | crand 4*cr0+eq,4*cr1+eq,4*cr0+eq | 99 | crand 4*cr0+eq,4*cr1+eq,4*cr0+eq |
96 | beq hardware_interrupt_entry | 100 | bne 2f |
97 | lbz r10,PACAPROCENABLED(r13) | 101 | b hardware_interrupt_entry |
98 | std r10,SOFTE(r1) | 102 | 2: |
99 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 103 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
100 | #endif | 104 | #endif |
101 | mfmsr r11 | 105 | mfmsr r11 |
@@ -460,9 +464,9 @@ _GLOBAL(ret_from_except_lite) | |||
460 | #endif | 464 | #endif |
461 | 465 | ||
462 | restore: | 466 | restore: |
467 | ld r5,SOFTE(r1) | ||
463 | #ifdef CONFIG_PPC_ISERIES | 468 | #ifdef CONFIG_PPC_ISERIES |
464 | BEGIN_FW_FTR_SECTION | 469 | BEGIN_FW_FTR_SECTION |
465 | ld r5,SOFTE(r1) | ||
466 | cmpdi 0,r5,0 | 470 | cmpdi 0,r5,0 |
467 | beq 4f | 471 | beq 4f |
468 | /* Check for pending interrupts (iSeries) */ | 472 | /* Check for pending interrupts (iSeries) */ |
@@ -472,21 +476,25 @@ BEGIN_FW_FTR_SECTION | |||
472 | beq+ 4f /* skip do_IRQ if no interrupts */ | 476 | beq+ 4f /* skip do_IRQ if no interrupts */ |
473 | 477 | ||
474 | li r3,0 | 478 | li r3,0 |
475 | stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ | 479 | stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */ |
476 | ori r10,r10,MSR_EE | 480 | ori r10,r10,MSR_EE |
477 | mtmsrd r10 /* hard-enable again */ | 481 | mtmsrd r10 /* hard-enable again */ |
478 | addi r3,r1,STACK_FRAME_OVERHEAD | 482 | addi r3,r1,STACK_FRAME_OVERHEAD |
479 | bl .do_IRQ | 483 | bl .do_IRQ |
480 | b .ret_from_except_lite /* loop back and handle more */ | 484 | b .ret_from_except_lite /* loop back and handle more */ |
481 | 485 | 4: | |
482 | 4: stb r5,PACAPROCENABLED(r13) | ||
483 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 486 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
484 | #endif | 487 | #endif |
488 | stb r5,PACASOFTIRQEN(r13) | ||
485 | 489 | ||
486 | ld r3,_MSR(r1) | 490 | ld r3,_MSR(r1) |
487 | andi. r0,r3,MSR_RI | 491 | andi. r0,r3,MSR_RI |
488 | beq- unrecov_restore | 492 | beq- unrecov_restore |
489 | 493 | ||
494 | /* extract EE bit and use it to restore paca->hard_enabled */ | ||
495 | rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ | ||
496 | stb r4,PACAHARDIRQEN(r13) | ||
497 | |||
490 | andi. r0,r3,MSR_PR | 498 | andi. r0,r3,MSR_PR |
491 | 499 | ||
492 | /* | 500 | /* |
@@ -538,25 +546,15 @@ do_work: | |||
538 | /* Check that preempt_count() == 0 and interrupts are enabled */ | 546 | /* Check that preempt_count() == 0 and interrupts are enabled */ |
539 | lwz r8,TI_PREEMPT(r9) | 547 | lwz r8,TI_PREEMPT(r9) |
540 | cmpwi cr1,r8,0 | 548 | cmpwi cr1,r8,0 |
541 | #ifdef CONFIG_PPC_ISERIES | ||
542 | BEGIN_FW_FTR_SECTION | ||
543 | ld r0,SOFTE(r1) | 549 | ld r0,SOFTE(r1) |
544 | cmpdi r0,0 | 550 | cmpdi r0,0 |
545 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | ||
546 | #endif | ||
547 | BEGIN_FW_FTR_SECTION | ||
548 | andi. r0,r3,MSR_EE | ||
549 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
550 | crandc eq,cr1*4+eq,eq | 551 | crandc eq,cr1*4+eq,eq |
551 | bne restore | 552 | bne restore |
552 | /* here we are preempting the current task */ | 553 | /* here we are preempting the current task */ |
553 | 1: | 554 | 1: |
554 | #ifdef CONFIG_PPC_ISERIES | ||
555 | BEGIN_FW_FTR_SECTION | ||
556 | li r0,1 | 555 | li r0,1 |
557 | stb r0,PACAPROCENABLED(r13) | 556 | stb r0,PACASOFTIRQEN(r13) |
558 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 557 | stb r0,PACAHARDIRQEN(r13) |
559 | #endif | ||
560 | ori r10,r10,MSR_EE | 558 | ori r10,r10,MSR_EE |
561 | mtmsrd r10,1 /* reenable interrupts */ | 559 | mtmsrd r10,1 /* reenable interrupts */ |
562 | bl .preempt_schedule | 560 | bl .preempt_schedule |
@@ -639,8 +637,7 @@ _GLOBAL(enter_rtas) | |||
639 | /* There is no way it is acceptable to get here with interrupts enabled, | 637 | /* There is no way it is acceptable to get here with interrupts enabled, |
640 | * check it with the asm equivalent of WARN_ON | 638 | * check it with the asm equivalent of WARN_ON |
641 | */ | 639 | */ |
642 | mfmsr r6 | 640 | lbz r0,PACASOFTIRQEN(r13) |
643 | andi. r0,r6,MSR_EE | ||
644 | 1: tdnei r0,0 | 641 | 1: tdnei r0,0 |
645 | .section __bug_table,"a" | 642 | .section __bug_table,"a" |
646 | .llong 1b,__LINE__ + 0x1000000, 1f, 2f | 643 | .llong 1b,__LINE__ + 0x1000000, 1f, 2f |
@@ -649,7 +646,13 @@ _GLOBAL(enter_rtas) | |||
649 | 1: .asciz __FILE__ | 646 | 1: .asciz __FILE__ |
650 | 2: .asciz "enter_rtas" | 647 | 2: .asciz "enter_rtas" |
651 | .previous | 648 | .previous |
652 | 649 | ||
650 | /* Hard-disable interrupts */ | ||
651 | mfmsr r6 | ||
652 | rldicl r7,r6,48,1 | ||
653 | rotldi r7,r7,16 | ||
654 | mtmsrd r7,1 | ||
655 | |||
653 | /* Unfortunately, the stack pointer and the MSR are also clobbered, | 656 | /* Unfortunately, the stack pointer and the MSR are also clobbered, |
654 | * so they are saved in the PACA which allows us to restore | 657 | * so they are saved in the PACA which allows us to restore |
655 | * our original state after RTAS returns. | 658 | * our original state after RTAS returns. |
@@ -735,8 +738,6 @@ _STATIC(rtas_restore_regs) | |||
735 | 738 | ||
736 | #endif /* CONFIG_PPC_RTAS */ | 739 | #endif /* CONFIG_PPC_RTAS */ |
737 | 740 | ||
738 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
739 | |||
740 | _GLOBAL(enter_prom) | 741 | _GLOBAL(enter_prom) |
741 | mflr r0 | 742 | mflr r0 |
742 | std r0,16(r1) | 743 | std r0,16(r1) |
@@ -821,5 +822,3 @@ _GLOBAL(enter_prom) | |||
821 | ld r0,16(r1) | 822 | ld r0,16(r1) |
822 | mtlr r0 | 823 | mtlr r0 |
823 | blr | 824 | blr |
824 | |||
825 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index e720729f3e5..71b1fe58e9e 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -35,9 +35,7 @@ | |||
35 | #include <asm/thread_info.h> | 35 | #include <asm/thread_info.h> |
36 | #include <asm/firmware.h> | 36 | #include <asm/firmware.h> |
37 | 37 | ||
38 | #ifdef CONFIG_PPC_ISERIES | ||
39 | #define DO_SOFT_DISABLE | 38 | #define DO_SOFT_DISABLE |
40 | #endif | ||
41 | 39 | ||
42 | /* | 40 | /* |
43 | * We layout physical memory as follows: | 41 | * We layout physical memory as follows: |
@@ -74,13 +72,11 @@ | |||
74 | .text | 72 | .text |
75 | .globl _stext | 73 | .globl _stext |
76 | _stext: | 74 | _stext: |
77 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
78 | _GLOBAL(__start) | 75 | _GLOBAL(__start) |
79 | /* NOP this out unconditionally */ | 76 | /* NOP this out unconditionally */ |
80 | BEGIN_FTR_SECTION | 77 | BEGIN_FTR_SECTION |
81 | b .__start_initialization_multiplatform | 78 | b .__start_initialization_multiplatform |
82 | END_FTR_SECTION(0, 1) | 79 | END_FTR_SECTION(0, 1) |
83 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
84 | 80 | ||
85 | /* Catch branch to 0 in real mode */ | 81 | /* Catch branch to 0 in real mode */ |
86 | trap | 82 | trap |
@@ -308,7 +304,9 @@ exception_marker: | |||
308 | std r9,_LINK(r1); \ | 304 | std r9,_LINK(r1); \ |
309 | mfctr r10; /* save CTR in stackframe */ \ | 305 | mfctr r10; /* save CTR in stackframe */ \ |
310 | std r10,_CTR(r1); \ | 306 | std r10,_CTR(r1); \ |
307 | lbz r10,PACASOFTIRQEN(r13); \ | ||
311 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ | 308 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ |
309 | std r10,SOFTE(r1); \ | ||
312 | std r11,_XER(r1); \ | 310 | std r11,_XER(r1); \ |
313 | li r9,(n)+1; \ | 311 | li r9,(n)+1; \ |
314 | std r9,_TRAP(r1); /* set trap number */ \ | 312 | std r9,_TRAP(r1); /* set trap number */ \ |
@@ -343,6 +341,34 @@ label##_pSeries: \ | |||
343 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | 341 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) |
344 | 342 | ||
345 | 343 | ||
344 | #define MASKABLE_EXCEPTION_PSERIES(n, label) \ | ||
345 | . = n; \ | ||
346 | .globl label##_pSeries; \ | ||
347 | label##_pSeries: \ | ||
348 | HMT_MEDIUM; \ | ||
349 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
350 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
351 | std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \ | ||
352 | std r10,PACA_EXGEN+EX_R10(r13); \ | ||
353 | lbz r10,PACASOFTIRQEN(r13); \ | ||
354 | mfcr r9; \ | ||
355 | cmpwi r10,0; \ | ||
356 | beq masked_interrupt; \ | ||
357 | mfspr r10,SPRN_SPRG1; \ | ||
358 | std r10,PACA_EXGEN+EX_R13(r13); \ | ||
359 | std r11,PACA_EXGEN+EX_R11(r13); \ | ||
360 | std r12,PACA_EXGEN+EX_R12(r13); \ | ||
361 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
362 | mfmsr r10; \ | ||
363 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
364 | LOAD_HANDLER(r12,label##_common) \ | ||
365 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
366 | mtspr SPRN_SRR0,r12; \ | ||
367 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
368 | mtspr SPRN_SRR1,r10; \ | ||
369 | rfid; \ | ||
370 | b . /* prevent speculative execution */ | ||
371 | |||
346 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | 372 | #define STD_EXCEPTION_ISERIES(n, label, area) \ |
347 | .globl label##_iSeries; \ | 373 | .globl label##_iSeries; \ |
348 | label##_iSeries: \ | 374 | label##_iSeries: \ |
@@ -358,40 +384,32 @@ label##_iSeries: \ | |||
358 | HMT_MEDIUM; \ | 384 | HMT_MEDIUM; \ |
359 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | 385 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ |
360 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ | 386 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ |
361 | lbz r10,PACAPROCENABLED(r13); \ | 387 | lbz r10,PACASOFTIRQEN(r13); \ |
362 | cmpwi 0,r10,0; \ | 388 | cmpwi 0,r10,0; \ |
363 | beq- label##_iSeries_masked; \ | 389 | beq- label##_iSeries_masked; \ |
364 | EXCEPTION_PROLOG_ISERIES_2; \ | 390 | EXCEPTION_PROLOG_ISERIES_2; \ |
365 | b label##_common; \ | 391 | b label##_common; \ |
366 | 392 | ||
367 | #ifdef DO_SOFT_DISABLE | 393 | #ifdef CONFIG_PPC_ISERIES |
368 | #define DISABLE_INTS \ | 394 | #define DISABLE_INTS \ |
369 | BEGIN_FW_FTR_SECTION; \ | ||
370 | lbz r10,PACAPROCENABLED(r13); \ | ||
371 | li r11,0; \ | 395 | li r11,0; \ |
372 | std r10,SOFTE(r1); \ | 396 | stb r11,PACASOFTIRQEN(r13); \ |
397 | BEGIN_FW_FTR_SECTION; \ | ||
398 | stb r11,PACAHARDIRQEN(r13); \ | ||
399 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ | ||
400 | BEGIN_FW_FTR_SECTION; \ | ||
373 | mfmsr r10; \ | 401 | mfmsr r10; \ |
374 | stb r11,PACAPROCENABLED(r13); \ | ||
375 | ori r10,r10,MSR_EE; \ | 402 | ori r10,r10,MSR_EE; \ |
376 | mtmsrd r10,1; \ | 403 | mtmsrd r10,1; \ |
377 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 404 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
378 | 405 | ||
379 | #define ENABLE_INTS \ | 406 | #else |
380 | BEGIN_FW_FTR_SECTION; \ | 407 | #define DISABLE_INTS \ |
381 | lbz r10,PACAPROCENABLED(r13); \ | 408 | li r11,0; \ |
382 | mfmsr r11; \ | 409 | stb r11,PACASOFTIRQEN(r13); \ |
383 | std r10,SOFTE(r1); \ | 410 | stb r11,PACAHARDIRQEN(r13) |
384 | ori r11,r11,MSR_EE; \ | ||
385 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \ | ||
386 | BEGIN_FW_FTR_SECTION; \ | ||
387 | ld r12,_MSR(r1); \ | ||
388 | mfmsr r11; \ | ||
389 | rlwimi r11,r12,0,MSR_EE; \ | ||
390 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ | ||
391 | mtmsrd r11,1 | ||
392 | 411 | ||
393 | #else /* hard enable/disable interrupts */ | 412 | #endif /* CONFIG_PPC_ISERIES */ |
394 | #define DISABLE_INTS | ||
395 | 413 | ||
396 | #define ENABLE_INTS \ | 414 | #define ENABLE_INTS \ |
397 | ld r12,_MSR(r1); \ | 415 | ld r12,_MSR(r1); \ |
@@ -399,8 +417,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ | |||
399 | rlwimi r11,r12,0,MSR_EE; \ | 417 | rlwimi r11,r12,0,MSR_EE; \ |
400 | mtmsrd r11,1 | 418 | mtmsrd r11,1 |
401 | 419 | ||
402 | #endif | ||
403 | |||
404 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | 420 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ |
405 | .align 7; \ | 421 | .align 7; \ |
406 | .globl label##_common; \ | 422 | .globl label##_common; \ |
@@ -541,11 +557,11 @@ instruction_access_slb_pSeries: | |||
541 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | 557 | mfspr r12,SPRN_SRR1 /* and SRR1 */ |
542 | b .slb_miss_realmode /* Rel. branch works in real mode */ | 558 | b .slb_miss_realmode /* Rel. branch works in real mode */ |
543 | 559 | ||
544 | STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) | 560 | MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt) |
545 | STD_EXCEPTION_PSERIES(0x600, alignment) | 561 | STD_EXCEPTION_PSERIES(0x600, alignment) |
546 | STD_EXCEPTION_PSERIES(0x700, program_check) | 562 | STD_EXCEPTION_PSERIES(0x700, program_check) |
547 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) | 563 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) |
548 | STD_EXCEPTION_PSERIES(0x900, decrementer) | 564 | MASKABLE_EXCEPTION_PSERIES(0x900, decrementer) |
549 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) | 565 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) |
550 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) | 566 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) |
551 | 567 | ||
@@ -597,7 +613,24 @@ system_call_pSeries: | |||
597 | /*** pSeries interrupt support ***/ | 613 | /*** pSeries interrupt support ***/ |
598 | 614 | ||
599 | /* moved from 0xf00 */ | 615 | /* moved from 0xf00 */ |
600 | STD_EXCEPTION_PSERIES(., performance_monitor) | 616 | MASKABLE_EXCEPTION_PSERIES(., performance_monitor) |
617 | |||
618 | /* | ||
619 | * An interrupt came in while soft-disabled; clear EE in SRR1, | ||
620 | * clear paca->hard_enabled and return. | ||
621 | */ | ||
622 | masked_interrupt: | ||
623 | stb r10,PACAHARDIRQEN(r13) | ||
624 | mtcrf 0x80,r9 | ||
625 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
626 | mfspr r10,SPRN_SRR1 | ||
627 | rldicl r10,r10,48,1 /* clear MSR_EE */ | ||
628 | rotldi r10,r10,16 | ||
629 | mtspr SPRN_SRR1,r10 | ||
630 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
631 | mfspr r13,SPRN_SPRG1 | ||
632 | rfid | ||
633 | b . | ||
601 | 634 | ||
602 | .align 7 | 635 | .align 7 |
603 | do_stab_bolted_pSeries: | 636 | do_stab_bolted_pSeries: |
@@ -792,7 +825,7 @@ system_reset_iSeries: | |||
792 | 825 | ||
793 | cmpwi 0,r23,0 | 826 | cmpwi 0,r23,0 |
794 | beq iSeries_secondary_smp_loop /* Loop until told to go */ | 827 | beq iSeries_secondary_smp_loop /* Loop until told to go */ |
795 | bne .__secondary_start /* Loop until told to go */ | 828 | bne __secondary_start /* Loop until told to go */ |
796 | iSeries_secondary_smp_loop: | 829 | iSeries_secondary_smp_loop: |
797 | /* Let the Hypervisor know we are alive */ | 830 | /* Let the Hypervisor know we are alive */ |
798 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ | 831 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ |
@@ -813,7 +846,6 @@ iSeries_secondary_smp_loop: | |||
813 | b 1b /* If SMP not configured, secondaries | 846 | b 1b /* If SMP not configured, secondaries |
814 | * loop forever */ | 847 | * loop forever */ |
815 | 848 | ||
816 | .globl decrementer_iSeries_masked | ||
817 | decrementer_iSeries_masked: | 849 | decrementer_iSeries_masked: |
818 | /* We may not have a valid TOC pointer in here. */ | 850 | /* We may not have a valid TOC pointer in here. */ |
819 | li r11,1 | 851 | li r11,1 |
@@ -824,7 +856,6 @@ decrementer_iSeries_masked: | |||
824 | mtspr SPRN_DEC,r12 | 856 | mtspr SPRN_DEC,r12 |
825 | /* fall through */ | 857 | /* fall through */ |
826 | 858 | ||
827 | .globl hardware_interrupt_iSeries_masked | ||
828 | hardware_interrupt_iSeries_masked: | 859 | hardware_interrupt_iSeries_masked: |
829 | mtcrf 0x80,r9 /* Restore regs */ | 860 | mtcrf 0x80,r9 /* Restore regs */ |
830 | ld r12,PACALPPACAPTR(r13) | 861 | ld r12,PACALPPACAPTR(r13) |
@@ -926,10 +957,18 @@ bad_stack: | |||
926 | * any task or sent any task a signal, you should use | 957 | * any task or sent any task a signal, you should use |
927 | * ret_from_except or ret_from_except_lite instead of this. | 958 | * ret_from_except or ret_from_except_lite instead of this. |
928 | */ | 959 | */ |
960 | fast_exc_return_irq: /* restores irq state too */ | ||
961 | ld r3,SOFTE(r1) | ||
962 | ld r12,_MSR(r1) | ||
963 | stb r3,PACASOFTIRQEN(r13) /* restore paca->soft_enabled */ | ||
964 | rldicl r4,r12,49,63 /* get MSR_EE to LSB */ | ||
965 | stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */ | ||
966 | b 1f | ||
967 | |||
929 | .globl fast_exception_return | 968 | .globl fast_exception_return |
930 | fast_exception_return: | 969 | fast_exception_return: |
931 | ld r12,_MSR(r1) | 970 | ld r12,_MSR(r1) |
932 | ld r11,_NIP(r1) | 971 | 1: ld r11,_NIP(r1) |
933 | andi. r3,r12,MSR_RI /* check if RI is set */ | 972 | andi. r3,r12,MSR_RI /* check if RI is set */ |
934 | beq- unrecov_fer | 973 | beq- unrecov_fer |
935 | 974 | ||
@@ -952,7 +991,8 @@ fast_exception_return: | |||
952 | REST_8GPRS(2, r1) | 991 | REST_8GPRS(2, r1) |
953 | 992 | ||
954 | mfmsr r10 | 993 | mfmsr r10 |
955 | clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ | 994 | rldicl r10,r10,48,1 /* clear EE */ |
995 | rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */ | ||
956 | mtmsrd r10,1 | 996 | mtmsrd r10,1 |
957 | 997 | ||
958 | mtspr SPRN_SRR1,r12 | 998 | mtspr SPRN_SRR1,r12 |
@@ -1326,6 +1366,16 @@ BEGIN_FW_FTR_SECTION | |||
1326 | * interrupts if necessary. | 1366 | * interrupts if necessary. |
1327 | */ | 1367 | */ |
1328 | beq 13f | 1368 | beq 13f |
1369 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | ||
1370 | #endif | ||
1371 | BEGIN_FW_FTR_SECTION | ||
1372 | /* | ||
1373 | * Here we have interrupts hard-disabled, so it is sufficient | ||
1374 | * to restore paca->{soft,hard}_enable and get out. | ||
1375 | */ | ||
1376 | beq fast_exc_return_irq /* Return from exception on success */ | ||
1377 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
1378 | |||
1329 | /* For a hash failure, we don't bother re-enabling interrupts */ | 1379 | /* For a hash failure, we don't bother re-enabling interrupts */ |
1330 | ble- 12f | 1380 | ble- 12f |
1331 | 1381 | ||
@@ -1337,14 +1387,6 @@ BEGIN_FW_FTR_SECTION | |||
1337 | ld r3,SOFTE(r1) | 1387 | ld r3,SOFTE(r1) |
1338 | bl .local_irq_restore | 1388 | bl .local_irq_restore |
1339 | b 11f | 1389 | b 11f |
1340 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | ||
1341 | #endif | ||
1342 | BEGIN_FW_FTR_SECTION | ||
1343 | beq fast_exception_return /* Return from exception on success */ | ||
1344 | ble- 12f /* Failure return from hash_page */ | ||
1345 | |||
1346 | /* fall through */ | ||
1347 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
1348 | 1390 | ||
1349 | /* Here we have a page fault that hash_page can't handle. */ | 1391 | /* Here we have a page fault that hash_page can't handle. */ |
1350 | handle_page_fault: | 1392 | handle_page_fault: |
@@ -1362,6 +1404,8 @@ handle_page_fault: | |||
1362 | bl .bad_page_fault | 1404 | bl .bad_page_fault |
1363 | b .ret_from_except | 1405 | b .ret_from_except |
1364 | 1406 | ||
1407 | 13: b .ret_from_except_lite | ||
1408 | |||
1365 | /* We have a page fault that hash_page could handle but HV refused | 1409 | /* We have a page fault that hash_page could handle but HV refused |
1366 | * the PTE insertion | 1410 | * the PTE insertion |
1367 | */ | 1411 | */ |
@@ -1371,8 +1415,6 @@ handle_page_fault: | |||
1371 | bl .low_hash_fault | 1415 | bl .low_hash_fault |
1372 | b .ret_from_except | 1416 | b .ret_from_except |
1373 | 1417 | ||
1374 | 13: b .ret_from_except_lite | ||
1375 | |||
1376 | /* here we have a segment miss */ | 1418 | /* here we have a segment miss */ |
1377 | do_ste_alloc: | 1419 | do_ste_alloc: |
1378 | bl .ste_allocate /* try to insert stab entry */ | 1420 | bl .ste_allocate /* try to insert stab entry */ |
@@ -1560,7 +1602,7 @@ _GLOBAL(generic_secondary_smp_init) | |||
1560 | ld r1,PACAEMERGSP(r13) | 1602 | ld r1,PACAEMERGSP(r13) |
1561 | subi r1,r1,STACK_FRAME_OVERHEAD | 1603 | subi r1,r1,STACK_FRAME_OVERHEAD |
1562 | 1604 | ||
1563 | b .__secondary_start | 1605 | b __secondary_start |
1564 | #endif | 1606 | #endif |
1565 | 1607 | ||
1566 | #ifdef CONFIG_PPC_ISERIES | 1608 | #ifdef CONFIG_PPC_ISERIES |
@@ -1595,7 +1637,6 @@ _STATIC(__start_initialization_iSeries) | |||
1595 | b .start_here_common | 1637 | b .start_here_common |
1596 | #endif /* CONFIG_PPC_ISERIES */ | 1638 | #endif /* CONFIG_PPC_ISERIES */ |
1597 | 1639 | ||
1598 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1599 | 1640 | ||
1600 | _STATIC(__mmu_off) | 1641 | _STATIC(__mmu_off) |
1601 | mfmsr r3 | 1642 | mfmsr r3 |
@@ -1621,13 +1662,11 @@ _STATIC(__mmu_off) | |||
1621 | * | 1662 | * |
1622 | */ | 1663 | */ |
1623 | _GLOBAL(__start_initialization_multiplatform) | 1664 | _GLOBAL(__start_initialization_multiplatform) |
1624 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1625 | /* | 1665 | /* |
1626 | * Are we booted from a PROM Of-type client-interface ? | 1666 | * Are we booted from a PROM Of-type client-interface ? |
1627 | */ | 1667 | */ |
1628 | cmpldi cr0,r5,0 | 1668 | cmpldi cr0,r5,0 |
1629 | bne .__boot_from_prom /* yes -> prom */ | 1669 | bne .__boot_from_prom /* yes -> prom */ |
1630 | #endif | ||
1631 | 1670 | ||
1632 | /* Save parameters */ | 1671 | /* Save parameters */ |
1633 | mr r31,r3 | 1672 | mr r31,r3 |
@@ -1656,7 +1695,6 @@ _GLOBAL(__start_initialization_multiplatform) | |||
1656 | bl .__mmu_off | 1695 | bl .__mmu_off |
1657 | b .__after_prom_start | 1696 | b .__after_prom_start |
1658 | 1697 | ||
1659 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1660 | _STATIC(__boot_from_prom) | 1698 | _STATIC(__boot_from_prom) |
1661 | /* Save parameters */ | 1699 | /* Save parameters */ |
1662 | mr r31,r3 | 1700 | mr r31,r3 |
@@ -1696,7 +1734,6 @@ _STATIC(__boot_from_prom) | |||
1696 | bl .prom_init | 1734 | bl .prom_init |
1697 | /* We never return */ | 1735 | /* We never return */ |
1698 | trap | 1736 | trap |
1699 | #endif | ||
1700 | 1737 | ||
1701 | /* | 1738 | /* |
1702 | * At this point, r3 contains the physical address we are running at, | 1739 | * At this point, r3 contains the physical address we are running at, |
@@ -1752,8 +1789,6 @@ _STATIC(__after_prom_start) | |||
1752 | bl .copy_and_flush /* copy the rest */ | 1789 | bl .copy_and_flush /* copy the rest */ |
1753 | b .start_here_multiplatform | 1790 | b .start_here_multiplatform |
1754 | 1791 | ||
1755 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1756 | |||
1757 | /* | 1792 | /* |
1758 | * Copy routine used to copy the kernel to start at physical address 0 | 1793 | * Copy routine used to copy the kernel to start at physical address 0 |
1759 | * and flush and invalidate the caches as needed. | 1794 | * and flush and invalidate the caches as needed. |
@@ -1836,7 +1871,7 @@ _GLOBAL(pmac_secondary_start) | |||
1836 | ld r1,PACAEMERGSP(r13) | 1871 | ld r1,PACAEMERGSP(r13) |
1837 | subi r1,r1,STACK_FRAME_OVERHEAD | 1872 | subi r1,r1,STACK_FRAME_OVERHEAD |
1838 | 1873 | ||
1839 | b .__secondary_start | 1874 | b __secondary_start |
1840 | 1875 | ||
1841 | #endif /* CONFIG_PPC_PMAC */ | 1876 | #endif /* CONFIG_PPC_PMAC */ |
1842 | 1877 | ||
@@ -1853,7 +1888,7 @@ _GLOBAL(pmac_secondary_start) | |||
1853 | * r13 = paca virtual address | 1888 | * r13 = paca virtual address |
1854 | * SPRG3 = paca virtual address | 1889 | * SPRG3 = paca virtual address |
1855 | */ | 1890 | */ |
1856 | _GLOBAL(__secondary_start) | 1891 | __secondary_start: |
1857 | /* Set thread priority to MEDIUM */ | 1892 | /* Set thread priority to MEDIUM */ |
1858 | HMT_MEDIUM | 1893 | HMT_MEDIUM |
1859 | 1894 | ||
@@ -1877,11 +1912,16 @@ _GLOBAL(__secondary_start) | |||
1877 | /* enable MMU and jump to start_secondary */ | 1912 | /* enable MMU and jump to start_secondary */ |
1878 | LOAD_REG_ADDR(r3, .start_secondary_prolog) | 1913 | LOAD_REG_ADDR(r3, .start_secondary_prolog) |
1879 | LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) | 1914 | LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) |
1880 | #ifdef DO_SOFT_DISABLE | 1915 | #ifdef CONFIG_PPC_ISERIES |
1881 | BEGIN_FW_FTR_SECTION | 1916 | BEGIN_FW_FTR_SECTION |
1882 | ori r4,r4,MSR_EE | 1917 | ori r4,r4,MSR_EE |
1883 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 1918 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
1884 | #endif | 1919 | #endif |
1920 | BEGIN_FW_FTR_SECTION | ||
1921 | stb r7,PACASOFTIRQEN(r13) | ||
1922 | stb r7,PACAHARDIRQEN(r13) | ||
1923 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
1924 | |||
1885 | mtspr SPRN_SRR0,r3 | 1925 | mtspr SPRN_SRR0,r3 |
1886 | mtspr SPRN_SRR1,r4 | 1926 | mtspr SPRN_SRR1,r4 |
1887 | rfid | 1927 | rfid |
@@ -1913,7 +1953,6 @@ _GLOBAL(enable_64b_mode) | |||
1913 | isync | 1953 | isync |
1914 | blr | 1954 | blr |
1915 | 1955 | ||
1916 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1917 | /* | 1956 | /* |
1918 | * This is where the main kernel code starts. | 1957 | * This is where the main kernel code starts. |
1919 | */ | 1958 | */ |
@@ -1977,7 +2016,6 @@ _STATIC(start_here_multiplatform) | |||
1977 | mtspr SPRN_SRR1,r4 | 2016 | mtspr SPRN_SRR1,r4 |
1978 | rfid | 2017 | rfid |
1979 | b . /* prevent speculative execution */ | 2018 | b . /* prevent speculative execution */ |
1980 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1981 | 2019 | ||
1982 | /* This is where all platforms converge execution */ | 2020 | /* This is where all platforms converge execution */ |
1983 | _STATIC(start_here_common) | 2021 | _STATIC(start_here_common) |
@@ -2005,15 +2043,18 @@ _STATIC(start_here_common) | |||
2005 | 2043 | ||
2006 | /* Load up the kernel context */ | 2044 | /* Load up the kernel context */ |
2007 | 5: | 2045 | 5: |
2008 | #ifdef DO_SOFT_DISABLE | ||
2009 | BEGIN_FW_FTR_SECTION | ||
2010 | li r5,0 | 2046 | li r5,0 |
2011 | stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ | 2047 | stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */ |
2048 | #ifdef CONFIG_PPC_ISERIES | ||
2049 | BEGIN_FW_FTR_SECTION | ||
2012 | mfmsr r5 | 2050 | mfmsr r5 |
2013 | ori r5,r5,MSR_EE /* Hard Enabled */ | 2051 | ori r5,r5,MSR_EE /* Hard Enabled */ |
2014 | mtmsrd r5 | 2052 | mtmsrd r5 |
2015 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 2053 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
2016 | #endif | 2054 | #endif |
2055 | BEGIN_FW_FTR_SECTION | ||
2056 | stb r5,PACAHARDIRQEN(r13) | ||
2057 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | ||
2017 | 2058 | ||
2018 | bl .start_kernel | 2059 | bl .start_kernel |
2019 | 2060 | ||
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 39db7a3affe..82bd2f10770 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -112,7 +112,7 @@ static int ibmebus_dma_supported(struct device *dev, u64 mask) | |||
112 | return 1; | 112 | return 1; |
113 | } | 113 | } |
114 | 114 | ||
115 | struct dma_mapping_ops ibmebus_dma_ops = { | 115 | static struct dma_mapping_ops ibmebus_dma_ops = { |
116 | .alloc_coherent = ibmebus_alloc_coherent, | 116 | .alloc_coherent = ibmebus_alloc_coherent, |
117 | .free_coherent = ibmebus_free_coherent, | 117 | .free_coherent = ibmebus_free_coherent, |
118 | .map_single = ibmebus_map_single, | 118 | .map_single = ibmebus_map_single, |
@@ -176,6 +176,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common( | |||
176 | dev->ofdev.dev.bus = &ibmebus_bus_type; | 176 | dev->ofdev.dev.bus = &ibmebus_bus_type; |
177 | dev->ofdev.dev.release = ibmebus_dev_release; | 177 | dev->ofdev.dev.release = ibmebus_dev_release; |
178 | 178 | ||
179 | dev->ofdev.dev.archdata.of_node = dev->ofdev.node; | ||
180 | dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops; | ||
181 | dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node); | ||
182 | |||
179 | /* An ibmebusdev is based on a of_device. We have to change the | 183 | /* An ibmebusdev is based on a of_device. We have to change the |
180 | * bus type to use our own DMA mapping operations. | 184 | * bus type to use our own DMA mapping operations. |
181 | */ | 185 | */ |
@@ -210,11 +214,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( | |||
210 | return NULL; | 214 | return NULL; |
211 | } | 215 | } |
212 | 216 | ||
213 | dev = kmalloc(sizeof(struct ibmebus_dev), GFP_KERNEL); | 217 | dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL); |
214 | if (!dev) { | 218 | if (!dev) { |
215 | return NULL; | 219 | return NULL; |
216 | } | 220 | } |
217 | memset(dev, 0, sizeof(struct ibmebus_dev)); | ||
218 | 221 | ||
219 | dev->ofdev.node = of_node_get(dn); | 222 | dev->ofdev.node = of_node_get(dn); |
220 | 223 | ||
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 4180c3998b3..8994af327b4 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c | |||
@@ -39,6 +39,13 @@ | |||
39 | #define cpu_should_die() 0 | 39 | #define cpu_should_die() 0 |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | static int __init powersave_off(char *arg) | ||
43 | { | ||
44 | ppc_md.power_save = NULL; | ||
45 | return 0; | ||
46 | } | ||
47 | __setup("powersave=off", powersave_off); | ||
48 | |||
42 | /* | 49 | /* |
43 | * The body of the idle task. | 50 | * The body of the idle task. |
44 | */ | 51 | */ |
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index 30de81da7b4..ba319547860 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S | |||
@@ -30,6 +30,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) | |||
30 | beqlr | 30 | beqlr |
31 | 31 | ||
32 | /* Go to NAP now */ | 32 | /* Go to NAP now */ |
33 | mfmsr r7 | ||
34 | rldicl r0,r7,48,1 | ||
35 | rotldi r0,r0,16 | ||
36 | mtmsrd r0,1 /* hard-disable interrupts */ | ||
37 | li r0,1 | ||
38 | stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */ | ||
39 | stb r0,PACAHARDIRQEN(r13) | ||
33 | BEGIN_FTR_SECTION | 40 | BEGIN_FTR_SECTION |
34 | DSSALL | 41 | DSSALL |
35 | sync | 42 | sync |
@@ -38,7 +45,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
38 | ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */ | 45 | ld r8,TI_LOCAL_FLAGS(r9) /* set napping bit */ |
39 | ori r8,r8,_TLF_NAPPING /* so when we take an exception */ | 46 | ori r8,r8,_TLF_NAPPING /* so when we take an exception */ |
40 | std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */ | 47 | std r8,TI_LOCAL_FLAGS(r9) /* it will return to our caller */ |
41 | mfmsr r7 | ||
42 | ori r7,r7,MSR_EE | 48 | ori r7,r7,MSR_EE |
43 | oris r7,r7,MSR_POW@h | 49 | oris r7,r7,MSR_POW@h |
44 | 1: sync | 50 | 1: sync |
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index e98180686b3..34ae11494dd 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c | |||
@@ -25,13 +25,11 @@ | |||
25 | #include <asm/firmware.h> | 25 | #include <asm/firmware.h> |
26 | #include <asm/bug.h> | 26 | #include <asm/bug.h> |
27 | 27 | ||
28 | void _insb(volatile u8 __iomem *port, void *buf, long count) | 28 | void _insb(const volatile u8 __iomem *port, void *buf, long count) |
29 | { | 29 | { |
30 | u8 *tbuf = buf; | 30 | u8 *tbuf = buf; |
31 | u8 tmp; | 31 | u8 tmp; |
32 | 32 | ||
33 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
34 | |||
35 | if (unlikely(count <= 0)) | 33 | if (unlikely(count <= 0)) |
36 | return; | 34 | return; |
37 | asm volatile("sync"); | 35 | asm volatile("sync"); |
@@ -48,8 +46,6 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count) | |||
48 | { | 46 | { |
49 | const u8 *tbuf = buf; | 47 | const u8 *tbuf = buf; |
50 | 48 | ||
51 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
52 | |||
53 | if (unlikely(count <= 0)) | 49 | if (unlikely(count <= 0)) |
54 | return; | 50 | return; |
55 | asm volatile("sync"); | 51 | asm volatile("sync"); |
@@ -60,13 +56,11 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count) | |||
60 | } | 56 | } |
61 | EXPORT_SYMBOL(_outsb); | 57 | EXPORT_SYMBOL(_outsb); |
62 | 58 | ||
63 | void _insw_ns(volatile u16 __iomem *port, void *buf, long count) | 59 | void _insw_ns(const volatile u16 __iomem *port, void *buf, long count) |
64 | { | 60 | { |
65 | u16 *tbuf = buf; | 61 | u16 *tbuf = buf; |
66 | u16 tmp; | 62 | u16 tmp; |
67 | 63 | ||
68 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
69 | |||
70 | if (unlikely(count <= 0)) | 64 | if (unlikely(count <= 0)) |
71 | return; | 65 | return; |
72 | asm volatile("sync"); | 66 | asm volatile("sync"); |
@@ -83,8 +77,6 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count) | |||
83 | { | 77 | { |
84 | const u16 *tbuf = buf; | 78 | const u16 *tbuf = buf; |
85 | 79 | ||
86 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
87 | |||
88 | if (unlikely(count <= 0)) | 80 | if (unlikely(count <= 0)) |
89 | return; | 81 | return; |
90 | asm volatile("sync"); | 82 | asm volatile("sync"); |
@@ -95,13 +87,11 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count) | |||
95 | } | 87 | } |
96 | EXPORT_SYMBOL(_outsw_ns); | 88 | EXPORT_SYMBOL(_outsw_ns); |
97 | 89 | ||
98 | void _insl_ns(volatile u32 __iomem *port, void *buf, long count) | 90 | void _insl_ns(const volatile u32 __iomem *port, void *buf, long count) |
99 | { | 91 | { |
100 | u32 *tbuf = buf; | 92 | u32 *tbuf = buf; |
101 | u32 tmp; | 93 | u32 tmp; |
102 | 94 | ||
103 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
104 | |||
105 | if (unlikely(count <= 0)) | 95 | if (unlikely(count <= 0)) |
106 | return; | 96 | return; |
107 | asm volatile("sync"); | 97 | asm volatile("sync"); |
@@ -118,8 +108,6 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count) | |||
118 | { | 108 | { |
119 | const u32 *tbuf = buf; | 109 | const u32 *tbuf = buf; |
120 | 110 | ||
121 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
122 | |||
123 | if (unlikely(count <= 0)) | 111 | if (unlikely(count <= 0)) |
124 | return; | 112 | return; |
125 | asm volatile("sync"); | 113 | asm volatile("sync"); |
@@ -129,3 +117,90 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count) | |||
129 | asm volatile("sync"); | 117 | asm volatile("sync"); |
130 | } | 118 | } |
131 | EXPORT_SYMBOL(_outsl_ns); | 119 | EXPORT_SYMBOL(_outsl_ns); |
120 | |||
121 | #define IO_CHECK_ALIGN(v,a) ((((unsigned long)(v)) & ((a) - 1)) == 0) | ||
122 | |||
123 | void _memset_io(volatile void __iomem *addr, int c, unsigned long n) | ||
124 | { | ||
125 | void *p = (void __force *)addr; | ||
126 | u32 lc = c; | ||
127 | lc |= lc << 8; | ||
128 | lc |= lc << 16; | ||
129 | |||
130 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
131 | while(n && !IO_CHECK_ALIGN(p, 4)) { | ||
132 | *((volatile u8 *)p) = c; | ||
133 | p++; | ||
134 | n--; | ||
135 | } | ||
136 | while(n >= 4) { | ||
137 | *((volatile u32 *)p) = lc; | ||
138 | p += 4; | ||
139 | n -= 4; | ||
140 | } | ||
141 | while(n) { | ||
142 | *((volatile u8 *)p) = c; | ||
143 | p++; | ||
144 | n--; | ||
145 | } | ||
146 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
147 | } | ||
148 | EXPORT_SYMBOL(_memset_io); | ||
149 | |||
150 | void _memcpy_fromio(void *dest, const volatile void __iomem *src, | ||
151 | unsigned long n) | ||
152 | { | ||
153 | void *vsrc = (void __force *) src; | ||
154 | |||
155 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
156 | while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { | ||
157 | *((u8 *)dest) = *((volatile u8 *)vsrc); | ||
158 | __asm__ __volatile__ ("eieio" : : : "memory"); | ||
159 | vsrc++; | ||
160 | dest++; | ||
161 | n--; | ||
162 | } | ||
163 | while(n > 4) { | ||
164 | *((u32 *)dest) = *((volatile u32 *)vsrc); | ||
165 | __asm__ __volatile__ ("eieio" : : : "memory"); | ||
166 | vsrc += 4; | ||
167 | dest += 4; | ||
168 | n -= 4; | ||
169 | } | ||
170 | while(n) { | ||
171 | *((u8 *)dest) = *((volatile u8 *)vsrc); | ||
172 | __asm__ __volatile__ ("eieio" : : : "memory"); | ||
173 | vsrc++; | ||
174 | dest++; | ||
175 | n--; | ||
176 | } | ||
177 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
178 | } | ||
179 | EXPORT_SYMBOL(_memcpy_fromio); | ||
180 | |||
181 | void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) | ||
182 | { | ||
183 | void *vdest = (void __force *) dest; | ||
184 | |||
185 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
186 | while(n && (!IO_CHECK_ALIGN(vdest, 4) || !IO_CHECK_ALIGN(src, 4))) { | ||
187 | *((volatile u8 *)vdest) = *((u8 *)src); | ||
188 | src++; | ||
189 | vdest++; | ||
190 | n--; | ||
191 | } | ||
192 | while(n > 4) { | ||
193 | *((volatile u32 *)vdest) = *((volatile u32 *)src); | ||
194 | src += 4; | ||
195 | vdest += 4; | ||
196 | n-=4; | ||
197 | } | ||
198 | while(n) { | ||
199 | *((volatile u8 *)vdest) = *((u8 *)src); | ||
200 | src++; | ||
201 | vdest++; | ||
202 | n--; | ||
203 | } | ||
204 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
205 | } | ||
206 | EXPORT_SYMBOL(_memcpy_toio); | ||
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index a13a93dfc65..c6811337105 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c | |||
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(iowrite32_rep); | |||
106 | 106 | ||
107 | void __iomem *ioport_map(unsigned long port, unsigned int len) | 107 | void __iomem *ioport_map(unsigned long port, unsigned int len) |
108 | { | 108 | { |
109 | return (void __iomem *) (port+pci_io_base); | 109 | return (void __iomem *) (port + _IO_BASE); |
110 | } | 110 | } |
111 | 111 | ||
112 | void ioport_unmap(void __iomem *addr) | 112 | void ioport_unmap(void __iomem *addr) |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index ba6b7256084..95edad4faf2 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -258,9 +258,9 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, | |||
258 | spin_unlock_irqrestore(&(tbl->it_lock), flags); | 258 | spin_unlock_irqrestore(&(tbl->it_lock), flags); |
259 | } | 259 | } |
260 | 260 | ||
261 | int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | 261 | int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, |
262 | struct scatterlist *sglist, int nelems, | 262 | int nelems, unsigned long mask, |
263 | unsigned long mask, enum dma_data_direction direction) | 263 | enum dma_data_direction direction) |
264 | { | 264 | { |
265 | dma_addr_t dma_next = 0, dma_addr; | 265 | dma_addr_t dma_next = 0, dma_addr; |
266 | unsigned long flags; | 266 | unsigned long flags; |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 5e37bf14ef2..0bd8c766583 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -64,8 +64,9 @@ | |||
64 | #include <asm/ptrace.h> | 64 | #include <asm/ptrace.h> |
65 | #include <asm/machdep.h> | 65 | #include <asm/machdep.h> |
66 | #include <asm/udbg.h> | 66 | #include <asm/udbg.h> |
67 | #ifdef CONFIG_PPC_ISERIES | 67 | #ifdef CONFIG_PPC64 |
68 | #include <asm/paca.h> | 68 | #include <asm/paca.h> |
69 | #include <asm/firmware.h> | ||
69 | #endif | 70 | #endif |
70 | 71 | ||
71 | int __irq_offset_value; | 72 | int __irq_offset_value; |
@@ -95,6 +96,74 @@ extern atomic_t ipi_sent; | |||
95 | EXPORT_SYMBOL(irq_desc); | 96 | EXPORT_SYMBOL(irq_desc); |
96 | 97 | ||
97 | int distribute_irqs = 1; | 98 | int distribute_irqs = 1; |
99 | |||
100 | static inline unsigned long get_hard_enabled(void) | ||
101 | { | ||
102 | unsigned long enabled; | ||
103 | |||
104 | __asm__ __volatile__("lbz %0,%1(13)" | ||
105 | : "=r" (enabled) : "i" (offsetof(struct paca_struct, hard_enabled))); | ||
106 | |||
107 | return enabled; | ||
108 | } | ||
109 | |||
110 | static inline void set_soft_enabled(unsigned long enable) | ||
111 | { | ||
112 | __asm__ __volatile__("stb %0,%1(13)" | ||
113 | : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled))); | ||
114 | } | ||
115 | |||
116 | void local_irq_restore(unsigned long en) | ||
117 | { | ||
118 | /* | ||
119 | * get_paca()->soft_enabled = en; | ||
120 | * Is it ever valid to use local_irq_restore(0) when soft_enabled is 1? | ||
121 | * That was allowed before, and in such a case we do need to take care | ||
122 | * that gcc will set soft_enabled directly via r13, not choose to use | ||
123 | * an intermediate register, lest we're preempted to a different cpu. | ||
124 | */ | ||
125 | set_soft_enabled(en); | ||
126 | if (!en) | ||
127 | return; | ||
128 | |||
129 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
130 | /* | ||
131 | * Do we need to disable preemption here? Not really: in the | ||
132 | * unlikely event that we're preempted to a different cpu in | ||
133 | * between getting r13, loading its lppaca_ptr, and loading | ||
134 | * its any_int, we might call iseries_handle_interrupts without | ||
135 | * an interrupt pending on the new cpu, but that's no disaster, | ||
136 | * is it? And the business of preempting us off the old cpu | ||
137 | * would itself involve a local_irq_restore which handles the | ||
138 | * interrupt to that cpu. | ||
139 | * | ||
140 | * But use "local_paca->lppaca_ptr" instead of "get_lppaca()" | ||
141 | * to avoid any preemption checking added into get_paca(). | ||
142 | */ | ||
143 | if (local_paca->lppaca_ptr->int_dword.any_int) | ||
144 | iseries_handle_interrupts(); | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * if (get_paca()->hard_enabled) return; | ||
150 | * But again we need to take care that gcc gets hard_enabled directly | ||
151 | * via r13, not choose to use an intermediate register, lest we're | ||
152 | * preempted to a different cpu in between the two instructions. | ||
153 | */ | ||
154 | if (get_hard_enabled()) | ||
155 | return; | ||
156 | |||
157 | /* | ||
158 | * Need to hard-enable interrupts here. Since currently disabled, | ||
159 | * no need to take further asm precautions against preemption; but | ||
160 | * use local_paca instead of get_paca() to avoid preemption checking. | ||
161 | */ | ||
162 | local_paca->hard_enabled = en; | ||
163 | if ((int)mfspr(SPRN_DEC) < 0) | ||
164 | mtspr(SPRN_DEC, 1); | ||
165 | hard_irq_enable(); | ||
166 | } | ||
98 | #endif /* CONFIG_PPC64 */ | 167 | #endif /* CONFIG_PPC64 */ |
99 | 168 | ||
100 | int show_interrupts(struct seq_file *p, void *v) | 169 | int show_interrupts(struct seq_file *p, void *v) |
@@ -246,7 +315,8 @@ void do_IRQ(struct pt_regs *regs) | |||
246 | set_irq_regs(old_regs); | 315 | set_irq_regs(old_regs); |
247 | 316 | ||
248 | #ifdef CONFIG_PPC_ISERIES | 317 | #ifdef CONFIG_PPC_ISERIES |
249 | if (get_lppaca()->int_dword.fields.decr_int) { | 318 | if (firmware_has_feature(FW_FEATURE_ISERIES) && |
319 | get_lppaca()->int_dword.fields.decr_int) { | ||
250 | get_lppaca()->int_dword.fields.decr_int = 0; | 320 | get_lppaca()->int_dword.fields.decr_int = 0; |
251 | /* Signal a fake decrementer interrupt */ | 321 | /* Signal a fake decrementer interrupt */ |
252 | timer_interrupt(regs); | 322 | timer_interrupt(regs); |
@@ -626,10 +696,14 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); | |||
626 | 696 | ||
627 | void irq_dispose_mapping(unsigned int virq) | 697 | void irq_dispose_mapping(unsigned int virq) |
628 | { | 698 | { |
629 | struct irq_host *host = irq_map[virq].host; | 699 | struct irq_host *host; |
630 | irq_hw_number_t hwirq; | 700 | irq_hw_number_t hwirq; |
631 | unsigned long flags; | 701 | unsigned long flags; |
632 | 702 | ||
703 | if (virq == NO_IRQ) | ||
704 | return; | ||
705 | |||
706 | host = irq_map[virq].host; | ||
633 | WARN_ON (host == NULL); | 707 | WARN_ON (host == NULL); |
634 | if (host == NULL) | 708 | if (host == NULL) |
635 | return; | 709 | return; |
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 397c83eda20..8a06724e029 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c | |||
@@ -9,30 +9,26 @@ | |||
9 | #include <asm/of_device.h> | 9 | #include <asm/of_device.h> |
10 | 10 | ||
11 | /** | 11 | /** |
12 | * of_match_device - Tell if an of_device structure has a matching | 12 | * of_match_node - Tell if an device_node has a matching of_match structure |
13 | * of_match structure | ||
14 | * @ids: array of of device match structures to search in | 13 | * @ids: array of of device match structures to search in |
15 | * @dev: the of device structure to match against | 14 | * @node: the of device structure to match against |
16 | * | 15 | * |
17 | * Used by a driver to check whether an of_device present in the | 16 | * Low level utility function used by device matching. |
18 | * system is in its list of supported devices. | ||
19 | */ | 17 | */ |
20 | const struct of_device_id *of_match_device(const struct of_device_id *matches, | 18 | const struct of_device_id *of_match_node(const struct of_device_id *matches, |
21 | const struct of_device *dev) | 19 | const struct device_node *node) |
22 | { | 20 | { |
23 | if (!dev->node) | ||
24 | return NULL; | ||
25 | while (matches->name[0] || matches->type[0] || matches->compatible[0]) { | 21 | while (matches->name[0] || matches->type[0] || matches->compatible[0]) { |
26 | int match = 1; | 22 | int match = 1; |
27 | if (matches->name[0]) | 23 | if (matches->name[0]) |
28 | match &= dev->node->name | 24 | match &= node->name |
29 | && !strcmp(matches->name, dev->node->name); | 25 | && !strcmp(matches->name, node->name); |
30 | if (matches->type[0]) | 26 | if (matches->type[0]) |
31 | match &= dev->node->type | 27 | match &= node->type |
32 | && !strcmp(matches->type, dev->node->type); | 28 | && !strcmp(matches->type, node->type); |
33 | if (matches->compatible[0]) | 29 | if (matches->compatible[0]) |
34 | match &= device_is_compatible(dev->node, | 30 | match &= device_is_compatible(node, |
35 | matches->compatible); | 31 | matches->compatible); |
36 | if (match) | 32 | if (match) |
37 | return matches; | 33 | return matches; |
38 | matches++; | 34 | matches++; |
@@ -40,16 +36,21 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches, | |||
40 | return NULL; | 36 | return NULL; |
41 | } | 37 | } |
42 | 38 | ||
43 | static int of_platform_bus_match(struct device *dev, struct device_driver *drv) | 39 | /** |
40 | * of_match_device - Tell if an of_device structure has a matching | ||
41 | * of_match structure | ||
42 | * @ids: array of of device match structures to search in | ||
43 | * @dev: the of device structure to match against | ||
44 | * | ||
45 | * Used by a driver to check whether an of_device present in the | ||
46 | * system is in its list of supported devices. | ||
47 | */ | ||
48 | const struct of_device_id *of_match_device(const struct of_device_id *matches, | ||
49 | const struct of_device *dev) | ||
44 | { | 50 | { |
45 | struct of_device * of_dev = to_of_device(dev); | 51 | if (!dev->node) |
46 | struct of_platform_driver * of_drv = to_of_platform_driver(drv); | 52 | return NULL; |
47 | const struct of_device_id * matches = of_drv->match_table; | 53 | return of_match_node(matches, dev->node); |
48 | |||
49 | if (!matches) | ||
50 | return 0; | ||
51 | |||
52 | return of_match_device(matches, of_dev) != NULL; | ||
53 | } | 54 | } |
54 | 55 | ||
55 | struct of_device *of_dev_get(struct of_device *dev) | 56 | struct of_device *of_dev_get(struct of_device *dev) |
@@ -71,96 +72,8 @@ void of_dev_put(struct of_device *dev) | |||
71 | put_device(&dev->dev); | 72 | put_device(&dev->dev); |
72 | } | 73 | } |
73 | 74 | ||
74 | 75 | static ssize_t dev_show_devspec(struct device *dev, | |
75 | static int of_device_probe(struct device *dev) | 76 | struct device_attribute *attr, char *buf) |
76 | { | ||
77 | int error = -ENODEV; | ||
78 | struct of_platform_driver *drv; | ||
79 | struct of_device *of_dev; | ||
80 | const struct of_device_id *match; | ||
81 | |||
82 | drv = to_of_platform_driver(dev->driver); | ||
83 | of_dev = to_of_device(dev); | ||
84 | |||
85 | if (!drv->probe) | ||
86 | return error; | ||
87 | |||
88 | of_dev_get(of_dev); | ||
89 | |||
90 | match = of_match_device(drv->match_table, of_dev); | ||
91 | if (match) | ||
92 | error = drv->probe(of_dev, match); | ||
93 | if (error) | ||
94 | of_dev_put(of_dev); | ||
95 | |||
96 | return error; | ||
97 | } | ||
98 | |||
99 | static int of_device_remove(struct device *dev) | ||
100 | { | ||
101 | struct of_device * of_dev = to_of_device(dev); | ||
102 | struct of_platform_driver * drv = to_of_platform_driver(dev->driver); | ||
103 | |||
104 | if (dev->driver && drv->remove) | ||
105 | drv->remove(of_dev); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int of_device_suspend(struct device *dev, pm_message_t state) | ||
110 | { | ||
111 | struct of_device * of_dev = to_of_device(dev); | ||
112 | struct of_platform_driver * drv = to_of_platform_driver(dev->driver); | ||
113 | int error = 0; | ||
114 | |||
115 | if (dev->driver && drv->suspend) | ||
116 | error = drv->suspend(of_dev, state); | ||
117 | return error; | ||
118 | } | ||
119 | |||
120 | static int of_device_resume(struct device * dev) | ||
121 | { | ||
122 | struct of_device * of_dev = to_of_device(dev); | ||
123 | struct of_platform_driver * drv = to_of_platform_driver(dev->driver); | ||
124 | int error = 0; | ||
125 | |||
126 | if (dev->driver && drv->resume) | ||
127 | error = drv->resume(of_dev); | ||
128 | return error; | ||
129 | } | ||
130 | |||
131 | struct bus_type of_platform_bus_type = { | ||
132 | .name = "of_platform", | ||
133 | .match = of_platform_bus_match, | ||
134 | .probe = of_device_probe, | ||
135 | .remove = of_device_remove, | ||
136 | .suspend = of_device_suspend, | ||
137 | .resume = of_device_resume, | ||
138 | }; | ||
139 | |||
140 | static int __init of_bus_driver_init(void) | ||
141 | { | ||
142 | return bus_register(&of_platform_bus_type); | ||
143 | } | ||
144 | |||
145 | postcore_initcall(of_bus_driver_init); | ||
146 | |||
147 | int of_register_driver(struct of_platform_driver *drv) | ||
148 | { | ||
149 | /* initialize common driver fields */ | ||
150 | drv->driver.name = drv->name; | ||
151 | drv->driver.bus = &of_platform_bus_type; | ||
152 | |||
153 | /* register with core */ | ||
154 | return driver_register(&drv->driver); | ||
155 | } | ||
156 | |||
157 | void of_unregister_driver(struct of_platform_driver *drv) | ||
158 | { | ||
159 | driver_unregister(&drv->driver); | ||
160 | } | ||
161 | |||
162 | |||
163 | static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | ||
164 | { | 77 | { |
165 | struct of_device *ofdev; | 78 | struct of_device *ofdev; |
166 | 79 | ||
@@ -208,41 +121,11 @@ void of_device_unregister(struct of_device *ofdev) | |||
208 | device_unregister(&ofdev->dev); | 121 | device_unregister(&ofdev->dev); |
209 | } | 122 | } |
210 | 123 | ||
211 | struct of_device* of_platform_device_create(struct device_node *np, | ||
212 | const char *bus_id, | ||
213 | struct device *parent) | ||
214 | { | ||
215 | struct of_device *dev; | ||
216 | |||
217 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | ||
218 | if (!dev) | ||
219 | return NULL; | ||
220 | memset(dev, 0, sizeof(*dev)); | ||
221 | |||
222 | dev->node = of_node_get(np); | ||
223 | dev->dma_mask = 0xffffffffUL; | ||
224 | dev->dev.dma_mask = &dev->dma_mask; | ||
225 | dev->dev.parent = parent; | ||
226 | dev->dev.bus = &of_platform_bus_type; | ||
227 | dev->dev.release = of_release_dev; | ||
228 | |||
229 | strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); | ||
230 | |||
231 | if (of_device_register(dev) != 0) { | ||
232 | kfree(dev); | ||
233 | return NULL; | ||
234 | } | ||
235 | |||
236 | return dev; | ||
237 | } | ||
238 | 124 | ||
125 | EXPORT_SYMBOL(of_match_node); | ||
239 | EXPORT_SYMBOL(of_match_device); | 126 | EXPORT_SYMBOL(of_match_device); |
240 | EXPORT_SYMBOL(of_platform_bus_type); | ||
241 | EXPORT_SYMBOL(of_register_driver); | ||
242 | EXPORT_SYMBOL(of_unregister_driver); | ||
243 | EXPORT_SYMBOL(of_device_register); | 127 | EXPORT_SYMBOL(of_device_register); |
244 | EXPORT_SYMBOL(of_device_unregister); | 128 | EXPORT_SYMBOL(of_device_unregister); |
245 | EXPORT_SYMBOL(of_dev_get); | 129 | EXPORT_SYMBOL(of_dev_get); |
246 | EXPORT_SYMBOL(of_dev_put); | 130 | EXPORT_SYMBOL(of_dev_put); |
247 | EXPORT_SYMBOL(of_platform_device_create); | ||
248 | EXPORT_SYMBOL(of_release_dev); | 131 | EXPORT_SYMBOL(of_release_dev); |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c new file mode 100644 index 00000000000..b3189d0161b --- /dev/null +++ b/arch/powerpc/kernel/of_platform.c | |||
@@ -0,0 +1,489 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. | ||
3 | * <benh@kernel.crashing.org> | ||
4 | * and Arnd Bergmann, IBM Corp. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #undef DEBUG | ||
14 | |||
15 | #include <linux/string.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/mod_devicetable.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/pci.h> | ||
22 | |||
23 | #include <asm/errno.h> | ||
24 | #include <asm/dcr.h> | ||
25 | #include <asm/of_device.h> | ||
26 | #include <asm/of_platform.h> | ||
27 | #include <asm/topology.h> | ||
28 | #include <asm/pci-bridge.h> | ||
29 | #include <asm/ppc-pci.h> | ||
30 | #include <asm/atomic.h> | ||
31 | |||
32 | |||
33 | /* | ||
34 | * The list of OF IDs below is used for matching bus types in the | ||
35 | * system whose devices are to be exposed as of_platform_devices. | ||
36 | * | ||
37 | * This is the default list valid for most platforms. This file provides | ||
38 | * functions who can take an explicit list if necessary though | ||
39 | * | ||
40 | * The search is always performed recursively looking for children of | ||
41 | * the provided device_node and recursively if such a children matches | ||
42 | * a bus type in the list | ||
43 | */ | ||
44 | |||
45 | static struct of_device_id of_default_bus_ids[] = { | ||
46 | { .type = "soc", }, | ||
47 | { .compatible = "soc", }, | ||
48 | { .type = "spider", }, | ||
49 | { .type = "axon", }, | ||
50 | { .type = "plb5", }, | ||
51 | { .type = "plb4", }, | ||
52 | { .type = "opb", }, | ||
53 | {}, | ||
54 | }; | ||
55 | |||
56 | static atomic_t bus_no_reg_magic; | ||
57 | |||
58 | /* | ||
59 | * | ||
60 | * OF platform device type definition & base infrastructure | ||
61 | * | ||
62 | */ | ||
63 | |||
64 | static int of_platform_bus_match(struct device *dev, struct device_driver *drv) | ||
65 | { | ||
66 | struct of_device * of_dev = to_of_device(dev); | ||
67 | struct of_platform_driver * of_drv = to_of_platform_driver(drv); | ||
68 | const struct of_device_id * matches = of_drv->match_table; | ||
69 | |||
70 | if (!matches) | ||
71 | return 0; | ||
72 | |||
73 | return of_match_device(matches, of_dev) != NULL; | ||
74 | } | ||
75 | |||
76 | static int of_platform_device_probe(struct device *dev) | ||
77 | { | ||
78 | int error = -ENODEV; | ||
79 | struct of_platform_driver *drv; | ||
80 | struct of_device *of_dev; | ||
81 | const struct of_device_id *match; | ||
82 | |||
83 | drv = to_of_platform_driver(dev->driver); | ||
84 | of_dev = to_of_device(dev); | ||
85 | |||
86 | if (!drv->probe) | ||
87 | return error; | ||
88 | |||
89 | of_dev_get(of_dev); | ||
90 | |||
91 | match = of_match_device(drv->match_table, of_dev); | ||
92 | if (match) | ||
93 | error = drv->probe(of_dev, match); | ||
94 | if (error) | ||
95 | of_dev_put(of_dev); | ||
96 | |||
97 | return error; | ||
98 | } | ||
99 | |||
100 | static int of_platform_device_remove(struct device *dev) | ||
101 | { | ||
102 | struct of_device * of_dev = to_of_device(dev); | ||
103 | struct of_platform_driver * drv = to_of_platform_driver(dev->driver); | ||
104 | |||
105 | if (dev->driver && drv->remove) | ||
106 | drv->remove(of_dev); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int of_platform_device_suspend(struct device *dev, pm_message_t state) | ||
111 | { | ||
112 | struct of_device * of_dev = to_of_device(dev); | ||
113 | struct of_platform_driver * drv = to_of_platform_driver(dev->driver); | ||
114 | int error = 0; | ||
115 | |||
116 | if (dev->driver && drv->suspend) | ||
117 | error = drv->suspend(of_dev, state); | ||
118 | return error; | ||
119 | } | ||
120 | |||
121 | static int of_platform_device_resume(struct device * dev) | ||
122 | { | ||
123 | struct of_device * of_dev = to_of_device(dev); | ||
124 | struct of_platform_driver * drv = to_of_platform_driver(dev->driver); | ||
125 | int error = 0; | ||
126 | |||
127 | if (dev->driver && drv->resume) | ||
128 | error = drv->resume(of_dev); | ||
129 | return error; | ||
130 | } | ||
131 | |||
132 | struct bus_type of_platform_bus_type = { | ||
133 | .name = "of_platform", | ||
134 | .match = of_platform_bus_match, | ||
135 | .probe = of_platform_device_probe, | ||
136 | .remove = of_platform_device_remove, | ||
137 | .suspend = of_platform_device_suspend, | ||
138 | .resume = of_platform_device_resume, | ||
139 | }; | ||
140 | EXPORT_SYMBOL(of_platform_bus_type); | ||
141 | |||
142 | static int __init of_bus_driver_init(void) | ||
143 | { | ||
144 | return bus_register(&of_platform_bus_type); | ||
145 | } | ||
146 | |||
147 | postcore_initcall(of_bus_driver_init); | ||
148 | |||
149 | int of_register_platform_driver(struct of_platform_driver *drv) | ||
150 | { | ||
151 | /* initialize common driver fields */ | ||
152 | drv->driver.name = drv->name; | ||
153 | drv->driver.bus = &of_platform_bus_type; | ||
154 | |||
155 | /* register with core */ | ||
156 | return driver_register(&drv->driver); | ||
157 | } | ||
158 | EXPORT_SYMBOL(of_register_platform_driver); | ||
159 | |||
160 | void of_unregister_platform_driver(struct of_platform_driver *drv) | ||
161 | { | ||
162 | driver_unregister(&drv->driver); | ||
163 | } | ||
164 | EXPORT_SYMBOL(of_unregister_platform_driver); | ||
165 | |||
166 | static void of_platform_make_bus_id(struct of_device *dev) | ||
167 | { | ||
168 | struct device_node *node = dev->node; | ||
169 | char *name = dev->dev.bus_id; | ||
170 | const u32 *reg; | ||
171 | u64 addr; | ||
172 | long magic; | ||
173 | |||
174 | /* | ||
175 | * If it's a DCR based device, use 'd' for native DCRs | ||
176 | * and 'D' for MMIO DCRs. | ||
177 | */ | ||
178 | #ifdef CONFIG_PPC_DCR | ||
179 | reg = get_property(node, "dcr-reg", NULL); | ||
180 | if (reg) { | ||
181 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
182 | snprintf(name, BUS_ID_SIZE, "d%x.%s", | ||
183 | *reg, node->name); | ||
184 | #else /* CONFIG_PPC_DCR_NATIVE */ | ||
185 | addr = of_translate_dcr_address(node, *reg, NULL); | ||
186 | if (addr != OF_BAD_ADDR) { | ||
187 | snprintf(name, BUS_ID_SIZE, | ||
188 | "D%llx.%s", (unsigned long long)addr, | ||
189 | node->name); | ||
190 | return; | ||
191 | } | ||
192 | #endif /* !CONFIG_PPC_DCR_NATIVE */ | ||
193 | } | ||
194 | #endif /* CONFIG_PPC_DCR */ | ||
195 | |||
196 | /* | ||
197 | * For MMIO, get the physical address | ||
198 | */ | ||
199 | reg = get_property(node, "reg", NULL); | ||
200 | if (reg) { | ||
201 | addr = of_translate_address(node, reg); | ||
202 | if (addr != OF_BAD_ADDR) { | ||
203 | snprintf(name, BUS_ID_SIZE, | ||
204 | "%llx.%s", (unsigned long long)addr, | ||
205 | node->name); | ||
206 | return; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * No BusID, use the node name and add a globally incremented | ||
212 | * counter (and pray...) | ||
213 | */ | ||
214 | magic = atomic_add_return(1, &bus_no_reg_magic); | ||
215 | snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); | ||
216 | } | ||
217 | |||
218 | struct of_device* of_platform_device_create(struct device_node *np, | ||
219 | const char *bus_id, | ||
220 | struct device *parent) | ||
221 | { | ||
222 | struct of_device *dev; | ||
223 | |||
224 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | ||
225 | if (!dev) | ||
226 | return NULL; | ||
227 | memset(dev, 0, sizeof(*dev)); | ||
228 | |||
229 | dev->node = of_node_get(np); | ||
230 | dev->dma_mask = 0xffffffffUL; | ||
231 | dev->dev.dma_mask = &dev->dma_mask; | ||
232 | dev->dev.parent = parent; | ||
233 | dev->dev.bus = &of_platform_bus_type; | ||
234 | dev->dev.release = of_release_dev; | ||
235 | dev->dev.archdata.of_node = np; | ||
236 | dev->dev.archdata.numa_node = of_node_to_nid(np); | ||
237 | |||
238 | /* We do not fill the DMA ops for platform devices by default. | ||
239 | * This is currently the responsibility of the platform code | ||
240 | * to do such, possibly using a device notifier | ||
241 | */ | ||
242 | |||
243 | if (bus_id) | ||
244 | strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); | ||
245 | else | ||
246 | of_platform_make_bus_id(dev); | ||
247 | |||
248 | if (of_device_register(dev) != 0) { | ||
249 | kfree(dev); | ||
250 | return NULL; | ||
251 | } | ||
252 | |||
253 | return dev; | ||
254 | } | ||
255 | EXPORT_SYMBOL(of_platform_device_create); | ||
256 | |||
257 | |||
258 | |||
259 | /** | ||
260 | * of_platform_bus_create - Create an OF device for a bus node and all its | ||
261 | * children. Optionally recursively instanciate matching busses. | ||
262 | * @bus: device node of the bus to instanciate | ||
263 | * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to | ||
264 | * disallow recursive creation of child busses | ||
265 | */ | ||
266 | static int of_platform_bus_create(struct device_node *bus, | ||
267 | struct of_device_id *matches, | ||
268 | struct device *parent) | ||
269 | { | ||
270 | struct device_node *child; | ||
271 | struct of_device *dev; | ||
272 | int rc = 0; | ||
273 | |||
274 | for (child = NULL; (child = of_get_next_child(bus, child)); ) { | ||
275 | pr_debug(" create child: %s\n", child->full_name); | ||
276 | dev = of_platform_device_create(child, NULL, parent); | ||
277 | if (dev == NULL) | ||
278 | rc = -ENOMEM; | ||
279 | else if (!of_match_node(matches, child)) | ||
280 | continue; | ||
281 | if (rc == 0) { | ||
282 | pr_debug(" and sub busses\n"); | ||
283 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
284 | } if (rc) { | ||
285 | of_node_put(child); | ||
286 | break; | ||
287 | } | ||
288 | } | ||
289 | return rc; | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * of_platform_bus_probe - Probe the device-tree for platform busses | ||
294 | * @root: parent of the first level to probe or NULL for the root of the tree | ||
295 | * @matches: match table, NULL to use the default | ||
296 | * @parent: parent to hook devices from, NULL for toplevel | ||
297 | * | ||
298 | * Note that children of the provided root are not instanciated as devices | ||
299 | * unless the specified root itself matches the bus list and is not NULL. | ||
300 | */ | ||
301 | |||
302 | int of_platform_bus_probe(struct device_node *root, | ||
303 | struct of_device_id *matches, | ||
304 | struct device *parent) | ||
305 | { | ||
306 | struct device_node *child; | ||
307 | struct of_device *dev; | ||
308 | int rc = 0; | ||
309 | |||
310 | if (matches == NULL) | ||
311 | matches = of_default_bus_ids; | ||
312 | if (matches == OF_NO_DEEP_PROBE) | ||
313 | return -EINVAL; | ||
314 | if (root == NULL) | ||
315 | root = of_find_node_by_path("/"); | ||
316 | else | ||
317 | of_node_get(root); | ||
318 | |||
319 | pr_debug("of_platform_bus_probe()\n"); | ||
320 | pr_debug(" starting at: %s\n", root->full_name); | ||
321 | |||
322 | /* Do a self check of bus type, if there's a match, create | ||
323 | * children | ||
324 | */ | ||
325 | if (of_match_node(matches, root)) { | ||
326 | pr_debug(" root match, create all sub devices\n"); | ||
327 | dev = of_platform_device_create(root, NULL, parent); | ||
328 | if (dev == NULL) { | ||
329 | rc = -ENOMEM; | ||
330 | goto bail; | ||
331 | } | ||
332 | pr_debug(" create all sub busses\n"); | ||
333 | rc = of_platform_bus_create(root, matches, &dev->dev); | ||
334 | goto bail; | ||
335 | } | ||
336 | for (child = NULL; (child = of_get_next_child(root, child)); ) { | ||
337 | if (!of_match_node(matches, child)) | ||
338 | continue; | ||
339 | |||
340 | pr_debug(" match: %s\n", child->full_name); | ||
341 | dev = of_platform_device_create(child, NULL, parent); | ||
342 | if (dev == NULL) | ||
343 | rc = -ENOMEM; | ||
344 | else | ||
345 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
346 | if (rc) { | ||
347 | of_node_put(child); | ||
348 | break; | ||
349 | } | ||
350 | } | ||
351 | bail: | ||
352 | of_node_put(root); | ||
353 | return rc; | ||
354 | } | ||
355 | EXPORT_SYMBOL(of_platform_bus_probe); | ||
356 | |||
357 | static int of_dev_node_match(struct device *dev, void *data) | ||
358 | { | ||
359 | return to_of_device(dev)->node == data; | ||
360 | } | ||
361 | |||
362 | struct of_device *of_find_device_by_node(struct device_node *np) | ||
363 | { | ||
364 | struct device *dev; | ||
365 | |||
366 | dev = bus_find_device(&of_platform_bus_type, | ||
367 | NULL, np, of_dev_node_match); | ||
368 | if (dev) | ||
369 | return to_of_device(dev); | ||
370 | return NULL; | ||
371 | } | ||
372 | EXPORT_SYMBOL(of_find_device_by_node); | ||
373 | |||
374 | static int of_dev_phandle_match(struct device *dev, void *data) | ||
375 | { | ||
376 | phandle *ph = data; | ||
377 | return to_of_device(dev)->node->linux_phandle == *ph; | ||
378 | } | ||
379 | |||
380 | struct of_device *of_find_device_by_phandle(phandle ph) | ||
381 | { | ||
382 | struct device *dev; | ||
383 | |||
384 | dev = bus_find_device(&of_platform_bus_type, | ||
385 | NULL, &ph, of_dev_phandle_match); | ||
386 | if (dev) | ||
387 | return to_of_device(dev); | ||
388 | return NULL; | ||
389 | } | ||
390 | EXPORT_SYMBOL(of_find_device_by_phandle); | ||
391 | |||
392 | |||
393 | #ifdef CONFIG_PPC_OF_PLATFORM_PCI | ||
394 | |||
395 | /* The probing of PCI controllers from of_platform is currently | ||
396 | * 64 bits only, mostly due to gratuitous differences between | ||
397 | * the 32 and 64 bits PCI code on PowerPC and the 32 bits one | ||
398 | * lacking some bits needed here. | ||
399 | */ | ||
400 | |||
401 | static int __devinit of_pci_phb_probe(struct of_device *dev, | ||
402 | const struct of_device_id *match) | ||
403 | { | ||
404 | struct pci_controller *phb; | ||
405 | |||
406 | /* Check if we can do that ... */ | ||
407 | if (ppc_md.pci_setup_phb == NULL) | ||
408 | return -ENODEV; | ||
409 | |||
410 | printk(KERN_INFO "Setting up PCI bus %s\n", dev->node->full_name); | ||
411 | |||
412 | /* Alloc and setup PHB data structure */ | ||
413 | phb = pcibios_alloc_controller(dev->node); | ||
414 | if (!phb) | ||
415 | return -ENODEV; | ||
416 | |||
417 | /* Setup parent in sysfs */ | ||
418 | phb->parent = &dev->dev; | ||
419 | |||
420 | /* Setup the PHB using arch provided callback */ | ||
421 | if (ppc_md.pci_setup_phb(phb)) { | ||
422 | pcibios_free_controller(phb); | ||
423 | return -ENODEV; | ||
424 | } | ||
425 | |||
426 | /* Process "ranges" property */ | ||
427 | pci_process_bridge_OF_ranges(phb, dev->node, 0); | ||
428 | |||
429 | /* Setup IO space. | ||
430 | * This will not work properly for ISA IOs, something needs to be done | ||
431 | * about it if we ever generalize that way of probing PCI brigdes | ||
432 | */ | ||
433 | pci_setup_phb_io_dynamic(phb, 0); | ||
434 | |||
435 | /* Init pci_dn data structures */ | ||
436 | pci_devs_phb_init_dynamic(phb); | ||
437 | |||
438 | /* Register devices with EEH */ | ||
439 | #ifdef CONFIG_EEH | ||
440 | if (dev->node->child) | ||
441 | eeh_add_device_tree_early(dev->node); | ||
442 | #endif /* CONFIG_EEH */ | ||
443 | |||
444 | /* Scan the bus */ | ||
445 | scan_phb(phb); | ||
446 | |||
447 | /* Claim resources. This might need some rework as well depending | ||
448 | * wether we are doing probe-only or not, like assigning unassigned | ||
449 | * resources etc... | ||
450 | */ | ||
451 | pcibios_claim_one_bus(phb->bus); | ||
452 | |||
453 | /* Finish EEH setup */ | ||
454 | #ifdef CONFIG_EEH | ||
455 | eeh_add_device_tree_late(phb->bus); | ||
456 | #endif | ||
457 | |||
458 | /* Add probed PCI devices to the device model */ | ||
459 | pci_bus_add_devices(phb->bus); | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static struct of_device_id of_pci_phb_ids[] = { | ||
465 | { .type = "pci", }, | ||
466 | { .type = "pcix", }, | ||
467 | { .type = "pcie", }, | ||
468 | { .type = "pciex", }, | ||
469 | { .type = "ht", }, | ||
470 | {} | ||
471 | }; | ||
472 | |||
473 | static struct of_platform_driver of_pci_phb_driver = { | ||
474 | .name = "of-pci", | ||
475 | .match_table = of_pci_phb_ids, | ||
476 | .probe = of_pci_phb_probe, | ||
477 | .driver = { | ||
478 | .multithread_probe = 1, | ||
479 | }, | ||
480 | }; | ||
481 | |||
482 | static __init int of_pci_phb_init(void) | ||
483 | { | ||
484 | return of_register_platform_driver(&of_pci_phb_driver); | ||
485 | } | ||
486 | |||
487 | device_initcall(of_pci_phb_init); | ||
488 | |||
489 | #endif /* CONFIG_PPC_OF_PLATFORM_PCI */ | ||
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 0d9ff72e285..2f54cd81dea 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/bootmem.h> | 13 | #include <linux/bootmem.h> |
14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
15 | #include <linux/list.h> | ||
15 | 16 | ||
16 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
@@ -99,7 +100,7 @@ pcibios_fixup_resources(struct pci_dev *dev) | |||
99 | continue; | 100 | continue; |
100 | if (res->end == 0xffffffff) { | 101 | if (res->end == 0xffffffff) { |
101 | DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n", | 102 | DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n", |
102 | pci_name(dev), i, res->start, res->end); | 103 | pci_name(dev), i, (u64)res->start, (u64)res->end); |
103 | res->end -= res->start; | 104 | res->end -= res->start; |
104 | res->start = 0; | 105 | res->start = 0; |
105 | res->flags |= IORESOURCE_UNSET; | 106 | res->flags |= IORESOURCE_UNSET; |
@@ -115,11 +116,9 @@ pcibios_fixup_resources(struct pci_dev *dev) | |||
115 | if (offset != 0) { | 116 | if (offset != 0) { |
116 | res->start += offset; | 117 | res->start += offset; |
117 | res->end += offset; | 118 | res->end += offset; |
118 | #ifdef DEBUG | 119 | DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n", |
119 | printk("Fixup res %d (%lx) of dev %s: %llx -> %llx\n", | 120 | i, res->flags, pci_name(dev), |
120 | i, res->flags, pci_name(dev), | 121 | (u64)res->start - offset, (u64)res->start); |
121 | res->start - offset, res->start); | ||
122 | #endif | ||
123 | } | 122 | } |
124 | } | 123 | } |
125 | 124 | ||
@@ -255,7 +254,7 @@ pcibios_allocate_bus_resources(struct list_head *bus_list) | |||
255 | } | 254 | } |
256 | 255 | ||
257 | DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n", | 256 | DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n", |
258 | res->start, res->end, res->flags, pr); | 257 | (u64)res->start, (u64)res->end, res->flags, pr); |
259 | if (pr) { | 258 | if (pr) { |
260 | if (request_resource(pr, res) == 0) | 259 | if (request_resource(pr, res) == 0) |
261 | continue; | 260 | continue; |
@@ -306,7 +305,7 @@ reparent_resources(struct resource *parent, struct resource *res) | |||
306 | for (p = res->child; p != NULL; p = p->sibling) { | 305 | for (p = res->child; p != NULL; p = p->sibling) { |
307 | p->parent = res; | 306 | p->parent = res; |
308 | DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n", | 307 | DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n", |
309 | p->name, p->start, p->end, res->name); | 308 | p->name, (u64)p->start, (u64)p->end, res->name); |
310 | } | 309 | } |
311 | return 0; | 310 | return 0; |
312 | } | 311 | } |
@@ -362,7 +361,7 @@ pci_relocate_bridge_resource(struct pci_bus *bus, int i) | |||
362 | } | 361 | } |
363 | if (request_resource(pr, res)) { | 362 | if (request_resource(pr, res)) { |
364 | DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n", | 363 | DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n", |
365 | res->start, res->end); | 364 | (u64)res->start, (u64)res->end); |
366 | return -1; /* "can't happen" */ | 365 | return -1; /* "can't happen" */ |
367 | } | 366 | } |
368 | update_bridge_base(bus, i); | 367 | update_bridge_base(bus, i); |
@@ -480,14 +479,14 @@ static inline void alloc_resource(struct pci_dev *dev, int idx) | |||
480 | struct resource *pr, *r = &dev->resource[idx]; | 479 | struct resource *pr, *r = &dev->resource[idx]; |
481 | 480 | ||
482 | DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n", | 481 | DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n", |
483 | pci_name(dev), idx, r->start, r->end, r->flags); | 482 | pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags); |
484 | pr = pci_find_parent_resource(dev, r); | 483 | pr = pci_find_parent_resource(dev, r); |
485 | if (!pr || request_resource(pr, r) < 0) { | 484 | if (!pr || request_resource(pr, r) < 0) { |
486 | printk(KERN_ERR "PCI: Cannot allocate resource region %d" | 485 | printk(KERN_ERR "PCI: Cannot allocate resource region %d" |
487 | " of device %s\n", idx, pci_name(dev)); | 486 | " of device %s\n", idx, pci_name(dev)); |
488 | if (pr) | 487 | if (pr) |
489 | DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n", | 488 | DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n", |
490 | pr, pr->start, pr->end, pr->flags); | 489 | pr, (u64)pr->start, (u64)pr->end, pr->flags); |
491 | /* We'll assign a new address later */ | 490 | /* We'll assign a new address later */ |
492 | r->flags |= IORESOURCE_UNSET; | 491 | r->flags |= IORESOURCE_UNSET; |
493 | r->end -= r->start; | 492 | r->end -= r->start; |
@@ -960,7 +959,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
960 | res->flags = IORESOURCE_IO; | 959 | res->flags = IORESOURCE_IO; |
961 | res->start = ranges[2]; | 960 | res->start = ranges[2]; |
962 | DBG("PCI: IO 0x%llx -> 0x%llx\n", | 961 | DBG("PCI: IO 0x%llx -> 0x%llx\n", |
963 | res->start, res->start + size - 1); | 962 | (u64)res->start, (u64)res->start + size - 1); |
964 | break; | 963 | break; |
965 | case 2: /* memory space */ | 964 | case 2: /* memory space */ |
966 | memno = 0; | 965 | memno = 0; |
@@ -982,7 +981,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
982 | res->flags |= IORESOURCE_PREFETCH; | 981 | res->flags |= IORESOURCE_PREFETCH; |
983 | res->start = ranges[na+2]; | 982 | res->start = ranges[na+2]; |
984 | DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno, | 983 | DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno, |
985 | res->start, res->start + size - 1); | 984 | (u64)res->start, (u64)res->start + size - 1); |
986 | } | 985 | } |
987 | break; | 986 | break; |
988 | } | 987 | } |
@@ -1268,7 +1267,10 @@ pcibios_init(void) | |||
1268 | if (pci_assign_all_buses) | 1267 | if (pci_assign_all_buses) |
1269 | hose->first_busno = next_busno; | 1268 | hose->first_busno = next_busno; |
1270 | hose->last_busno = 0xff; | 1269 | hose->last_busno = 0xff; |
1271 | bus = pci_scan_bus(hose->first_busno, hose->ops, hose); | 1270 | bus = pci_scan_bus_parented(hose->parent, hose->first_busno, |
1271 | hose->ops, hose); | ||
1272 | if (bus) | ||
1273 | pci_bus_add_devices(bus); | ||
1272 | hose->last_busno = bus->subordinate; | 1274 | hose->last_busno = bus->subordinate; |
1273 | if (pci_assign_all_buses || next_busno <= hose->last_busno) | 1275 | if (pci_assign_all_buses || next_busno <= hose->last_busno) |
1274 | next_busno = hose->last_busno + pcibios_assign_bus_offset; | 1276 | next_busno = hose->last_busno + pcibios_assign_bus_offset; |
@@ -1282,10 +1284,6 @@ pcibios_init(void) | |||
1282 | if (pci_assign_all_buses && have_of) | 1284 | if (pci_assign_all_buses && have_of) |
1283 | pcibios_make_OF_bus_map(); | 1285 | pcibios_make_OF_bus_map(); |
1284 | 1286 | ||
1285 | /* Do machine dependent PCI interrupt routing */ | ||
1286 | if (ppc_md.pci_swizzle && ppc_md.pci_map_irq) | ||
1287 | pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq); | ||
1288 | |||
1289 | /* Call machine dependent fixup */ | 1287 | /* Call machine dependent fixup */ |
1290 | if (ppc_md.pcibios_fixup) | 1288 | if (ppc_md.pcibios_fixup) |
1291 | ppc_md.pcibios_fixup(); | 1289 | ppc_md.pcibios_fixup(); |
@@ -1308,25 +1306,6 @@ pcibios_init(void) | |||
1308 | 1306 | ||
1309 | subsys_initcall(pcibios_init); | 1307 | subsys_initcall(pcibios_init); |
1310 | 1308 | ||
1311 | unsigned char __init | ||
1312 | common_swizzle(struct pci_dev *dev, unsigned char *pinp) | ||
1313 | { | ||
1314 | struct pci_controller *hose = dev->sysdata; | ||
1315 | |||
1316 | if (dev->bus->number != hose->first_busno) { | ||
1317 | u8 pin = *pinp; | ||
1318 | do { | ||
1319 | pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); | ||
1320 | /* Move up the chain of bridges. */ | ||
1321 | dev = dev->bus->self; | ||
1322 | } while (dev->bus->self); | ||
1323 | *pinp = pin; | ||
1324 | |||
1325 | /* The slot is the idsel of the last bridge. */ | ||
1326 | } | ||
1327 | return PCI_SLOT(dev->devfn); | ||
1328 | } | ||
1329 | |||
1330 | unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, | 1309 | unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, |
1331 | unsigned long start, unsigned long size) | 1310 | unsigned long start, unsigned long size) |
1332 | { | 1311 | { |
@@ -1338,6 +1317,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
1338 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; | 1317 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; |
1339 | unsigned long io_offset; | 1318 | unsigned long io_offset; |
1340 | struct resource *res; | 1319 | struct resource *res; |
1320 | struct pci_dev *dev; | ||
1341 | int i; | 1321 | int i; |
1342 | 1322 | ||
1343 | io_offset = (unsigned long)hose->io_base_virt - isa_io_base; | 1323 | io_offset = (unsigned long)hose->io_base_virt - isa_io_base; |
@@ -1390,8 +1370,16 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
1390 | } | 1370 | } |
1391 | } | 1371 | } |
1392 | 1372 | ||
1373 | /* Platform specific bus fixups */ | ||
1393 | if (ppc_md.pcibios_fixup_bus) | 1374 | if (ppc_md.pcibios_fixup_bus) |
1394 | ppc_md.pcibios_fixup_bus(bus); | 1375 | ppc_md.pcibios_fixup_bus(bus); |
1376 | |||
1377 | /* Read default IRQs and fixup if necessary */ | ||
1378 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
1379 | pci_read_irq_line(dev); | ||
1380 | if (ppc_md.pci_irq_fixup) | ||
1381 | ppc_md.pci_irq_fixup(dev); | ||
1382 | } | ||
1395 | } | 1383 | } |
1396 | 1384 | ||
1397 | char __init *pcibios_setup(char *str) | 1385 | char __init *pcibios_setup(char *str) |
@@ -1571,7 +1559,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | |||
1571 | *offset += hose->pci_mem_offset; | 1559 | *offset += hose->pci_mem_offset; |
1572 | res_bit = IORESOURCE_MEM; | 1560 | res_bit = IORESOURCE_MEM; |
1573 | } else { | 1561 | } else { |
1574 | io_offset = hose->io_base_virt - ___IO_BASE; | 1562 | io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; |
1575 | *offset += io_offset; | 1563 | *offset += io_offset; |
1576 | res_bit = IORESOURCE_IO; | 1564 | res_bit = IORESOURCE_IO; |
1577 | } | 1565 | } |
@@ -1826,7 +1814,8 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, | |||
1826 | return; | 1814 | return; |
1827 | 1815 | ||
1828 | if (rsrc->flags & IORESOURCE_IO) | 1816 | if (rsrc->flags & IORESOURCE_IO) |
1829 | offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; | 1817 | offset = (void __iomem *)_IO_BASE - hose->io_base_virt |
1818 | + hose->io_base_phys; | ||
1830 | 1819 | ||
1831 | *start = rsrc->start + offset; | 1820 | *start = rsrc->start + offset; |
1832 | *end = rsrc->end + offset; | 1821 | *end = rsrc->end + offset; |
@@ -1845,35 +1834,6 @@ pci_init_resource(struct resource *res, unsigned long start, unsigned long end, | |||
1845 | res->child = NULL; | 1834 | res->child = NULL; |
1846 | } | 1835 | } |
1847 | 1836 | ||
1848 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) | ||
1849 | { | ||
1850 | unsigned long start = pci_resource_start(dev, bar); | ||
1851 | unsigned long len = pci_resource_len(dev, bar); | ||
1852 | unsigned long flags = pci_resource_flags(dev, bar); | ||
1853 | |||
1854 | if (!len) | ||
1855 | return NULL; | ||
1856 | if (max && len > max) | ||
1857 | len = max; | ||
1858 | if (flags & IORESOURCE_IO) | ||
1859 | return ioport_map(start, len); | ||
1860 | if (flags & IORESOURCE_MEM) | ||
1861 | /* Not checking IORESOURCE_CACHEABLE because PPC does | ||
1862 | * not currently distinguish between ioremap and | ||
1863 | * ioremap_nocache. | ||
1864 | */ | ||
1865 | return ioremap(start, len); | ||
1866 | /* What? */ | ||
1867 | return NULL; | ||
1868 | } | ||
1869 | |||
1870 | void pci_iounmap(struct pci_dev *dev, void __iomem *addr) | ||
1871 | { | ||
1872 | /* Nothing to do */ | ||
1873 | } | ||
1874 | EXPORT_SYMBOL(pci_iomap); | ||
1875 | EXPORT_SYMBOL(pci_iounmap); | ||
1876 | |||
1877 | unsigned long pci_address_to_pio(phys_addr_t address) | 1837 | unsigned long pci_address_to_pio(phys_addr_t address) |
1878 | { | 1838 | { |
1879 | struct pci_controller* hose = hose_head; | 1839 | struct pci_controller* hose = hose_head; |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 9bae8a5bf67..6fa9a0a5c8d 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -42,11 +42,9 @@ | |||
42 | unsigned long pci_probe_only = 1; | 42 | unsigned long pci_probe_only = 1; |
43 | int pci_assign_all_buses = 0; | 43 | int pci_assign_all_buses = 0; |
44 | 44 | ||
45 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
46 | static void fixup_resource(struct resource *res, struct pci_dev *dev); | 45 | static void fixup_resource(struct resource *res, struct pci_dev *dev); |
47 | static void do_bus_setup(struct pci_bus *bus); | 46 | static void do_bus_setup(struct pci_bus *bus); |
48 | static void phbs_remap_io(void); | 47 | static void phbs_remap_io(void); |
49 | #endif | ||
50 | 48 | ||
51 | /* pci_io_base -- the base address from which io bars are offsets. | 49 | /* pci_io_base -- the base address from which io bars are offsets. |
52 | * This is the lowest I/O base address (so bar values are always positive), | 50 | * This is the lowest I/O base address (so bar values are always positive), |
@@ -63,7 +61,7 @@ void iSeries_pcibios_init(void); | |||
63 | 61 | ||
64 | LIST_HEAD(hose_list); | 62 | LIST_HEAD(hose_list); |
65 | 63 | ||
66 | struct dma_mapping_ops pci_dma_ops; | 64 | struct dma_mapping_ops *pci_dma_ops; |
67 | EXPORT_SYMBOL(pci_dma_ops); | 65 | EXPORT_SYMBOL(pci_dma_ops); |
68 | 66 | ||
69 | int global_phb_number; /* Global phb counter */ | 67 | int global_phb_number; /* Global phb counter */ |
@@ -212,6 +210,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | |||
212 | 210 | ||
213 | void pcibios_free_controller(struct pci_controller *phb) | 211 | void pcibios_free_controller(struct pci_controller *phb) |
214 | { | 212 | { |
213 | spin_lock(&hose_spinlock); | ||
214 | list_del(&phb->list_node); | ||
215 | spin_unlock(&hose_spinlock); | ||
216 | |||
215 | if (phb->is_dynamic) | 217 | if (phb->is_dynamic) |
216 | kfree(phb); | 218 | kfree(phb); |
217 | } | 219 | } |
@@ -251,7 +253,6 @@ static void __init pcibios_claim_of_setup(void) | |||
251 | pcibios_claim_one_bus(b); | 253 | pcibios_claim_one_bus(b); |
252 | } | 254 | } |
253 | 255 | ||
254 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
255 | static u32 get_int_prop(struct device_node *np, const char *name, u32 def) | 256 | static u32 get_int_prop(struct device_node *np, const char *name, u32 def) |
256 | { | 257 | { |
257 | const u32 *prop; | 258 | const u32 *prop; |
@@ -329,7 +330,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
329 | struct pci_dev *dev; | 330 | struct pci_dev *dev; |
330 | const char *type; | 331 | const char *type; |
331 | 332 | ||
332 | dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | 333 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); |
333 | if (!dev) | 334 | if (!dev) |
334 | return NULL; | 335 | return NULL; |
335 | type = get_property(node, "device_type", NULL); | 336 | type = get_property(node, "device_type", NULL); |
@@ -338,7 +339,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
338 | 339 | ||
339 | DBG(" create device, devfn: %x, type: %s\n", devfn, type); | 340 | DBG(" create device, devfn: %x, type: %s\n", devfn, type); |
340 | 341 | ||
341 | memset(dev, 0, sizeof(struct pci_dev)); | ||
342 | dev->bus = bus; | 342 | dev->bus = bus; |
343 | dev->sysdata = node; | 343 | dev->sysdata = node; |
344 | dev->dev.parent = bus->bridge; | 344 | dev->dev.parent = bus->bridge; |
@@ -506,7 +506,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
506 | pci_scan_child_bus(bus); | 506 | pci_scan_child_bus(bus); |
507 | } | 507 | } |
508 | EXPORT_SYMBOL(of_scan_pci_bridge); | 508 | EXPORT_SYMBOL(of_scan_pci_bridge); |
509 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
510 | 509 | ||
511 | void __devinit scan_phb(struct pci_controller *hose) | 510 | void __devinit scan_phb(struct pci_controller *hose) |
512 | { | 511 | { |
@@ -517,7 +516,7 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
517 | 516 | ||
518 | DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>"); | 517 | DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>"); |
519 | 518 | ||
520 | bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node); | 519 | bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node); |
521 | if (bus == NULL) { | 520 | if (bus == NULL) { |
522 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", | 521 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", |
523 | hose->global_number); | 522 | hose->global_number); |
@@ -540,7 +539,7 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
540 | } | 539 | } |
541 | 540 | ||
542 | mode = PCI_PROBE_NORMAL; | 541 | mode = PCI_PROBE_NORMAL; |
543 | #ifdef CONFIG_PPC_MULTIPLATFORM | 542 | |
544 | if (node && ppc_md.pci_probe_mode) | 543 | if (node && ppc_md.pci_probe_mode) |
545 | mode = ppc_md.pci_probe_mode(bus); | 544 | mode = ppc_md.pci_probe_mode(bus); |
546 | DBG(" probe mode: %d\n", mode); | 545 | DBG(" probe mode: %d\n", mode); |
@@ -548,7 +547,7 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
548 | bus->subordinate = hose->last_busno; | 547 | bus->subordinate = hose->last_busno; |
549 | of_scan_bus(node, bus); | 548 | of_scan_bus(node, bus); |
550 | } | 549 | } |
551 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 550 | |
552 | if (mode == PCI_PROBE_NORMAL) | 551 | if (mode == PCI_PROBE_NORMAL) |
553 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | 552 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); |
554 | } | 553 | } |
@@ -592,11 +591,9 @@ static int __init pcibios_init(void) | |||
592 | if (ppc64_isabridge_dev != NULL) | 591 | if (ppc64_isabridge_dev != NULL) |
593 | printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | 592 | printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); |
594 | 593 | ||
595 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
596 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | 594 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) |
597 | /* map in PCI I/O space */ | 595 | /* map in PCI I/O space */ |
598 | phbs_remap_io(); | 596 | phbs_remap_io(); |
599 | #endif | ||
600 | 597 | ||
601 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); | 598 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); |
602 | 599 | ||
@@ -873,8 +870,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev) | |||
873 | device_create_file(&pdev->dev, &dev_attr_devspec); | 870 | device_create_file(&pdev->dev, &dev_attr_devspec); |
874 | } | 871 | } |
875 | 872 | ||
876 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
877 | |||
878 | #define ISA_SPACE_MASK 0x1 | 873 | #define ISA_SPACE_MASK 0x1 |
879 | #define ISA_SPACE_IO 0x1 | 874 | #define ISA_SPACE_IO 0x1 |
880 | 875 | ||
@@ -975,11 +970,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
975 | res = NULL; | 970 | res = NULL; |
976 | pci_space = ranges[0]; | 971 | pci_space = ranges[0]; |
977 | pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2]; | 972 | pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2]; |
978 | 973 | cpu_phys_addr = of_translate_address(dev, &ranges[3]); | |
979 | cpu_phys_addr = ranges[3]; | ||
980 | if (na >= 2) | ||
981 | cpu_phys_addr = (cpu_phys_addr << 32) | ranges[4]; | ||
982 | |||
983 | size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4]; | 974 | size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4]; |
984 | ranges += np; | 975 | ranges += np; |
985 | if (size == 0) | 976 | if (size == 0) |
@@ -1145,7 +1136,7 @@ int unmap_bus_range(struct pci_bus *bus) | |||
1145 | 1136 | ||
1146 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | 1137 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) |
1147 | return 1; | 1138 | return 1; |
1148 | if (iounmap_explicit((void __iomem *) start_virt, size)) | 1139 | if (__iounmap_explicit((void __iomem *) start_virt, size)) |
1149 | return 1; | 1140 | return 1; |
1150 | 1141 | ||
1151 | return 0; | 1142 | return 0; |
@@ -1213,23 +1204,52 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | |||
1213 | } | 1204 | } |
1214 | EXPORT_SYMBOL(pcibios_fixup_device_resources); | 1205 | EXPORT_SYMBOL(pcibios_fixup_device_resources); |
1215 | 1206 | ||
1207 | void __devinit pcibios_setup_new_device(struct pci_dev *dev) | ||
1208 | { | ||
1209 | struct dev_archdata *sd = &dev->dev.archdata; | ||
1210 | |||
1211 | sd->of_node = pci_device_to_OF_node(dev); | ||
1212 | |||
1213 | DBG("PCI device %s OF node: %s\n", pci_name(dev), | ||
1214 | sd->of_node ? sd->of_node->full_name : "<none>"); | ||
1215 | |||
1216 | sd->dma_ops = pci_dma_ops; | ||
1217 | #ifdef CONFIG_NUMA | ||
1218 | sd->numa_node = pcibus_to_node(dev->bus); | ||
1219 | #else | ||
1220 | sd->numa_node = -1; | ||
1221 | #endif | ||
1222 | if (ppc_md.pci_dma_dev_setup) | ||
1223 | ppc_md.pci_dma_dev_setup(dev); | ||
1224 | } | ||
1225 | EXPORT_SYMBOL(pcibios_setup_new_device); | ||
1216 | 1226 | ||
1217 | static void __devinit do_bus_setup(struct pci_bus *bus) | 1227 | static void __devinit do_bus_setup(struct pci_bus *bus) |
1218 | { | 1228 | { |
1219 | struct pci_dev *dev; | 1229 | struct pci_dev *dev; |
1220 | 1230 | ||
1221 | ppc_md.iommu_bus_setup(bus); | 1231 | if (ppc_md.pci_dma_bus_setup) |
1232 | ppc_md.pci_dma_bus_setup(bus); | ||
1222 | 1233 | ||
1223 | list_for_each_entry(dev, &bus->devices, bus_list) | 1234 | list_for_each_entry(dev, &bus->devices, bus_list) |
1224 | ppc_md.iommu_dev_setup(dev); | 1235 | pcibios_setup_new_device(dev); |
1225 | 1236 | ||
1226 | if (ppc_md.irq_bus_setup) | 1237 | /* Read default IRQs and fixup if necessary */ |
1227 | ppc_md.irq_bus_setup(bus); | 1238 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1239 | pci_read_irq_line(dev); | ||
1240 | if (ppc_md.pci_irq_fixup) | ||
1241 | ppc_md.pci_irq_fixup(dev); | ||
1242 | } | ||
1228 | } | 1243 | } |
1229 | 1244 | ||
1230 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 1245 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) |
1231 | { | 1246 | { |
1232 | struct pci_dev *dev = bus->self; | 1247 | struct pci_dev *dev = bus->self; |
1248 | struct device_node *np; | ||
1249 | |||
1250 | np = pci_bus_to_OF_node(bus); | ||
1251 | |||
1252 | DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>"); | ||
1233 | 1253 | ||
1234 | if (dev && pci_probe_only && | 1254 | if (dev && pci_probe_only && |
1235 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | 1255 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
@@ -1343,8 +1363,6 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | |||
1343 | return NULL; | 1363 | return NULL; |
1344 | } | 1364 | } |
1345 | 1365 | ||
1346 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1347 | |||
1348 | unsigned long pci_address_to_pio(phys_addr_t address) | 1366 | unsigned long pci_address_to_pio(phys_addr_t address) |
1349 | { | 1367 | { |
1350 | struct pci_controller *hose, *tmp; | 1368 | struct pci_controller *hose, *tmp; |
diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c deleted file mode 100644 index 72ce082ce73..00000000000 --- a/arch/powerpc/kernel/pci_direct_iommu.c +++ /dev/null | |||
@@ -1,98 +0,0 @@ | |||
1 | /* | ||
2 | * Support for DMA from PCI devices to main memory on | ||
3 | * machines without an iommu or with directly addressable | ||
4 | * RAM (typically a pmac with 2Gb of RAM or less) | ||
5 | * | ||
6 | * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
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 | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/bootmem.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/dma-mapping.h> | ||
22 | |||
23 | #include <asm/sections.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/pci-bridge.h> | ||
27 | #include <asm/machdep.h> | ||
28 | #include <asm/pmac_feature.h> | ||
29 | #include <asm/abs_addr.h> | ||
30 | #include <asm/ppc-pci.h> | ||
31 | |||
32 | static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size, | ||
33 | dma_addr_t *dma_handle, gfp_t flag) | ||
34 | { | ||
35 | void *ret; | ||
36 | |||
37 | ret = (void *)__get_free_pages(flag, get_order(size)); | ||
38 | if (ret != NULL) { | ||
39 | memset(ret, 0, size); | ||
40 | *dma_handle = virt_to_abs(ret); | ||
41 | } | ||
42 | return ret; | ||
43 | } | ||
44 | |||
45 | static void pci_direct_free_coherent(struct device *hwdev, size_t size, | ||
46 | void *vaddr, dma_addr_t dma_handle) | ||
47 | { | ||
48 | free_pages((unsigned long)vaddr, get_order(size)); | ||
49 | } | ||
50 | |||
51 | static dma_addr_t pci_direct_map_single(struct device *hwdev, void *ptr, | ||
52 | size_t size, enum dma_data_direction direction) | ||
53 | { | ||
54 | return virt_to_abs(ptr); | ||
55 | } | ||
56 | |||
57 | static void pci_direct_unmap_single(struct device *hwdev, dma_addr_t dma_addr, | ||
58 | size_t size, enum dma_data_direction direction) | ||
59 | { | ||
60 | } | ||
61 | |||
62 | static int pci_direct_map_sg(struct device *hwdev, struct scatterlist *sg, | ||
63 | int nents, enum dma_data_direction direction) | ||
64 | { | ||
65 | int i; | ||
66 | |||
67 | for (i = 0; i < nents; i++, sg++) { | ||
68 | sg->dma_address = page_to_phys(sg->page) + sg->offset; | ||
69 | sg->dma_length = sg->length; | ||
70 | } | ||
71 | |||
72 | return nents; | ||
73 | } | ||
74 | |||
75 | static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg, | ||
76 | int nents, enum dma_data_direction direction) | ||
77 | { | ||
78 | } | ||
79 | |||
80 | static int pci_direct_dma_supported(struct device *dev, u64 mask) | ||
81 | { | ||
82 | return mask < 0x100000000ull; | ||
83 | } | ||
84 | |||
85 | static struct dma_mapping_ops pci_direct_ops = { | ||
86 | .alloc_coherent = pci_direct_alloc_coherent, | ||
87 | .free_coherent = pci_direct_free_coherent, | ||
88 | .map_single = pci_direct_map_single, | ||
89 | .unmap_single = pci_direct_unmap_single, | ||
90 | .map_sg = pci_direct_map_sg, | ||
91 | .unmap_sg = pci_direct_unmap_sg, | ||
92 | .dma_supported = pci_direct_dma_supported, | ||
93 | }; | ||
94 | |||
95 | void __init pci_direct_iommu_init(void) | ||
96 | { | ||
97 | pci_dma_ops = pci_direct_ops; | ||
98 | } | ||
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c deleted file mode 100644 index 0688b2534ac..00000000000 --- a/arch/powerpc/kernel/pci_iommu.c +++ /dev/null | |||
@@ -1,164 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation | ||
3 | * | ||
4 | * Rewrite, cleanup, new allocation schemes: | ||
5 | * Copyright (C) 2004 Olof Johansson, IBM Corporation | ||
6 | * | ||
7 | * Dynamic DMA mapping support, platform-independent parts. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | |||
25 | #include <linux/init.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/dma-mapping.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/prom.h> | ||
35 | #include <asm/iommu.h> | ||
36 | #include <asm/pci-bridge.h> | ||
37 | #include <asm/machdep.h> | ||
38 | #include <asm/ppc-pci.h> | ||
39 | |||
40 | /* | ||
41 | * We can use ->sysdata directly and avoid the extra work in | ||
42 | * pci_device_to_OF_node since ->sysdata will have been initialised | ||
43 | * in the iommu init code for all devices. | ||
44 | */ | ||
45 | #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata)) | ||
46 | |||
47 | static inline struct iommu_table *device_to_table(struct device *hwdev) | ||
48 | { | ||
49 | struct pci_dev *pdev; | ||
50 | |||
51 | if (!hwdev) { | ||
52 | pdev = ppc64_isabridge_dev; | ||
53 | if (!pdev) | ||
54 | return NULL; | ||
55 | } else | ||
56 | pdev = to_pci_dev(hwdev); | ||
57 | |||
58 | return PCI_DN(PCI_GET_DN(pdev))->iommu_table; | ||
59 | } | ||
60 | |||
61 | |||
62 | static inline unsigned long device_to_mask(struct device *hwdev) | ||
63 | { | ||
64 | struct pci_dev *pdev; | ||
65 | |||
66 | if (!hwdev) { | ||
67 | pdev = ppc64_isabridge_dev; | ||
68 | if (!pdev) /* This is the best guess we can do */ | ||
69 | return 0xfffffffful; | ||
70 | } else | ||
71 | pdev = to_pci_dev(hwdev); | ||
72 | |||
73 | if (pdev->dma_mask) | ||
74 | return pdev->dma_mask; | ||
75 | |||
76 | /* Assume devices without mask can take 32 bit addresses */ | ||
77 | return 0xfffffffful; | ||
78 | } | ||
79 | |||
80 | |||
81 | /* Allocates a contiguous real buffer and creates mappings over it. | ||
82 | * Returns the virtual address of the buffer and sets dma_handle | ||
83 | * to the dma address (mapping) of the first page. | ||
84 | */ | ||
85 | static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, | ||
86 | dma_addr_t *dma_handle, gfp_t flag) | ||
87 | { | ||
88 | return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, | ||
89 | device_to_mask(hwdev), flag, | ||
90 | pcibus_to_node(to_pci_dev(hwdev)->bus)); | ||
91 | } | ||
92 | |||
93 | static void pci_iommu_free_coherent(struct device *hwdev, size_t size, | ||
94 | void *vaddr, dma_addr_t dma_handle) | ||
95 | { | ||
96 | iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle); | ||
97 | } | ||
98 | |||
99 | /* Creates TCEs for a user provided buffer. The user buffer must be | ||
100 | * contiguous real kernel storage (not vmalloc). The address of the buffer | ||
101 | * passed here is the kernel (virtual) address of the buffer. The buffer | ||
102 | * need not be page aligned, the dma_addr_t returned will point to the same | ||
103 | * byte within the page as vaddr. | ||
104 | */ | ||
105 | static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, | ||
106 | size_t size, enum dma_data_direction direction) | ||
107 | { | ||
108 | return iommu_map_single(device_to_table(hwdev), vaddr, size, | ||
109 | device_to_mask(hwdev), direction); | ||
110 | } | ||
111 | |||
112 | |||
113 | static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle, | ||
114 | size_t size, enum dma_data_direction direction) | ||
115 | { | ||
116 | iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction); | ||
117 | } | ||
118 | |||
119 | |||
120 | static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist, | ||
121 | int nelems, enum dma_data_direction direction) | ||
122 | { | ||
123 | return iommu_map_sg(pdev, device_to_table(pdev), sglist, | ||
124 | nelems, device_to_mask(pdev), direction); | ||
125 | } | ||
126 | |||
127 | static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, | ||
128 | int nelems, enum dma_data_direction direction) | ||
129 | { | ||
130 | iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction); | ||
131 | } | ||
132 | |||
133 | /* We support DMA to/from any memory page via the iommu */ | ||
134 | static int pci_iommu_dma_supported(struct device *dev, u64 mask) | ||
135 | { | ||
136 | struct iommu_table *tbl = device_to_table(dev); | ||
137 | |||
138 | if (!tbl || tbl->it_offset > mask) { | ||
139 | printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n"); | ||
140 | if (tbl) | ||
141 | printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n", | ||
142 | mask, tbl->it_offset); | ||
143 | else | ||
144 | printk(KERN_INFO "mask: 0x%08lx, table unavailable\n", | ||
145 | mask); | ||
146 | return 0; | ||
147 | } else | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | struct dma_mapping_ops pci_iommu_ops = { | ||
152 | .alloc_coherent = pci_iommu_alloc_coherent, | ||
153 | .free_coherent = pci_iommu_free_coherent, | ||
154 | .map_single = pci_iommu_map_single, | ||
155 | .unmap_single = pci_iommu_unmap_single, | ||
156 | .map_sg = pci_iommu_map_sg, | ||
157 | .unmap_sg = pci_iommu_unmap_sg, | ||
158 | .dma_supported = pci_iommu_dma_supported, | ||
159 | }; | ||
160 | |||
161 | void pci_iommu_init(void) | ||
162 | { | ||
163 | pci_dma_ops = pci_iommu_ops; | ||
164 | } | ||
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 807193a3c78..9179f0739ea 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -49,6 +49,10 @@ | |||
49 | #include <asm/commproc.h> | 49 | #include <asm/commproc.h> |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifdef CONFIG_PPC64 | ||
53 | EXPORT_SYMBOL(local_irq_restore); | ||
54 | #endif | ||
55 | |||
52 | #ifdef CONFIG_PPC32 | 56 | #ifdef CONFIG_PPC32 |
53 | extern void transfer_to_handler(void); | 57 | extern void transfer_to_handler(void); |
54 | extern void do_IRQ(struct pt_regs *regs); | 58 | extern void do_IRQ(struct pt_regs *regs); |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index bdb412d4b74..c18dbe77fdc 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -538,35 +538,31 @@ static struct ibm_pa_feature { | |||
538 | {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, | 538 | {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, |
539 | }; | 539 | }; |
540 | 540 | ||
541 | static void __init check_cpu_pa_features(unsigned long node) | 541 | static void __init scan_features(unsigned long node, unsigned char *ftrs, |
542 | unsigned long tablelen, | ||
543 | struct ibm_pa_feature *fp, | ||
544 | unsigned long ft_size) | ||
542 | { | 545 | { |
543 | unsigned char *pa_ftrs; | 546 | unsigned long i, len, bit; |
544 | unsigned long len, tablelen, i, bit; | ||
545 | |||
546 | pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); | ||
547 | if (pa_ftrs == NULL) | ||
548 | return; | ||
549 | 547 | ||
550 | /* find descriptor with type == 0 */ | 548 | /* find descriptor with type == 0 */ |
551 | for (;;) { | 549 | for (;;) { |
552 | if (tablelen < 3) | 550 | if (tablelen < 3) |
553 | return; | 551 | return; |
554 | len = 2 + pa_ftrs[0]; | 552 | len = 2 + ftrs[0]; |
555 | if (tablelen < len) | 553 | if (tablelen < len) |
556 | return; /* descriptor 0 not found */ | 554 | return; /* descriptor 0 not found */ |
557 | if (pa_ftrs[1] == 0) | 555 | if (ftrs[1] == 0) |
558 | break; | 556 | break; |
559 | tablelen -= len; | 557 | tablelen -= len; |
560 | pa_ftrs += len; | 558 | ftrs += len; |
561 | } | 559 | } |
562 | 560 | ||
563 | /* loop over bits we know about */ | 561 | /* loop over bits we know about */ |
564 | for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) { | 562 | for (i = 0; i < ft_size; ++i, ++fp) { |
565 | struct ibm_pa_feature *fp = &ibm_pa_features[i]; | 563 | if (fp->pabyte >= ftrs[0]) |
566 | |||
567 | if (fp->pabyte >= pa_ftrs[0]) | ||
568 | continue; | 564 | continue; |
569 | bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1; | 565 | bit = (ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1; |
570 | if (bit ^ fp->invert) { | 566 | if (bit ^ fp->invert) { |
571 | cur_cpu_spec->cpu_features |= fp->cpu_features; | 567 | cur_cpu_spec->cpu_features |= fp->cpu_features; |
572 | cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; | 568 | cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; |
@@ -577,16 +573,59 @@ static void __init check_cpu_pa_features(unsigned long node) | |||
577 | } | 573 | } |
578 | } | 574 | } |
579 | 575 | ||
576 | static void __init check_cpu_pa_features(unsigned long node) | ||
577 | { | ||
578 | unsigned char *pa_ftrs; | ||
579 | unsigned long tablelen; | ||
580 | |||
581 | pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); | ||
582 | if (pa_ftrs == NULL) | ||
583 | return; | ||
584 | |||
585 | scan_features(node, pa_ftrs, tablelen, | ||
586 | ibm_pa_features, ARRAY_SIZE(ibm_pa_features)); | ||
587 | } | ||
588 | |||
589 | static struct feature_property { | ||
590 | const char *name; | ||
591 | u32 min_value; | ||
592 | unsigned long cpu_feature; | ||
593 | unsigned long cpu_user_ftr; | ||
594 | } feature_properties[] __initdata = { | ||
595 | #ifdef CONFIG_ALTIVEC | ||
596 | {"altivec", 0, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC}, | ||
597 | {"ibm,vmx", 1, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC}, | ||
598 | #endif /* CONFIG_ALTIVEC */ | ||
599 | #ifdef CONFIG_PPC64 | ||
600 | {"ibm,dfp", 1, 0, PPC_FEATURE_HAS_DFP}, | ||
601 | {"ibm,purr", 1, CPU_FTR_PURR, 0}, | ||
602 | {"ibm,spurr", 1, CPU_FTR_SPURR, 0}, | ||
603 | #endif /* CONFIG_PPC64 */ | ||
604 | }; | ||
605 | |||
606 | static void __init check_cpu_feature_properties(unsigned long node) | ||
607 | { | ||
608 | unsigned long i; | ||
609 | struct feature_property *fp = feature_properties; | ||
610 | const u32 *prop; | ||
611 | |||
612 | for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) { | ||
613 | prop = of_get_flat_dt_prop(node, fp->name, NULL); | ||
614 | if (prop && *prop >= fp->min_value) { | ||
615 | cur_cpu_spec->cpu_features |= fp->cpu_feature; | ||
616 | cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftr; | ||
617 | } | ||
618 | } | ||
619 | } | ||
620 | |||
580 | static int __init early_init_dt_scan_cpus(unsigned long node, | 621 | static int __init early_init_dt_scan_cpus(unsigned long node, |
581 | const char *uname, int depth, | 622 | const char *uname, int depth, |
582 | void *data) | 623 | void *data) |
583 | { | 624 | { |
584 | static int logical_cpuid = 0; | 625 | static int logical_cpuid = 0; |
585 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 626 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
586 | #ifdef CONFIG_ALTIVEC | 627 | const u32 *prop; |
587 | u32 *prop; | 628 | const u32 *intserv; |
588 | #endif | ||
589 | u32 *intserv; | ||
590 | int i, nthreads; | 629 | int i, nthreads; |
591 | unsigned long len; | 630 | unsigned long len; |
592 | int found = 0; | 631 | int found = 0; |
@@ -643,24 +682,27 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
643 | intserv[i]); | 682 | intserv[i]); |
644 | boot_cpuid = logical_cpuid; | 683 | boot_cpuid = logical_cpuid; |
645 | set_hard_smp_processor_id(boot_cpuid, intserv[i]); | 684 | set_hard_smp_processor_id(boot_cpuid, intserv[i]); |
646 | } | ||
647 | 685 | ||
648 | #ifdef CONFIG_ALTIVEC | 686 | /* |
649 | /* Check if we have a VMX and eventually update CPU features */ | 687 | * PAPR defines "logical" PVR values for cpus that |
650 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); | 688 | * meet various levels of the architecture: |
651 | if (prop && (*prop) > 0) { | 689 | * 0x0f000001 Architecture version 2.04 |
652 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | 690 | * 0x0f000002 Architecture version 2.05 |
653 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | 691 | * If the cpu-version property in the cpu node contains |
654 | } | 692 | * such a value, we call identify_cpu again with the |
655 | 693 | * logical PVR value in order to use the cpu feature | |
656 | /* Same goes for Apple's "altivec" property */ | 694 | * bits appropriate for the architecture level. |
657 | prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); | 695 | * |
658 | if (prop) { | 696 | * A POWER6 partition in "POWER6 architected" mode |
659 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | 697 | * uses the 0x0f000002 PVR value; in POWER5+ mode |
660 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | 698 | * it uses 0x0f000001. |
699 | */ | ||
700 | prop = of_get_flat_dt_prop(node, "cpu-version", NULL); | ||
701 | if (prop && (*prop & 0xff000000) == 0x0f000000) | ||
702 | identify_cpu(0, *prop); | ||
661 | } | 703 | } |
662 | #endif /* CONFIG_ALTIVEC */ | ||
663 | 704 | ||
705 | check_cpu_feature_properties(node); | ||
664 | check_cpu_pa_features(node); | 706 | check_cpu_pa_features(node); |
665 | 707 | ||
666 | #ifdef CONFIG_PPC_PSERIES | 708 | #ifdef CONFIG_PPC_PSERIES |
@@ -1674,6 +1716,7 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | |||
1674 | } | 1716 | } |
1675 | return NULL; | 1717 | return NULL; |
1676 | } | 1718 | } |
1719 | EXPORT_SYMBOL(of_get_cpu_node); | ||
1677 | 1720 | ||
1678 | #ifdef DEBUG | 1721 | #ifdef DEBUG |
1679 | static struct debugfs_blob_wrapper flat_dt_blob; | 1722 | static struct debugfs_blob_wrapper flat_dt_blob; |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index b91761639d9..46cf32670dd 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -173,8 +173,8 @@ static unsigned long __initdata dt_string_start, dt_string_end; | |||
173 | static unsigned long __initdata prom_initrd_start, prom_initrd_end; | 173 | static unsigned long __initdata prom_initrd_start, prom_initrd_end; |
174 | 174 | ||
175 | #ifdef CONFIG_PPC64 | 175 | #ifdef CONFIG_PPC64 |
176 | static int __initdata iommu_force_on; | 176 | static int __initdata prom_iommu_force_on; |
177 | static int __initdata ppc64_iommu_off; | 177 | static int __initdata prom_iommu_off; |
178 | static unsigned long __initdata prom_tce_alloc_start; | 178 | static unsigned long __initdata prom_tce_alloc_start; |
179 | static unsigned long __initdata prom_tce_alloc_end; | 179 | static unsigned long __initdata prom_tce_alloc_end; |
180 | #endif | 180 | #endif |
@@ -582,9 +582,9 @@ static void __init early_cmdline_parse(void) | |||
582 | while (*opt && *opt == ' ') | 582 | while (*opt && *opt == ' ') |
583 | opt++; | 583 | opt++; |
584 | if (!strncmp(opt, RELOC("off"), 3)) | 584 | if (!strncmp(opt, RELOC("off"), 3)) |
585 | RELOC(ppc64_iommu_off) = 1; | 585 | RELOC(prom_iommu_off) = 1; |
586 | else if (!strncmp(opt, RELOC("force"), 5)) | 586 | else if (!strncmp(opt, RELOC("force"), 5)) |
587 | RELOC(iommu_force_on) = 1; | 587 | RELOC(prom_iommu_force_on) = 1; |
588 | } | 588 | } |
589 | #endif | 589 | #endif |
590 | } | 590 | } |
@@ -627,6 +627,7 @@ static void __init early_cmdline_parse(void) | |||
627 | /* Option vector 3: processor options supported */ | 627 | /* Option vector 3: processor options supported */ |
628 | #define OV3_FP 0x80 /* floating point */ | 628 | #define OV3_FP 0x80 /* floating point */ |
629 | #define OV3_VMX 0x40 /* VMX/Altivec */ | 629 | #define OV3_VMX 0x40 /* VMX/Altivec */ |
630 | #define OV3_DFP 0x20 /* decimal FP */ | ||
630 | 631 | ||
631 | /* Option vector 5: PAPR/OF options supported */ | 632 | /* Option vector 5: PAPR/OF options supported */ |
632 | #define OV5_LPAR 0x80 /* logical partitioning supported */ | 633 | #define OV5_LPAR 0x80 /* logical partitioning supported */ |
@@ -642,6 +643,7 @@ static void __init early_cmdline_parse(void) | |||
642 | static unsigned char ibm_architecture_vec[] = { | 643 | static unsigned char ibm_architecture_vec[] = { |
643 | W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */ | 644 | W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */ |
644 | W(0xffff0000), W(0x003e0000), /* POWER6 */ | 645 | W(0xffff0000), W(0x003e0000), /* POWER6 */ |
646 | W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */ | ||
645 | W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ | 647 | W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ |
646 | 5 - 1, /* 5 option vectors */ | 648 | 5 - 1, /* 5 option vectors */ |
647 | 649 | ||
@@ -668,7 +670,7 @@ static unsigned char ibm_architecture_vec[] = { | |||
668 | /* option vector 3: processor options supported */ | 670 | /* option vector 3: processor options supported */ |
669 | 3 - 2, /* length */ | 671 | 3 - 2, /* length */ |
670 | 0, /* don't ignore, don't halt */ | 672 | 0, /* don't ignore, don't halt */ |
671 | OV3_FP | OV3_VMX, | 673 | OV3_FP | OV3_VMX | OV3_DFP, |
672 | 674 | ||
673 | /* option vector 4: IBM PAPR implementation */ | 675 | /* option vector 4: IBM PAPR implementation */ |
674 | 2 - 2, /* length */ | 676 | 2 - 2, /* length */ |
@@ -1167,7 +1169,7 @@ static void __init prom_initialize_tce_table(void) | |||
1167 | u64 local_alloc_top, local_alloc_bottom; | 1169 | u64 local_alloc_top, local_alloc_bottom; |
1168 | u64 i; | 1170 | u64 i; |
1169 | 1171 | ||
1170 | if (RELOC(ppc64_iommu_off)) | 1172 | if (RELOC(prom_iommu_off)) |
1171 | return; | 1173 | return; |
1172 | 1174 | ||
1173 | prom_debug("starting prom_initialize_tce_table\n"); | 1175 | prom_debug("starting prom_initialize_tce_table\n"); |
@@ -2283,11 +2285,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2283 | * Fill in some infos for use by the kernel later on | 2285 | * Fill in some infos for use by the kernel later on |
2284 | */ | 2286 | */ |
2285 | #ifdef CONFIG_PPC64 | 2287 | #ifdef CONFIG_PPC64 |
2286 | if (RELOC(ppc64_iommu_off)) | 2288 | if (RELOC(prom_iommu_off)) |
2287 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", | 2289 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", |
2288 | NULL, 0); | 2290 | NULL, 0); |
2289 | 2291 | ||
2290 | if (RELOC(iommu_force_on)) | 2292 | if (RELOC(prom_iommu_force_on)) |
2291 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on", | 2293 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on", |
2292 | NULL, 0); | 2294 | NULL, 0); |
2293 | 2295 | ||
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 603dff3ad62..0dfbe1cd28e 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c | |||
@@ -25,6 +25,12 @@ | |||
25 | #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ | 25 | #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ |
26 | (ns) > 0) | 26 | (ns) > 0) |
27 | 27 | ||
28 | static struct of_bus *of_match_bus(struct device_node *np); | ||
29 | static int __of_address_to_resource(struct device_node *dev, | ||
30 | const u32 *addrp, u64 size, unsigned int flags, | ||
31 | struct resource *r); | ||
32 | |||
33 | |||
28 | /* Debug utility */ | 34 | /* Debug utility */ |
29 | #ifdef DEBUG | 35 | #ifdef DEBUG |
30 | static void of_dump_addr(const char *s, const u32 *addr, int na) | 36 | static void of_dump_addr(const char *s, const u32 *addr, int na) |
@@ -101,6 +107,7 @@ static unsigned int of_bus_default_get_flags(const u32 *addr) | |||
101 | } | 107 | } |
102 | 108 | ||
103 | 109 | ||
110 | #ifdef CONFIG_PCI | ||
104 | /* | 111 | /* |
105 | * PCI bus specific translator | 112 | * PCI bus specific translator |
106 | */ | 113 | */ |
@@ -153,15 +160,156 @@ static unsigned int of_bus_pci_get_flags(const u32 *addr) | |||
153 | switch((w >> 24) & 0x03) { | 160 | switch((w >> 24) & 0x03) { |
154 | case 0x01: | 161 | case 0x01: |
155 | flags |= IORESOURCE_IO; | 162 | flags |= IORESOURCE_IO; |
163 | break; | ||
156 | case 0x02: /* 32 bits */ | 164 | case 0x02: /* 32 bits */ |
157 | case 0x03: /* 64 bits */ | 165 | case 0x03: /* 64 bits */ |
158 | flags |= IORESOURCE_MEM; | 166 | flags |= IORESOURCE_MEM; |
167 | break; | ||
159 | } | 168 | } |
160 | if (w & 0x40000000) | 169 | if (w & 0x40000000) |
161 | flags |= IORESOURCE_PREFETCH; | 170 | flags |= IORESOURCE_PREFETCH; |
162 | return flags; | 171 | return flags; |
163 | } | 172 | } |
164 | 173 | ||
174 | const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, | ||
175 | unsigned int *flags) | ||
176 | { | ||
177 | const u32 *prop; | ||
178 | unsigned int psize; | ||
179 | struct device_node *parent; | ||
180 | struct of_bus *bus; | ||
181 | int onesize, i, na, ns; | ||
182 | |||
183 | /* Get parent & match bus type */ | ||
184 | parent = of_get_parent(dev); | ||
185 | if (parent == NULL) | ||
186 | return NULL; | ||
187 | bus = of_match_bus(parent); | ||
188 | if (strcmp(bus->name, "pci")) { | ||
189 | of_node_put(parent); | ||
190 | return NULL; | ||
191 | } | ||
192 | bus->count_cells(dev, &na, &ns); | ||
193 | of_node_put(parent); | ||
194 | if (!OF_CHECK_COUNTS(na, ns)) | ||
195 | return NULL; | ||
196 | |||
197 | /* Get "reg" or "assigned-addresses" property */ | ||
198 | prop = get_property(dev, bus->addresses, &psize); | ||
199 | if (prop == NULL) | ||
200 | return NULL; | ||
201 | psize /= 4; | ||
202 | |||
203 | onesize = na + ns; | ||
204 | for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) | ||
205 | if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { | ||
206 | if (size) | ||
207 | *size = of_read_number(prop + na, ns); | ||
208 | if (flags) | ||
209 | *flags = bus->get_flags(prop); | ||
210 | return prop; | ||
211 | } | ||
212 | return NULL; | ||
213 | } | ||
214 | EXPORT_SYMBOL(of_get_pci_address); | ||
215 | |||
216 | int of_pci_address_to_resource(struct device_node *dev, int bar, | ||
217 | struct resource *r) | ||
218 | { | ||
219 | const u32 *addrp; | ||
220 | u64 size; | ||
221 | unsigned int flags; | ||
222 | |||
223 | addrp = of_get_pci_address(dev, bar, &size, &flags); | ||
224 | if (addrp == NULL) | ||
225 | return -EINVAL; | ||
226 | return __of_address_to_resource(dev, addrp, size, flags, r); | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); | ||
229 | |||
230 | static u8 of_irq_pci_swizzle(u8 slot, u8 pin) | ||
231 | { | ||
232 | return (((pin - 1) + slot) % 4) + 1; | ||
233 | } | ||
234 | |||
235 | int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) | ||
236 | { | ||
237 | struct device_node *dn, *ppnode; | ||
238 | struct pci_dev *ppdev; | ||
239 | u32 lspec; | ||
240 | u32 laddr[3]; | ||
241 | u8 pin; | ||
242 | int rc; | ||
243 | |||
244 | /* Check if we have a device node, if yes, fallback to standard OF | ||
245 | * parsing | ||
246 | */ | ||
247 | dn = pci_device_to_OF_node(pdev); | ||
248 | if (dn) | ||
249 | return of_irq_map_one(dn, 0, out_irq); | ||
250 | |||
251 | /* Ok, we don't, time to have fun. Let's start by building up an | ||
252 | * interrupt spec. we assume #interrupt-cells is 1, which is standard | ||
253 | * for PCI. If you do different, then don't use that routine. | ||
254 | */ | ||
255 | rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); | ||
256 | if (rc != 0) | ||
257 | return rc; | ||
258 | /* No pin, exit */ | ||
259 | if (pin == 0) | ||
260 | return -ENODEV; | ||
261 | |||
262 | /* Now we walk up the PCI tree */ | ||
263 | lspec = pin; | ||
264 | for (;;) { | ||
265 | /* Get the pci_dev of our parent */ | ||
266 | ppdev = pdev->bus->self; | ||
267 | |||
268 | /* Ouch, it's a host bridge... */ | ||
269 | if (ppdev == NULL) { | ||
270 | #ifdef CONFIG_PPC64 | ||
271 | ppnode = pci_bus_to_OF_node(pdev->bus); | ||
272 | #else | ||
273 | struct pci_controller *host; | ||
274 | host = pci_bus_to_host(pdev->bus); | ||
275 | ppnode = host ? host->arch_data : NULL; | ||
276 | #endif | ||
277 | /* No node for host bridge ? give up */ | ||
278 | if (ppnode == NULL) | ||
279 | return -EINVAL; | ||
280 | } else | ||
281 | /* We found a P2P bridge, check if it has a node */ | ||
282 | ppnode = pci_device_to_OF_node(ppdev); | ||
283 | |||
284 | /* Ok, we have found a parent with a device-node, hand over to | ||
285 | * the OF parsing code. | ||
286 | * We build a unit address from the linux device to be used for | ||
287 | * resolution. Note that we use the linux bus number which may | ||
288 | * not match your firmware bus numbering. | ||
289 | * Fortunately, in most cases, interrupt-map-mask doesn't include | ||
290 | * the bus number as part of the matching. | ||
291 | * You should still be careful about that though if you intend | ||
292 | * to rely on this function (you ship a firmware that doesn't | ||
293 | * create device nodes for all PCI devices). | ||
294 | */ | ||
295 | if (ppnode) | ||
296 | break; | ||
297 | |||
298 | /* We can only get here if we hit a P2P bridge with no node, | ||
299 | * let's do standard swizzling and try again | ||
300 | */ | ||
301 | lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); | ||
302 | pdev = ppdev; | ||
303 | } | ||
304 | |||
305 | laddr[0] = (pdev->bus->number << 16) | ||
306 | | (pdev->devfn << 8); | ||
307 | laddr[1] = laddr[2] = 0; | ||
308 | return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(of_irq_map_pci); | ||
311 | #endif /* CONFIG_PCI */ | ||
312 | |||
165 | /* | 313 | /* |
166 | * ISA bus specific translator | 314 | * ISA bus specific translator |
167 | */ | 315 | */ |
@@ -223,6 +371,7 @@ static unsigned int of_bus_isa_get_flags(const u32 *addr) | |||
223 | */ | 371 | */ |
224 | 372 | ||
225 | static struct of_bus of_busses[] = { | 373 | static struct of_bus of_busses[] = { |
374 | #ifdef CONFIG_PCI | ||
226 | /* PCI */ | 375 | /* PCI */ |
227 | { | 376 | { |
228 | .name = "pci", | 377 | .name = "pci", |
@@ -233,6 +382,7 @@ static struct of_bus of_busses[] = { | |||
233 | .translate = of_bus_pci_translate, | 382 | .translate = of_bus_pci_translate, |
234 | .get_flags = of_bus_pci_get_flags, | 383 | .get_flags = of_bus_pci_get_flags, |
235 | }, | 384 | }, |
385 | #endif /* CONFIG_PCI */ | ||
236 | /* ISA */ | 386 | /* ISA */ |
237 | { | 387 | { |
238 | .name = "isa", | 388 | .name = "isa", |
@@ -445,48 +595,6 @@ const u32 *of_get_address(struct device_node *dev, int index, u64 *size, | |||
445 | } | 595 | } |
446 | EXPORT_SYMBOL(of_get_address); | 596 | EXPORT_SYMBOL(of_get_address); |
447 | 597 | ||
448 | const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, | ||
449 | unsigned int *flags) | ||
450 | { | ||
451 | const u32 *prop; | ||
452 | unsigned int psize; | ||
453 | struct device_node *parent; | ||
454 | struct of_bus *bus; | ||
455 | int onesize, i, na, ns; | ||
456 | |||
457 | /* Get parent & match bus type */ | ||
458 | parent = of_get_parent(dev); | ||
459 | if (parent == NULL) | ||
460 | return NULL; | ||
461 | bus = of_match_bus(parent); | ||
462 | if (strcmp(bus->name, "pci")) { | ||
463 | of_node_put(parent); | ||
464 | return NULL; | ||
465 | } | ||
466 | bus->count_cells(dev, &na, &ns); | ||
467 | of_node_put(parent); | ||
468 | if (!OF_CHECK_COUNTS(na, ns)) | ||
469 | return NULL; | ||
470 | |||
471 | /* Get "reg" or "assigned-addresses" property */ | ||
472 | prop = get_property(dev, bus->addresses, &psize); | ||
473 | if (prop == NULL) | ||
474 | return NULL; | ||
475 | psize /= 4; | ||
476 | |||
477 | onesize = na + ns; | ||
478 | for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) | ||
479 | if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { | ||
480 | if (size) | ||
481 | *size = of_read_number(prop + na, ns); | ||
482 | if (flags) | ||
483 | *flags = bus->get_flags(prop); | ||
484 | return prop; | ||
485 | } | ||
486 | return NULL; | ||
487 | } | ||
488 | EXPORT_SYMBOL(of_get_pci_address); | ||
489 | |||
490 | static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, | 598 | static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, |
491 | u64 size, unsigned int flags, | 599 | u64 size, unsigned int flags, |
492 | struct resource *r) | 600 | struct resource *r) |
@@ -529,20 +637,6 @@ int of_address_to_resource(struct device_node *dev, int index, | |||
529 | } | 637 | } |
530 | EXPORT_SYMBOL_GPL(of_address_to_resource); | 638 | EXPORT_SYMBOL_GPL(of_address_to_resource); |
531 | 639 | ||
532 | int of_pci_address_to_resource(struct device_node *dev, int bar, | ||
533 | struct resource *r) | ||
534 | { | ||
535 | const u32 *addrp; | ||
536 | u64 size; | ||
537 | unsigned int flags; | ||
538 | |||
539 | addrp = of_get_pci_address(dev, bar, &size, &flags); | ||
540 | if (addrp == NULL) | ||
541 | return -EINVAL; | ||
542 | return __of_address_to_resource(dev, addrp, size, flags, r); | ||
543 | } | ||
544 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); | ||
545 | |||
546 | void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, | 640 | void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, |
547 | unsigned long *busno, unsigned long *phys, unsigned long *size) | 641 | unsigned long *busno, unsigned long *phys, unsigned long *size) |
548 | { | 642 | { |
@@ -898,87 +992,3 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq | |||
898 | return res; | 992 | return res; |
899 | } | 993 | } |
900 | EXPORT_SYMBOL_GPL(of_irq_map_one); | 994 | EXPORT_SYMBOL_GPL(of_irq_map_one); |
901 | |||
902 | #ifdef CONFIG_PCI | ||
903 | static u8 of_irq_pci_swizzle(u8 slot, u8 pin) | ||
904 | { | ||
905 | return (((pin - 1) + slot) % 4) + 1; | ||
906 | } | ||
907 | |||
908 | int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) | ||
909 | { | ||
910 | struct device_node *dn, *ppnode; | ||
911 | struct pci_dev *ppdev; | ||
912 | u32 lspec; | ||
913 | u32 laddr[3]; | ||
914 | u8 pin; | ||
915 | int rc; | ||
916 | |||
917 | /* Check if we have a device node, if yes, fallback to standard OF | ||
918 | * parsing | ||
919 | */ | ||
920 | dn = pci_device_to_OF_node(pdev); | ||
921 | if (dn) | ||
922 | return of_irq_map_one(dn, 0, out_irq); | ||
923 | |||
924 | /* Ok, we don't, time to have fun. Let's start by building up an | ||
925 | * interrupt spec. we assume #interrupt-cells is 1, which is standard | ||
926 | * for PCI. If you do different, then don't use that routine. | ||
927 | */ | ||
928 | rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); | ||
929 | if (rc != 0) | ||
930 | return rc; | ||
931 | /* No pin, exit */ | ||
932 | if (pin == 0) | ||
933 | return -ENODEV; | ||
934 | |||
935 | /* Now we walk up the PCI tree */ | ||
936 | lspec = pin; | ||
937 | for (;;) { | ||
938 | /* Get the pci_dev of our parent */ | ||
939 | ppdev = pdev->bus->self; | ||
940 | |||
941 | /* Ouch, it's a host bridge... */ | ||
942 | if (ppdev == NULL) { | ||
943 | #ifdef CONFIG_PPC64 | ||
944 | ppnode = pci_bus_to_OF_node(pdev->bus); | ||
945 | #else | ||
946 | struct pci_controller *host; | ||
947 | host = pci_bus_to_host(pdev->bus); | ||
948 | ppnode = host ? host->arch_data : NULL; | ||
949 | #endif | ||
950 | /* No node for host bridge ? give up */ | ||
951 | if (ppnode == NULL) | ||
952 | return -EINVAL; | ||
953 | } else | ||
954 | /* We found a P2P bridge, check if it has a node */ | ||
955 | ppnode = pci_device_to_OF_node(ppdev); | ||
956 | |||
957 | /* Ok, we have found a parent with a device-node, hand over to | ||
958 | * the OF parsing code. | ||
959 | * We build a unit address from the linux device to be used for | ||
960 | * resolution. Note that we use the linux bus number which may | ||
961 | * not match your firmware bus numbering. | ||
962 | * Fortunately, in most cases, interrupt-map-mask doesn't include | ||
963 | * the bus number as part of the matching. | ||
964 | * You should still be careful about that though if you intend | ||
965 | * to rely on this function (you ship a firmware that doesn't | ||
966 | * create device nodes for all PCI devices). | ||
967 | */ | ||
968 | if (ppnode) | ||
969 | break; | ||
970 | |||
971 | /* We can only get here if we hit a P2P bridge with no node, | ||
972 | * let's do standard swizzling and try again | ||
973 | */ | ||
974 | lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); | ||
975 | pdev = ppdev; | ||
976 | } | ||
977 | |||
978 | laddr[0] = (pdev->bus->number << 16) | ||
979 | | (pdev->devfn << 8); | ||
980 | laddr[1] = laddr[2] = 0; | ||
981 | return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); | ||
982 | } | ||
983 | EXPORT_SYMBOL_GPL(of_irq_map_pci); | ||
984 | #endif /* CONFIG_PCI */ | ||
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 6ef80d4e38d..387ed0d9ad6 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -810,9 +810,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
810 | return 0; | 810 | return 0; |
811 | } | 811 | } |
812 | 812 | ||
813 | #ifdef CONFIG_HOTPLUG_CPU | ||
813 | /* This version can't take the spinlock, because it never returns */ | 814 | /* This version can't take the spinlock, because it never returns */ |
814 | 815 | static struct rtas_args rtas_stop_self_args = { | |
815 | struct rtas_args rtas_stop_self_args = { | ||
816 | /* The token is initialized for real in setup_system() */ | 816 | /* The token is initialized for real in setup_system() */ |
817 | .token = RTAS_UNKNOWN_SERVICE, | 817 | .token = RTAS_UNKNOWN_SERVICE, |
818 | .nargs = 0, | 818 | .nargs = 0, |
@@ -834,6 +834,7 @@ void rtas_stop_self(void) | |||
834 | 834 | ||
835 | panic("Alas, I survived.\n"); | 835 | panic("Alas, I survived.\n"); |
836 | } | 836 | } |
837 | #endif | ||
837 | 838 | ||
838 | /* | 839 | /* |
839 | * Call early during boot, before mem init or bootmem, to retrieve the RTAS | 840 | * Call early during boot, before mem init or bootmem, to retrieve the RTAS |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 6f6fc977cb3..b9561d30051 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -681,14 +681,12 @@ static int initialize_flash_pde_data(const char *rtas_call_name, | |||
681 | int *status; | 681 | int *status; |
682 | int token; | 682 | int token; |
683 | 683 | ||
684 | dp->data = kmalloc(buf_size, GFP_KERNEL); | 684 | dp->data = kzalloc(buf_size, GFP_KERNEL); |
685 | if (dp->data == NULL) { | 685 | if (dp->data == NULL) { |
686 | remove_flash_pde(dp); | 686 | remove_flash_pde(dp); |
687 | return -ENOMEM; | 687 | return -ENOMEM; |
688 | } | 688 | } |
689 | 689 | ||
690 | memset(dp->data, 0, buf_size); | ||
691 | |||
692 | /* | 690 | /* |
693 | * This code assumes that the status int is the first member of the | 691 | * This code assumes that the status int is the first member of the |
694 | * struct | 692 | * struct |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index b4a0de79c06..ace9f4c86e6 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/rtas.h> | 38 | #include <asm/rtas.h> |
39 | #include <asm/mpic.h> | 39 | #include <asm/mpic.h> |
40 | #include <asm/ppc-pci.h> | 40 | #include <asm/ppc-pci.h> |
41 | #include <asm/eeh.h> | ||
41 | 42 | ||
42 | /* RTAS tokens */ | 43 | /* RTAS tokens */ |
43 | static int read_pci_config; | 44 | static int read_pci_config; |
@@ -231,32 +232,13 @@ void __init init_pci_config_tokens (void) | |||
231 | 232 | ||
232 | unsigned long __devinit get_phb_buid (struct device_node *phb) | 233 | unsigned long __devinit get_phb_buid (struct device_node *phb) |
233 | { | 234 | { |
234 | int addr_cells; | 235 | struct resource r; |
235 | const unsigned int *buid_vals; | ||
236 | unsigned int len; | ||
237 | unsigned long buid; | ||
238 | |||
239 | if (ibm_read_pci_config == -1) return 0; | ||
240 | 236 | ||
241 | /* PHB's will always be children of the root node, | 237 | if (ibm_read_pci_config == -1) |
242 | * or so it is promised by the current firmware. */ | ||
243 | if (phb->parent == NULL) | ||
244 | return 0; | 238 | return 0; |
245 | if (phb->parent->parent) | 239 | if (of_address_to_resource(phb, 0, &r)) |
246 | return 0; | ||
247 | |||
248 | buid_vals = get_property(phb, "reg", &len); | ||
249 | if (buid_vals == NULL) | ||
250 | return 0; | 240 | return 0; |
251 | 241 | return r.start; | |
252 | addr_cells = prom_n_addr_cells(phb); | ||
253 | if (addr_cells == 1) { | ||
254 | buid = (unsigned long) buid_vals[0]; | ||
255 | } else { | ||
256 | buid = (((unsigned long)buid_vals[0]) << 32UL) | | ||
257 | (((unsigned long)buid_vals[1]) & 0xffffffff); | ||
258 | } | ||
259 | return buid; | ||
260 | } | 242 | } |
261 | 243 | ||
262 | static int phb_set_bus_ranges(struct device_node *dev, | 244 | static int phb_set_bus_ranges(struct device_node *dev, |
@@ -276,8 +258,10 @@ static int phb_set_bus_ranges(struct device_node *dev, | |||
276 | return 0; | 258 | return 0; |
277 | } | 259 | } |
278 | 260 | ||
279 | int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb) | 261 | int __devinit rtas_setup_phb(struct pci_controller *phb) |
280 | { | 262 | { |
263 | struct device_node *dev = phb->arch_data; | ||
264 | |||
281 | if (is_python(dev)) | 265 | if (is_python(dev)) |
282 | python_countermeasures(dev); | 266 | python_countermeasures(dev); |
283 | 267 | ||
@@ -309,7 +293,7 @@ unsigned long __init find_and_init_phbs(void) | |||
309 | phb = pcibios_alloc_controller(node); | 293 | phb = pcibios_alloc_controller(node); |
310 | if (!phb) | 294 | if (!phb) |
311 | continue; | 295 | continue; |
312 | setup_phb(node, phb); | 296 | rtas_setup_phb(phb); |
313 | pci_process_bridge_OF_ranges(phb, node, 0); | 297 | pci_process_bridge_OF_ranges(phb, node, 0); |
314 | pci_setup_phb_io(phb, index == 0); | 298 | pci_setup_phb_io(phb, index == 0); |
315 | index++; | 299 | index++; |
@@ -381,7 +365,6 @@ int pcibios_remove_root_bus(struct pci_controller *phb) | |||
381 | } | 365 | } |
382 | } | 366 | } |
383 | 367 | ||
384 | list_del(&phb->list_node); | ||
385 | pcibios_free_controller(phb); | 368 | pcibios_free_controller(phb); |
386 | 369 | ||
387 | return 0; | 370 | return 0; |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index a4c2964a3ca..61c65d19ef0 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -63,10 +63,6 @@ unsigned int DMA_MODE_WRITE; | |||
63 | 63 | ||
64 | int have_of = 1; | 64 | int have_of = 1; |
65 | 65 | ||
66 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
67 | dev_t boot_dev; | ||
68 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
69 | |||
70 | #ifdef CONFIG_VGA_CONSOLE | 66 | #ifdef CONFIG_VGA_CONSOLE |
71 | unsigned long vgacon_remap_base; | 67 | unsigned long vgacon_remap_base; |
72 | #endif | 68 | #endif |
@@ -101,7 +97,7 @@ unsigned long __init early_init(unsigned long dt_ptr) | |||
101 | * Identify the CPU type and fix up code sections | 97 | * Identify the CPU type and fix up code sections |
102 | * that depend on which cpu we have. | 98 | * that depend on which cpu we have. |
103 | */ | 99 | */ |
104 | spec = identify_cpu(offset); | 100 | spec = identify_cpu(offset, mfspr(SPRN_PVR)); |
105 | 101 | ||
106 | do_feature_fixups(spec->cpu_features, | 102 | do_feature_fixups(spec->cpu_features, |
107 | PTRRELOC(&__start___ftr_fixup), | 103 | PTRRELOC(&__start___ftr_fixup), |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 16278968dab..3733de30e84 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
34 | #include <linux/serial_8250.h> | 34 | #include <linux/serial_8250.h> |
35 | #include <linux/bootmem.h> | 35 | #include <linux/bootmem.h> |
36 | #include <linux/pci.h> | ||
36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
37 | #include <asm/kdump.h> | 38 | #include <asm/kdump.h> |
38 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
@@ -71,7 +72,6 @@ | |||
71 | 72 | ||
72 | int have_of = 1; | 73 | int have_of = 1; |
73 | int boot_cpuid = 0; | 74 | int boot_cpuid = 0; |
74 | dev_t boot_dev; | ||
75 | u64 ppc64_pft_size; | 75 | u64 ppc64_pft_size; |
76 | 76 | ||
77 | /* Pick defaults since we might want to patch instructions | 77 | /* Pick defaults since we might want to patch instructions |
@@ -171,7 +171,7 @@ void __init setup_paca(int cpu) | |||
171 | void __init early_setup(unsigned long dt_ptr) | 171 | void __init early_setup(unsigned long dt_ptr) |
172 | { | 172 | { |
173 | /* Identify CPU type */ | 173 | /* Identify CPU type */ |
174 | identify_cpu(0); | 174 | identify_cpu(0, mfspr(SPRN_PVR)); |
175 | 175 | ||
176 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ | 176 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ |
177 | setup_paca(0); | 177 | setup_paca(0); |
@@ -226,8 +226,8 @@ void early_setup_secondary(void) | |||
226 | { | 226 | { |
227 | struct paca_struct *lpaca = get_paca(); | 227 | struct paca_struct *lpaca = get_paca(); |
228 | 228 | ||
229 | /* Mark enabled in PACA */ | 229 | /* Mark interrupts enabled in PACA */ |
230 | lpaca->proc_enabled = 0; | 230 | lpaca->soft_enabled = 0; |
231 | 231 | ||
232 | /* Initialize hash table for that CPU */ | 232 | /* Initialize hash table for that CPU */ |
233 | htab_initialize_secondary(); | 233 | htab_initialize_secondary(); |
@@ -392,7 +392,8 @@ void __init setup_system(void) | |||
392 | * setting up the hash table pointers. It also sets up some interrupt-mapping | 392 | * setting up the hash table pointers. It also sets up some interrupt-mapping |
393 | * related options that will be used by finish_device_tree() | 393 | * related options that will be used by finish_device_tree() |
394 | */ | 394 | */ |
395 | ppc_md.init_early(); | 395 | if (ppc_md.init_early) |
396 | ppc_md.init_early(); | ||
396 | 397 | ||
397 | /* | 398 | /* |
398 | * We can discover serial ports now since the above did setup the | 399 | * We can discover serial ports now since the above did setup the |
@@ -598,3 +599,10 @@ void __init setup_per_cpu_areas(void) | |||
598 | } | 599 | } |
599 | } | 600 | } |
600 | #endif | 601 | #endif |
602 | |||
603 | |||
604 | #ifdef CONFIG_PPC_INDIRECT_IO | ||
605 | struct ppc_pci_io ppc_pci_io; | ||
606 | EXPORT_SYMBOL(ppc_pci_io); | ||
607 | #endif /* CONFIG_PPC_INDIRECT_IO */ | ||
608 | |||
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c index de59c6c31a5..bc892e69b4f 100644 --- a/arch/powerpc/kernel/smp-tbsync.c +++ b/arch/powerpc/kernel/smp-tbsync.c | |||
@@ -78,7 +78,7 @@ static int __devinit start_contest(int cmd, long offset, int num) | |||
78 | { | 78 | { |
79 | int i, score=0; | 79 | int i, score=0; |
80 | u64 tb; | 80 | u64 tb; |
81 | long mark; | 81 | u64 mark; |
82 | 82 | ||
83 | tbsync->cmd = cmd; | 83 | tbsync->cmd = cmd; |
84 | 84 | ||
@@ -116,8 +116,7 @@ void __devinit smp_generic_give_timebase(void) | |||
116 | printk("Synchronizing timebase\n"); | 116 | printk("Synchronizing timebase\n"); |
117 | 117 | ||
118 | /* if this fails then this kernel won't work anyway... */ | 118 | /* if this fails then this kernel won't work anyway... */ |
119 | tbsync = kmalloc( sizeof(*tbsync), GFP_KERNEL ); | 119 | tbsync = kzalloc( sizeof(*tbsync), GFP_KERNEL ); |
120 | memset( tbsync, 0, sizeof(*tbsync) ); | ||
121 | mb(); | 120 | mb(); |
122 | running = 1; | 121 | running = 1; |
123 | 122 | ||
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 35c6309bdb7..9b28c238b6c 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -65,6 +65,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; | |||
65 | 65 | ||
66 | EXPORT_SYMBOL(cpu_online_map); | 66 | EXPORT_SYMBOL(cpu_online_map); |
67 | EXPORT_SYMBOL(cpu_possible_map); | 67 | EXPORT_SYMBOL(cpu_possible_map); |
68 | EXPORT_SYMBOL(cpu_sibling_map); | ||
68 | 69 | ||
69 | /* SMP operations for this machine */ | 70 | /* SMP operations for this machine */ |
70 | struct smp_ops_t *smp_ops; | 71 | struct smp_ops_t *smp_ops; |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index d15c33e9595..03a2a2f30d6 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <asm/time.h> | 51 | #include <asm/time.h> |
52 | #include <asm/mmu_context.h> | 52 | #include <asm/mmu_context.h> |
53 | #include <asm/ppc-pci.h> | 53 | #include <asm/ppc-pci.h> |
54 | #include <asm/syscalls.h> | ||
54 | 55 | ||
55 | /* readdir & getdents */ | 56 | /* readdir & getdents */ |
56 | #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) | 57 | #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index d45a168bdac..22123a0d541 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -200,10 +200,9 @@ static void register_cpu_online(unsigned int cpu) | |||
200 | struct cpu *c = &per_cpu(cpu_devices, cpu); | 200 | struct cpu *c = &per_cpu(cpu_devices, cpu); |
201 | struct sys_device *s = &c->sysdev; | 201 | struct sys_device *s = &c->sysdev; |
202 | 202 | ||
203 | #ifndef CONFIG_PPC_ISERIES | 203 | if (!firmware_has_feature(FW_FEATURE_ISERIES) && |
204 | if (cpu_has_feature(CPU_FTR_SMT)) | 204 | cpu_has_feature(CPU_FTR_SMT)) |
205 | sysdev_create_file(s, &attr_smt_snooze_delay); | 205 | sysdev_create_file(s, &attr_smt_snooze_delay); |
206 | #endif | ||
207 | 206 | ||
208 | /* PMC stuff */ | 207 | /* PMC stuff */ |
209 | 208 | ||
@@ -242,10 +241,9 @@ static void unregister_cpu_online(unsigned int cpu) | |||
242 | 241 | ||
243 | BUG_ON(c->no_control); | 242 | BUG_ON(c->no_control); |
244 | 243 | ||
245 | #ifndef CONFIG_PPC_ISERIES | 244 | if (!firmware_has_feature(FW_FEATURE_ISERIES) && |
246 | if (cpu_has_feature(CPU_FTR_SMT)) | 245 | cpu_has_feature(CPU_FTR_SMT)) |
247 | sysdev_remove_file(s, &attr_smt_snooze_delay); | 246 | sysdev_remove_file(s, &attr_smt_snooze_delay); |
248 | #endif | ||
249 | 247 | ||
250 | /* PMC stuff */ | 248 | /* PMC stuff */ |
251 | 249 | ||
@@ -299,6 +297,72 @@ static struct notifier_block __cpuinitdata sysfs_cpu_nb = { | |||
299 | .notifier_call = sysfs_cpu_notify, | 297 | .notifier_call = sysfs_cpu_notify, |
300 | }; | 298 | }; |
301 | 299 | ||
300 | static DEFINE_MUTEX(cpu_mutex); | ||
301 | |||
302 | int cpu_add_sysdev_attr(struct sysdev_attribute *attr) | ||
303 | { | ||
304 | int cpu; | ||
305 | |||
306 | mutex_lock(&cpu_mutex); | ||
307 | |||
308 | for_each_possible_cpu(cpu) { | ||
309 | sysdev_create_file(get_cpu_sysdev(cpu), attr); | ||
310 | } | ||
311 | |||
312 | mutex_unlock(&cpu_mutex); | ||
313 | return 0; | ||
314 | } | ||
315 | EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr); | ||
316 | |||
317 | int cpu_add_sysdev_attr_group(struct attribute_group *attrs) | ||
318 | { | ||
319 | int cpu; | ||
320 | struct sys_device *sysdev; | ||
321 | |||
322 | mutex_lock(&cpu_mutex); | ||
323 | |||
324 | for_each_possible_cpu(cpu) { | ||
325 | sysdev = get_cpu_sysdev(cpu); | ||
326 | sysfs_create_group(&sysdev->kobj, attrs); | ||
327 | } | ||
328 | |||
329 | mutex_unlock(&cpu_mutex); | ||
330 | return 0; | ||
331 | } | ||
332 | EXPORT_SYMBOL_GPL(cpu_add_sysdev_attr_group); | ||
333 | |||
334 | |||
335 | void cpu_remove_sysdev_attr(struct sysdev_attribute *attr) | ||
336 | { | ||
337 | int cpu; | ||
338 | |||
339 | mutex_lock(&cpu_mutex); | ||
340 | |||
341 | for_each_possible_cpu(cpu) { | ||
342 | sysdev_remove_file(get_cpu_sysdev(cpu), attr); | ||
343 | } | ||
344 | |||
345 | mutex_unlock(&cpu_mutex); | ||
346 | } | ||
347 | EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr); | ||
348 | |||
349 | void cpu_remove_sysdev_attr_group(struct attribute_group *attrs) | ||
350 | { | ||
351 | int cpu; | ||
352 | struct sys_device *sysdev; | ||
353 | |||
354 | mutex_lock(&cpu_mutex); | ||
355 | |||
356 | for_each_possible_cpu(cpu) { | ||
357 | sysdev = get_cpu_sysdev(cpu); | ||
358 | sysfs_remove_group(&sysdev->kobj, attrs); | ||
359 | } | ||
360 | |||
361 | mutex_unlock(&cpu_mutex); | ||
362 | } | ||
363 | EXPORT_SYMBOL_GPL(cpu_remove_sysdev_attr_group); | ||
364 | |||
365 | |||
302 | /* NUMA stuff */ | 366 | /* NUMA stuff */ |
303 | 367 | ||
304 | #ifdef CONFIG_NUMA | 368 | #ifdef CONFIG_NUMA |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 46a24de36fe..f6f0c6b07c4 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -631,7 +631,8 @@ void timer_interrupt(struct pt_regs * regs) | |||
631 | calculate_steal_time(); | 631 | calculate_steal_time(); |
632 | 632 | ||
633 | #ifdef CONFIG_PPC_ISERIES | 633 | #ifdef CONFIG_PPC_ISERIES |
634 | get_lppaca()->int_dword.fields.decr_int = 0; | 634 | if (firmware_has_feature(FW_FEATURE_ISERIES)) |
635 | get_lppaca()->int_dword.fields.decr_int = 0; | ||
635 | #endif | 636 | #endif |
636 | 637 | ||
637 | while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) | 638 | while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) |
@@ -674,7 +675,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
674 | set_dec(next_dec); | 675 | set_dec(next_dec); |
675 | 676 | ||
676 | #ifdef CONFIG_PPC_ISERIES | 677 | #ifdef CONFIG_PPC_ISERIES |
677 | if (hvlpevent_is_pending()) | 678 | if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending()) |
678 | process_hvlpevents(); | 679 | process_hvlpevents(); |
679 | #endif | 680 | #endif |
680 | 681 | ||
@@ -774,7 +775,7 @@ int do_settimeofday(struct timespec *tv) | |||
774 | * settimeofday to perform this operation. | 775 | * settimeofday to perform this operation. |
775 | */ | 776 | */ |
776 | #ifdef CONFIG_PPC_ISERIES | 777 | #ifdef CONFIG_PPC_ISERIES |
777 | if (first_settimeofday) { | 778 | if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) { |
778 | iSeries_tb_recal(); | 779 | iSeries_tb_recal(); |
779 | first_settimeofday = 0; | 780 | first_settimeofday = 0; |
780 | } | 781 | } |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index c66b4771ef4..0d4e203fa7a 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -53,10 +53,6 @@ | |||
53 | #endif | 53 | #endif |
54 | #include <asm/kexec.h> | 54 | #include <asm/kexec.h> |
55 | 55 | ||
56 | #ifdef CONFIG_PPC64 /* XXX */ | ||
57 | #define _IO_BASE pci_io_base | ||
58 | #endif | ||
59 | |||
60 | #ifdef CONFIG_DEBUGGER | 56 | #ifdef CONFIG_DEBUGGER |
61 | int (*__debugger)(struct pt_regs *regs); | 57 | int (*__debugger)(struct pt_regs *regs); |
62 | int (*__debugger_ipi)(struct pt_regs *regs); | 58 | int (*__debugger_ipi)(struct pt_regs *regs); |
@@ -241,7 +237,7 @@ void system_reset_exception(struct pt_regs *regs) | |||
241 | */ | 237 | */ |
242 | static inline int check_io_access(struct pt_regs *regs) | 238 | static inline int check_io_access(struct pt_regs *regs) |
243 | { | 239 | { |
244 | #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) | 240 | #ifdef CONFIG_PPC32 |
245 | unsigned long msr = regs->msr; | 241 | unsigned long msr = regs->msr; |
246 | const struct exception_table_entry *entry; | 242 | const struct exception_table_entry *entry; |
247 | unsigned int *nip = (unsigned int *)regs->nip; | 243 | unsigned int *nip = (unsigned int *)regs->nip; |
@@ -274,7 +270,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
274 | return 1; | 270 | return 1; |
275 | } | 271 | } |
276 | } | 272 | } |
277 | #endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */ | 273 | #endif /* CONFIG_PPC32 */ |
278 | return 0; | 274 | return 0; |
279 | } | 275 | } |
280 | 276 | ||
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index ed007878d1b..a80f8f1d2e5 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -81,15 +81,15 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) | |||
81 | struct iommu_table *tbl; | 81 | struct iommu_table *tbl; |
82 | unsigned long offset, size; | 82 | unsigned long offset, size; |
83 | 83 | ||
84 | dma_window = get_property(dev->dev.platform_data, | 84 | dma_window = get_property(dev->dev.archdata.of_node, |
85 | "ibm,my-dma-window", NULL); | 85 | "ibm,my-dma-window", NULL); |
86 | if (!dma_window) | 86 | if (!dma_window) |
87 | return NULL; | 87 | return NULL; |
88 | 88 | ||
89 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); | 89 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); |
90 | 90 | ||
91 | of_parse_dma_window(dev->dev.platform_data, dma_window, | 91 | of_parse_dma_window(dev->dev.archdata.of_node, dma_window, |
92 | &tbl->it_index, &offset, &size); | 92 | &tbl->it_index, &offset, &size); |
93 | 93 | ||
94 | /* TCE table size - measured in tce entries */ | 94 | /* TCE table size - measured in tce entries */ |
95 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; | 95 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; |
@@ -117,7 +117,8 @@ static const struct vio_device_id *vio_match_device( | |||
117 | { | 117 | { |
118 | while (ids->type[0] != '\0') { | 118 | while (ids->type[0] != '\0') { |
119 | if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && | 119 | if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && |
120 | device_is_compatible(dev->dev.platform_data, ids->compat)) | 120 | device_is_compatible(dev->dev.archdata.of_node, |
121 | ids->compat)) | ||
121 | return ids; | 122 | return ids; |
122 | ids++; | 123 | ids++; |
123 | } | 124 | } |
@@ -198,9 +199,9 @@ EXPORT_SYMBOL(vio_unregister_driver); | |||
198 | /* vio_dev refcount hit 0 */ | 199 | /* vio_dev refcount hit 0 */ |
199 | static void __devinit vio_dev_release(struct device *dev) | 200 | static void __devinit vio_dev_release(struct device *dev) |
200 | { | 201 | { |
201 | if (dev->platform_data) { | 202 | if (dev->archdata.of_node) { |
202 | /* XXX free TCE table */ | 203 | /* XXX should free TCE table */ |
203 | of_node_put(dev->platform_data); | 204 | of_node_put(dev->archdata.of_node); |
204 | } | 205 | } |
205 | kfree(to_vio_dev(dev)); | 206 | kfree(to_vio_dev(dev)); |
206 | } | 207 | } |
@@ -210,7 +211,7 @@ static void __devinit vio_dev_release(struct device *dev) | |||
210 | * @of_node: The OF node for this device. | 211 | * @of_node: The OF node for this device. |
211 | * | 212 | * |
212 | * Creates and initializes a vio_dev structure from the data in | 213 | * Creates and initializes a vio_dev structure from the data in |
213 | * of_node (dev.platform_data) and adds it to the list of virtual devices. | 214 | * of_node and adds it to the list of virtual devices. |
214 | * Returns a pointer to the created vio_dev or NULL if node has | 215 | * Returns a pointer to the created vio_dev or NULL if node has |
215 | * NULL device_type or compatible fields. | 216 | * NULL device_type or compatible fields. |
216 | */ | 217 | */ |
@@ -240,8 +241,6 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) | |||
240 | if (viodev == NULL) | 241 | if (viodev == NULL) |
241 | return NULL; | 242 | return NULL; |
242 | 243 | ||
243 | viodev->dev.platform_data = of_node_get(of_node); | ||
244 | |||
245 | viodev->irq = irq_of_parse_and_map(of_node, 0); | 244 | viodev->irq = irq_of_parse_and_map(of_node, 0); |
246 | 245 | ||
247 | snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); | 246 | snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); |
@@ -254,7 +253,10 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) | |||
254 | if (unit_address != NULL) | 253 | if (unit_address != NULL) |
255 | viodev->unit_address = *unit_address; | 254 | viodev->unit_address = *unit_address; |
256 | } | 255 | } |
257 | viodev->iommu_table = vio_build_iommu_table(viodev); | 256 | viodev->dev.archdata.of_node = of_node_get(of_node); |
257 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; | ||
258 | viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev); | ||
259 | viodev->dev.archdata.numa_node = of_node_to_nid(of_node); | ||
258 | 260 | ||
259 | /* init generic 'struct device' fields: */ | 261 | /* init generic 'struct device' fields: */ |
260 | viodev->dev.parent = &vio_bus_device.dev; | 262 | viodev->dev.parent = &vio_bus_device.dev; |
@@ -285,10 +287,11 @@ static int __init vio_bus_init(void) | |||
285 | #ifdef CONFIG_PPC_ISERIES | 287 | #ifdef CONFIG_PPC_ISERIES |
286 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | 288 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { |
287 | iommu_vio_init(); | 289 | iommu_vio_init(); |
288 | vio_bus_device.iommu_table = &vio_iommu_table; | 290 | vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops; |
291 | vio_bus_device.dev.archdata.dma_data = &vio_iommu_table; | ||
289 | iSeries_vio_dev = &vio_bus_device.dev; | 292 | iSeries_vio_dev = &vio_bus_device.dev; |
290 | } | 293 | } |
291 | #endif | 294 | #endif /* CONFIG_PPC_ISERIES */ |
292 | 295 | ||
293 | err = bus_register(&vio_bus_type); | 296 | err = bus_register(&vio_bus_type); |
294 | if (err) { | 297 | if (err) { |
@@ -336,7 +339,7 @@ static ssize_t name_show(struct device *dev, | |||
336 | static ssize_t devspec_show(struct device *dev, | 339 | static ssize_t devspec_show(struct device *dev, |
337 | struct device_attribute *attr, char *buf) | 340 | struct device_attribute *attr, char *buf) |
338 | { | 341 | { |
339 | struct device_node *of_node = dev->platform_data; | 342 | struct device_node *of_node = dev->archdata.of_node; |
340 | 343 | ||
341 | return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); | 344 | return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); |
342 | } | 345 | } |
@@ -353,62 +356,6 @@ void __devinit vio_unregister_device(struct vio_dev *viodev) | |||
353 | } | 356 | } |
354 | EXPORT_SYMBOL(vio_unregister_device); | 357 | EXPORT_SYMBOL(vio_unregister_device); |
355 | 358 | ||
356 | static dma_addr_t vio_map_single(struct device *dev, void *vaddr, | ||
357 | size_t size, enum dma_data_direction direction) | ||
358 | { | ||
359 | return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size, | ||
360 | ~0ul, direction); | ||
361 | } | ||
362 | |||
363 | static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle, | ||
364 | size_t size, enum dma_data_direction direction) | ||
365 | { | ||
366 | iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size, | ||
367 | direction); | ||
368 | } | ||
369 | |||
370 | static int vio_map_sg(struct device *dev, struct scatterlist *sglist, | ||
371 | int nelems, enum dma_data_direction direction) | ||
372 | { | ||
373 | return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist, | ||
374 | nelems, ~0ul, direction); | ||
375 | } | ||
376 | |||
377 | static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist, | ||
378 | int nelems, enum dma_data_direction direction) | ||
379 | { | ||
380 | iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction); | ||
381 | } | ||
382 | |||
383 | static void *vio_alloc_coherent(struct device *dev, size_t size, | ||
384 | dma_addr_t *dma_handle, gfp_t flag) | ||
385 | { | ||
386 | return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, | ||
387 | dma_handle, ~0ul, flag, -1); | ||
388 | } | ||
389 | |||
390 | static void vio_free_coherent(struct device *dev, size_t size, | ||
391 | void *vaddr, dma_addr_t dma_handle) | ||
392 | { | ||
393 | iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr, | ||
394 | dma_handle); | ||
395 | } | ||
396 | |||
397 | static int vio_dma_supported(struct device *dev, u64 mask) | ||
398 | { | ||
399 | return 1; | ||
400 | } | ||
401 | |||
402 | struct dma_mapping_ops vio_dma_ops = { | ||
403 | .alloc_coherent = vio_alloc_coherent, | ||
404 | .free_coherent = vio_free_coherent, | ||
405 | .map_single = vio_map_single, | ||
406 | .unmap_single = vio_unmap_single, | ||
407 | .map_sg = vio_map_sg, | ||
408 | .unmap_sg = vio_unmap_sg, | ||
409 | .dma_supported = vio_dma_supported, | ||
410 | }; | ||
411 | |||
412 | static int vio_bus_match(struct device *dev, struct device_driver *drv) | 359 | static int vio_bus_match(struct device *dev, struct device_driver *drv) |
413 | { | 360 | { |
414 | const struct vio_dev *vio_dev = to_vio_dev(dev); | 361 | const struct vio_dev *vio_dev = to_vio_dev(dev); |
@@ -422,13 +369,14 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, | |||
422 | char *buffer, int buffer_size) | 369 | char *buffer, int buffer_size) |
423 | { | 370 | { |
424 | const struct vio_dev *vio_dev = to_vio_dev(dev); | 371 | const struct vio_dev *vio_dev = to_vio_dev(dev); |
425 | struct device_node *dn = dev->platform_data; | 372 | struct device_node *dn; |
426 | const char *cp; | 373 | const char *cp; |
427 | int length; | 374 | int length; |
428 | 375 | ||
429 | if (!num_envp) | 376 | if (!num_envp) |
430 | return -ENOMEM; | 377 | return -ENOMEM; |
431 | 378 | ||
379 | dn = dev->archdata.of_node; | ||
432 | if (!dn) | 380 | if (!dn) |
433 | return -ENODEV; | 381 | return -ENODEV; |
434 | cp = get_property(dn, "compatible", &length); | 382 | cp = get_property(dn, "compatible", &length); |
@@ -465,7 +413,7 @@ struct bus_type vio_bus_type = { | |||
465 | */ | 413 | */ |
466 | const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) | 414 | const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) |
467 | { | 415 | { |
468 | return get_property(vdev->dev.platform_data, which, length); | 416 | return get_property(vdev->dev.archdata.of_node, which, length); |
469 | } | 417 | } |
470 | EXPORT_SYMBOL(vio_get_attribute); | 418 | EXPORT_SYMBOL(vio_get_attribute); |
471 | 419 | ||
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 93441e7a292..38a81967ca0 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
@@ -8,7 +8,7 @@ endif | |||
8 | 8 | ||
9 | obj-y := fault.o mem.o lmb.o | 9 | obj-y := fault.o mem.o lmb.o |
10 | obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o | 10 | obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o |
11 | hash-$(CONFIG_PPC_MULTIPLATFORM) := hash_native_64.o | 11 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ | 12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ |
13 | hash_utils_64.o hash_low_64.o tlb_64.o \ | 13 | hash_utils_64.o hash_low_64.o tlb_64.o \ |
14 | slb_low.o slb.o stab.o mmap.o imalloc.o \ | 14 | slb_low.o slb.o stab.o mmap.o imalloc.o \ |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index e8fa50624b7..03aeb3a4607 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -426,18 +426,21 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) | |||
426 | 426 | ||
427 | /* kernel has accessed a bad area */ | 427 | /* kernel has accessed a bad area */ |
428 | 428 | ||
429 | printk(KERN_ALERT "Unable to handle kernel paging request for "); | ||
430 | switch (regs->trap) { | 429 | switch (regs->trap) { |
431 | case 0x300: | 430 | case 0x300: |
432 | case 0x380: | 431 | case 0x380: |
433 | printk("data at address 0x%08lx\n", regs->dar); | 432 | printk(KERN_ALERT "Unable to handle kernel paging request for " |
434 | break; | 433 | "data at address 0x%08lx\n", regs->dar); |
435 | case 0x400: | 434 | break; |
436 | case 0x480: | 435 | case 0x400: |
437 | printk("instruction fetch\n"); | 436 | case 0x480: |
438 | break; | 437 | printk(KERN_ALERT "Unable to handle kernel paging request for " |
439 | default: | 438 | "instruction fetch\n"); |
440 | printk("unknown fault\n"); | 439 | break; |
440 | default: | ||
441 | printk(KERN_ALERT "Unable to handle kernel paging request for " | ||
442 | "unknown fault\n"); | ||
443 | break; | ||
441 | } | 444 | } |
442 | printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", | 445 | printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", |
443 | regs->nip); | 446 | regs->nip); |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index c90f124f3c7..6f1016acdbf 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -123,7 +123,7 @@ static inline void native_unlock_hpte(hpte_t *hptep) | |||
123 | clear_bit(HPTE_LOCK_BIT, word); | 123 | clear_bit(HPTE_LOCK_BIT, word); |
124 | } | 124 | } |
125 | 125 | ||
126 | long native_hpte_insert(unsigned long hpte_group, unsigned long va, | 126 | static long native_hpte_insert(unsigned long hpte_group, unsigned long va, |
127 | unsigned long pa, unsigned long rflags, | 127 | unsigned long pa, unsigned long rflags, |
128 | unsigned long vflags, int psize) | 128 | unsigned long vflags, int psize) |
129 | { | 129 | { |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 1915661c2c8..c0d2a694fa3 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -277,7 +277,7 @@ static void __init htab_init_page_sizes(void) | |||
277 | * Not in the device-tree, let's fallback on known size | 277 | * Not in the device-tree, let's fallback on known size |
278 | * list for 16M capable GP & GR | 278 | * list for 16M capable GP & GR |
279 | */ | 279 | */ |
280 | if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries)) | 280 | if (cpu_has_feature(CPU_FTR_16M_PAGE)) |
281 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, | 281 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, |
282 | sizeof(mmu_psize_defaults_gp)); | 282 | sizeof(mmu_psize_defaults_gp)); |
283 | found: | 283 | found: |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 3ff374697e3..9a178549cbc 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -130,7 +130,7 @@ static int __init setup_kcore(void) | |||
130 | /* GFP_ATOMIC to avoid might_sleep warnings during boot */ | 130 | /* GFP_ATOMIC to avoid might_sleep warnings during boot */ |
131 | kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC); | 131 | kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC); |
132 | if (!kcore_mem) | 132 | if (!kcore_mem) |
133 | panic("mem_init: kmalloc failed\n"); | 133 | panic("%s: kmalloc failed\n", __FUNCTION__); |
134 | 134 | ||
135 | kclist_add(kcore_mem, __va(base), size); | 135 | kclist_add(kcore_mem, __va(base), size); |
136 | } | 136 | } |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 8fcacb0239d..1891dbeeb8e 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -141,29 +141,19 @@ void pte_free(struct page *ptepage) | |||
141 | __free_page(ptepage); | 141 | __free_page(ptepage); |
142 | } | 142 | } |
143 | 143 | ||
144 | #ifndef CONFIG_PHYS_64BIT | ||
145 | void __iomem * | 144 | void __iomem * |
146 | ioremap(phys_addr_t addr, unsigned long size) | 145 | ioremap(phys_addr_t addr, unsigned long size) |
147 | { | 146 | { |
148 | return __ioremap(addr, size, _PAGE_NO_CACHE); | 147 | return __ioremap(addr, size, _PAGE_NO_CACHE); |
149 | } | 148 | } |
150 | #else /* CONFIG_PHYS_64BIT */ | 149 | EXPORT_SYMBOL(ioremap); |
151 | void __iomem * | ||
152 | ioremap64(unsigned long long addr, unsigned long size) | ||
153 | { | ||
154 | return __ioremap(addr, size, _PAGE_NO_CACHE); | ||
155 | } | ||
156 | EXPORT_SYMBOL(ioremap64); | ||
157 | 150 | ||
158 | void __iomem * | 151 | void __iomem * |
159 | ioremap(phys_addr_t addr, unsigned long size) | 152 | ioremap_flags(phys_addr_t addr, unsigned long size, unsigned long flags) |
160 | { | 153 | { |
161 | phys_addr_t addr64 = fixup_bigphys_addr(addr, size); | 154 | return __ioremap(addr, size, flags); |
162 | |||
163 | return ioremap64(addr64, size); | ||
164 | } | 155 | } |
165 | #endif /* CONFIG_PHYS_64BIT */ | 156 | EXPORT_SYMBOL(ioremap_flags); |
166 | EXPORT_SYMBOL(ioremap); | ||
167 | 157 | ||
168 | void __iomem * | 158 | void __iomem * |
169 | __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) | 159 | __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) |
@@ -264,20 +254,7 @@ void iounmap(volatile void __iomem *addr) | |||
264 | } | 254 | } |
265 | EXPORT_SYMBOL(iounmap); | 255 | EXPORT_SYMBOL(iounmap); |
266 | 256 | ||
267 | void __iomem *ioport_map(unsigned long port, unsigned int len) | 257 | int map_page(unsigned long va, phys_addr_t pa, int flags) |
268 | { | ||
269 | return (void __iomem *) (port + _IO_BASE); | ||
270 | } | ||
271 | |||
272 | void ioport_unmap(void __iomem *addr) | ||
273 | { | ||
274 | /* Nothing to do */ | ||
275 | } | ||
276 | EXPORT_SYMBOL(ioport_map); | ||
277 | EXPORT_SYMBOL(ioport_unmap); | ||
278 | |||
279 | int | ||
280 | map_page(unsigned long va, phys_addr_t pa, int flags) | ||
281 | { | 258 | { |
282 | pmd_t *pd; | 259 | pmd_t *pd; |
283 | pte_t *pg; | 260 | pte_t *pg; |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index ac64f4aaa50..16e4ee1c231 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -113,7 +113,7 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
116 | static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, | 116 | static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, |
117 | unsigned long ea, unsigned long size, | 117 | unsigned long ea, unsigned long size, |
118 | unsigned long flags) | 118 | unsigned long flags) |
119 | { | 119 | { |
@@ -129,22 +129,12 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa, | |||
129 | return (void __iomem *) (ea + (addr & ~PAGE_MASK)); | 129 | return (void __iomem *) (ea + (addr & ~PAGE_MASK)); |
130 | } | 130 | } |
131 | 131 | ||
132 | 132 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | |
133 | void __iomem * | ||
134 | ioremap(unsigned long addr, unsigned long size) | ||
135 | { | ||
136 | return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
137 | } | ||
138 | |||
139 | void __iomem * __ioremap(unsigned long addr, unsigned long size, | ||
140 | unsigned long flags) | 133 | unsigned long flags) |
141 | { | 134 | { |
142 | unsigned long pa, ea; | 135 | unsigned long pa, ea; |
143 | void __iomem *ret; | 136 | void __iomem *ret; |
144 | 137 | ||
145 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
146 | return (void __iomem *)addr; | ||
147 | |||
148 | /* | 138 | /* |
149 | * Choose an address to map it to. | 139 | * Choose an address to map it to. |
150 | * Once the imalloc system is running, we use it. | 140 | * Once the imalloc system is running, we use it. |
@@ -178,9 +168,28 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size, | |||
178 | return ret; | 168 | return ret; |
179 | } | 169 | } |
180 | 170 | ||
171 | |||
172 | void __iomem * ioremap(phys_addr_t addr, unsigned long size) | ||
173 | { | ||
174 | unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
175 | |||
176 | if (ppc_md.ioremap) | ||
177 | return ppc_md.ioremap(addr, size, flags); | ||
178 | return __ioremap(addr, size, flags); | ||
179 | } | ||
180 | |||
181 | void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size, | ||
182 | unsigned long flags) | ||
183 | { | ||
184 | if (ppc_md.ioremap) | ||
185 | return ppc_md.ioremap(addr, size, flags); | ||
186 | return __ioremap(addr, size, flags); | ||
187 | } | ||
188 | |||
189 | |||
181 | #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) | 190 | #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) |
182 | 191 | ||
183 | int __ioremap_explicit(unsigned long pa, unsigned long ea, | 192 | int __ioremap_explicit(phys_addr_t pa, unsigned long ea, |
184 | unsigned long size, unsigned long flags) | 193 | unsigned long size, unsigned long flags) |
185 | { | 194 | { |
186 | struct vm_struct *area; | 195 | struct vm_struct *area; |
@@ -235,13 +244,10 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, | |||
235 | * | 244 | * |
236 | * XXX what about calls before mem_init_done (ie python_countermeasures()) | 245 | * XXX what about calls before mem_init_done (ie python_countermeasures()) |
237 | */ | 246 | */ |
238 | void iounmap(volatile void __iomem *token) | 247 | void __iounmap(volatile void __iomem *token) |
239 | { | 248 | { |
240 | void *addr; | 249 | void *addr; |
241 | 250 | ||
242 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
243 | return; | ||
244 | |||
245 | if (!mem_init_done) | 251 | if (!mem_init_done) |
246 | return; | 252 | return; |
247 | 253 | ||
@@ -250,6 +256,14 @@ void iounmap(volatile void __iomem *token) | |||
250 | im_free(addr); | 256 | im_free(addr); |
251 | } | 257 | } |
252 | 258 | ||
259 | void iounmap(volatile void __iomem *token) | ||
260 | { | ||
261 | if (ppc_md.iounmap) | ||
262 | ppc_md.iounmap(token); | ||
263 | else | ||
264 | __iounmap(token); | ||
265 | } | ||
266 | |||
253 | static int iounmap_subset_regions(unsigned long addr, unsigned long size) | 267 | static int iounmap_subset_regions(unsigned long addr, unsigned long size) |
254 | { | 268 | { |
255 | struct vm_struct *area; | 269 | struct vm_struct *area; |
@@ -268,7 +282,7 @@ static int iounmap_subset_regions(unsigned long addr, unsigned long size) | |||
268 | return 0; | 282 | return 0; |
269 | } | 283 | } |
270 | 284 | ||
271 | int iounmap_explicit(volatile void __iomem *start, unsigned long size) | 285 | int __iounmap_explicit(volatile void __iomem *start, unsigned long size) |
272 | { | 286 | { |
273 | struct vm_struct *area; | 287 | struct vm_struct *area; |
274 | unsigned long addr; | 288 | unsigned long addr; |
@@ -303,8 +317,10 @@ int iounmap_explicit(volatile void __iomem *start, unsigned long size) | |||
303 | } | 317 | } |
304 | 318 | ||
305 | EXPORT_SYMBOL(ioremap); | 319 | EXPORT_SYMBOL(ioremap); |
320 | EXPORT_SYMBOL(ioremap_flags); | ||
306 | EXPORT_SYMBOL(__ioremap); | 321 | EXPORT_SYMBOL(__ioremap); |
307 | EXPORT_SYMBOL(iounmap); | 322 | EXPORT_SYMBOL(iounmap); |
323 | EXPORT_SYMBOL(__iounmap); | ||
308 | 324 | ||
309 | void __iomem * reserve_phb_iospace(unsigned long size) | 325 | void __iomem * reserve_phb_iospace(unsigned long size) |
310 | { | 326 | { |
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index d3733912adb..224e960650a 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/cputable.h> | 23 | #include <asm/cputable.h> |
24 | #include <asm/cacheflush.h> | 24 | #include <asm/cacheflush.h> |
25 | #include <asm/smp.h> | 25 | #include <asm/smp.h> |
26 | #include <asm/firmware.h> | ||
26 | #include <linux/compiler.h> | 27 | #include <linux/compiler.h> |
27 | 28 | ||
28 | #ifdef DEBUG | 29 | #ifdef DEBUG |
@@ -193,6 +194,7 @@ static inline void patch_slb_encoding(unsigned int *insn_addr, | |||
193 | void slb_initialize(void) | 194 | void slb_initialize(void) |
194 | { | 195 | { |
195 | unsigned long linear_llp, vmalloc_llp, io_llp; | 196 | unsigned long linear_llp, vmalloc_llp, io_llp; |
197 | unsigned long lflags, vflags; | ||
196 | static int slb_encoding_inited; | 198 | static int slb_encoding_inited; |
197 | extern unsigned int *slb_miss_kernel_load_linear; | 199 | extern unsigned int *slb_miss_kernel_load_linear; |
198 | extern unsigned int *slb_miss_kernel_load_io; | 200 | extern unsigned int *slb_miss_kernel_load_io; |
@@ -225,11 +227,12 @@ void slb_initialize(void) | |||
225 | #endif | 227 | #endif |
226 | } | 228 | } |
227 | 229 | ||
230 | get_paca()->stab_rr = SLB_NUM_BOLTED; | ||
231 | |||
228 | /* On iSeries the bolted entries have already been set up by | 232 | /* On iSeries the bolted entries have already been set up by |
229 | * the hypervisor from the lparMap data in head.S */ | 233 | * the hypervisor from the lparMap data in head.S */ |
230 | #ifndef CONFIG_PPC_ISERIES | 234 | if (firmware_has_feature(FW_FEATURE_ISERIES)) |
231 | { | 235 | return; |
232 | unsigned long lflags, vflags; | ||
233 | 236 | ||
234 | lflags = SLB_VSID_KERNEL | linear_llp; | 237 | lflags = SLB_VSID_KERNEL | linear_llp; |
235 | vflags = SLB_VSID_KERNEL | vmalloc_llp; | 238 | vflags = SLB_VSID_KERNEL | vmalloc_llp; |
@@ -247,8 +250,4 @@ void slb_initialize(void) | |||
247 | * elsewhere, we'll call _switch() which will bolt in the new | 250 | * elsewhere, we'll call _switch() which will bolt in the new |
248 | * one. */ | 251 | * one. */ |
249 | asm volatile("isync":::"memory"); | 252 | asm volatile("isync":::"memory"); |
250 | } | ||
251 | #endif /* CONFIG_PPC_ISERIES */ | ||
252 | |||
253 | get_paca()->stab_rr = SLB_NUM_BOLTED; | ||
254 | } | 253 | } |
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 0b5df9c96ae..4ccef2d5530 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
@@ -11,6 +11,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ | |||
11 | timer_int.o ) | 11 | timer_int.o ) |
12 | 12 | ||
13 | oprofile-y := $(DRIVER_OBJS) common.o backtrace.o | 13 | oprofile-y := $(DRIVER_OBJS) common.o backtrace.o |
14 | oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o | ||
14 | oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o | 15 | oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o |
15 | oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o | 16 | oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o |
16 | oprofile-$(CONFIG_6xx) += op_model_7450.o | 17 | oprofile-$(CONFIG_6xx) += op_model_7450.o |
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 63bbef3b63f..b6d82390b6a 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
@@ -69,7 +69,10 @@ static void op_powerpc_cpu_start(void *dummy) | |||
69 | 69 | ||
70 | static int op_powerpc_start(void) | 70 | static int op_powerpc_start(void) |
71 | { | 71 | { |
72 | on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); | 72 | if (model->global_start) |
73 | model->global_start(ctr); | ||
74 | if (model->start) | ||
75 | on_each_cpu(op_powerpc_cpu_start, NULL, 0, 1); | ||
73 | return 0; | 76 | return 0; |
74 | } | 77 | } |
75 | 78 | ||
@@ -80,7 +83,10 @@ static inline void op_powerpc_cpu_stop(void *dummy) | |||
80 | 83 | ||
81 | static void op_powerpc_stop(void) | 84 | static void op_powerpc_stop(void) |
82 | { | 85 | { |
83 | on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1); | 86 | if (model->stop) |
87 | on_each_cpu(op_powerpc_cpu_stop, NULL, 0, 1); | ||
88 | if (model->global_stop) | ||
89 | model->global_stop(); | ||
84 | } | 90 | } |
85 | 91 | ||
86 | static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) | 92 | static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) |
@@ -141,6 +147,11 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
141 | 147 | ||
142 | switch (cur_cpu_spec->oprofile_type) { | 148 | switch (cur_cpu_spec->oprofile_type) { |
143 | #ifdef CONFIG_PPC64 | 149 | #ifdef CONFIG_PPC64 |
150 | #ifdef CONFIG_PPC_CELL_NATIVE | ||
151 | case PPC_OPROFILE_CELL: | ||
152 | model = &op_model_cell; | ||
153 | break; | ||
154 | #endif | ||
144 | case PPC_OPROFILE_RS64: | 155 | case PPC_OPROFILE_RS64: |
145 | model = &op_model_rs64; | 156 | model = &op_model_rs64; |
146 | break; | 157 | break; |
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c new file mode 100644 index 00000000000..2eb15f38810 --- /dev/null +++ b/arch/powerpc/oprofile/op_model_cell.c | |||
@@ -0,0 +1,724 @@ | |||
1 | /* | ||
2 | * Cell Broadband Engine OProfile Support | ||
3 | * | ||
4 | * (C) Copyright IBM Corporation 2006 | ||
5 | * | ||
6 | * Author: David Erb (djerb@us.ibm.com) | ||
7 | * Modifications: | ||
8 | * Carl Love <carll@us.ibm.com> | ||
9 | * Maynard Johnson <maynardj@us.ibm.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/cpufreq.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/jiffies.h> | ||
21 | #include <linux/kthread.h> | ||
22 | #include <linux/oprofile.h> | ||
23 | #include <linux/percpu.h> | ||
24 | #include <linux/smp.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | #include <linux/timer.h> | ||
27 | #include <asm/cell-pmu.h> | ||
28 | #include <asm/cputable.h> | ||
29 | #include <asm/firmware.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/oprofile_impl.h> | ||
32 | #include <asm/processor.h> | ||
33 | #include <asm/prom.h> | ||
34 | #include <asm/ptrace.h> | ||
35 | #include <asm/reg.h> | ||
36 | #include <asm/rtas.h> | ||
37 | #include <asm/system.h> | ||
38 | |||
39 | #include "../platforms/cell/interrupt.h" | ||
40 | |||
41 | #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ | ||
42 | #define CBE_COUNT_ALL_CYCLES 0x42800000 /* PPU cycle event specifier */ | ||
43 | |||
44 | #define NUM_THREADS 2 | ||
45 | #define VIRT_CNTR_SW_TIME_NS 100000000 // 0.5 seconds | ||
46 | |||
47 | struct pmc_cntrl_data { | ||
48 | unsigned long vcntr; | ||
49 | unsigned long evnts; | ||
50 | unsigned long masks; | ||
51 | unsigned long enabled; | ||
52 | }; | ||
53 | |||
54 | /* | ||
55 | * ibm,cbe-perftools rtas parameters | ||
56 | */ | ||
57 | |||
58 | struct pm_signal { | ||
59 | u16 cpu; /* Processor to modify */ | ||
60 | u16 sub_unit; /* hw subunit this applies to (if applicable) */ | ||
61 | u16 signal_group; /* Signal Group to Enable/Disable */ | ||
62 | u8 bus_word; /* Enable/Disable on this Trace/Trigger/Event | ||
63 | * Bus Word(s) (bitmask) | ||
64 | */ | ||
65 | u8 bit; /* Trigger/Event bit (if applicable) */ | ||
66 | }; | ||
67 | |||
68 | /* | ||
69 | * rtas call arguments | ||
70 | */ | ||
71 | enum { | ||
72 | SUBFUNC_RESET = 1, | ||
73 | SUBFUNC_ACTIVATE = 2, | ||
74 | SUBFUNC_DEACTIVATE = 3, | ||
75 | |||
76 | PASSTHRU_IGNORE = 0, | ||
77 | PASSTHRU_ENABLE = 1, | ||
78 | PASSTHRU_DISABLE = 2, | ||
79 | }; | ||
80 | |||
81 | struct pm_cntrl { | ||
82 | u16 enable; | ||
83 | u16 stop_at_max; | ||
84 | u16 trace_mode; | ||
85 | u16 freeze; | ||
86 | u16 count_mode; | ||
87 | }; | ||
88 | |||
89 | static struct { | ||
90 | u32 group_control; | ||
91 | u32 debug_bus_control; | ||
92 | struct pm_cntrl pm_cntrl; | ||
93 | u32 pm07_cntrl[NR_PHYS_CTRS]; | ||
94 | } pm_regs; | ||
95 | |||
96 | |||
97 | #define GET_SUB_UNIT(x) ((x & 0x0000f000) >> 12) | ||
98 | #define GET_BUS_WORD(x) ((x & 0x000000f0) >> 4) | ||
99 | #define GET_BUS_TYPE(x) ((x & 0x00000300) >> 8) | ||
100 | #define GET_POLARITY(x) ((x & 0x00000002) >> 1) | ||
101 | #define GET_COUNT_CYCLES(x) (x & 0x00000001) | ||
102 | #define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2) | ||
103 | |||
104 | |||
105 | static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values); | ||
106 | |||
107 | static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS]; | ||
108 | |||
109 | /* Interpetation of hdw_thread: | ||
110 | * 0 - even virtual cpus 0, 2, 4,... | ||
111 | * 1 - odd virtual cpus 1, 3, 5, ... | ||
112 | */ | ||
113 | static u32 hdw_thread; | ||
114 | |||
115 | static u32 virt_cntr_inter_mask; | ||
116 | static struct timer_list timer_virt_cntr; | ||
117 | |||
118 | /* pm_signal needs to be global since it is initialized in | ||
119 | * cell_reg_setup at the time when the necessary information | ||
120 | * is available. | ||
121 | */ | ||
122 | static struct pm_signal pm_signal[NR_PHYS_CTRS]; | ||
123 | static int pm_rtas_token; | ||
124 | |||
125 | static u32 reset_value[NR_PHYS_CTRS]; | ||
126 | static int num_counters; | ||
127 | static int oprofile_running; | ||
128 | static spinlock_t virt_cntr_lock = SPIN_LOCK_UNLOCKED; | ||
129 | |||
130 | static u32 ctr_enabled; | ||
131 | |||
132 | static unsigned char trace_bus[4]; | ||
133 | static unsigned char input_bus[2]; | ||
134 | |||
135 | /* | ||
136 | * Firmware interface functions | ||
137 | */ | ||
138 | static int | ||
139 | rtas_ibm_cbe_perftools(int subfunc, int passthru, | ||
140 | void *address, unsigned long length) | ||
141 | { | ||
142 | u64 paddr = __pa(address); | ||
143 | |||
144 | return rtas_call(pm_rtas_token, 5, 1, NULL, subfunc, passthru, | ||
145 | paddr >> 32, paddr & 0xffffffff, length); | ||
146 | } | ||
147 | |||
148 | static void pm_rtas_reset_signals(u32 node) | ||
149 | { | ||
150 | int ret; | ||
151 | struct pm_signal pm_signal_local; | ||
152 | |||
153 | /* The debug bus is being set to the passthru disable state. | ||
154 | * However, the FW still expects atleast one legal signal routing | ||
155 | * entry or it will return an error on the arguments. If we don't | ||
156 | * supply a valid entry, we must ignore all return values. Ignoring | ||
157 | * all return values means we might miss an error we should be | ||
158 | * concerned about. | ||
159 | */ | ||
160 | |||
161 | /* fw expects physical cpu #. */ | ||
162 | pm_signal_local.cpu = node; | ||
163 | pm_signal_local.signal_group = 21; | ||
164 | pm_signal_local.bus_word = 1; | ||
165 | pm_signal_local.sub_unit = 0; | ||
166 | pm_signal_local.bit = 0; | ||
167 | |||
168 | ret = rtas_ibm_cbe_perftools(SUBFUNC_RESET, PASSTHRU_DISABLE, | ||
169 | &pm_signal_local, | ||
170 | sizeof(struct pm_signal)); | ||
171 | |||
172 | if (ret) | ||
173 | printk(KERN_WARNING "%s: rtas returned: %d\n", | ||
174 | __FUNCTION__, ret); | ||
175 | } | ||
176 | |||
177 | static void pm_rtas_activate_signals(u32 node, u32 count) | ||
178 | { | ||
179 | int ret; | ||
180 | int j; | ||
181 | struct pm_signal pm_signal_local[NR_PHYS_CTRS]; | ||
182 | |||
183 | for (j = 0; j < count; j++) { | ||
184 | /* fw expects physical cpu # */ | ||
185 | pm_signal_local[j].cpu = node; | ||
186 | pm_signal_local[j].signal_group = pm_signal[j].signal_group; | ||
187 | pm_signal_local[j].bus_word = pm_signal[j].bus_word; | ||
188 | pm_signal_local[j].sub_unit = pm_signal[j].sub_unit; | ||
189 | pm_signal_local[j].bit = pm_signal[j].bit; | ||
190 | } | ||
191 | |||
192 | ret = rtas_ibm_cbe_perftools(SUBFUNC_ACTIVATE, PASSTHRU_ENABLE, | ||
193 | pm_signal_local, | ||
194 | count * sizeof(struct pm_signal)); | ||
195 | |||
196 | if (ret) | ||
197 | printk(KERN_WARNING "%s: rtas returned: %d\n", | ||
198 | __FUNCTION__, ret); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * PM Signal functions | ||
203 | */ | ||
204 | static void set_pm_event(u32 ctr, int event, u32 unit_mask) | ||
205 | { | ||
206 | struct pm_signal *p; | ||
207 | u32 signal_bit; | ||
208 | u32 bus_word, bus_type, count_cycles, polarity, input_control; | ||
209 | int j, i; | ||
210 | |||
211 | if (event == PPU_CYCLES_EVENT_NUM) { | ||
212 | /* Special Event: Count all cpu cycles */ | ||
213 | pm_regs.pm07_cntrl[ctr] = CBE_COUNT_ALL_CYCLES; | ||
214 | p = &(pm_signal[ctr]); | ||
215 | p->signal_group = 21; | ||
216 | p->bus_word = 1; | ||
217 | p->sub_unit = 0; | ||
218 | p->bit = 0; | ||
219 | goto out; | ||
220 | } else { | ||
221 | pm_regs.pm07_cntrl[ctr] = 0; | ||
222 | } | ||
223 | |||
224 | bus_word = GET_BUS_WORD(unit_mask); | ||
225 | bus_type = GET_BUS_TYPE(unit_mask); | ||
226 | count_cycles = GET_COUNT_CYCLES(unit_mask); | ||
227 | polarity = GET_POLARITY(unit_mask); | ||
228 | input_control = GET_INPUT_CONTROL(unit_mask); | ||
229 | signal_bit = (event % 100); | ||
230 | |||
231 | p = &(pm_signal[ctr]); | ||
232 | |||
233 | p->signal_group = event / 100; | ||
234 | p->bus_word = bus_word; | ||
235 | p->sub_unit = unit_mask & 0x0000f000; | ||
236 | |||
237 | pm_regs.pm07_cntrl[ctr] = 0; | ||
238 | pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles); | ||
239 | pm_regs.pm07_cntrl[ctr] |= PM07_CTR_POLARITY(polarity); | ||
240 | pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_CONTROL(input_control); | ||
241 | |||
242 | if (input_control == 0) { | ||
243 | if (signal_bit > 31) { | ||
244 | signal_bit -= 32; | ||
245 | if (bus_word == 0x3) | ||
246 | bus_word = 0x2; | ||
247 | else if (bus_word == 0xc) | ||
248 | bus_word = 0x8; | ||
249 | } | ||
250 | |||
251 | if ((bus_type == 0) && p->signal_group >= 60) | ||
252 | bus_type = 2; | ||
253 | if ((bus_type == 1) && p->signal_group >= 50) | ||
254 | bus_type = 0; | ||
255 | |||
256 | pm_regs.pm07_cntrl[ctr] |= PM07_CTR_INPUT_MUX(signal_bit); | ||
257 | } else { | ||
258 | pm_regs.pm07_cntrl[ctr] = 0; | ||
259 | p->bit = signal_bit; | ||
260 | } | ||
261 | |||
262 | for (i = 0; i < 4; i++) { | ||
263 | if (bus_word & (1 << i)) { | ||
264 | pm_regs.debug_bus_control |= | ||
265 | (bus_type << (31 - (2 * i) + 1)); | ||
266 | |||
267 | for (j = 0; j < 2; j++) { | ||
268 | if (input_bus[j] == 0xff) { | ||
269 | input_bus[j] = i; | ||
270 | pm_regs.group_control |= | ||
271 | (i << (31 - i)); | ||
272 | break; | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | out: | ||
278 | ; | ||
279 | } | ||
280 | |||
281 | static void write_pm_cntrl(int cpu, struct pm_cntrl *pm_cntrl) | ||
282 | { | ||
283 | /* Oprofile will use 32 bit counters, set bits 7:10 to 0 */ | ||
284 | u32 val = 0; | ||
285 | if (pm_cntrl->enable == 1) | ||
286 | val |= CBE_PM_ENABLE_PERF_MON; | ||
287 | |||
288 | if (pm_cntrl->stop_at_max == 1) | ||
289 | val |= CBE_PM_STOP_AT_MAX; | ||
290 | |||
291 | if (pm_cntrl->trace_mode == 1) | ||
292 | val |= CBE_PM_TRACE_MODE_SET(pm_cntrl->trace_mode); | ||
293 | |||
294 | if (pm_cntrl->freeze == 1) | ||
295 | val |= CBE_PM_FREEZE_ALL_CTRS; | ||
296 | |||
297 | /* Routine set_count_mode must be called previously to set | ||
298 | * the count mode based on the user selection of user and kernel. | ||
299 | */ | ||
300 | val |= CBE_PM_COUNT_MODE_SET(pm_cntrl->count_mode); | ||
301 | cbe_write_pm(cpu, pm_control, val); | ||
302 | } | ||
303 | |||
304 | static inline void | ||
305 | set_count_mode(u32 kernel, u32 user, struct pm_cntrl *pm_cntrl) | ||
306 | { | ||
307 | /* The user must specify user and kernel if they want them. If | ||
308 | * neither is specified, OProfile will count in hypervisor mode | ||
309 | */ | ||
310 | if (kernel) { | ||
311 | if (user) | ||
312 | pm_cntrl->count_mode = CBE_COUNT_ALL_MODES; | ||
313 | else | ||
314 | pm_cntrl->count_mode = CBE_COUNT_SUPERVISOR_MODE; | ||
315 | } else { | ||
316 | if (user) | ||
317 | pm_cntrl->count_mode = CBE_COUNT_PROBLEM_MODE; | ||
318 | else | ||
319 | pm_cntrl->count_mode = CBE_COUNT_HYPERVISOR_MODE; | ||
320 | } | ||
321 | } | ||
322 | |||
323 | static inline void enable_ctr(u32 cpu, u32 ctr, u32 * pm07_cntrl) | ||
324 | { | ||
325 | |||
326 | pm07_cntrl[ctr] |= PM07_CTR_ENABLE(1); | ||
327 | cbe_write_pm07_control(cpu, ctr, pm07_cntrl[ctr]); | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Oprofile is expected to collect data on all CPUs simultaneously. | ||
332 | * However, there is one set of performance counters per node. There are | ||
333 | * two hardware threads or virtual CPUs on each node. Hence, OProfile must | ||
334 | * multiplex in time the performance counter collection on the two virtual | ||
335 | * CPUs. The multiplexing of the performance counters is done by this | ||
336 | * virtual counter routine. | ||
337 | * | ||
338 | * The pmc_values used below is defined as 'per-cpu' but its use is | ||
339 | * more akin to 'per-node'. We need to store two sets of counter | ||
340 | * values per node -- one for the previous run and one for the next. | ||
341 | * The per-cpu[NR_PHYS_CTRS] gives us the storage we need. Each odd/even | ||
342 | * pair of per-cpu arrays is used for storing the previous and next | ||
343 | * pmc values for a given node. | ||
344 | * NOTE: We use the per-cpu variable to improve cache performance. | ||
345 | */ | ||
346 | static void cell_virtual_cntr(unsigned long data) | ||
347 | { | ||
348 | /* This routine will alternate loading the virtual counters for | ||
349 | * virtual CPUs | ||
350 | */ | ||
351 | int i, prev_hdw_thread, next_hdw_thread; | ||
352 | u32 cpu; | ||
353 | unsigned long flags; | ||
354 | |||
355 | /* Make sure that the interrupt_hander and | ||
356 | * the virt counter are not both playing with | ||
357 | * the counters on the same node. | ||
358 | */ | ||
359 | |||
360 | spin_lock_irqsave(&virt_cntr_lock, flags); | ||
361 | |||
362 | prev_hdw_thread = hdw_thread; | ||
363 | |||
364 | /* switch the cpu handling the interrupts */ | ||
365 | hdw_thread = 1 ^ hdw_thread; | ||
366 | next_hdw_thread = hdw_thread; | ||
367 | |||
368 | /* The following is done only once per each node, but | ||
369 | * we need cpu #, not node #, to pass to the cbe_xxx functions. | ||
370 | */ | ||
371 | for_each_online_cpu(cpu) { | ||
372 | if (cbe_get_hw_thread_id(cpu)) | ||
373 | continue; | ||
374 | |||
375 | /* stop counters, save counter values, restore counts | ||
376 | * for previous thread | ||
377 | */ | ||
378 | cbe_disable_pm(cpu); | ||
379 | cbe_disable_pm_interrupts(cpu); | ||
380 | for (i = 0; i < num_counters; i++) { | ||
381 | per_cpu(pmc_values, cpu + prev_hdw_thread)[i] | ||
382 | = cbe_read_ctr(cpu, i); | ||
383 | |||
384 | if (per_cpu(pmc_values, cpu + next_hdw_thread)[i] | ||
385 | == 0xFFFFFFFF) | ||
386 | /* If the cntr value is 0xffffffff, we must | ||
387 | * reset that to 0xfffffff0 when the current | ||
388 | * thread is restarted. This will generate a new | ||
389 | * interrupt and make sure that we never restore | ||
390 | * the counters to the max value. If the counters | ||
391 | * were restored to the max value, they do not | ||
392 | * increment and no interrupts are generated. Hence | ||
393 | * no more samples will be collected on that cpu. | ||
394 | */ | ||
395 | cbe_write_ctr(cpu, i, 0xFFFFFFF0); | ||
396 | else | ||
397 | cbe_write_ctr(cpu, i, | ||
398 | per_cpu(pmc_values, | ||
399 | cpu + | ||
400 | next_hdw_thread)[i]); | ||
401 | } | ||
402 | |||
403 | /* Switch to the other thread. Change the interrupt | ||
404 | * and control regs to be scheduled on the CPU | ||
405 | * corresponding to the thread to execute. | ||
406 | */ | ||
407 | for (i = 0; i < num_counters; i++) { | ||
408 | if (pmc_cntrl[next_hdw_thread][i].enabled) { | ||
409 | /* There are some per thread events. | ||
410 | * Must do the set event, enable_cntr | ||
411 | * for each cpu. | ||
412 | */ | ||
413 | set_pm_event(i, | ||
414 | pmc_cntrl[next_hdw_thread][i].evnts, | ||
415 | pmc_cntrl[next_hdw_thread][i].masks); | ||
416 | enable_ctr(cpu, i, | ||
417 | pm_regs.pm07_cntrl); | ||
418 | } else { | ||
419 | cbe_write_pm07_control(cpu, i, 0); | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /* Enable interrupts on the CPU thread that is starting */ | ||
424 | cbe_enable_pm_interrupts(cpu, next_hdw_thread, | ||
425 | virt_cntr_inter_mask); | ||
426 | cbe_enable_pm(cpu); | ||
427 | } | ||
428 | |||
429 | spin_unlock_irqrestore(&virt_cntr_lock, flags); | ||
430 | |||
431 | mod_timer(&timer_virt_cntr, jiffies + HZ / 10); | ||
432 | } | ||
433 | |||
434 | static void start_virt_cntrs(void) | ||
435 | { | ||
436 | init_timer(&timer_virt_cntr); | ||
437 | timer_virt_cntr.function = cell_virtual_cntr; | ||
438 | timer_virt_cntr.data = 0UL; | ||
439 | timer_virt_cntr.expires = jiffies + HZ / 10; | ||
440 | add_timer(&timer_virt_cntr); | ||
441 | } | ||
442 | |||
443 | /* This function is called once for all cpus combined */ | ||
444 | static void | ||
445 | cell_reg_setup(struct op_counter_config *ctr, | ||
446 | struct op_system_config *sys, int num_ctrs) | ||
447 | { | ||
448 | int i, j, cpu; | ||
449 | |||
450 | pm_rtas_token = rtas_token("ibm,cbe-perftools"); | ||
451 | if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) { | ||
452 | printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n", | ||
453 | __FUNCTION__); | ||
454 | goto out; | ||
455 | } | ||
456 | |||
457 | num_counters = num_ctrs; | ||
458 | |||
459 | pm_regs.group_control = 0; | ||
460 | pm_regs.debug_bus_control = 0; | ||
461 | |||
462 | /* setup the pm_control register */ | ||
463 | memset(&pm_regs.pm_cntrl, 0, sizeof(struct pm_cntrl)); | ||
464 | pm_regs.pm_cntrl.stop_at_max = 1; | ||
465 | pm_regs.pm_cntrl.trace_mode = 0; | ||
466 | pm_regs.pm_cntrl.freeze = 1; | ||
467 | |||
468 | set_count_mode(sys->enable_kernel, sys->enable_user, | ||
469 | &pm_regs.pm_cntrl); | ||
470 | |||
471 | /* Setup the thread 0 events */ | ||
472 | for (i = 0; i < num_ctrs; ++i) { | ||
473 | |||
474 | pmc_cntrl[0][i].evnts = ctr[i].event; | ||
475 | pmc_cntrl[0][i].masks = ctr[i].unit_mask; | ||
476 | pmc_cntrl[0][i].enabled = ctr[i].enabled; | ||
477 | pmc_cntrl[0][i].vcntr = i; | ||
478 | |||
479 | for_each_possible_cpu(j) | ||
480 | per_cpu(pmc_values, j)[i] = 0; | ||
481 | } | ||
482 | |||
483 | /* Setup the thread 1 events, map the thread 0 event to the | ||
484 | * equivalent thread 1 event. | ||
485 | */ | ||
486 | for (i = 0; i < num_ctrs; ++i) { | ||
487 | if ((ctr[i].event >= 2100) && (ctr[i].event <= 2111)) | ||
488 | pmc_cntrl[1][i].evnts = ctr[i].event + 19; | ||
489 | else if (ctr[i].event == 2203) | ||
490 | pmc_cntrl[1][i].evnts = ctr[i].event; | ||
491 | else if ((ctr[i].event >= 2200) && (ctr[i].event <= 2215)) | ||
492 | pmc_cntrl[1][i].evnts = ctr[i].event + 16; | ||
493 | else | ||
494 | pmc_cntrl[1][i].evnts = ctr[i].event; | ||
495 | |||
496 | pmc_cntrl[1][i].masks = ctr[i].unit_mask; | ||
497 | pmc_cntrl[1][i].enabled = ctr[i].enabled; | ||
498 | pmc_cntrl[1][i].vcntr = i; | ||
499 | } | ||
500 | |||
501 | for (i = 0; i < 4; i++) | ||
502 | trace_bus[i] = 0xff; | ||
503 | |||
504 | for (i = 0; i < 2; i++) | ||
505 | input_bus[i] = 0xff; | ||
506 | |||
507 | /* Our counters count up, and "count" refers to | ||
508 | * how much before the next interrupt, and we interrupt | ||
509 | * on overflow. So we calculate the starting value | ||
510 | * which will give us "count" until overflow. | ||
511 | * Then we set the events on the enabled counters. | ||
512 | */ | ||
513 | for (i = 0; i < num_counters; ++i) { | ||
514 | /* start with virtual counter set 0 */ | ||
515 | if (pmc_cntrl[0][i].enabled) { | ||
516 | /* Using 32bit counters, reset max - count */ | ||
517 | reset_value[i] = 0xFFFFFFFF - ctr[i].count; | ||
518 | set_pm_event(i, | ||
519 | pmc_cntrl[0][i].evnts, | ||
520 | pmc_cntrl[0][i].masks); | ||
521 | |||
522 | /* global, used by cell_cpu_setup */ | ||
523 | ctr_enabled |= (1 << i); | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /* initialize the previous counts for the virtual cntrs */ | ||
528 | for_each_online_cpu(cpu) | ||
529 | for (i = 0; i < num_counters; ++i) { | ||
530 | per_cpu(pmc_values, cpu)[i] = reset_value[i]; | ||
531 | } | ||
532 | out: | ||
533 | ; | ||
534 | } | ||
535 | |||
536 | /* This function is called once for each cpu */ | ||
537 | static void cell_cpu_setup(struct op_counter_config *cntr) | ||
538 | { | ||
539 | u32 cpu = smp_processor_id(); | ||
540 | u32 num_enabled = 0; | ||
541 | int i; | ||
542 | |||
543 | /* There is one performance monitor per processor chip (i.e. node), | ||
544 | * so we only need to perform this function once per node. | ||
545 | */ | ||
546 | if (cbe_get_hw_thread_id(cpu)) | ||
547 | goto out; | ||
548 | |||
549 | if (pm_rtas_token == RTAS_UNKNOWN_SERVICE) { | ||
550 | printk(KERN_WARNING "%s: RTAS_UNKNOWN_SERVICE\n", | ||
551 | __FUNCTION__); | ||
552 | goto out; | ||
553 | } | ||
554 | |||
555 | /* Stop all counters */ | ||
556 | cbe_disable_pm(cpu); | ||
557 | cbe_disable_pm_interrupts(cpu); | ||
558 | |||
559 | cbe_write_pm(cpu, pm_interval, 0); | ||
560 | cbe_write_pm(cpu, pm_start_stop, 0); | ||
561 | cbe_write_pm(cpu, group_control, pm_regs.group_control); | ||
562 | cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control); | ||
563 | write_pm_cntrl(cpu, &pm_regs.pm_cntrl); | ||
564 | |||
565 | for (i = 0; i < num_counters; ++i) { | ||
566 | if (ctr_enabled & (1 << i)) { | ||
567 | pm_signal[num_enabled].cpu = cbe_cpu_to_node(cpu); | ||
568 | num_enabled++; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | pm_rtas_activate_signals(cbe_cpu_to_node(cpu), num_enabled); | ||
573 | out: | ||
574 | ; | ||
575 | } | ||
576 | |||
577 | static void cell_global_start(struct op_counter_config *ctr) | ||
578 | { | ||
579 | u32 cpu; | ||
580 | u32 interrupt_mask = 0; | ||
581 | u32 i; | ||
582 | |||
583 | /* This routine gets called once for the system. | ||
584 | * There is one performance monitor per node, so we | ||
585 | * only need to perform this function once per node. | ||
586 | */ | ||
587 | for_each_online_cpu(cpu) { | ||
588 | if (cbe_get_hw_thread_id(cpu)) | ||
589 | continue; | ||
590 | |||
591 | interrupt_mask = 0; | ||
592 | |||
593 | for (i = 0; i < num_counters; ++i) { | ||
594 | if (ctr_enabled & (1 << i)) { | ||
595 | cbe_write_ctr(cpu, i, reset_value[i]); | ||
596 | enable_ctr(cpu, i, pm_regs.pm07_cntrl); | ||
597 | interrupt_mask |= | ||
598 | CBE_PM_CTR_OVERFLOW_INTR(i); | ||
599 | } else { | ||
600 | /* Disable counter */ | ||
601 | cbe_write_pm07_control(cpu, i, 0); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | cbe_clear_pm_interrupts(cpu); | ||
606 | cbe_enable_pm_interrupts(cpu, hdw_thread, interrupt_mask); | ||
607 | cbe_enable_pm(cpu); | ||
608 | } | ||
609 | |||
610 | virt_cntr_inter_mask = interrupt_mask; | ||
611 | oprofile_running = 1; | ||
612 | smp_wmb(); | ||
613 | |||
614 | /* NOTE: start_virt_cntrs will result in cell_virtual_cntr() being | ||
615 | * executed which manipulates the PMU. We start the "virtual counter" | ||
616 | * here so that we do not need to synchronize access to the PMU in | ||
617 | * the above for-loop. | ||
618 | */ | ||
619 | start_virt_cntrs(); | ||
620 | } | ||
621 | |||
622 | static void cell_global_stop(void) | ||
623 | { | ||
624 | int cpu; | ||
625 | |||
626 | /* This routine will be called once for the system. | ||
627 | * There is one performance monitor per node, so we | ||
628 | * only need to perform this function once per node. | ||
629 | */ | ||
630 | del_timer_sync(&timer_virt_cntr); | ||
631 | oprofile_running = 0; | ||
632 | smp_wmb(); | ||
633 | |||
634 | for_each_online_cpu(cpu) { | ||
635 | if (cbe_get_hw_thread_id(cpu)) | ||
636 | continue; | ||
637 | |||
638 | cbe_sync_irq(cbe_cpu_to_node(cpu)); | ||
639 | /* Stop the counters */ | ||
640 | cbe_disable_pm(cpu); | ||
641 | |||
642 | /* Deactivate the signals */ | ||
643 | pm_rtas_reset_signals(cbe_cpu_to_node(cpu)); | ||
644 | |||
645 | /* Deactivate interrupts */ | ||
646 | cbe_disable_pm_interrupts(cpu); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | static void | ||
651 | cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr) | ||
652 | { | ||
653 | u32 cpu; | ||
654 | u64 pc; | ||
655 | int is_kernel; | ||
656 | unsigned long flags = 0; | ||
657 | u32 interrupt_mask; | ||
658 | int i; | ||
659 | |||
660 | cpu = smp_processor_id(); | ||
661 | |||
662 | /* Need to make sure the interrupt handler and the virt counter | ||
663 | * routine are not running at the same time. See the | ||
664 | * cell_virtual_cntr() routine for additional comments. | ||
665 | */ | ||
666 | spin_lock_irqsave(&virt_cntr_lock, flags); | ||
667 | |||
668 | /* Need to disable and reenable the performance counters | ||
669 | * to get the desired behavior from the hardware. This | ||
670 | * is hardware specific. | ||
671 | */ | ||
672 | |||
673 | cbe_disable_pm(cpu); | ||
674 | |||
675 | interrupt_mask = cbe_clear_pm_interrupts(cpu); | ||
676 | |||
677 | /* If the interrupt mask has been cleared, then the virt cntr | ||
678 | * has cleared the interrupt. When the thread that generated | ||
679 | * the interrupt is restored, the data count will be restored to | ||
680 | * 0xffffff0 to cause the interrupt to be regenerated. | ||
681 | */ | ||
682 | |||
683 | if ((oprofile_running == 1) && (interrupt_mask != 0)) { | ||
684 | pc = regs->nip; | ||
685 | is_kernel = is_kernel_addr(pc); | ||
686 | |||
687 | for (i = 0; i < num_counters; ++i) { | ||
688 | if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(i)) | ||
689 | && ctr[i].enabled) { | ||
690 | oprofile_add_pc(pc, is_kernel, i); | ||
691 | cbe_write_ctr(cpu, i, reset_value[i]); | ||
692 | } | ||
693 | } | ||
694 | |||
695 | /* The counters were frozen by the interrupt. | ||
696 | * Reenable the interrupt and restart the counters. | ||
697 | * If there was a race between the interrupt handler and | ||
698 | * the virtual counter routine. The virutal counter | ||
699 | * routine may have cleared the interrupts. Hence must | ||
700 | * use the virt_cntr_inter_mask to re-enable the interrupts. | ||
701 | */ | ||
702 | cbe_enable_pm_interrupts(cpu, hdw_thread, | ||
703 | virt_cntr_inter_mask); | ||
704 | |||
705 | /* The writes to the various performance counters only writes | ||
706 | * to a latch. The new values (interrupt setting bits, reset | ||
707 | * counter value etc.) are not copied to the actual registers | ||
708 | * until the performance monitor is enabled. In order to get | ||
709 | * this to work as desired, the permormance monitor needs to | ||
710 | * be disabled while writting to the latches. This is a | ||
711 | * HW design issue. | ||
712 | */ | ||
713 | cbe_enable_pm(cpu); | ||
714 | } | ||
715 | spin_unlock_irqrestore(&virt_cntr_lock, flags); | ||
716 | } | ||
717 | |||
718 | struct op_powerpc_model op_model_cell = { | ||
719 | .reg_setup = cell_reg_setup, | ||
720 | .cpu_setup = cell_cpu_setup, | ||
721 | .global_start = cell_global_start, | ||
722 | .global_stop = cell_global_stop, | ||
723 | .handle_interrupt = cell_handle_interrupt, | ||
724 | }; | ||
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile new file mode 100644 index 00000000000..a46184a0c75 --- /dev/null +++ b/arch/powerpc/platforms/52xx/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # | ||
2 | # Makefile for 52xx based boards | ||
3 | # | ||
4 | ifeq ($(CONFIG_PPC_MERGE),y) | ||
5 | obj-y += mpc52xx_pic.o mpc52xx_common.o | ||
6 | endif | ||
7 | |||
8 | obj-$(CONFIG_PPC_EFIKA) += efika-setup.o efika-pci.o | ||
9 | obj-$(CONFIG_PPC_LITE5200) += lite5200.o | ||
diff --git a/arch/powerpc/platforms/52xx/efika-pci.c b/arch/powerpc/platforms/52xx/efika-pci.c new file mode 100644 index 00000000000..62e05b2a922 --- /dev/null +++ b/arch/powerpc/platforms/52xx/efika-pci.c | |||
@@ -0,0 +1,119 @@ | |||
1 | |||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/pci.h> | ||
4 | #include <linux/string.h> | ||
5 | #include <linux/init.h> | ||
6 | |||
7 | #include <asm/io.h> | ||
8 | #include <asm/irq.h> | ||
9 | #include <asm/prom.h> | ||
10 | #include <asm/machdep.h> | ||
11 | #include <asm/sections.h> | ||
12 | #include <asm/pci-bridge.h> | ||
13 | #include <asm/rtas.h> | ||
14 | |||
15 | #include "efika.h" | ||
16 | |||
17 | #ifdef CONFIG_PCI | ||
18 | /* | ||
19 | * Access functions for PCI config space using RTAS calls. | ||
20 | */ | ||
21 | static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
22 | int len, u32 * val) | ||
23 | { | ||
24 | struct pci_controller *hose = bus->sysdata; | ||
25 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | ||
26 | | (((bus->number - hose->first_busno) & 0xff) << 16) | ||
27 | | (hose->index << 24); | ||
28 | int ret = -1; | ||
29 | int rval; | ||
30 | |||
31 | rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len); | ||
32 | *val = ret; | ||
33 | return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
34 | } | ||
35 | |||
36 | static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, | ||
37 | int offset, int len, u32 val) | ||
38 | { | ||
39 | struct pci_controller *hose = bus->sysdata; | ||
40 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | ||
41 | | (((bus->number - hose->first_busno) & 0xff) << 16) | ||
42 | | (hose->index << 24); | ||
43 | int rval; | ||
44 | |||
45 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, | ||
46 | addr, len, val); | ||
47 | return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
48 | } | ||
49 | |||
50 | static struct pci_ops rtas_pci_ops = { | ||
51 | rtas_read_config, | ||
52 | rtas_write_config | ||
53 | }; | ||
54 | |||
55 | void __init efika_pcisetup(void) | ||
56 | { | ||
57 | const int *bus_range; | ||
58 | int len; | ||
59 | struct pci_controller *hose; | ||
60 | struct device_node *root; | ||
61 | struct device_node *pcictrl; | ||
62 | |||
63 | root = of_find_node_by_path("/"); | ||
64 | if (root == NULL) { | ||
65 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | ||
66 | ": Unable to find the root node\n"); | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | for (pcictrl = NULL;;) { | ||
71 | pcictrl = of_get_next_child(root, pcictrl); | ||
72 | if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0)) | ||
73 | break; | ||
74 | } | ||
75 | |||
76 | of_node_put(root); | ||
77 | |||
78 | if (pcictrl == NULL) { | ||
79 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | ||
80 | ": Unable to find the PCI bridge node\n"); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | bus_range = get_property(pcictrl, "bus-range", &len); | ||
85 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
86 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | ||
87 | ": Can't get bus-range for %s\n", pcictrl->full_name); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | if (bus_range[1] == bus_range[0]) | ||
92 | printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d", | ||
93 | bus_range[0]); | ||
94 | else | ||
95 | printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d", | ||
96 | bus_range[0], bus_range[1]); | ||
97 | printk(" controlled by %s\n", pcictrl->full_name); | ||
98 | printk("\n"); | ||
99 | |||
100 | hose = pcibios_alloc_controller(); | ||
101 | if (!hose) { | ||
102 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | ||
103 | ": Can't allocate PCI controller structure for %s\n", | ||
104 | pcictrl->full_name); | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | hose->arch_data = of_node_get(pcictrl); | ||
109 | hose->first_busno = bus_range[0]; | ||
110 | hose->last_busno = bus_range[1]; | ||
111 | hose->ops = &rtas_pci_ops; | ||
112 | |||
113 | pci_process_bridge_OF_ranges(hose, pcictrl, 0); | ||
114 | } | ||
115 | |||
116 | #else | ||
117 | void __init efika_pcisetup(void) | ||
118 | {} | ||
119 | #endif | ||
diff --git a/arch/powerpc/platforms/52xx/efika-setup.c b/arch/powerpc/platforms/52xx/efika-setup.c new file mode 100644 index 00000000000..110c980ed1e --- /dev/null +++ b/arch/powerpc/platforms/52xx/efika-setup.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Efika 5K2 platform setup | ||
4 | * Some code really inspired from the lite5200b platform. | ||
5 | * | ||
6 | * Copyright (C) 2006 bplan GmbH | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/errno.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/reboot.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/utsrelease.h> | ||
20 | #include <linux/seq_file.h> | ||
21 | #include <linux/root_dev.h> | ||
22 | #include <linux/initrd.h> | ||
23 | #include <linux/timer.h> | ||
24 | #include <linux/pci.h> | ||
25 | |||
26 | #include <asm/pgtable.h> | ||
27 | #include <asm/prom.h> | ||
28 | #include <asm/time.h> | ||
29 | #include <asm/machdep.h> | ||
30 | #include <asm/rtas.h> | ||
31 | #include <asm/of_device.h> | ||
32 | #include <asm/of_platform.h> | ||
33 | #include <asm/mpc52xx.h> | ||
34 | |||
35 | #include "efika.h" | ||
36 | |||
37 | static void efika_show_cpuinfo(struct seq_file *m) | ||
38 | { | ||
39 | struct device_node *root; | ||
40 | const char *revision = NULL; | ||
41 | const char *codegendescription = NULL; | ||
42 | const char *codegenvendor = NULL; | ||
43 | |||
44 | root = of_find_node_by_path("/"); | ||
45 | if (root) { | ||
46 | revision = get_property(root, "revision", NULL); | ||
47 | codegendescription = | ||
48 | get_property(root, "CODEGEN,description", NULL); | ||
49 | codegenvendor = get_property(root, "CODEGEN,vendor", NULL); | ||
50 | |||
51 | of_node_put(root); | ||
52 | } | ||
53 | |||
54 | if (codegendescription) | ||
55 | seq_printf(m, "machine\t\t: %s\n", codegendescription); | ||
56 | else | ||
57 | seq_printf(m, "machine\t\t: Efika\n"); | ||
58 | |||
59 | if (revision) | ||
60 | seq_printf(m, "revision\t: %s\n", revision); | ||
61 | |||
62 | if (codegenvendor) | ||
63 | seq_printf(m, "vendor\t\t: %s\n", codegenvendor); | ||
64 | |||
65 | of_node_put(root); | ||
66 | } | ||
67 | |||
68 | static void __init efika_setup_arch(void) | ||
69 | { | ||
70 | rtas_initialize(); | ||
71 | |||
72 | #ifdef CONFIG_BLK_DEV_INITRD | ||
73 | initrd_below_start_ok = 1; | ||
74 | |||
75 | if (initrd_start) | ||
76 | ROOT_DEV = Root_RAM0; | ||
77 | else | ||
78 | #endif | ||
79 | ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ | ||
80 | |||
81 | efika_pcisetup(); | ||
82 | |||
83 | if (ppc_md.progress) | ||
84 | ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0); | ||
85 | } | ||
86 | |||
87 | static void __init efika_init(void) | ||
88 | { | ||
89 | struct device_node *np; | ||
90 | struct device_node *cnp = NULL; | ||
91 | const u32 *base; | ||
92 | |||
93 | /* Find every child of the SOC node and add it to of_platform */ | ||
94 | np = of_find_node_by_name(NULL, "builtin"); | ||
95 | if (np) { | ||
96 | char name[BUS_ID_SIZE]; | ||
97 | while ((cnp = of_get_next_child(np, cnp))) { | ||
98 | strcpy(name, cnp->name); | ||
99 | |||
100 | base = get_property(cnp, "reg", NULL); | ||
101 | if (base == NULL) | ||
102 | continue; | ||
103 | |||
104 | snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base); | ||
105 | of_platform_device_create(cnp, name, NULL); | ||
106 | |||
107 | printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (ppc_md.progress) | ||
112 | ppc_md.progress(" Have fun with your Efika! ", 0x7777); | ||
113 | } | ||
114 | |||
115 | static int __init efika_probe(void) | ||
116 | { | ||
117 | char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), | ||
118 | "model", NULL); | ||
119 | |||
120 | if (model == NULL) | ||
121 | return 0; | ||
122 | if (strcmp(model, "EFIKA5K2")) | ||
123 | return 0; | ||
124 | |||
125 | ISA_DMA_THRESHOLD = ~0L; | ||
126 | DMA_MODE_READ = 0x44; | ||
127 | DMA_MODE_WRITE = 0x48; | ||
128 | |||
129 | return 1; | ||
130 | } | ||
131 | |||
132 | define_machine(efika) | ||
133 | { | ||
134 | .name = EFIKA_PLATFORM_NAME, | ||
135 | .probe = efika_probe, | ||
136 | .setup_arch = efika_setup_arch, | ||
137 | .init = efika_init, | ||
138 | .show_cpuinfo = efika_show_cpuinfo, | ||
139 | .init_IRQ = mpc52xx_init_irq, | ||
140 | .get_irq = mpc52xx_get_irq, | ||
141 | .restart = rtas_restart, | ||
142 | .power_off = rtas_power_off, | ||
143 | .halt = rtas_halt, | ||
144 | .set_rtc_time = rtas_set_rtc_time, | ||
145 | .get_rtc_time = rtas_get_rtc_time, | ||
146 | .progress = rtas_progress, | ||
147 | .get_boot_time = rtas_get_boot_time, | ||
148 | .calibrate_decr = generic_calibrate_decr, | ||
149 | .phys_mem_access_prot = pci_phys_mem_access_prot, | ||
150 | }; | ||
diff --git a/arch/powerpc/platforms/52xx/efika.h b/arch/powerpc/platforms/52xx/efika.h new file mode 100644 index 00000000000..2f060fd097d --- /dev/null +++ b/arch/powerpc/platforms/52xx/efika.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * Efika 5K2 platform setup - Header file | ||
3 | * | ||
4 | * Copyright (C) 2006 bplan GmbH | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef __ARCH_POWERPC_EFIKA__ | ||
13 | #define __ARCH_POWERPC_EFIKA__ | ||
14 | |||
15 | #define EFIKA_PLATFORM_NAME "Efika" | ||
16 | |||
17 | extern void __init efika_pcisetup(void); | ||
18 | |||
19 | #endif | ||
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c new file mode 100644 index 00000000000..a375c15b431 --- /dev/null +++ b/arch/powerpc/platforms/52xx/lite5200.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * Freescale Lite5200 board support | ||
3 | * | ||
4 | * Written by: Grant Likely <grant.likely@secretlab.ca> | ||
5 | * | ||
6 | * Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved. | ||
7 | * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. | ||
8 | * | ||
9 | * Description: | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #undef DEBUG | ||
17 | |||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/reboot.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/kdev_t.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/console.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/root_dev.h> | ||
30 | #include <linux/initrd.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | #include <asm/atomic.h> | ||
34 | #include <asm/time.h> | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/machdep.h> | ||
37 | #include <asm/ipic.h> | ||
38 | #include <asm/bootinfo.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/prom.h> | ||
41 | #include <asm/udbg.h> | ||
42 | #include <sysdev/fsl_soc.h> | ||
43 | #include <asm/qe.h> | ||
44 | #include <asm/qe_ic.h> | ||
45 | #include <asm/of_platform.h> | ||
46 | |||
47 | #include <asm/mpc52xx.h> | ||
48 | |||
49 | /* ************************************************************************ | ||
50 | * | ||
51 | * Setup the architecture | ||
52 | * | ||
53 | */ | ||
54 | |||
55 | static void __init | ||
56 | lite52xx_setup_cpu(void) | ||
57 | { | ||
58 | struct mpc52xx_gpio __iomem *gpio; | ||
59 | u32 port_config; | ||
60 | |||
61 | /* Map zones */ | ||
62 | gpio = mpc52xx_find_and_map("mpc52xx-gpio"); | ||
63 | if (!gpio) { | ||
64 | printk(KERN_ERR __FILE__ ": " | ||
65 | "Error while mapping GPIO register for port config. " | ||
66 | "Expect some abnormal behavior\n"); | ||
67 | goto error; | ||
68 | } | ||
69 | |||
70 | /* Set port config */ | ||
71 | port_config = in_be32(&gpio->port_config); | ||
72 | |||
73 | port_config &= ~0x00800000; /* 48Mhz internal, pin is GPIO */ | ||
74 | |||
75 | port_config &= ~0x00007000; /* USB port : Differential mode */ | ||
76 | port_config |= 0x00001000; /* USB 1 only */ | ||
77 | |||
78 | port_config &= ~0x03000000; /* ATA CS is on csb_4/5 */ | ||
79 | port_config |= 0x01000000; | ||
80 | |||
81 | pr_debug("port_config: old:%x new:%x\n", | ||
82 | in_be32(&gpio->port_config), port_config); | ||
83 | out_be32(&gpio->port_config, port_config); | ||
84 | |||
85 | /* Unmap zone */ | ||
86 | error: | ||
87 | iounmap(gpio); | ||
88 | } | ||
89 | |||
90 | static void __init lite52xx_setup_arch(void) | ||
91 | { | ||
92 | struct device_node *np; | ||
93 | |||
94 | if (ppc_md.progress) | ||
95 | ppc_md.progress("lite52xx_setup_arch()", 0); | ||
96 | |||
97 | np = of_find_node_by_type(NULL, "cpu"); | ||
98 | if (np) { | ||
99 | unsigned int *fp = | ||
100 | (int *)get_property(np, "clock-frequency", NULL); | ||
101 | if (fp != 0) | ||
102 | loops_per_jiffy = *fp / HZ; | ||
103 | else | ||
104 | loops_per_jiffy = 50000000 / HZ; | ||
105 | of_node_put(np); | ||
106 | } | ||
107 | |||
108 | /* CPU & Port mux setup */ | ||
109 | mpc52xx_setup_cpu(); /* Generic */ | ||
110 | lite52xx_setup_cpu(); /* Platorm specific */ | ||
111 | |||
112 | #ifdef CONFIG_BLK_DEV_INITRD | ||
113 | if (initrd_start) | ||
114 | ROOT_DEV = Root_RAM0; | ||
115 | else | ||
116 | #endif | ||
117 | #ifdef CONFIG_ROOT_NFS | ||
118 | ROOT_DEV = Root_NFS; | ||
119 | #else | ||
120 | ROOT_DEV = Root_HDA1; | ||
121 | #endif | ||
122 | |||
123 | } | ||
124 | |||
125 | void lite52xx_show_cpuinfo(struct seq_file *m) | ||
126 | { | ||
127 | struct device_node* np = of_find_all_nodes(NULL); | ||
128 | const char *model = NULL; | ||
129 | |||
130 | if (np) | ||
131 | model = get_property(np, "model", NULL); | ||
132 | |||
133 | seq_printf(m, "vendor\t\t: Freescale Semiconductor\n"); | ||
134 | seq_printf(m, "machine\t\t: %s\n", model ? model : "unknown"); | ||
135 | |||
136 | of_node_put(np); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Called very early, MMU is off, device-tree isn't unflattened | ||
141 | */ | ||
142 | static int __init lite52xx_probe(void) | ||
143 | { | ||
144 | unsigned long node = of_get_flat_dt_root(); | ||
145 | const char *model = of_get_flat_dt_prop(node, "model", NULL); | ||
146 | |||
147 | if (!of_flat_dt_is_compatible(node, "lite52xx")) | ||
148 | return 0; | ||
149 | pr_debug("%s board w/ mpc52xx found\n", model ? model : "unknown"); | ||
150 | |||
151 | return 1; | ||
152 | } | ||
153 | |||
154 | define_machine(lite52xx) { | ||
155 | .name = "lite52xx", | ||
156 | .probe = lite52xx_probe, | ||
157 | .setup_arch = lite52xx_setup_arch, | ||
158 | .init_IRQ = mpc52xx_init_irq, | ||
159 | .get_irq = mpc52xx_get_irq, | ||
160 | .show_cpuinfo = lite52xx_show_cpuinfo, | ||
161 | .calibrate_decr = generic_calibrate_decr, | ||
162 | }; | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c new file mode 100644 index 00000000000..8331ff45777 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Utility functions for the Freescale MPC52xx. | ||
4 | * | ||
5 | * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public License | ||
8 | * version 2. This program is licensed "as is" without any warranty of any | ||
9 | * kind, whether express or implied. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #undef DEBUG | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | |||
17 | #include <asm/io.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/of_platform.h> | ||
20 | #include <asm/mpc52xx.h> | ||
21 | |||
22 | |||
23 | void __iomem * | ||
24 | mpc52xx_find_and_map(const char *compatible) | ||
25 | { | ||
26 | struct device_node *ofn; | ||
27 | const u32 *regaddr_p; | ||
28 | u64 regaddr64, size64; | ||
29 | |||
30 | ofn = of_find_compatible_node(NULL, NULL, compatible); | ||
31 | if (!ofn) | ||
32 | return NULL; | ||
33 | |||
34 | regaddr_p = of_get_address(ofn, 0, &size64, NULL); | ||
35 | if (!regaddr_p) { | ||
36 | of_node_put(ofn); | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | regaddr64 = of_translate_address(ofn, regaddr_p); | ||
41 | |||
42 | of_node_put(ofn); | ||
43 | |||
44 | return ioremap((u32)regaddr64, (u32)size64); | ||
45 | } | ||
46 | EXPORT_SYMBOL(mpc52xx_find_and_map); | ||
47 | |||
48 | |||
49 | /** | ||
50 | * mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device | ||
51 | * @node: device node | ||
52 | * | ||
53 | * Returns IPB bus frequency, or 0 if the bus frequency cannot be found. | ||
54 | */ | ||
55 | unsigned int | ||
56 | mpc52xx_find_ipb_freq(struct device_node *node) | ||
57 | { | ||
58 | struct device_node *np; | ||
59 | const unsigned int *p_ipb_freq = NULL; | ||
60 | |||
61 | of_node_get(node); | ||
62 | while (node) { | ||
63 | p_ipb_freq = get_property(node, "bus-frequency", NULL); | ||
64 | if (p_ipb_freq) | ||
65 | break; | ||
66 | |||
67 | np = of_get_parent(node); | ||
68 | of_node_put(node); | ||
69 | node = np; | ||
70 | } | ||
71 | if (node) | ||
72 | of_node_put(node); | ||
73 | |||
74 | return p_ipb_freq ? *p_ipb_freq : 0; | ||
75 | } | ||
76 | EXPORT_SYMBOL(mpc52xx_find_ipb_freq); | ||
77 | |||
78 | |||
79 | void __init | ||
80 | mpc52xx_setup_cpu(void) | ||
81 | { | ||
82 | struct mpc52xx_cdm __iomem *cdm; | ||
83 | struct mpc52xx_xlb __iomem *xlb; | ||
84 | |||
85 | /* Map zones */ | ||
86 | cdm = mpc52xx_find_and_map("mpc52xx-cdm"); | ||
87 | xlb = mpc52xx_find_and_map("mpc52xx-xlb"); | ||
88 | |||
89 | if (!cdm || !xlb) { | ||
90 | printk(KERN_ERR __FILE__ ": " | ||
91 | "Error while mapping CDM/XLB during mpc52xx_setup_cpu. " | ||
92 | "Expect some abnormal behavior\n"); | ||
93 | goto unmap_regs; | ||
94 | } | ||
95 | |||
96 | /* Use internal 48 Mhz */ | ||
97 | out_8(&cdm->ext_48mhz_en, 0x00); | ||
98 | out_8(&cdm->fd_enable, 0x01); | ||
99 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | ||
100 | out_be16(&cdm->fd_counters, 0x0001); | ||
101 | else | ||
102 | out_be16(&cdm->fd_counters, 0x5555); | ||
103 | |||
104 | /* Configure the XLB Arbiter priorities */ | ||
105 | out_be32(&xlb->master_pri_enable, 0xff); | ||
106 | out_be32(&xlb->master_priority, 0x11111111); | ||
107 | |||
108 | /* Disable XLB pipelining */ | ||
109 | /* (cfr errate 292. We could do this only just before ATA PIO | ||
110 | transaction and re-enable it afterwards ...) */ | ||
111 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); | ||
112 | |||
113 | /* Unmap zones */ | ||
114 | unmap_regs: | ||
115 | if (cdm) iounmap(cdm); | ||
116 | if (xlb) iounmap(xlb); | ||
117 | } | ||
118 | |||
119 | static int __init | ||
120 | mpc52xx_declare_of_platform_devices(void) | ||
121 | { | ||
122 | /* Find every child of the SOC node and add it to of_platform */ | ||
123 | return of_platform_bus_probe(NULL, NULL, NULL); | ||
124 | } | ||
125 | |||
126 | device_initcall(mpc52xx_declare_of_platform_devices); | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c new file mode 100644 index 00000000000..cd91a6c3aaf --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c | |||
@@ -0,0 +1,473 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Programmable Interrupt Controller functions for the Freescale MPC52xx. | ||
4 | * | ||
5 | * Copyright (C) 2006 bplan GmbH | ||
6 | * | ||
7 | * Based on the code from the 2.4 kernel by | ||
8 | * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg. | ||
9 | * | ||
10 | * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com> | ||
11 | * Copyright (C) 2003 Montavista Software, Inc | ||
12 | * | ||
13 | * This file is licensed under the terms of the GNU General Public License | ||
14 | * version 2. This program is licensed "as is" without any warranty of any | ||
15 | * kind, whether express or implied. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #undef DEBUG | ||
20 | |||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/signal.h> | ||
25 | #include <linux/stddef.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/hardirq.h> | ||
29 | |||
30 | #include <asm/io.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/irq.h> | ||
34 | #include <asm/prom.h> | ||
35 | #include <asm/mpc52xx.h> | ||
36 | #include "mpc52xx_pic.h" | ||
37 | |||
38 | /* | ||
39 | * | ||
40 | */ | ||
41 | |||
42 | static struct mpc52xx_intr __iomem *intr; | ||
43 | static struct mpc52xx_sdma __iomem *sdma; | ||
44 | static struct irq_host *mpc52xx_irqhost = NULL; | ||
45 | |||
46 | static unsigned char mpc52xx_map_senses[4] = { | ||
47 | IRQ_TYPE_LEVEL_HIGH, | ||
48 | IRQ_TYPE_EDGE_RISING, | ||
49 | IRQ_TYPE_EDGE_FALLING, | ||
50 | IRQ_TYPE_LEVEL_LOW, | ||
51 | }; | ||
52 | |||
53 | /* | ||
54 | * | ||
55 | */ | ||
56 | |||
57 | static inline void io_be_setbit(u32 __iomem *addr, int bitno) | ||
58 | { | ||
59 | out_be32(addr, in_be32(addr) | (1 << bitno)); | ||
60 | } | ||
61 | |||
62 | static inline void io_be_clrbit(u32 __iomem *addr, int bitno) | ||
63 | { | ||
64 | out_be32(addr, in_be32(addr) & ~(1 << bitno)); | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * IRQ[0-3] interrupt irq_chip | ||
69 | */ | ||
70 | |||
71 | static void mpc52xx_extirq_mask(unsigned int virq) | ||
72 | { | ||
73 | int irq; | ||
74 | int l2irq; | ||
75 | |||
76 | irq = irq_map[virq].hwirq; | ||
77 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
78 | |||
79 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
80 | |||
81 | io_be_clrbit(&intr->ctrl, 11 - l2irq); | ||
82 | } | ||
83 | |||
84 | static void mpc52xx_extirq_unmask(unsigned int virq) | ||
85 | { | ||
86 | int irq; | ||
87 | int l2irq; | ||
88 | |||
89 | irq = irq_map[virq].hwirq; | ||
90 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
91 | |||
92 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
93 | |||
94 | io_be_setbit(&intr->ctrl, 11 - l2irq); | ||
95 | } | ||
96 | |||
97 | static void mpc52xx_extirq_ack(unsigned int virq) | ||
98 | { | ||
99 | int irq; | ||
100 | int l2irq; | ||
101 | |||
102 | irq = irq_map[virq].hwirq; | ||
103 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
104 | |||
105 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
106 | |||
107 | io_be_setbit(&intr->ctrl, 27-l2irq); | ||
108 | } | ||
109 | |||
110 | static struct irq_chip mpc52xx_extirq_irqchip = { | ||
111 | .typename = " MPC52xx IRQ[0-3] ", | ||
112 | .mask = mpc52xx_extirq_mask, | ||
113 | .unmask = mpc52xx_extirq_unmask, | ||
114 | .ack = mpc52xx_extirq_ack, | ||
115 | }; | ||
116 | |||
117 | /* | ||
118 | * Main interrupt irq_chip | ||
119 | */ | ||
120 | |||
121 | static void mpc52xx_main_mask(unsigned int virq) | ||
122 | { | ||
123 | int irq; | ||
124 | int l2irq; | ||
125 | |||
126 | irq = irq_map[virq].hwirq; | ||
127 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
128 | |||
129 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
130 | |||
131 | io_be_setbit(&intr->main_mask, 15 - l2irq); | ||
132 | } | ||
133 | |||
134 | static void mpc52xx_main_unmask(unsigned int virq) | ||
135 | { | ||
136 | int irq; | ||
137 | int l2irq; | ||
138 | |||
139 | irq = irq_map[virq].hwirq; | ||
140 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
141 | |||
142 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
143 | |||
144 | io_be_clrbit(&intr->main_mask, 15 - l2irq); | ||
145 | } | ||
146 | |||
147 | static struct irq_chip mpc52xx_main_irqchip = { | ||
148 | .typename = "MPC52xx Main", | ||
149 | .mask = mpc52xx_main_mask, | ||
150 | .mask_ack = mpc52xx_main_mask, | ||
151 | .unmask = mpc52xx_main_unmask, | ||
152 | }; | ||
153 | |||
154 | /* | ||
155 | * Peripherals interrupt irq_chip | ||
156 | */ | ||
157 | |||
158 | static void mpc52xx_periph_mask(unsigned int virq) | ||
159 | { | ||
160 | int irq; | ||
161 | int l2irq; | ||
162 | |||
163 | irq = irq_map[virq].hwirq; | ||
164 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
165 | |||
166 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
167 | |||
168 | io_be_setbit(&intr->per_mask, 31 - l2irq); | ||
169 | } | ||
170 | |||
171 | static void mpc52xx_periph_unmask(unsigned int virq) | ||
172 | { | ||
173 | int irq; | ||
174 | int l2irq; | ||
175 | |||
176 | irq = irq_map[virq].hwirq; | ||
177 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
178 | |||
179 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
180 | |||
181 | io_be_clrbit(&intr->per_mask, 31 - l2irq); | ||
182 | } | ||
183 | |||
184 | static struct irq_chip mpc52xx_periph_irqchip = { | ||
185 | .typename = "MPC52xx Peripherals", | ||
186 | .mask = mpc52xx_periph_mask, | ||
187 | .mask_ack = mpc52xx_periph_mask, | ||
188 | .unmask = mpc52xx_periph_unmask, | ||
189 | }; | ||
190 | |||
191 | /* | ||
192 | * SDMA interrupt irq_chip | ||
193 | */ | ||
194 | |||
195 | static void mpc52xx_sdma_mask(unsigned int virq) | ||
196 | { | ||
197 | int irq; | ||
198 | int l2irq; | ||
199 | |||
200 | irq = irq_map[virq].hwirq; | ||
201 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
202 | |||
203 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
204 | |||
205 | io_be_setbit(&sdma->IntMask, l2irq); | ||
206 | } | ||
207 | |||
208 | static void mpc52xx_sdma_unmask(unsigned int virq) | ||
209 | { | ||
210 | int irq; | ||
211 | int l2irq; | ||
212 | |||
213 | irq = irq_map[virq].hwirq; | ||
214 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
215 | |||
216 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
217 | |||
218 | io_be_clrbit(&sdma->IntMask, l2irq); | ||
219 | } | ||
220 | |||
221 | static void mpc52xx_sdma_ack(unsigned int virq) | ||
222 | { | ||
223 | int irq; | ||
224 | int l2irq; | ||
225 | |||
226 | irq = irq_map[virq].hwirq; | ||
227 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
228 | |||
229 | pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq); | ||
230 | |||
231 | out_be32(&sdma->IntPend, 1 << l2irq); | ||
232 | } | ||
233 | |||
234 | static struct irq_chip mpc52xx_sdma_irqchip = { | ||
235 | .typename = "MPC52xx SDMA", | ||
236 | .mask = mpc52xx_sdma_mask, | ||
237 | .unmask = mpc52xx_sdma_unmask, | ||
238 | .ack = mpc52xx_sdma_ack, | ||
239 | }; | ||
240 | |||
241 | /* | ||
242 | * irq_host | ||
243 | */ | ||
244 | |||
245 | static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node) | ||
246 | { | ||
247 | pr_debug("%s: node=%p\n", __func__, node); | ||
248 | return mpc52xx_irqhost->host_data == node; | ||
249 | } | ||
250 | |||
251 | static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, | ||
252 | u32 * intspec, unsigned int intsize, | ||
253 | irq_hw_number_t * out_hwirq, | ||
254 | unsigned int *out_flags) | ||
255 | { | ||
256 | int intrvect_l1; | ||
257 | int intrvect_l2; | ||
258 | int intrvect_type; | ||
259 | int intrvect_linux; | ||
260 | |||
261 | if (intsize != 3) | ||
262 | return -1; | ||
263 | |||
264 | intrvect_l1 = (int)intspec[0]; | ||
265 | intrvect_l2 = (int)intspec[1]; | ||
266 | intrvect_type = (int)intspec[2]; | ||
267 | |||
268 | intrvect_linux = | ||
269 | (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK; | ||
270 | intrvect_linux |= | ||
271 | (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK; | ||
272 | |||
273 | pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1, | ||
274 | intrvect_l2); | ||
275 | |||
276 | *out_hwirq = intrvect_linux; | ||
277 | *out_flags = mpc52xx_map_senses[intrvect_type]; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * this function retrieves the correct IRQ type out | ||
284 | * of the MPC regs | ||
285 | * Only externals IRQs needs this | ||
286 | */ | ||
287 | static int mpc52xx_irqx_gettype(int irq) | ||
288 | { | ||
289 | int type; | ||
290 | u32 ctrl_reg; | ||
291 | |||
292 | ctrl_reg = in_be32(&intr->ctrl); | ||
293 | type = (ctrl_reg >> (22 - irq * 2)) & 0x3; | ||
294 | |||
295 | return mpc52xx_map_senses[type]; | ||
296 | } | ||
297 | |||
298 | static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, | ||
299 | irq_hw_number_t irq) | ||
300 | { | ||
301 | int l1irq; | ||
302 | int l2irq; | ||
303 | struct irq_chip *good_irqchip; | ||
304 | void *good_handle; | ||
305 | int type; | ||
306 | |||
307 | l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET; | ||
308 | l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET; | ||
309 | |||
310 | /* | ||
311 | * Most of ours IRQs will be level low | ||
312 | * Only external IRQs on some platform may be others | ||
313 | */ | ||
314 | type = IRQ_TYPE_LEVEL_LOW; | ||
315 | |||
316 | switch (l1irq) { | ||
317 | case MPC52xx_IRQ_L1_CRIT: | ||
318 | pr_debug("%s: Critical. l2=%x\n", __func__, l2irq); | ||
319 | |||
320 | BUG_ON(l2irq != 0); | ||
321 | |||
322 | type = mpc52xx_irqx_gettype(l2irq); | ||
323 | good_irqchip = &mpc52xx_extirq_irqchip; | ||
324 | break; | ||
325 | |||
326 | case MPC52xx_IRQ_L1_MAIN: | ||
327 | pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq); | ||
328 | |||
329 | if ((l2irq >= 1) && (l2irq <= 3)) { | ||
330 | type = mpc52xx_irqx_gettype(l2irq); | ||
331 | good_irqchip = &mpc52xx_extirq_irqchip; | ||
332 | } else { | ||
333 | good_irqchip = &mpc52xx_main_irqchip; | ||
334 | } | ||
335 | break; | ||
336 | |||
337 | case MPC52xx_IRQ_L1_PERP: | ||
338 | pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq); | ||
339 | good_irqchip = &mpc52xx_periph_irqchip; | ||
340 | break; | ||
341 | |||
342 | case MPC52xx_IRQ_L1_SDMA: | ||
343 | pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq); | ||
344 | good_irqchip = &mpc52xx_sdma_irqchip; | ||
345 | break; | ||
346 | |||
347 | default: | ||
348 | pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq); | ||
349 | printk(KERN_ERR "Unknow IRQ!\n"); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | |||
353 | switch (type) { | ||
354 | case IRQ_TYPE_EDGE_FALLING: | ||
355 | case IRQ_TYPE_EDGE_RISING: | ||
356 | good_handle = handle_edge_irq; | ||
357 | break; | ||
358 | default: | ||
359 | good_handle = handle_level_irq; | ||
360 | } | ||
361 | |||
362 | set_irq_chip_and_handler(virq, good_irqchip, good_handle); | ||
363 | |||
364 | pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq, | ||
365 | (int)irq, type); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static struct irq_host_ops mpc52xx_irqhost_ops = { | ||
371 | .match = mpc52xx_irqhost_match, | ||
372 | .xlate = mpc52xx_irqhost_xlate, | ||
373 | .map = mpc52xx_irqhost_map, | ||
374 | }; | ||
375 | |||
376 | /* | ||
377 | * init (public) | ||
378 | */ | ||
379 | |||
380 | void __init mpc52xx_init_irq(void) | ||
381 | { | ||
382 | u32 intr_ctrl; | ||
383 | struct device_node *picnode; | ||
384 | |||
385 | /* Remap the necessary zones */ | ||
386 | picnode = of_find_compatible_node(NULL, NULL, "mpc52xx-pic"); | ||
387 | |||
388 | intr = mpc52xx_find_and_map("mpc52xx-pic"); | ||
389 | if (!intr) | ||
390 | panic(__FILE__ ": find_and_map failed on 'mpc52xx-pic'. " | ||
391 | "Check node !"); | ||
392 | |||
393 | sdma = mpc52xx_find_and_map("mpc52xx-bestcomm"); | ||
394 | if (!sdma) | ||
395 | panic(__FILE__ ": find_and_map failed on 'mpc52xx-bestcomm'. " | ||
396 | "Check node !"); | ||
397 | |||
398 | /* Disable all interrupt sources. */ | ||
399 | out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ | ||
400 | out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ | ||
401 | out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */ | ||
402 | out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */ | ||
403 | intr_ctrl = in_be32(&intr->ctrl); | ||
404 | intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */ | ||
405 | intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */ | ||
406 | 0x00001000 | /* MEE master external enable */ | ||
407 | 0x00000000 | /* 0 means disable IRQ 0-3 */ | ||
408 | 0x00000001; /* CEb route critical normally */ | ||
409 | out_be32(&intr->ctrl, intr_ctrl); | ||
410 | |||
411 | /* Zero a bunch of the priority settings. */ | ||
412 | out_be32(&intr->per_pri1, 0); | ||
413 | out_be32(&intr->per_pri2, 0); | ||
414 | out_be32(&intr->per_pri3, 0); | ||
415 | out_be32(&intr->main_pri1, 0); | ||
416 | out_be32(&intr->main_pri2, 0); | ||
417 | |||
418 | /* | ||
419 | * As last step, add an irq host to translate the real | ||
420 | * hw irq information provided by the ofw to linux virq | ||
421 | */ | ||
422 | |||
423 | mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, | ||
424 | MPC52xx_IRQ_HIGHTESTHWIRQ, | ||
425 | &mpc52xx_irqhost_ops, -1); | ||
426 | |||
427 | if (!mpc52xx_irqhost) | ||
428 | panic(__FILE__ ": Cannot allocate the IRQ host\n"); | ||
429 | |||
430 | mpc52xx_irqhost->host_data = picnode; | ||
431 | printk(KERN_INFO "MPC52xx PIC is up and running!\n"); | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * get_irq (public) | ||
436 | */ | ||
437 | unsigned int mpc52xx_get_irq(void) | ||
438 | { | ||
439 | u32 status; | ||
440 | int irq = NO_IRQ_IGNORE; | ||
441 | |||
442 | status = in_be32(&intr->enc_status); | ||
443 | if (status & 0x00000400) { /* critical */ | ||
444 | irq = (status >> 8) & 0x3; | ||
445 | if (irq == 2) /* high priority peripheral */ | ||
446 | goto peripheral; | ||
447 | irq |= (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) & | ||
448 | MPC52xx_IRQ_L1_MASK; | ||
449 | } else if (status & 0x00200000) { /* main */ | ||
450 | irq = (status >> 16) & 0x1f; | ||
451 | if (irq == 4) /* low priority peripheral */ | ||
452 | goto peripheral; | ||
453 | irq |= (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) & | ||
454 | MPC52xx_IRQ_L1_MASK; | ||
455 | } else if (status & 0x20000000) { /* peripheral */ | ||
456 | peripheral: | ||
457 | irq = (status >> 24) & 0x1f; | ||
458 | if (irq == 0) { /* bestcomm */ | ||
459 | status = in_be32(&sdma->IntPend); | ||
460 | irq = ffs(status) - 1; | ||
461 | irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) & | ||
462 | MPC52xx_IRQ_L1_MASK; | ||
463 | } else { | ||
464 | irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) & | ||
465 | MPC52xx_IRQ_L1_MASK; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | pr_debug("%s: irq=%x. virq=%d\n", __func__, irq, | ||
470 | irq_linear_revmap(mpc52xx_irqhost, irq)); | ||
471 | |||
472 | return irq_linear_revmap(mpc52xx_irqhost, irq); | ||
473 | } | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.h b/arch/powerpc/platforms/52xx/mpc52xx_pic.h new file mode 100644 index 00000000000..1a26bcdb304 --- /dev/null +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Header file for Freescale MPC52xx Interrupt controller | ||
3 | * | ||
4 | * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com> | ||
5 | * Copyright (C) 2003 MontaVista, Software, Inc. | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public License | ||
8 | * version 2. This program is licensed "as is" without any warranty of any | ||
9 | * kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #ifndef __POWERPC_SYSDEV_MPC52xx_PIC_H__ | ||
13 | #define __POWERPC_SYSDEV_MPC52xx_PIC_H__ | ||
14 | |||
15 | #include <asm/types.h> | ||
16 | |||
17 | |||
18 | /* HW IRQ mapping */ | ||
19 | #define MPC52xx_IRQ_L1_CRIT (0) | ||
20 | #define MPC52xx_IRQ_L1_MAIN (1) | ||
21 | #define MPC52xx_IRQ_L1_PERP (2) | ||
22 | #define MPC52xx_IRQ_L1_SDMA (3) | ||
23 | |||
24 | #define MPC52xx_IRQ_L1_OFFSET (6) | ||
25 | #define MPC52xx_IRQ_L1_MASK (0x00c0) | ||
26 | |||
27 | #define MPC52xx_IRQ_L2_OFFSET (0) | ||
28 | #define MPC52xx_IRQ_L2_MASK (0x003f) | ||
29 | |||
30 | #define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0) | ||
31 | |||
32 | |||
33 | /* Interrupt controller Register set */ | ||
34 | struct mpc52xx_intr { | ||
35 | u32 per_mask; /* INTR + 0x00 */ | ||
36 | u32 per_pri1; /* INTR + 0x04 */ | ||
37 | u32 per_pri2; /* INTR + 0x08 */ | ||
38 | u32 per_pri3; /* INTR + 0x0c */ | ||
39 | u32 ctrl; /* INTR + 0x10 */ | ||
40 | u32 main_mask; /* INTR + 0x14 */ | ||
41 | u32 main_pri1; /* INTR + 0x18 */ | ||
42 | u32 main_pri2; /* INTR + 0x1c */ | ||
43 | u32 reserved1; /* INTR + 0x20 */ | ||
44 | u32 enc_status; /* INTR + 0x24 */ | ||
45 | u32 crit_status; /* INTR + 0x28 */ | ||
46 | u32 main_status; /* INTR + 0x2c */ | ||
47 | u32 per_status; /* INTR + 0x30 */ | ||
48 | u32 reserved2; /* INTR + 0x34 */ | ||
49 | u32 per_error; /* INTR + 0x38 */ | ||
50 | }; | ||
51 | |||
52 | #endif /* __POWERPC_SYSDEV_MPC52xx_PIC_H__ */ | ||
53 | |||
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c index bb9acbb9817..ea880f1f0dc 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c | |||
@@ -515,16 +515,6 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn) | |||
515 | return PCIBIOS_SUCCESSFUL; | 515 | return PCIBIOS_SUCCESSFUL; |
516 | } | 516 | } |
517 | 517 | ||
518 | static void | ||
519 | __init mpc82xx_pcibios_fixup(void) | ||
520 | { | ||
521 | struct pci_dev *dev = NULL; | ||
522 | |||
523 | for_each_pci_dev(dev) { | ||
524 | pci_read_irq_line(dev); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | void __init add_bridge(struct device_node *np) | 518 | void __init add_bridge(struct device_node *np) |
529 | { | 519 | { |
530 | int len; | 520 | int len; |
@@ -597,9 +587,6 @@ static void __init mpc82xx_ads_setup_arch(void) | |||
597 | add_bridge(np); | 587 | add_bridge(np); |
598 | 588 | ||
599 | of_node_put(np); | 589 | of_node_put(np); |
600 | ppc_md.pci_map_irq = NULL; | ||
601 | ppc_md.pcibios_fixup = mpc82xx_pcibios_fixup; | ||
602 | ppc_md.pcibios_fixup_bus = NULL; | ||
603 | #endif | 590 | #endif |
604 | 591 | ||
605 | #ifdef CONFIG_ROOT_NFS | 592 | #ifdef CONFIG_ROOT_NFS |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index a43ac71ab74..f58c9780b66 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c | |||
@@ -97,8 +97,6 @@ static void __init mpc832x_sys_setup_arch(void) | |||
97 | #ifdef CONFIG_PCI | 97 | #ifdef CONFIG_PCI |
98 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 98 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
99 | add_bridge(np); | 99 | add_bridge(np); |
100 | |||
101 | ppc_md.pci_swizzle = common_swizzle; | ||
102 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 100 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
103 | #endif | 101 | #endif |
104 | 102 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index e2bcaaf6b32..314c42ac604 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c | |||
@@ -118,7 +118,4 @@ define_machine(mpc834x_itx) { | |||
118 | .time_init = mpc83xx_time_init, | 118 | .time_init = mpc83xx_time_init, |
119 | .calibrate_decr = generic_calibrate_decr, | 119 | .calibrate_decr = generic_calibrate_decr, |
120 | .progress = udbg_progress, | 120 | .progress = udbg_progress, |
121 | #ifdef CONFIG_PCI | ||
122 | .pcibios_fixup = mpc83xx_pcibios_fixup, | ||
123 | #endif | ||
124 | }; | 121 | }; |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c index 677196187a4..80b735a414d 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_sys.c +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c | |||
@@ -137,7 +137,4 @@ define_machine(mpc834x_sys) { | |||
137 | .time_init = mpc83xx_time_init, | 137 | .time_init = mpc83xx_time_init, |
138 | .calibrate_decr = generic_calibrate_decr, | 138 | .calibrate_decr = generic_calibrate_decr, |
139 | .progress = udbg_progress, | 139 | .progress = udbg_progress, |
140 | #ifdef CONFIG_PCI | ||
141 | .pcibios_fixup = mpc83xx_pcibios_fixup, | ||
142 | #endif | ||
143 | }; | 140 | }; |
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c index 1a523c81c06..7bfd47ad723 100644 --- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c +++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c | |||
@@ -102,8 +102,6 @@ static void __init mpc8360_sys_setup_arch(void) | |||
102 | #ifdef CONFIG_PCI | 102 | #ifdef CONFIG_PCI |
103 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 103 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
104 | add_bridge(np); | 104 | add_bridge(np); |
105 | |||
106 | ppc_md.pci_swizzle = common_swizzle; | ||
107 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 105 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
108 | #endif | 106 | #endif |
109 | 107 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 2c82bca9bfb..01cae106912 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | extern int add_bridge(struct device_node *dev); | 12 | extern int add_bridge(struct device_node *dev); |
13 | extern int mpc83xx_exclude_device(u_char bus, u_char devfn); | 13 | extern int mpc83xx_exclude_device(u_char bus, u_char devfn); |
14 | extern void mpc83xx_pcibios_fixup(void); | ||
15 | extern void mpc83xx_restart(char *cmd); | 14 | extern void mpc83xx_restart(char *cmd); |
16 | extern long mpc83xx_time_init(void); | 15 | extern long mpc83xx_time_init(void); |
17 | 16 | ||
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 4557ac5255c..9c365055514 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c | |||
@@ -45,15 +45,6 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn) | |||
45 | return PCIBIOS_SUCCESSFUL; | 45 | return PCIBIOS_SUCCESSFUL; |
46 | } | 46 | } |
47 | 47 | ||
48 | void __init mpc83xx_pcibios_fixup(void) | ||
49 | { | ||
50 | struct pci_dev *dev = NULL; | ||
51 | |||
52 | /* map all the PCI irqs */ | ||
53 | for_each_pci_dev(dev) | ||
54 | pci_read_irq_line(dev); | ||
55 | } | ||
56 | |||
57 | int __init add_bridge(struct device_node *dev) | 48 | int __init add_bridge(struct device_node *dev) |
58 | { | 49 | { |
59 | int len; | 50 | int len; |
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c index 26c5e822c7c..3e62fcb04c1 100644 --- a/arch/powerpc/platforms/85xx/misc.c +++ b/arch/powerpc/platforms/85xx/misc.c | |||
@@ -21,11 +21,3 @@ void mpc85xx_restart(char *cmd) | |||
21 | local_irq_disable(); | 21 | local_irq_disable(); |
22 | abort(); | 22 | abort(); |
23 | } | 23 | } |
24 | |||
25 | /* For now this is a pass through */ | ||
26 | phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) | ||
27 | { | ||
28 | return addr; | ||
29 | }; | ||
30 | |||
31 | EXPORT_SYMBOL(fixup_bigphys_addr); | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index d3e669d69c7..bda2e55e6c4 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
@@ -53,15 +53,6 @@ mpc85xx_exclude_device(u_char bus, u_char devfn) | |||
53 | else | 53 | else |
54 | return PCIBIOS_SUCCESSFUL; | 54 | return PCIBIOS_SUCCESSFUL; |
55 | } | 55 | } |
56 | |||
57 | void __init | ||
58 | mpc85xx_pcibios_fixup(void) | ||
59 | { | ||
60 | struct pci_dev *dev = NULL; | ||
61 | |||
62 | for_each_pci_dev(dev) | ||
63 | pci_read_irq_line(dev); | ||
64 | } | ||
65 | #endif /* CONFIG_PCI */ | 56 | #endif /* CONFIG_PCI */ |
66 | 57 | ||
67 | #ifdef CONFIG_CPM2 | 58 | #ifdef CONFIG_CPM2 |
@@ -253,8 +244,6 @@ static void __init mpc85xx_ads_setup_arch(void) | |||
253 | #ifdef CONFIG_PCI | 244 | #ifdef CONFIG_PCI |
254 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 245 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
255 | add_bridge(np); | 246 | add_bridge(np); |
256 | |||
257 | ppc_md.pcibios_fixup = mpc85xx_pcibios_fixup; | ||
258 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 247 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
259 | #endif | 248 | #endif |
260 | 249 | ||
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 1a1c226ad4d..f4dd5f2f8a2 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | |||
@@ -398,15 +398,6 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) | |||
398 | } | 398 | } |
399 | 399 | ||
400 | 400 | ||
401 | void __init mpc86xx_hpcn_pcibios_fixup(void) | ||
402 | { | ||
403 | struct pci_dev *dev = NULL; | ||
404 | |||
405 | for_each_pci_dev(dev) | ||
406 | pci_read_irq_line(dev); | ||
407 | } | ||
408 | |||
409 | |||
410 | /* | 401 | /* |
411 | * Called very early, device-tree isn't unflattened | 402 | * Called very early, device-tree isn't unflattened |
412 | */ | 403 | */ |
@@ -461,7 +452,6 @@ define_machine(mpc86xx_hpcn) { | |||
461 | .setup_arch = mpc86xx_hpcn_setup_arch, | 452 | .setup_arch = mpc86xx_hpcn_setup_arch, |
462 | .init_IRQ = mpc86xx_hpcn_init_irq, | 453 | .init_IRQ = mpc86xx_hpcn_init_irq, |
463 | .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, | 454 | .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, |
464 | .pcibios_fixup = mpc86xx_hpcn_pcibios_fixup, | ||
465 | .get_irq = mpic_get_irq, | 455 | .get_irq = mpic_get_irq, |
466 | .restart = mpc86xx_restart, | 456 | .restart = mpc86xx_restart, |
467 | .time_init = mpc86xx_time_init, | 457 | .time_init = mpc86xx_time_init, |
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index e58fa953a50..44d95eaf22e 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
@@ -7,12 +7,14 @@ endif | |||
7 | endif | 7 | endif |
8 | obj-$(CONFIG_PPC_CHRP) += chrp/ | 8 | obj-$(CONFIG_PPC_CHRP) += chrp/ |
9 | obj-$(CONFIG_4xx) += 4xx/ | 9 | obj-$(CONFIG_4xx) += 4xx/ |
10 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ | ||
10 | obj-$(CONFIG_PPC_83xx) += 83xx/ | 11 | obj-$(CONFIG_PPC_83xx) += 83xx/ |
11 | obj-$(CONFIG_PPC_85xx) += 85xx/ | 12 | obj-$(CONFIG_PPC_85xx) += 85xx/ |
12 | obj-$(CONFIG_PPC_86xx) += 86xx/ | 13 | obj-$(CONFIG_PPC_86xx) += 86xx/ |
13 | obj-$(CONFIG_PPC_PSERIES) += pseries/ | 14 | obj-$(CONFIG_PPC_PSERIES) += pseries/ |
14 | obj-$(CONFIG_PPC_ISERIES) += iseries/ | 15 | obj-$(CONFIG_PPC_ISERIES) += iseries/ |
15 | obj-$(CONFIG_PPC_MAPLE) += maple/ | 16 | obj-$(CONFIG_PPC_MAPLE) += maple/ |
16 | obj-$(CONFIG_PPC_PASEMI) += pasemi/ | 17 | obj-$(CONFIG_PPC_PASEMI) += pasemi/ |
17 | obj-$(CONFIG_PPC_CELL) += cell/ | 18 | obj-$(CONFIG_PPC_CELL) += cell/ |
19 | obj-$(CONFIG_PPC_PS3) += ps3/ | ||
18 | obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ | 20 | obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 3e430b489bb..06a85b70433 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -20,4 +20,18 @@ config CBE_RAS | |||
20 | bool "RAS features for bare metal Cell BE" | 20 | bool "RAS features for bare metal Cell BE" |
21 | default y | 21 | default y |
22 | 22 | ||
23 | config CBE_THERM | ||
24 | tristate "CBE thermal support" | ||
25 | default m | ||
26 | depends on CBE_RAS | ||
27 | |||
28 | config CBE_CPUFREQ | ||
29 | tristate "CBE frequency scaling" | ||
30 | depends on CBE_RAS && CPU_FREQ | ||
31 | default m | ||
32 | help | ||
33 | This adds the cpufreq driver for Cell BE processors. | ||
34 | For details, take a look at <file:Documentation/cpu-freq/>. | ||
35 | If you don't have such processor, say N | ||
36 | |||
23 | endmenu | 37 | endmenu |
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index c89cdd67383..f90e8337796 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
@@ -1,7 +1,11 @@ | |||
1 | obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ | 1 | obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ |
2 | cbe_regs.o spider-pic.o pervasive.o | 2 | cbe_regs.o spider-pic.o \ |
3 | pervasive.o pmu.o io-workarounds.o | ||
3 | obj-$(CONFIG_CBE_RAS) += ras.o | 4 | obj-$(CONFIG_CBE_RAS) += ras.o |
4 | 5 | ||
6 | obj-$(CONFIG_CBE_THERM) += cbe_thermal.o | ||
7 | obj-$(CONFIG_CBE_CPUFREQ) += cbe_cpufreq.o | ||
8 | |||
5 | ifeq ($(CONFIG_SMP),y) | 9 | ifeq ($(CONFIG_SMP),y) |
6 | obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o | 10 | obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o |
7 | endif | 11 | endif |
@@ -11,5 +15,6 @@ spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o | |||
11 | spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o | 15 | spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o |
12 | 16 | ||
13 | obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ | 17 | obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ |
18 | spu_coredump.o \ | ||
14 | $(spufs-modular-m) \ | 19 | $(spufs-modular-m) \ |
15 | $(spu-priv1-y) spufs/ | 20 | $(spu-priv1-y) spufs/ |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c new file mode 100644 index 00000000000..a3850fd1e94 --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * cpufreq driver for the cell processor | ||
3 | * | ||
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 | ||
5 | * | ||
6 | * Author: Christian Krafft <krafft@de.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/cpufreq.h> | ||
24 | #include <linux/timer.h> | ||
25 | |||
26 | #include <asm/hw_irq.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/processor.h> | ||
29 | #include <asm/prom.h> | ||
30 | #include <asm/time.h> | ||
31 | |||
32 | #include "cbe_regs.h" | ||
33 | |||
34 | static DEFINE_MUTEX(cbe_switch_mutex); | ||
35 | |||
36 | |||
37 | /* the CBE supports an 8 step frequency scaling */ | ||
38 | static struct cpufreq_frequency_table cbe_freqs[] = { | ||
39 | {1, 0}, | ||
40 | {2, 0}, | ||
41 | {3, 0}, | ||
42 | {4, 0}, | ||
43 | {5, 0}, | ||
44 | {6, 0}, | ||
45 | {8, 0}, | ||
46 | {10, 0}, | ||
47 | {0, CPUFREQ_TABLE_END}, | ||
48 | }; | ||
49 | |||
50 | /* to write to MIC register */ | ||
51 | static u64 MIC_Slow_Fast_Timer_table[] = { | ||
52 | [0 ... 7] = 0x007fc00000000000ull, | ||
53 | }; | ||
54 | |||
55 | /* more values for the MIC */ | ||
56 | static u64 MIC_Slow_Next_Timer_table[] = { | ||
57 | 0x0000240000000000ull, | ||
58 | 0x0000268000000000ull, | ||
59 | 0x000029C000000000ull, | ||
60 | 0x00002D0000000000ull, | ||
61 | 0x0000300000000000ull, | ||
62 | 0x0000334000000000ull, | ||
63 | 0x000039C000000000ull, | ||
64 | 0x00003FC000000000ull, | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * hardware specific functions | ||
69 | */ | ||
70 | |||
71 | static int get_pmode(int cpu) | ||
72 | { | ||
73 | int ret; | ||
74 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
75 | |||
76 | pmd_regs = cbe_get_cpu_pmd_regs(cpu); | ||
77 | ret = in_be64(&pmd_regs->pmsr) & 0x07; | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | static int set_pmode(int cpu, unsigned int pmode) | ||
83 | { | ||
84 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
85 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; | ||
86 | u64 flags; | ||
87 | u64 value; | ||
88 | |||
89 | local_irq_save(flags); | ||
90 | |||
91 | mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu); | ||
92 | pmd_regs = cbe_get_cpu_pmd_regs(cpu); | ||
93 | |||
94 | pr_debug("pm register is mapped at %p\n", &pmd_regs->pmcr); | ||
95 | pr_debug("mic register is mapped at %p\n", &mic_tm_regs->slow_fast_timer_0); | ||
96 | |||
97 | out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]); | ||
98 | out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]); | ||
99 | |||
100 | out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]); | ||
101 | out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]); | ||
102 | |||
103 | value = in_be64(&pmd_regs->pmcr); | ||
104 | /* set bits to zero */ | ||
105 | value &= 0xFFFFFFFFFFFFFFF8ull; | ||
106 | /* set bits to next pmode */ | ||
107 | value |= pmode; | ||
108 | |||
109 | out_be64(&pmd_regs->pmcr, value); | ||
110 | |||
111 | /* wait until new pmode appears in status register */ | ||
112 | value = in_be64(&pmd_regs->pmsr) & 0x07; | ||
113 | while(value != pmode) { | ||
114 | cpu_relax(); | ||
115 | value = in_be64(&pmd_regs->pmsr) & 0x07; | ||
116 | } | ||
117 | |||
118 | local_irq_restore(flags); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * cpufreq functions | ||
125 | */ | ||
126 | |||
127 | static int cbe_cpufreq_cpu_init (struct cpufreq_policy *policy) | ||
128 | { | ||
129 | u32 *max_freq; | ||
130 | int i, cur_pmode; | ||
131 | struct device_node *cpu; | ||
132 | |||
133 | cpu = of_get_cpu_node(policy->cpu, NULL); | ||
134 | |||
135 | if(!cpu) | ||
136 | return -ENODEV; | ||
137 | |||
138 | pr_debug("init cpufreq on CPU %d\n", policy->cpu); | ||
139 | |||
140 | max_freq = (u32*) get_property(cpu, "clock-frequency", NULL); | ||
141 | |||
142 | if(!max_freq) | ||
143 | return -EINVAL; | ||
144 | |||
145 | // we need the freq in kHz | ||
146 | *max_freq /= 1000; | ||
147 | |||
148 | pr_debug("max clock-frequency is at %u kHz\n", *max_freq); | ||
149 | pr_debug("initializing frequency table\n"); | ||
150 | |||
151 | // initialize frequency table | ||
152 | for (i=0; cbe_freqs[i].frequency!=CPUFREQ_TABLE_END; i++) { | ||
153 | cbe_freqs[i].frequency = *max_freq / cbe_freqs[i].index; | ||
154 | pr_debug("%d: %d\n", i, cbe_freqs[i].frequency); | ||
155 | } | ||
156 | |||
157 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
158 | /* if DEBUG is enabled set_pmode() measures the correct latency of a transition */ | ||
159 | policy->cpuinfo.transition_latency = 25000; | ||
160 | |||
161 | cur_pmode = get_pmode(policy->cpu); | ||
162 | pr_debug("current pmode is at %d\n",cur_pmode); | ||
163 | |||
164 | policy->cur = cbe_freqs[cur_pmode].frequency; | ||
165 | |||
166 | #ifdef CONFIG_SMP | ||
167 | policy->cpus = cpu_sibling_map[policy->cpu]; | ||
168 | #endif | ||
169 | |||
170 | cpufreq_frequency_table_get_attr (cbe_freqs, policy->cpu); | ||
171 | |||
172 | /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */ | ||
173 | return cpufreq_frequency_table_cpuinfo (policy, cbe_freqs); | ||
174 | } | ||
175 | |||
176 | static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy) | ||
177 | { | ||
178 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int cbe_cpufreq_verify(struct cpufreq_policy *policy) | ||
183 | { | ||
184 | return cpufreq_frequency_table_verify(policy, cbe_freqs); | ||
185 | } | ||
186 | |||
187 | |||
188 | static int cbe_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, | ||
189 | unsigned int relation) | ||
190 | { | ||
191 | int rc; | ||
192 | struct cpufreq_freqs freqs; | ||
193 | int cbe_pmode_new; | ||
194 | |||
195 | cpufreq_frequency_table_target(policy, | ||
196 | cbe_freqs, | ||
197 | target_freq, | ||
198 | relation, | ||
199 | &cbe_pmode_new); | ||
200 | |||
201 | freqs.old = policy->cur; | ||
202 | freqs.new = cbe_freqs[cbe_pmode_new].frequency; | ||
203 | freqs.cpu = policy->cpu; | ||
204 | |||
205 | mutex_lock (&cbe_switch_mutex); | ||
206 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
207 | |||
208 | pr_debug("setting frequency for cpu %d to %d kHz, 1/%d of max frequency\n", | ||
209 | policy->cpu, | ||
210 | cbe_freqs[cbe_pmode_new].frequency, | ||
211 | cbe_freqs[cbe_pmode_new].index); | ||
212 | |||
213 | rc = set_pmode(policy->cpu, cbe_pmode_new); | ||
214 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
215 | mutex_unlock(&cbe_switch_mutex); | ||
216 | |||
217 | return rc; | ||
218 | } | ||
219 | |||
220 | static struct cpufreq_driver cbe_cpufreq_driver = { | ||
221 | .verify = cbe_cpufreq_verify, | ||
222 | .target = cbe_cpufreq_target, | ||
223 | .init = cbe_cpufreq_cpu_init, | ||
224 | .exit = cbe_cpufreq_cpu_exit, | ||
225 | .name = "cbe-cpufreq", | ||
226 | .owner = THIS_MODULE, | ||
227 | .flags = CPUFREQ_CONST_LOOPS, | ||
228 | }; | ||
229 | |||
230 | /* | ||
231 | * module init and destoy | ||
232 | */ | ||
233 | |||
234 | static int __init cbe_cpufreq_init(void) | ||
235 | { | ||
236 | return cpufreq_register_driver(&cbe_cpufreq_driver); | ||
237 | } | ||
238 | |||
239 | static void __exit cbe_cpufreq_exit(void) | ||
240 | { | ||
241 | cpufreq_unregister_driver(&cbe_cpufreq_driver); | ||
242 | } | ||
243 | |||
244 | module_init(cbe_cpufreq_init); | ||
245 | module_exit(cbe_cpufreq_exit); | ||
246 | |||
247 | MODULE_LICENSE("GPL"); | ||
248 | MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); | ||
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 2f194ba2989..9a0ee62691d 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/percpu.h> | 9 | #include <linux/percpu.h> |
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/module.h> | ||
11 | 12 | ||
12 | #include <asm/io.h> | 13 | #include <asm/io.h> |
13 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
@@ -16,8 +17,6 @@ | |||
16 | 17 | ||
17 | #include "cbe_regs.h" | 18 | #include "cbe_regs.h" |
18 | 19 | ||
19 | #define MAX_CBE 2 | ||
20 | |||
21 | /* | 20 | /* |
22 | * Current implementation uses "cpu" nodes. We build our own mapping | 21 | * Current implementation uses "cpu" nodes. We build our own mapping |
23 | * array of cpu numbers to cpu nodes locally for now to allow interrupt | 22 | * array of cpu numbers to cpu nodes locally for now to allow interrupt |
@@ -30,6 +29,8 @@ static struct cbe_regs_map | |||
30 | struct device_node *cpu_node; | 29 | struct device_node *cpu_node; |
31 | struct cbe_pmd_regs __iomem *pmd_regs; | 30 | struct cbe_pmd_regs __iomem *pmd_regs; |
32 | struct cbe_iic_regs __iomem *iic_regs; | 31 | struct cbe_iic_regs __iomem *iic_regs; |
32 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; | ||
33 | struct cbe_pmd_shadow_regs pmd_shadow_regs; | ||
33 | } cbe_regs_maps[MAX_CBE]; | 34 | } cbe_regs_maps[MAX_CBE]; |
34 | static int cbe_regs_map_count; | 35 | static int cbe_regs_map_count; |
35 | 36 | ||
@@ -42,6 +43,19 @@ static struct cbe_thread_map | |||
42 | static struct cbe_regs_map *cbe_find_map(struct device_node *np) | 43 | static struct cbe_regs_map *cbe_find_map(struct device_node *np) |
43 | { | 44 | { |
44 | int i; | 45 | int i; |
46 | struct device_node *tmp_np; | ||
47 | |||
48 | if (strcasecmp(np->type, "spe") == 0) { | ||
49 | if (np->data == NULL) { | ||
50 | /* walk up path until cpu node was found */ | ||
51 | tmp_np = np->parent; | ||
52 | while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0) | ||
53 | tmp_np = tmp_np->parent; | ||
54 | |||
55 | np->data = cbe_find_map(tmp_np); | ||
56 | } | ||
57 | return np->data; | ||
58 | } | ||
45 | 59 | ||
46 | for (i = 0; i < cbe_regs_map_count; i++) | 60 | for (i = 0; i < cbe_regs_map_count; i++) |
47 | if (cbe_regs_maps[i].cpu_node == np) | 61 | if (cbe_regs_maps[i].cpu_node == np) |
@@ -56,6 +70,7 @@ struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) | |||
56 | return NULL; | 70 | return NULL; |
57 | return map->pmd_regs; | 71 | return map->pmd_regs; |
58 | } | 72 | } |
73 | EXPORT_SYMBOL_GPL(cbe_get_pmd_regs); | ||
59 | 74 | ||
60 | struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) | 75 | struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) |
61 | { | 76 | { |
@@ -64,7 +79,23 @@ struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) | |||
64 | return NULL; | 79 | return NULL; |
65 | return map->pmd_regs; | 80 | return map->pmd_regs; |
66 | } | 81 | } |
82 | EXPORT_SYMBOL_GPL(cbe_get_cpu_pmd_regs); | ||
67 | 83 | ||
84 | struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np) | ||
85 | { | ||
86 | struct cbe_regs_map *map = cbe_find_map(np); | ||
87 | if (map == NULL) | ||
88 | return NULL; | ||
89 | return &map->pmd_shadow_regs; | ||
90 | } | ||
91 | |||
92 | struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu) | ||
93 | { | ||
94 | struct cbe_regs_map *map = cbe_thread_map[cpu].regs; | ||
95 | if (map == NULL) | ||
96 | return NULL; | ||
97 | return &map->pmd_shadow_regs; | ||
98 | } | ||
68 | 99 | ||
69 | struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) | 100 | struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) |
70 | { | 101 | { |
@@ -73,6 +104,7 @@ struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) | |||
73 | return NULL; | 104 | return NULL; |
74 | return map->iic_regs; | 105 | return map->iic_regs; |
75 | } | 106 | } |
107 | |||
76 | struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) | 108 | struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) |
77 | { | 109 | { |
78 | struct cbe_regs_map *map = cbe_thread_map[cpu].regs; | 110 | struct cbe_regs_map *map = cbe_thread_map[cpu].regs; |
@@ -81,6 +113,36 @@ struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) | |||
81 | return map->iic_regs; | 113 | return map->iic_regs; |
82 | } | 114 | } |
83 | 115 | ||
116 | struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np) | ||
117 | { | ||
118 | struct cbe_regs_map *map = cbe_find_map(np); | ||
119 | if (map == NULL) | ||
120 | return NULL; | ||
121 | return map->mic_tm_regs; | ||
122 | } | ||
123 | |||
124 | struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) | ||
125 | { | ||
126 | struct cbe_regs_map *map = cbe_thread_map[cpu].regs; | ||
127 | if (map == NULL) | ||
128 | return NULL; | ||
129 | return map->mic_tm_regs; | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); | ||
132 | |||
133 | /* FIXME | ||
134 | * This is little more than a stub at the moment. It should be | ||
135 | * fleshed out so that it works for both SMT and non-SMT, no | ||
136 | * matter if the passed cpu is odd or even. | ||
137 | * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. | ||
138 | * For SMT disabled, returns 0 for all cpus. | ||
139 | */ | ||
140 | u32 cbe_get_hw_thread_id(int cpu) | ||
141 | { | ||
142 | return (cpu & 1); | ||
143 | } | ||
144 | EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); | ||
145 | |||
84 | void __init cbe_regs_init(void) | 146 | void __init cbe_regs_init(void) |
85 | { | 147 | { |
86 | int i; | 148 | int i; |
@@ -119,6 +181,11 @@ void __init cbe_regs_init(void) | |||
119 | prop = get_property(cpu, "iic", NULL); | 181 | prop = get_property(cpu, "iic", NULL); |
120 | if (prop != NULL) | 182 | if (prop != NULL) |
121 | map->iic_regs = ioremap(prop->address, prop->len); | 183 | map->iic_regs = ioremap(prop->address, prop->len); |
184 | |||
185 | prop = (struct address_prop *)get_property(cpu, "mic-tm", | ||
186 | NULL); | ||
187 | if (prop != NULL) | ||
188 | map->mic_tm_regs = ioremap(prop->address, prop->len); | ||
122 | } | 189 | } |
123 | } | 190 | } |
124 | 191 | ||
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index e76e4a6af5b..440a7ecc66e 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h | |||
@@ -4,12 +4,19 @@ | |||
4 | * This file is intended to hold the various register definitions for CBE | 4 | * This file is intended to hold the various register definitions for CBE |
5 | * on-chip system devices (memory controller, IO controller, etc...) | 5 | * on-chip system devices (memory controller, IO controller, etc...) |
6 | * | 6 | * |
7 | * (C) Copyright IBM Corporation 2001,2006 | ||
8 | * | ||
9 | * Authors: Maximino Aguilar (maguilar@us.ibm.com) | ||
10 | * David J. Erb (djerb@us.ibm.com) | ||
11 | * | ||
7 | * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. | 12 | * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. |
8 | */ | 13 | */ |
9 | 14 | ||
10 | #ifndef CBE_REGS_H | 15 | #ifndef CBE_REGS_H |
11 | #define CBE_REGS_H | 16 | #define CBE_REGS_H |
12 | 17 | ||
18 | #include <asm/cell-pmu.h> | ||
19 | |||
13 | /* | 20 | /* |
14 | * | 21 | * |
15 | * Some HID register definitions | 22 | * Some HID register definitions |
@@ -22,6 +29,7 @@ | |||
22 | #define HID0_CBE_THERM_INT_EN 0x0000000400000000ul | 29 | #define HID0_CBE_THERM_INT_EN 0x0000000400000000ul |
23 | #define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul | 30 | #define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul |
24 | 31 | ||
32 | #define MAX_CBE 2 | ||
25 | 33 | ||
26 | /* | 34 | /* |
27 | * | 35 | * |
@@ -29,51 +37,124 @@ | |||
29 | * | 37 | * |
30 | */ | 38 | */ |
31 | 39 | ||
40 | union spe_reg { | ||
41 | u64 val; | ||
42 | u8 spe[8]; | ||
43 | }; | ||
44 | |||
45 | union ppe_spe_reg { | ||
46 | u64 val; | ||
47 | struct { | ||
48 | u32 ppe; | ||
49 | u32 spe; | ||
50 | }; | ||
51 | }; | ||
52 | |||
53 | |||
32 | struct cbe_pmd_regs { | 54 | struct cbe_pmd_regs { |
33 | u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ | 55 | /* Debug Bus Control */ |
56 | u64 pad_0x0000; /* 0x0000 */ | ||
57 | |||
58 | u64 group_control; /* 0x0008 */ | ||
59 | |||
60 | u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */ | ||
61 | |||
62 | u64 debug_bus_control; /* 0x00a8 */ | ||
63 | |||
64 | u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */ | ||
65 | |||
66 | u64 trace_aux_data; /* 0x0100 */ | ||
67 | u64 trace_buffer_0_63; /* 0x0108 */ | ||
68 | u64 trace_buffer_64_127; /* 0x0110 */ | ||
69 | u64 trace_address; /* 0x0118 */ | ||
70 | u64 ext_tr_timer; /* 0x0120 */ | ||
71 | |||
72 | u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */ | ||
73 | |||
74 | /* Performance Monitor */ | ||
75 | u64 pm_status; /* 0x0400 */ | ||
76 | u64 pm_control; /* 0x0408 */ | ||
77 | u64 pm_interval; /* 0x0410 */ | ||
78 | u64 pm_ctr[4]; /* 0x0418 */ | ||
79 | u64 pm_start_stop; /* 0x0438 */ | ||
80 | u64 pm07_control[8]; /* 0x0440 */ | ||
81 | |||
82 | u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */ | ||
34 | 83 | ||
35 | /* Thermal Sensor Registers */ | 84 | /* Thermal Sensor Registers */ |
36 | u64 ts_ctsr1; /* 0x0800 */ | 85 | union spe_reg ts_ctsr1; /* 0x0800 */ |
37 | u64 ts_ctsr2; /* 0x0808 */ | 86 | u64 ts_ctsr2; /* 0x0808 */ |
38 | u64 ts_mtsr1; /* 0x0810 */ | 87 | union spe_reg ts_mtsr1; /* 0x0810 */ |
39 | u64 ts_mtsr2; /* 0x0818 */ | 88 | u64 ts_mtsr2; /* 0x0818 */ |
40 | u64 ts_itr1; /* 0x0820 */ | 89 | union spe_reg ts_itr1; /* 0x0820 */ |
41 | u64 ts_itr2; /* 0x0828 */ | 90 | u64 ts_itr2; /* 0x0828 */ |
42 | u64 ts_gitr; /* 0x0830 */ | 91 | u64 ts_gitr; /* 0x0830 */ |
43 | u64 ts_isr; /* 0x0838 */ | 92 | u64 ts_isr; /* 0x0838 */ |
44 | u64 ts_imr; /* 0x0840 */ | 93 | u64 ts_imr; /* 0x0840 */ |
45 | u64 tm_cr1; /* 0x0848 */ | 94 | union spe_reg tm_cr1; /* 0x0848 */ |
46 | u64 tm_cr2; /* 0x0850 */ | 95 | u64 tm_cr2; /* 0x0850 */ |
47 | u64 tm_simr; /* 0x0858 */ | 96 | u64 tm_simr; /* 0x0858 */ |
48 | u64 tm_tpr; /* 0x0860 */ | 97 | union ppe_spe_reg tm_tpr; /* 0x0860 */ |
49 | u64 tm_str1; /* 0x0868 */ | 98 | union spe_reg tm_str1; /* 0x0868 */ |
50 | u64 tm_str2; /* 0x0870 */ | 99 | u64 tm_str2; /* 0x0870 */ |
51 | u64 tm_tsr; /* 0x0878 */ | 100 | union ppe_spe_reg tm_tsr; /* 0x0878 */ |
52 | 101 | ||
53 | /* Power Management */ | 102 | /* Power Management */ |
54 | u64 pm_control; /* 0x0880 */ | 103 | u64 pmcr; /* 0x0880 */ |
55 | #define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 | 104 | #define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 |
56 | u64 pm_status; /* 0x0888 */ | 105 | u64 pmsr; /* 0x0888 */ |
57 | 106 | ||
58 | /* Time Base Register */ | 107 | /* Time Base Register */ |
59 | u64 tbr; /* 0x0890 */ | 108 | u64 tbr; /* 0x0890 */ |
60 | 109 | ||
61 | u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ | 110 | u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ |
62 | 111 | ||
63 | /* Fault Isolation Registers */ | 112 | /* Fault Isolation Registers */ |
64 | u64 checkstop_fir; /* 0x0c00 */ | 113 | u64 checkstop_fir; /* 0x0c00 */ |
65 | u64 recoverable_fir; | 114 | u64 recoverable_fir; /* 0x0c08 */ |
66 | u64 spec_att_mchk_fir; | 115 | u64 spec_att_mchk_fir; /* 0x0c10 */ |
67 | u64 fir_mode_reg; | 116 | u64 fir_mode_reg; /* 0x0c18 */ |
68 | u64 fir_enable_mask; | 117 | u64 fir_enable_mask; /* 0x0c20 */ |
69 | 118 | ||
70 | u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ | 119 | u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ |
71 | }; | 120 | }; |
72 | 121 | ||
73 | extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); | 122 | extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); |
74 | extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); | 123 | extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); |
75 | 124 | ||
76 | /* | 125 | /* |
126 | * PMU shadow registers | ||
127 | * | ||
128 | * Many of the registers in the performance monitoring unit are write-only, | ||
129 | * so we need to save a copy of what we write to those registers. | ||
130 | * | ||
131 | * The actual data counters are read/write. However, writing to the counters | ||
132 | * only takes effect if the PMU is enabled. Otherwise the value is stored in | ||
133 | * a hardware latch until the next time the PMU is enabled. So we save a copy | ||
134 | * of the counter values if we need to read them back while the PMU is | ||
135 | * disabled. The counter_value_in_latch field is a bitmap indicating which | ||
136 | * counters currently have a value waiting to be written. | ||
137 | */ | ||
138 | |||
139 | struct cbe_pmd_shadow_regs { | ||
140 | u32 group_control; | ||
141 | u32 debug_bus_control; | ||
142 | u32 trace_address; | ||
143 | u32 ext_tr_timer; | ||
144 | u32 pm_status; | ||
145 | u32 pm_control; | ||
146 | u32 pm_interval; | ||
147 | u32 pm_start_stop; | ||
148 | u32 pm07_control[NR_CTRS]; | ||
149 | |||
150 | u32 pm_ctr[NR_PHYS_CTRS]; | ||
151 | u32 counter_value_in_latch; | ||
152 | }; | ||
153 | |||
154 | extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np); | ||
155 | extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu); | ||
156 | |||
157 | /* | ||
77 | * | 158 | * |
78 | * IIC unit register definitions | 159 | * IIC unit register definitions |
79 | * | 160 | * |
@@ -102,18 +183,28 @@ struct cbe_iic_regs { | |||
102 | 183 | ||
103 | /* IIC interrupt registers */ | 184 | /* IIC interrupt registers */ |
104 | struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ | 185 | struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ |
105 | u64 iic_ir; /* 0x0440 */ | 186 | |
106 | u64 iic_is; /* 0x0448 */ | 187 | u64 iic_ir; /* 0x0440 */ |
188 | #define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12) | ||
189 | #define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4) | ||
190 | #define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf) | ||
191 | #define CBE_IIC_IR_IOC_0 0x0 | ||
192 | #define CBE_IIC_IR_IOC_1S 0xb | ||
193 | #define CBE_IIC_IR_PT_0 0xe | ||
194 | #define CBE_IIC_IR_PT_1 0xf | ||
195 | |||
196 | u64 iic_is; /* 0x0448 */ | ||
197 | #define CBE_IIC_IS_PMI 0x2 | ||
107 | 198 | ||
108 | u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ | 199 | u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ |
109 | 200 | ||
110 | /* IOC FIR */ | 201 | /* IOC FIR */ |
111 | u64 ioc_fir_reset; /* 0x0500 */ | 202 | u64 ioc_fir_reset; /* 0x0500 */ |
112 | u64 ioc_fir_set; | 203 | u64 ioc_fir_set; /* 0x0508 */ |
113 | u64 ioc_checkstop_enable; | 204 | u64 ioc_checkstop_enable; /* 0x0510 */ |
114 | u64 ioc_fir_error_mask; | 205 | u64 ioc_fir_error_mask; /* 0x0518 */ |
115 | u64 ioc_syserr_enable; | 206 | u64 ioc_syserr_enable; /* 0x0520 */ |
116 | u64 ioc_fir; | 207 | u64 ioc_fir; /* 0x0528 */ |
117 | 208 | ||
118 | u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ | 209 | u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ |
119 | }; | 210 | }; |
@@ -122,6 +213,48 @@ extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); | |||
122 | extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); | 213 | extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); |
123 | 214 | ||
124 | 215 | ||
216 | struct cbe_mic_tm_regs { | ||
217 | u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */ | ||
218 | |||
219 | u64 mic_ctl_cnfg2; /* 0x0040 */ | ||
220 | #define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL | ||
221 | #define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL | ||
222 | #define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL | ||
223 | #define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL | ||
224 | |||
225 | u64 pad_0x0048; /* 0x0048 */ | ||
226 | |||
227 | u64 mic_aux_trc_base; /* 0x0050 */ | ||
228 | u64 mic_aux_trc_max_addr; /* 0x0058 */ | ||
229 | u64 mic_aux_trc_cur_addr; /* 0x0060 */ | ||
230 | u64 mic_aux_trc_grf_addr; /* 0x0068 */ | ||
231 | u64 mic_aux_trc_grf_data; /* 0x0070 */ | ||
232 | |||
233 | u64 pad_0x0078; /* 0x0078 */ | ||
234 | |||
235 | u64 mic_ctl_cnfg_0; /* 0x0080 */ | ||
236 | #define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL | ||
237 | |||
238 | u64 pad_0x0088; /* 0x0088 */ | ||
239 | |||
240 | u64 slow_fast_timer_0; /* 0x0090 */ | ||
241 | u64 slow_next_timer_0; /* 0x0098 */ | ||
242 | |||
243 | u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */ | ||
244 | |||
245 | u64 mic_ctl_cnfg_1; /* 0x01c0 */ | ||
246 | #define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL | ||
247 | u64 pad_0x01c8; /* 0x01c8 */ | ||
248 | |||
249 | u64 slow_fast_timer_1; /* 0x01d0 */ | ||
250 | u64 slow_next_timer_1; /* 0x01d8 */ | ||
251 | |||
252 | u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */ | ||
253 | }; | ||
254 | |||
255 | extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); | ||
256 | extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); | ||
257 | |||
125 | /* Init this module early */ | 258 | /* Init this module early */ |
126 | extern void cbe_regs_init(void); | 259 | extern void cbe_regs_init(void); |
127 | 260 | ||
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c new file mode 100644 index 00000000000..616a0a3fd0e --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_thermal.c | |||
@@ -0,0 +1,226 @@ | |||
1 | /* | ||
2 | * thermal support for the cell processor | ||
3 | * | ||
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 | ||
5 | * | ||
6 | * Author: Christian Krafft <krafft@de.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/sysdev.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/cpu.h> | ||
27 | #include <asm/spu.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/prom.h> | ||
30 | |||
31 | #include "cbe_regs.h" | ||
32 | #include "spu_priv1_mmio.h" | ||
33 | |||
34 | static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) | ||
35 | { | ||
36 | struct spu *spu; | ||
37 | |||
38 | spu = container_of(sysdev, struct spu, sysdev); | ||
39 | |||
40 | return cbe_get_pmd_regs(spu_devnode(spu)); | ||
41 | } | ||
42 | |||
43 | /* returns the value for a given spu in a given register */ | ||
44 | static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg) | ||
45 | { | ||
46 | unsigned int *id; | ||
47 | union spe_reg value; | ||
48 | struct spu *spu; | ||
49 | |||
50 | /* getting the id from the reg attribute will not work on future device-tree layouts | ||
51 | * in future we should store the id to the spu struct and use it here */ | ||
52 | spu = container_of(sysdev, struct spu, sysdev); | ||
53 | id = (unsigned int *)get_property(spu_devnode(spu), "reg", NULL); | ||
54 | value.val = in_be64(®->val); | ||
55 | |||
56 | return value.spe[*id]; | ||
57 | } | ||
58 | |||
59 | static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) | ||
60 | { | ||
61 | int value; | ||
62 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
63 | |||
64 | pmd_regs = get_pmd_regs(sysdev); | ||
65 | |||
66 | value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); | ||
67 | /* clear all other bits */ | ||
68 | value &= 0x3F; | ||
69 | /* temp is stored in steps of 2 degrees */ | ||
70 | value *= 2; | ||
71 | /* base temp is 65 degrees */ | ||
72 | value += 65; | ||
73 | |||
74 | return sprintf(buf, "%d\n", (int) value); | ||
75 | } | ||
76 | |||
77 | static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) | ||
78 | { | ||
79 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
80 | u64 value; | ||
81 | |||
82 | pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); | ||
83 | value = in_be64(&pmd_regs->ts_ctsr2); | ||
84 | |||
85 | /* access the corresponding byte */ | ||
86 | value >>= pos; | ||
87 | /* clear all other bits */ | ||
88 | value &= 0x3F; | ||
89 | /* temp is stored in steps of 2 degrees */ | ||
90 | value *= 2; | ||
91 | /* base temp is 65 degrees */ | ||
92 | value += 65; | ||
93 | |||
94 | return sprintf(buf, "%d\n", (int) value); | ||
95 | } | ||
96 | |||
97 | |||
98 | /* shows the temperature of the DTS on the PPE, | ||
99 | * located near the linear thermal sensor */ | ||
100 | static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf) | ||
101 | { | ||
102 | return ppe_show_temp(sysdev, buf, 32); | ||
103 | } | ||
104 | |||
105 | /* shows the temperature of the second DTS on the PPE */ | ||
106 | static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) | ||
107 | { | ||
108 | return ppe_show_temp(sysdev, buf, 0); | ||
109 | } | ||
110 | |||
111 | static struct sysdev_attribute attr_spu_temperature = { | ||
112 | .attr = {.name = "temperature", .mode = 0400 }, | ||
113 | .show = spu_show_temp, | ||
114 | }; | ||
115 | |||
116 | static struct attribute *spu_attributes[] = { | ||
117 | &attr_spu_temperature.attr, | ||
118 | }; | ||
119 | |||
120 | static struct attribute_group spu_attribute_group = { | ||
121 | .name = "thermal", | ||
122 | .attrs = spu_attributes, | ||
123 | }; | ||
124 | |||
125 | static struct sysdev_attribute attr_ppe_temperature0 = { | ||
126 | .attr = {.name = "temperature0", .mode = 0400 }, | ||
127 | .show = ppe_show_temp0, | ||
128 | }; | ||
129 | |||
130 | static struct sysdev_attribute attr_ppe_temperature1 = { | ||
131 | .attr = {.name = "temperature1", .mode = 0400 }, | ||
132 | .show = ppe_show_temp1, | ||
133 | }; | ||
134 | |||
135 | static struct attribute *ppe_attributes[] = { | ||
136 | &attr_ppe_temperature0.attr, | ||
137 | &attr_ppe_temperature1.attr, | ||
138 | }; | ||
139 | |||
140 | static struct attribute_group ppe_attribute_group = { | ||
141 | .name = "thermal", | ||
142 | .attrs = ppe_attributes, | ||
143 | }; | ||
144 | |||
145 | /* | ||
146 | * initialize throttling with default values | ||
147 | */ | ||
148 | static void __init init_default_values(void) | ||
149 | { | ||
150 | int cpu; | ||
151 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
152 | struct sys_device *sysdev; | ||
153 | union ppe_spe_reg tpr; | ||
154 | union spe_reg str1; | ||
155 | u64 str2; | ||
156 | union spe_reg cr1; | ||
157 | u64 cr2; | ||
158 | |||
159 | /* TPR defaults */ | ||
160 | /* ppe | ||
161 | * 1F - no full stop | ||
162 | * 08 - dynamic throttling starts if over 80 degrees | ||
163 | * 03 - dynamic throttling ceases if below 70 degrees */ | ||
164 | tpr.ppe = 0x1F0803; | ||
165 | /* spe | ||
166 | * 10 - full stopped when over 96 degrees | ||
167 | * 08 - dynamic throttling starts if over 80 degrees | ||
168 | * 03 - dynamic throttling ceases if below 70 degrees | ||
169 | */ | ||
170 | tpr.spe = 0x100803; | ||
171 | |||
172 | /* STR defaults */ | ||
173 | /* str1 | ||
174 | * 10 - stop 16 of 32 cycles | ||
175 | */ | ||
176 | str1.val = 0x1010101010101010ull; | ||
177 | /* str2 | ||
178 | * 10 - stop 16 of 32 cycles | ||
179 | */ | ||
180 | str2 = 0x10; | ||
181 | |||
182 | /* CR defaults */ | ||
183 | /* cr1 | ||
184 | * 4 - normal operation | ||
185 | */ | ||
186 | cr1.val = 0x0404040404040404ull; | ||
187 | /* cr2 | ||
188 | * 4 - normal operation | ||
189 | */ | ||
190 | cr2 = 0x04; | ||
191 | |||
192 | for_each_possible_cpu (cpu) { | ||
193 | pr_debug("processing cpu %d\n", cpu); | ||
194 | sysdev = get_cpu_sysdev(cpu); | ||
195 | pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); | ||
196 | |||
197 | out_be64(&pmd_regs->tm_str2, str2); | ||
198 | out_be64(&pmd_regs->tm_str1.val, str1.val); | ||
199 | out_be64(&pmd_regs->tm_tpr.val, tpr.val); | ||
200 | out_be64(&pmd_regs->tm_cr1.val, cr1.val); | ||
201 | out_be64(&pmd_regs->tm_cr2, cr2); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | |||
206 | static int __init thermal_init(void) | ||
207 | { | ||
208 | init_default_values(); | ||
209 | |||
210 | spu_add_sysdev_attr_group(&spu_attribute_group); | ||
211 | cpu_add_sysdev_attr_group(&ppe_attribute_group); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | module_init(thermal_init); | ||
216 | |||
217 | static void __exit thermal_exit(void) | ||
218 | { | ||
219 | spu_remove_sysdev_attr_group(&spu_attribute_group); | ||
220 | cpu_remove_sysdev_attr_group(&ppe_attribute_group); | ||
221 | } | ||
222 | module_exit(thermal_exit); | ||
223 | |||
224 | MODULE_LICENSE("GPL"); | ||
225 | MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); | ||
226 | |||
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index a914c12b406..6666d037eb4 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
@@ -396,3 +396,19 @@ void __init iic_init_IRQ(void) | |||
396 | /* Enable on current CPU */ | 396 | /* Enable on current CPU */ |
397 | iic_setup_cpu(); | 397 | iic_setup_cpu(); |
398 | } | 398 | } |
399 | |||
400 | void iic_set_interrupt_routing(int cpu, int thread, int priority) | ||
401 | { | ||
402 | struct cbe_iic_regs __iomem *iic_regs = cbe_get_cpu_iic_regs(cpu); | ||
403 | u64 iic_ir = 0; | ||
404 | int node = cpu >> 1; | ||
405 | |||
406 | /* Set which node and thread will handle the next interrupt */ | ||
407 | iic_ir |= CBE_IIC_IR_PRIO(priority) | | ||
408 | CBE_IIC_IR_DEST_NODE(node); | ||
409 | if (thread == 0) | ||
410 | iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_0); | ||
411 | else | ||
412 | iic_ir |= CBE_IIC_IR_DEST_UNIT(CBE_IIC_IR_PT_1); | ||
413 | out_be64(&iic_regs->iic_ir, iic_ir); | ||
414 | } | ||
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h index 9ba1d3c17b4..942dc39d604 100644 --- a/arch/powerpc/platforms/cell/interrupt.h +++ b/arch/powerpc/platforms/cell/interrupt.h | |||
@@ -83,5 +83,7 @@ extern u8 iic_get_target_id(int cpu); | |||
83 | 83 | ||
84 | extern void spider_init_IRQ(void); | 84 | extern void spider_init_IRQ(void); |
85 | 85 | ||
86 | extern void iic_set_interrupt_routing(int cpu, int thread, int priority); | ||
87 | |||
86 | #endif | 88 | #endif |
87 | #endif /* ASM_CELL_PIC_H */ | 89 | #endif /* ASM_CELL_PIC_H */ |
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c new file mode 100644 index 00000000000..580d4259591 --- /dev/null +++ b/arch/powerpc/platforms/cell/io-workarounds.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
3 | * IBM, Corp. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | #undef DEBUG | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/mm.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <asm/io.h> | ||
15 | #include <asm/machdep.h> | ||
16 | #include <asm/pci-bridge.h> | ||
17 | #include <asm/ppc-pci.h> | ||
18 | |||
19 | |||
20 | #define SPIDER_PCI_REG_BASE 0xd000 | ||
21 | #define SPIDER_PCI_VCI_CNTL_STAT 0x0110 | ||
22 | #define SPIDER_PCI_DUMMY_READ 0x0810 | ||
23 | #define SPIDER_PCI_DUMMY_READ_BASE 0x0814 | ||
24 | |||
25 | /* Undefine that to re-enable bogus prefetch | ||
26 | * | ||
27 | * Without that workaround, the chip will do bogus prefetch past | ||
28 | * page boundary from system memory. This setting will disable that, | ||
29 | * though the documentation is unclear as to the consequences of doing | ||
30 | * so, either purely performances, or possible misbehaviour... It's not | ||
31 | * clear wether the chip can handle unaligned accesses at all without | ||
32 | * prefetching enabled. | ||
33 | * | ||
34 | * For now, things appear to be behaving properly with that prefetching | ||
35 | * disabled and IDE, possibly because IDE isn't doing any unaligned | ||
36 | * access. | ||
37 | */ | ||
38 | #define SPIDER_DISABLE_PREFETCH | ||
39 | |||
40 | #define MAX_SPIDERS 2 | ||
41 | |||
42 | static struct spider_pci_bus { | ||
43 | void __iomem *regs; | ||
44 | unsigned long mmio_start; | ||
45 | unsigned long mmio_end; | ||
46 | unsigned long pio_vstart; | ||
47 | unsigned long pio_vend; | ||
48 | } spider_pci_busses[MAX_SPIDERS]; | ||
49 | static int spider_pci_count; | ||
50 | |||
51 | static struct spider_pci_bus *spider_pci_find(unsigned long vaddr, | ||
52 | unsigned long paddr) | ||
53 | { | ||
54 | int i; | ||
55 | |||
56 | for (i = 0; i < spider_pci_count; i++) { | ||
57 | struct spider_pci_bus *bus = &spider_pci_busses[i]; | ||
58 | if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end) | ||
59 | return bus; | ||
60 | if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend) | ||
61 | return bus; | ||
62 | } | ||
63 | return NULL; | ||
64 | } | ||
65 | |||
66 | static void spider_io_flush(const volatile void __iomem *addr) | ||
67 | { | ||
68 | struct spider_pci_bus *bus; | ||
69 | int token; | ||
70 | |||
71 | /* Get platform token (set by ioremap) from address */ | ||
72 | token = PCI_GET_ADDR_TOKEN(addr); | ||
73 | |||
74 | /* Fast path if we have a non-0 token, it indicates which bus we | ||
75 | * are on. | ||
76 | * | ||
77 | * If the token is 0, that means either the the ioremap was done | ||
78 | * before we initialized this layer, or it's a PIO operation. We | ||
79 | * fallback to a low path in this case. Hopefully, internal devices | ||
80 | * which are ioremap'ed early should use in_XX/out_XX functions | ||
81 | * instead of the PCI ones and thus not suffer from the slowdown. | ||
82 | * | ||
83 | * Also note that currently, the workaround will not work for areas | ||
84 | * that are not mapped with PTEs (bolted in the hash table). This | ||
85 | * is the case for ioremaps done very early at boot (before | ||
86 | * mem_init_done) and includes the mapping of the ISA IO space. | ||
87 | * | ||
88 | * Fortunately, none of the affected devices is expected to do DMA | ||
89 | * and thus there should be no problem in practice. | ||
90 | * | ||
91 | * In order to improve performances, we only do the PTE search for | ||
92 | * addresses falling in the PHB IO space area. That means it will | ||
93 | * not work for hotplug'ed PHBs but those don't exist with Spider. | ||
94 | */ | ||
95 | if (token && token <= spider_pci_count) | ||
96 | bus = &spider_pci_busses[token - 1]; | ||
97 | else { | ||
98 | unsigned long vaddr, paddr; | ||
99 | pte_t *ptep; | ||
100 | |||
101 | /* Fixup physical address */ | ||
102 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | ||
103 | |||
104 | /* Check if it's in allowed range for PIO */ | ||
105 | if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE) | ||
106 | return; | ||
107 | |||
108 | /* Try to find a PTE. If not, clear the paddr, we'll do | ||
109 | * a vaddr only lookup (PIO only) | ||
110 | */ | ||
111 | ptep = find_linux_pte(init_mm.pgd, vaddr); | ||
112 | if (ptep == NULL) | ||
113 | paddr = 0; | ||
114 | else | ||
115 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; | ||
116 | |||
117 | bus = spider_pci_find(vaddr, paddr); | ||
118 | if (bus == NULL) | ||
119 | return; | ||
120 | } | ||
121 | |||
122 | /* Now do the workaround | ||
123 | */ | ||
124 | (void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ); | ||
125 | } | ||
126 | |||
127 | static u8 spider_readb(const volatile void __iomem *addr) | ||
128 | { | ||
129 | u8 val = __do_readb(addr); | ||
130 | spider_io_flush(addr); | ||
131 | return val; | ||
132 | } | ||
133 | |||
134 | static u16 spider_readw(const volatile void __iomem *addr) | ||
135 | { | ||
136 | u16 val = __do_readw(addr); | ||
137 | spider_io_flush(addr); | ||
138 | return val; | ||
139 | } | ||
140 | |||
141 | static u32 spider_readl(const volatile void __iomem *addr) | ||
142 | { | ||
143 | u32 val = __do_readl(addr); | ||
144 | spider_io_flush(addr); | ||
145 | return val; | ||
146 | } | ||
147 | |||
148 | static u64 spider_readq(const volatile void __iomem *addr) | ||
149 | { | ||
150 | u64 val = __do_readq(addr); | ||
151 | spider_io_flush(addr); | ||
152 | return val; | ||
153 | } | ||
154 | |||
155 | static u16 spider_readw_be(const volatile void __iomem *addr) | ||
156 | { | ||
157 | u16 val = __do_readw_be(addr); | ||
158 | spider_io_flush(addr); | ||
159 | return val; | ||
160 | } | ||
161 | |||
162 | static u32 spider_readl_be(const volatile void __iomem *addr) | ||
163 | { | ||
164 | u32 val = __do_readl_be(addr); | ||
165 | spider_io_flush(addr); | ||
166 | return val; | ||
167 | } | ||
168 | |||
169 | static u64 spider_readq_be(const volatile void __iomem *addr) | ||
170 | { | ||
171 | u64 val = __do_readq_be(addr); | ||
172 | spider_io_flush(addr); | ||
173 | return val; | ||
174 | } | ||
175 | |||
176 | static void spider_readsb(const volatile void __iomem *addr, void *buf, | ||
177 | unsigned long count) | ||
178 | { | ||
179 | __do_readsb(addr, buf, count); | ||
180 | spider_io_flush(addr); | ||
181 | } | ||
182 | |||
183 | static void spider_readsw(const volatile void __iomem *addr, void *buf, | ||
184 | unsigned long count) | ||
185 | { | ||
186 | __do_readsw(addr, buf, count); | ||
187 | spider_io_flush(addr); | ||
188 | } | ||
189 | |||
190 | static void spider_readsl(const volatile void __iomem *addr, void *buf, | ||
191 | unsigned long count) | ||
192 | { | ||
193 | __do_readsl(addr, buf, count); | ||
194 | spider_io_flush(addr); | ||
195 | } | ||
196 | |||
197 | static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src, | ||
198 | unsigned long n) | ||
199 | { | ||
200 | __do_memcpy_fromio(dest, src, n); | ||
201 | spider_io_flush(src); | ||
202 | } | ||
203 | |||
204 | |||
205 | static void __iomem * spider_ioremap(unsigned long addr, unsigned long size, | ||
206 | unsigned long flags) | ||
207 | { | ||
208 | struct spider_pci_bus *bus; | ||
209 | void __iomem *res = __ioremap(addr, size, flags); | ||
210 | int busno; | ||
211 | |||
212 | pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n", | ||
213 | addr, size, flags, res); | ||
214 | |||
215 | bus = spider_pci_find(0, addr); | ||
216 | if (bus != NULL) { | ||
217 | busno = bus - spider_pci_busses; | ||
218 | pr_debug(" found bus %d, setting token\n", busno); | ||
219 | PCI_SET_ADDR_TOKEN(res, busno + 1); | ||
220 | } | ||
221 | pr_debug(" result=0x%p\n", res); | ||
222 | |||
223 | return res; | ||
224 | } | ||
225 | |||
226 | static void __init spider_pci_setup_chip(struct spider_pci_bus *bus) | ||
227 | { | ||
228 | #ifdef SPIDER_DISABLE_PREFETCH | ||
229 | u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT); | ||
230 | pr_debug(" PVCI_Control_Status was 0x%08x\n", val); | ||
231 | out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8); | ||
232 | #endif | ||
233 | |||
234 | /* Configure the dummy address for the workaround */ | ||
235 | out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000); | ||
236 | } | ||
237 | |||
238 | static void __init spider_pci_add_one(struct pci_controller *phb) | ||
239 | { | ||
240 | struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count]; | ||
241 | struct device_node *np = phb->arch_data; | ||
242 | struct resource rsrc; | ||
243 | void __iomem *regs; | ||
244 | |||
245 | if (spider_pci_count >= MAX_SPIDERS) { | ||
246 | printk(KERN_ERR "Too many spider bridges, workarounds" | ||
247 | " disabled for %s\n", np->full_name); | ||
248 | return; | ||
249 | } | ||
250 | |||
251 | /* Get the registers for the beast */ | ||
252 | if (of_address_to_resource(np, 0, &rsrc)) { | ||
253 | printk(KERN_ERR "Failed to get registers for spider %s" | ||
254 | " workarounds disabled\n", np->full_name); | ||
255 | return; | ||
256 | } | ||
257 | |||
258 | /* Mask out some useless bits in there to get to the base of the | ||
259 | * spider chip | ||
260 | */ | ||
261 | rsrc.start &= ~0xfffffffful; | ||
262 | |||
263 | /* Map them */ | ||
264 | regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000); | ||
265 | if (regs == NULL) { | ||
266 | printk(KERN_ERR "Failed to map registers for spider %s" | ||
267 | " workarounds disabled\n", np->full_name); | ||
268 | return; | ||
269 | } | ||
270 | |||
271 | spider_pci_count++; | ||
272 | |||
273 | /* We assume spiders only have one MMIO resource */ | ||
274 | bus->mmio_start = phb->mem_resources[0].start; | ||
275 | bus->mmio_end = phb->mem_resources[0].end + 1; | ||
276 | |||
277 | bus->pio_vstart = (unsigned long)phb->io_base_virt; | ||
278 | bus->pio_vend = bus->pio_vstart + phb->pci_io_size; | ||
279 | |||
280 | bus->regs = regs; | ||
281 | |||
282 | printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name); | ||
283 | |||
284 | pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n", | ||
285 | bus->mmio_start, bus->mmio_end); | ||
286 | pr_debug(" pio (V) = 0x%016lx..0x%016lx\n", | ||
287 | bus->pio_vstart, bus->pio_vend); | ||
288 | pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n", | ||
289 | rsrc.start + SPIDER_PCI_REG_BASE, bus->regs); | ||
290 | |||
291 | spider_pci_setup_chip(bus); | ||
292 | } | ||
293 | |||
294 | static struct ppc_pci_io __initdata spider_pci_io = { | ||
295 | .readb = spider_readb, | ||
296 | .readw = spider_readw, | ||
297 | .readl = spider_readl, | ||
298 | .readq = spider_readq, | ||
299 | .readw_be = spider_readw_be, | ||
300 | .readl_be = spider_readl_be, | ||
301 | .readq_be = spider_readq_be, | ||
302 | .readsb = spider_readsb, | ||
303 | .readsw = spider_readsw, | ||
304 | .readsl = spider_readsl, | ||
305 | .memcpy_fromio = spider_memcpy_fromio, | ||
306 | }; | ||
307 | |||
308 | static int __init spider_pci_workaround_init(void) | ||
309 | { | ||
310 | struct pci_controller *phb; | ||
311 | |||
312 | if (!machine_is(cell)) | ||
313 | return 0; | ||
314 | |||
315 | /* Find spider bridges. We assume they have been all probed | ||
316 | * in setup_arch(). If that was to change, we would need to | ||
317 | * update this code to cope with dynamically added busses | ||
318 | */ | ||
319 | list_for_each_entry(phb, &hose_list, list_node) { | ||
320 | struct device_node *np = phb->arch_data; | ||
321 | const char *model = get_property(np, "model", NULL); | ||
322 | |||
323 | /* If no model property or name isn't exactly "pci", skip */ | ||
324 | if (model == NULL || strcmp(np->name, "pci")) | ||
325 | continue; | ||
326 | /* If model is not "Spider", skip */ | ||
327 | if (strcmp(model, "Spider")) | ||
328 | continue; | ||
329 | spider_pci_add_one(phb); | ||
330 | } | ||
331 | |||
332 | /* No Spider PCI found, exit */ | ||
333 | if (spider_pci_count == 0) | ||
334 | return 0; | ||
335 | |||
336 | /* Setup IO callbacks. We only setup MMIO reads. PIO reads will | ||
337 | * fallback to MMIO reads (though without a token, thus slower) | ||
338 | */ | ||
339 | ppc_pci_io = spider_pci_io; | ||
340 | |||
341 | /* Setup ioremap callback */ | ||
342 | ppc_md.ioremap = spider_ioremap; | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | arch_initcall(spider_pci_workaround_init); | ||
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index aca4c3db0dd..b43466ba809 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -1,514 +1,747 @@ | |||
1 | /* | 1 | /* |
2 | * IOMMU implementation for Cell Broadband Processor Architecture | 2 | * IOMMU implementation for Cell Broadband Processor Architecture |
3 | * We just establish a linear mapping at boot by setting all the | ||
4 | * IOPT cache entries in the CPU. | ||
5 | * The mapping functions should be identical to pci_direct_iommu, | ||
6 | * except for the handling of the high order bit that is required | ||
7 | * by the Spider bridge. These should be split into a separate | ||
8 | * file at the point where we get a different bridge chip. | ||
9 | * | 3 | * |
10 | * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH, | 4 | * (C) Copyright IBM Corporation 2006 |
11 | * Arnd Bergmann <arndb@de.ibm.com> | ||
12 | * | 5 | * |
13 | * Based on linear mapping | 6 | * Author: Jeremy Kerr <jk@ozlabs.org> |
14 | * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
15 | * | 7 | * |
16 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or modify |
17 | * modify it under the terms of the GNU General Public License | 9 | * it under the terms of the GNU General Public License as published by |
18 | * as published by the Free Software Foundation; either version | 10 | * the Free Software Foundation; either version 2, or (at your option) |
19 | * 2 of the License, or (at your option) any later version. | 11 | * any later version. |
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | 21 | */ |
21 | 22 | ||
22 | #undef DEBUG | 23 | #undef DEBUG |
23 | 24 | ||
24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
25 | #include <linux/pci.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/string.h> | ||
28 | #include <linux/init.h> | 26 | #include <linux/init.h> |
29 | #include <linux/bootmem.h> | 27 | #include <linux/interrupt.h> |
30 | #include <linux/mm.h> | 28 | #include <linux/notifier.h> |
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/compiler.h> | ||
34 | 29 | ||
35 | #include <asm/sections.h> | ||
36 | #include <asm/iommu.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/prom.h> | 30 | #include <asm/prom.h> |
39 | #include <asm/pci-bridge.h> | 31 | #include <asm/iommu.h> |
40 | #include <asm/machdep.h> | 32 | #include <asm/machdep.h> |
41 | #include <asm/pmac_feature.h> | 33 | #include <asm/pci-bridge.h> |
42 | #include <asm/abs_addr.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/ppc-pci.h> | ||
45 | #include <asm/udbg.h> | 34 | #include <asm/udbg.h> |
35 | #include <asm/of_platform.h> | ||
36 | #include <asm/lmb.h> | ||
46 | 37 | ||
47 | #include "iommu.h" | 38 | #include "cbe_regs.h" |
39 | #include "interrupt.h" | ||
48 | 40 | ||
49 | static inline unsigned long | 41 | /* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages |
50 | get_iopt_entry(unsigned long real_address, unsigned long ioid, | 42 | * instead of leaving them mapped to some dummy page. This can be |
51 | unsigned long prot) | 43 | * enabled once the appropriate workarounds for spider bugs have |
52 | { | 44 | * been enabled |
53 | return (prot & IOPT_PROT_MASK) | 45 | */ |
54 | | (IOPT_COHERENT) | 46 | #define CELL_IOMMU_REAL_UNMAP |
55 | | (IOPT_ORDER_VC) | ||
56 | | (real_address & IOPT_RPN_MASK) | ||
57 | | (ioid & IOPT_IOID_MASK); | ||
58 | } | ||
59 | 47 | ||
60 | typedef struct { | 48 | /* Define CELL_IOMMU_STRICT_PROTECTION to enforce protection of |
61 | unsigned long val; | 49 | * IO PTEs based on the transfer direction. That can be enabled |
62 | } ioste; | 50 | * once spider-net has been fixed to pass the correct direction |
51 | * to the DMA mapping functions | ||
52 | */ | ||
53 | #define CELL_IOMMU_STRICT_PROTECTION | ||
54 | |||
55 | |||
56 | #define NR_IOMMUS 2 | ||
57 | |||
58 | /* IOC mmap registers */ | ||
59 | #define IOC_Reg_Size 0x2000 | ||
60 | |||
61 | #define IOC_IOPT_CacheInvd 0x908 | ||
62 | #define IOC_IOPT_CacheInvd_NE_Mask 0xffe0000000000000ul | ||
63 | #define IOC_IOPT_CacheInvd_IOPTE_Mask 0x000003fffffffff8ul | ||
64 | #define IOC_IOPT_CacheInvd_Busy 0x0000000000000001ul | ||
65 | |||
66 | #define IOC_IOST_Origin 0x918 | ||
67 | #define IOC_IOST_Origin_E 0x8000000000000000ul | ||
68 | #define IOC_IOST_Origin_HW 0x0000000000000800ul | ||
69 | #define IOC_IOST_Origin_HL 0x0000000000000400ul | ||
70 | |||
71 | #define IOC_IO_ExcpStat 0x920 | ||
72 | #define IOC_IO_ExcpStat_V 0x8000000000000000ul | ||
73 | #define IOC_IO_ExcpStat_SPF_Mask 0x6000000000000000ul | ||
74 | #define IOC_IO_ExcpStat_SPF_S 0x6000000000000000ul | ||
75 | #define IOC_IO_ExcpStat_SPF_P 0x4000000000000000ul | ||
76 | #define IOC_IO_ExcpStat_ADDR_Mask 0x00000007fffff000ul | ||
77 | #define IOC_IO_ExcpStat_RW_Mask 0x0000000000000800ul | ||
78 | #define IOC_IO_ExcpStat_IOID_Mask 0x00000000000007fful | ||
79 | |||
80 | #define IOC_IO_ExcpMask 0x928 | ||
81 | #define IOC_IO_ExcpMask_SFE 0x4000000000000000ul | ||
82 | #define IOC_IO_ExcpMask_PFE 0x2000000000000000ul | ||
83 | |||
84 | #define IOC_IOCmd_Offset 0x1000 | ||
85 | |||
86 | #define IOC_IOCmd_Cfg 0xc00 | ||
87 | #define IOC_IOCmd_Cfg_TE 0x0000800000000000ul | ||
88 | |||
89 | |||
90 | /* Segment table entries */ | ||
91 | #define IOSTE_V 0x8000000000000000ul /* valid */ | ||
92 | #define IOSTE_H 0x4000000000000000ul /* cache hint */ | ||
93 | #define IOSTE_PT_Base_RPN_Mask 0x3ffffffffffff000ul /* base RPN of IOPT */ | ||
94 | #define IOSTE_NPPT_Mask 0x0000000000000fe0ul /* no. pages in IOPT */ | ||
95 | #define IOSTE_PS_Mask 0x0000000000000007ul /* page size */ | ||
96 | #define IOSTE_PS_4K 0x0000000000000001ul /* - 4kB */ | ||
97 | #define IOSTE_PS_64K 0x0000000000000003ul /* - 64kB */ | ||
98 | #define IOSTE_PS_1M 0x0000000000000005ul /* - 1MB */ | ||
99 | #define IOSTE_PS_16M 0x0000000000000007ul /* - 16MB */ | ||
100 | |||
101 | /* Page table entries */ | ||
102 | #define IOPTE_PP_W 0x8000000000000000ul /* protection: write */ | ||
103 | #define IOPTE_PP_R 0x4000000000000000ul /* protection: read */ | ||
104 | #define IOPTE_M 0x2000000000000000ul /* coherency required */ | ||
105 | #define IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */ | ||
106 | #define IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */ | ||
107 | #define IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */ | ||
108 | #define IOPTE_H 0x0000000000000800ul /* cache hint */ | ||
109 | #define IOPTE_IOID_Mask 0x00000000000007fful /* ioid */ | ||
110 | |||
111 | |||
112 | /* IOMMU sizing */ | ||
113 | #define IO_SEGMENT_SHIFT 28 | ||
114 | #define IO_PAGENO_BITS (IO_SEGMENT_SHIFT - IOMMU_PAGE_SHIFT) | ||
115 | |||
116 | /* The high bit needs to be set on every DMA address */ | ||
117 | #define SPIDER_DMA_OFFSET 0x80000000ul | ||
118 | |||
119 | struct iommu_window { | ||
120 | struct list_head list; | ||
121 | struct cbe_iommu *iommu; | ||
122 | unsigned long offset; | ||
123 | unsigned long size; | ||
124 | unsigned long pte_offset; | ||
125 | unsigned int ioid; | ||
126 | struct iommu_table table; | ||
127 | }; | ||
63 | 128 | ||
64 | static inline ioste | 129 | #define NAMESIZE 8 |
65 | mk_ioste(unsigned long val) | 130 | struct cbe_iommu { |
66 | { | 131 | int nid; |
67 | ioste ioste = { .val = val, }; | 132 | char name[NAMESIZE]; |
68 | return ioste; | 133 | void __iomem *xlate_regs; |
69 | } | 134 | void __iomem *cmd_regs; |
135 | unsigned long *stab; | ||
136 | unsigned long *ptab; | ||
137 | void *pad_page; | ||
138 | struct list_head windows; | ||
139 | }; | ||
140 | |||
141 | /* Static array of iommus, one per node | ||
142 | * each contains a list of windows, keyed from dma_window property | ||
143 | * - on bus setup, look for a matching window, or create one | ||
144 | * - on dev setup, assign iommu_table ptr | ||
145 | */ | ||
146 | static struct cbe_iommu iommus[NR_IOMMUS]; | ||
147 | static int cbe_nr_iommus; | ||
70 | 148 | ||
71 | static inline ioste | 149 | static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte, |
72 | get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size) | 150 | long n_ptes) |
73 | { | 151 | { |
74 | unsigned long ps; | 152 | unsigned long *reg, val; |
75 | unsigned long iostep; | 153 | long n; |
76 | unsigned long nnpt; | ||
77 | unsigned long shift; | ||
78 | |||
79 | switch (page_size) { | ||
80 | case 0x1000000: | ||
81 | ps = IOST_PS_16M; | ||
82 | nnpt = 0; /* one page per segment */ | ||
83 | shift = 5; /* segment has 16 iopt entries */ | ||
84 | break; | ||
85 | |||
86 | case 0x100000: | ||
87 | ps = IOST_PS_1M; | ||
88 | nnpt = 0; /* one page per segment */ | ||
89 | shift = 1; /* segment has 256 iopt entries */ | ||
90 | break; | ||
91 | |||
92 | case 0x10000: | ||
93 | ps = IOST_PS_64K; | ||
94 | nnpt = 0x07; /* 8 pages per io page table */ | ||
95 | shift = 0; /* all entries are used */ | ||
96 | break; | ||
97 | |||
98 | case 0x1000: | ||
99 | ps = IOST_PS_4K; | ||
100 | nnpt = 0x7f; /* 128 pages per io page table */ | ||
101 | shift = 0; /* all entries are used */ | ||
102 | break; | ||
103 | |||
104 | default: /* not a known compile time constant */ | ||
105 | { | ||
106 | /* BUILD_BUG_ON() is not usable here */ | ||
107 | extern void __get_iost_entry_bad_page_size(void); | ||
108 | __get_iost_entry_bad_page_size(); | ||
109 | } | ||
110 | break; | ||
111 | } | ||
112 | 154 | ||
113 | iostep = iopt_base + | 155 | reg = iommu->xlate_regs + IOC_IOPT_CacheInvd; |
114 | /* need 8 bytes per iopte */ | ||
115 | (((io_address / page_size * 8) | ||
116 | /* align io page tables on 4k page boundaries */ | ||
117 | << shift) | ||
118 | /* nnpt+1 pages go into each iopt */ | ||
119 | & ~(nnpt << 12)); | ||
120 | |||
121 | nnpt++; /* this seems to work, but the documentation is not clear | ||
122 | about wether we put nnpt or nnpt-1 into the ioste bits. | ||
123 | In theory, this can't work for 4k pages. */ | ||
124 | return mk_ioste(IOST_VALID_MASK | ||
125 | | (iostep & IOST_PT_BASE_MASK) | ||
126 | | ((nnpt << 5) & IOST_NNPT_MASK) | ||
127 | | (ps & IOST_PS_MASK)); | ||
128 | } | ||
129 | 156 | ||
130 | /* compute the address of an io pte */ | 157 | while (n_ptes > 0) { |
131 | static inline unsigned long | 158 | /* we can invalidate up to 1 << 11 PTEs at once */ |
132 | get_ioptep(ioste iost_entry, unsigned long io_address) | 159 | n = min(n_ptes, 1l << 11); |
133 | { | 160 | val = (((n /*- 1*/) << 53) & IOC_IOPT_CacheInvd_NE_Mask) |
134 | unsigned long iopt_base; | 161 | | (__pa(pte) & IOC_IOPT_CacheInvd_IOPTE_Mask) |
135 | unsigned long page_size; | 162 | | IOC_IOPT_CacheInvd_Busy; |
136 | unsigned long page_number; | ||
137 | unsigned long iopt_offset; | ||
138 | |||
139 | iopt_base = iost_entry.val & IOST_PT_BASE_MASK; | ||
140 | page_size = iost_entry.val & IOST_PS_MASK; | ||
141 | |||
142 | /* decode page size to compute page number */ | ||
143 | page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size); | ||
144 | /* page number is an offset into the io page table */ | ||
145 | iopt_offset = (page_number << 3) & 0x7fff8ul; | ||
146 | return iopt_base + iopt_offset; | ||
147 | } | ||
148 | 163 | ||
149 | /* compute the tag field of the iopt cache entry */ | 164 | out_be64(reg, val); |
150 | static inline unsigned long | 165 | while (in_be64(reg) & IOC_IOPT_CacheInvd_Busy) |
151 | get_ioc_tag(ioste iost_entry, unsigned long io_address) | 166 | ; |
152 | { | ||
153 | unsigned long iopte = get_ioptep(iost_entry, io_address); | ||
154 | 167 | ||
155 | return IOPT_VALID_MASK | 168 | n_ptes -= n; |
156 | | ((iopte & 0x00000000000000ff8ul) >> 3) | 169 | pte += n; |
157 | | ((iopte & 0x0000003fffffc0000ul) >> 9); | 170 | } |
158 | } | 171 | } |
159 | 172 | ||
160 | /* compute the hashed 6 bit index for the 4-way associative pte cache */ | 173 | static void tce_build_cell(struct iommu_table *tbl, long index, long npages, |
161 | static inline unsigned long | 174 | unsigned long uaddr, enum dma_data_direction direction) |
162 | get_ioc_hash(ioste iost_entry, unsigned long io_address) | ||
163 | { | 175 | { |
164 | unsigned long iopte = get_ioptep(iost_entry, io_address); | 176 | int i; |
165 | 177 | unsigned long *io_pte, base_pte; | |
166 | return ((iopte & 0x000000000000001f8ul) >> 3) | 178 | struct iommu_window *window = |
167 | ^ ((iopte & 0x00000000000020000ul) >> 17) | 179 | container_of(tbl, struct iommu_window, table); |
168 | ^ ((iopte & 0x00000000000010000ul) >> 15) | 180 | |
169 | ^ ((iopte & 0x00000000000008000ul) >> 13) | 181 | /* implementing proper protection causes problems with the spidernet |
170 | ^ ((iopte & 0x00000000000004000ul) >> 11) | 182 | * driver - check mapping directions later, but allow read & write by |
171 | ^ ((iopte & 0x00000000000002000ul) >> 9) | 183 | * default for now.*/ |
172 | ^ ((iopte & 0x00000000000001000ul) >> 7); | 184 | #ifdef CELL_IOMMU_STRICT_PROTECTION |
185 | /* to avoid referencing a global, we use a trick here to setup the | ||
186 | * protection bit. "prot" is setup to be 3 fields of 4 bits apprended | ||
187 | * together for each of the 3 supported direction values. It is then | ||
188 | * shifted left so that the fields matching the desired direction | ||
189 | * lands on the appropriate bits, and other bits are masked out. | ||
190 | */ | ||
191 | const unsigned long prot = 0xc48; | ||
192 | base_pte = | ||
193 | ((prot << (52 + 4 * direction)) & (IOPTE_PP_W | IOPTE_PP_R)) | ||
194 | | IOPTE_M | IOPTE_SO_RW | (window->ioid & IOPTE_IOID_Mask); | ||
195 | #else | ||
196 | base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | | ||
197 | (window->ioid & IOPTE_IOID_Mask); | ||
198 | #endif | ||
199 | |||
200 | io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset); | ||
201 | |||
202 | for (i = 0; i < npages; i++, uaddr += IOMMU_PAGE_SIZE) | ||
203 | io_pte[i] = base_pte | (__pa(uaddr) & IOPTE_RPN_Mask); | ||
204 | |||
205 | mb(); | ||
206 | |||
207 | invalidate_tce_cache(window->iommu, io_pte, npages); | ||
208 | |||
209 | pr_debug("tce_build_cell(index=%lx,n=%lx,dir=%d,base_pte=%lx)\n", | ||
210 | index, npages, direction, base_pte); | ||
173 | } | 211 | } |
174 | 212 | ||
175 | /* same as above, but pretend that we have a simpler 1-way associative | 213 | static void tce_free_cell(struct iommu_table *tbl, long index, long npages) |
176 | pte cache with an 8 bit index */ | ||
177 | static inline unsigned long | ||
178 | get_ioc_hash_1way(ioste iost_entry, unsigned long io_address) | ||
179 | { | 214 | { |
180 | unsigned long iopte = get_ioptep(iost_entry, io_address); | ||
181 | |||
182 | return ((iopte & 0x000000000000001f8ul) >> 3) | ||
183 | ^ ((iopte & 0x00000000000020000ul) >> 17) | ||
184 | ^ ((iopte & 0x00000000000010000ul) >> 15) | ||
185 | ^ ((iopte & 0x00000000000008000ul) >> 13) | ||
186 | ^ ((iopte & 0x00000000000004000ul) >> 11) | ||
187 | ^ ((iopte & 0x00000000000002000ul) >> 9) | ||
188 | ^ ((iopte & 0x00000000000001000ul) >> 7) | ||
189 | ^ ((iopte & 0x0000000000000c000ul) >> 8); | ||
190 | } | ||
191 | 215 | ||
192 | static inline ioste | 216 | int i; |
193 | get_iost_cache(void __iomem *base, unsigned long index) | 217 | unsigned long *io_pte, pte; |
194 | { | 218 | struct iommu_window *window = |
195 | unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); | 219 | container_of(tbl, struct iommu_window, table); |
196 | return mk_ioste(in_be64(&p[index])); | ||
197 | } | ||
198 | 220 | ||
199 | static inline void | 221 | pr_debug("tce_free_cell(index=%lx,n=%lx)\n", index, npages); |
200 | set_iost_cache(void __iomem *base, unsigned long index, ioste ste) | ||
201 | { | ||
202 | unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR); | ||
203 | pr_debug("ioste %02lx was %016lx, store %016lx", index, | ||
204 | get_iost_cache(base, index).val, ste.val); | ||
205 | out_be64(&p[index], ste.val); | ||
206 | pr_debug(" now %016lx\n", get_iost_cache(base, index).val); | ||
207 | } | ||
208 | 222 | ||
209 | static inline unsigned long | 223 | #ifdef CELL_IOMMU_REAL_UNMAP |
210 | get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag) | 224 | pte = 0; |
211 | { | 225 | #else |
212 | unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR); | 226 | /* spider bridge does PCI reads after freeing - insert a mapping |
213 | unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); | 227 | * to a scratch page instead of an invalid entry */ |
228 | pte = IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW | __pa(window->iommu->pad_page) | ||
229 | | (window->ioid & IOPTE_IOID_Mask); | ||
230 | #endif | ||
214 | 231 | ||
215 | *tag = tags[index]; | 232 | io_pte = (unsigned long *)tbl->it_base + (index - window->pte_offset); |
216 | rmb(); | ||
217 | return *p; | ||
218 | } | ||
219 | 233 | ||
220 | static inline void | 234 | for (i = 0; i < npages; i++) |
221 | set_iopt_cache(void __iomem *base, unsigned long index, | 235 | io_pte[i] = pte; |
222 | unsigned long tag, unsigned long val) | 236 | |
223 | { | 237 | mb(); |
224 | unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR; | ||
225 | unsigned long __iomem *p = base + IOC_PT_CACHE_REG; | ||
226 | 238 | ||
227 | out_be64(p, val); | 239 | invalidate_tce_cache(window->iommu, io_pte, npages); |
228 | out_be64(&tags[index], tag); | ||
229 | } | 240 | } |
230 | 241 | ||
231 | static inline void | 242 | static irqreturn_t ioc_interrupt(int irq, void *data) |
232 | set_iost_origin(void __iomem *base) | ||
233 | { | 243 | { |
234 | unsigned long __iomem *p = base + IOC_ST_ORIGIN; | 244 | unsigned long stat; |
235 | unsigned long origin = IOSTO_ENABLE | IOSTO_SW; | 245 | struct cbe_iommu *iommu = data; |
236 | 246 | ||
237 | pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin); | 247 | stat = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat); |
238 | out_be64(p, origin); | 248 | |
249 | /* Might want to rate limit it */ | ||
250 | printk(KERN_ERR "iommu: DMA exception 0x%016lx\n", stat); | ||
251 | printk(KERN_ERR " V=%d, SPF=[%c%c], RW=%s, IOID=0x%04x\n", | ||
252 | !!(stat & IOC_IO_ExcpStat_V), | ||
253 | (stat & IOC_IO_ExcpStat_SPF_S) ? 'S' : ' ', | ||
254 | (stat & IOC_IO_ExcpStat_SPF_P) ? 'P' : ' ', | ||
255 | (stat & IOC_IO_ExcpStat_RW_Mask) ? "Read" : "Write", | ||
256 | (unsigned int)(stat & IOC_IO_ExcpStat_IOID_Mask)); | ||
257 | printk(KERN_ERR " page=0x%016lx\n", | ||
258 | stat & IOC_IO_ExcpStat_ADDR_Mask); | ||
259 | |||
260 | /* clear interrupt */ | ||
261 | stat &= ~IOC_IO_ExcpStat_V; | ||
262 | out_be64(iommu->xlate_regs + IOC_IO_ExcpStat, stat); | ||
263 | |||
264 | return IRQ_HANDLED; | ||
239 | } | 265 | } |
240 | 266 | ||
241 | static inline void | 267 | static int cell_iommu_find_ioc(int nid, unsigned long *base) |
242 | set_iocmd_config(void __iomem *base) | ||
243 | { | 268 | { |
244 | unsigned long __iomem *p = base + 0xc00; | 269 | struct device_node *np; |
245 | unsigned long conf; | 270 | struct resource r; |
271 | |||
272 | *base = 0; | ||
273 | |||
274 | /* First look for new style /be nodes */ | ||
275 | for_each_node_by_name(np, "ioc") { | ||
276 | if (of_node_to_nid(np) != nid) | ||
277 | continue; | ||
278 | if (of_address_to_resource(np, 0, &r)) { | ||
279 | printk(KERN_ERR "iommu: can't get address for %s\n", | ||
280 | np->full_name); | ||
281 | continue; | ||
282 | } | ||
283 | *base = r.start; | ||
284 | of_node_put(np); | ||
285 | return 0; | ||
286 | } | ||
246 | 287 | ||
247 | conf = in_be64(p); | 288 | /* Ok, let's try the old way */ |
248 | pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE); | 289 | for_each_node_by_type(np, "cpu") { |
249 | out_be64(p, conf | IOCMD_CONF_TE); | 290 | const unsigned int *nidp; |
291 | const unsigned long *tmp; | ||
292 | |||
293 | nidp = get_property(np, "node-id", NULL); | ||
294 | if (nidp && *nidp == nid) { | ||
295 | tmp = get_property(np, "ioc-translation", NULL); | ||
296 | if (tmp) { | ||
297 | *base = *tmp; | ||
298 | of_node_put(np); | ||
299 | return 0; | ||
300 | } | ||
301 | } | ||
302 | } | ||
303 | |||
304 | return -ENODEV; | ||
250 | } | 305 | } |
251 | 306 | ||
252 | static void enable_mapping(void __iomem *base, void __iomem *mmio_base) | 307 | static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long size) |
253 | { | 308 | { |
254 | set_iocmd_config(base); | 309 | struct page *page; |
255 | set_iost_origin(mmio_base); | 310 | int ret, i; |
256 | } | 311 | unsigned long reg, segments, pages_per_segment, ptab_size, n_pte_pages; |
312 | unsigned long xlate_base; | ||
313 | unsigned int virq; | ||
314 | |||
315 | if (cell_iommu_find_ioc(iommu->nid, &xlate_base)) | ||
316 | panic("%s: missing IOC register mappings for node %d\n", | ||
317 | __FUNCTION__, iommu->nid); | ||
318 | |||
319 | iommu->xlate_regs = ioremap(xlate_base, IOC_Reg_Size); | ||
320 | iommu->cmd_regs = iommu->xlate_regs + IOC_IOCmd_Offset; | ||
321 | |||
322 | segments = size >> IO_SEGMENT_SHIFT; | ||
323 | pages_per_segment = 1ull << IO_PAGENO_BITS; | ||
324 | |||
325 | pr_debug("%s: iommu[%d]: segments: %lu, pages per segment: %lu\n", | ||
326 | __FUNCTION__, iommu->nid, segments, pages_per_segment); | ||
327 | |||
328 | /* set up the segment table */ | ||
329 | page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0); | ||
330 | BUG_ON(!page); | ||
331 | iommu->stab = page_address(page); | ||
332 | clear_page(iommu->stab); | ||
333 | |||
334 | /* ... and the page tables. Since these are contiguous, we can treat | ||
335 | * the page tables as one array of ptes, like pSeries does. | ||
336 | */ | ||
337 | ptab_size = segments * pages_per_segment * sizeof(unsigned long); | ||
338 | pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __FUNCTION__, | ||
339 | iommu->nid, ptab_size, get_order(ptab_size)); | ||
340 | page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(ptab_size)); | ||
341 | BUG_ON(!page); | ||
342 | |||
343 | iommu->ptab = page_address(page); | ||
344 | memset(iommu->ptab, 0, ptab_size); | ||
345 | |||
346 | /* allocate a bogus page for the end of each mapping */ | ||
347 | page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0); | ||
348 | BUG_ON(!page); | ||
349 | iommu->pad_page = page_address(page); | ||
350 | clear_page(iommu->pad_page); | ||
351 | |||
352 | /* number of pages needed for a page table */ | ||
353 | n_pte_pages = (pages_per_segment * | ||
354 | sizeof(unsigned long)) >> IOMMU_PAGE_SHIFT; | ||
355 | |||
356 | pr_debug("%s: iommu[%d]: stab at %p, ptab at %p, n_pte_pages: %lu\n", | ||
357 | __FUNCTION__, iommu->nid, iommu->stab, iommu->ptab, | ||
358 | n_pte_pages); | ||
359 | |||
360 | /* initialise the STEs */ | ||
361 | reg = IOSTE_V | ((n_pte_pages - 1) << 5); | ||
362 | |||
363 | if (IOMMU_PAGE_SIZE == 0x1000) | ||
364 | reg |= IOSTE_PS_4K; | ||
365 | else if (IOMMU_PAGE_SIZE == 0x10000) | ||
366 | reg |= IOSTE_PS_64K; | ||
367 | else { | ||
368 | extern void __unknown_page_size_error(void); | ||
369 | __unknown_page_size_error(); | ||
370 | } | ||
371 | |||
372 | pr_debug("Setting up IOMMU stab:\n"); | ||
373 | for (i = 0; i * (1ul << IO_SEGMENT_SHIFT) < size; i++) { | ||
374 | iommu->stab[i] = reg | | ||
375 | (__pa(iommu->ptab) + n_pte_pages * IOMMU_PAGE_SIZE * i); | ||
376 | pr_debug("\t[%d] 0x%016lx\n", i, iommu->stab[i]); | ||
377 | } | ||
257 | 378 | ||
258 | static void iommu_dev_setup_null(struct pci_dev *d) { } | 379 | /* ensure that the STEs have updated */ |
259 | static void iommu_bus_setup_null(struct pci_bus *b) { } | 380 | mb(); |
260 | 381 | ||
261 | struct cell_iommu { | 382 | /* setup interrupts for the iommu. */ |
262 | unsigned long base; | 383 | reg = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat); |
263 | unsigned long mmio_base; | 384 | out_be64(iommu->xlate_regs + IOC_IO_ExcpStat, |
264 | void __iomem *mapped_base; | 385 | reg & ~IOC_IO_ExcpStat_V); |
265 | void __iomem *mapped_mmio_base; | 386 | out_be64(iommu->xlate_regs + IOC_IO_ExcpMask, |
266 | }; | 387 | IOC_IO_ExcpMask_PFE | IOC_IO_ExcpMask_SFE); |
267 | 388 | ||
268 | static struct cell_iommu cell_iommus[NR_CPUS]; | 389 | virq = irq_create_mapping(NULL, |
390 | IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT)); | ||
391 | BUG_ON(virq == NO_IRQ); | ||
269 | 392 | ||
270 | /* initialize the iommu to support a simple linear mapping | 393 | ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED, |
271 | * for each DMA window used by any device. For now, we | 394 | iommu->name, iommu); |
272 | * happen to know that there is only one DMA window in use, | 395 | BUG_ON(ret); |
273 | * starting at iopt_phys_offset. */ | ||
274 | static void cell_do_map_iommu(struct cell_iommu *iommu, | ||
275 | unsigned int ioid, | ||
276 | unsigned long map_start, | ||
277 | unsigned long map_size) | ||
278 | { | ||
279 | unsigned long io_address, real_address; | ||
280 | void __iomem *ioc_base, *ioc_mmio_base; | ||
281 | ioste ioste; | ||
282 | unsigned long index; | ||
283 | 396 | ||
284 | /* we pretend the io page table was at a very high address */ | 397 | /* set the IOC segment table origin register (and turn on the iommu) */ |
285 | const unsigned long fake_iopt = 0x10000000000ul; | 398 | reg = IOC_IOST_Origin_E | __pa(iommu->stab) | IOC_IOST_Origin_HW; |
286 | const unsigned long io_page_size = 0x1000000; /* use 16M pages */ | 399 | out_be64(iommu->xlate_regs + IOC_IOST_Origin, reg); |
287 | const unsigned long io_segment_size = 0x10000000; /* 256M */ | 400 | in_be64(iommu->xlate_regs + IOC_IOST_Origin); |
288 | 401 | ||
289 | ioc_base = iommu->mapped_base; | 402 | /* turn on IO translation */ |
290 | ioc_mmio_base = iommu->mapped_mmio_base; | 403 | reg = in_be64(iommu->cmd_regs + IOC_IOCmd_Cfg) | IOC_IOCmd_Cfg_TE; |
291 | 404 | out_be64(iommu->cmd_regs + IOC_IOCmd_Cfg, reg); | |
292 | for (real_address = 0, io_address = map_start; | ||
293 | io_address <= map_start + map_size; | ||
294 | real_address += io_page_size, io_address += io_page_size) { | ||
295 | ioste = get_iost_entry(fake_iopt, io_address, io_page_size); | ||
296 | if ((real_address % io_segment_size) == 0) /* segment start */ | ||
297 | set_iost_cache(ioc_mmio_base, | ||
298 | io_address >> 28, ioste); | ||
299 | index = get_ioc_hash_1way(ioste, io_address); | ||
300 | pr_debug("addr %08lx, index %02lx, ioste %016lx\n", | ||
301 | io_address, index, ioste.val); | ||
302 | set_iopt_cache(ioc_mmio_base, | ||
303 | get_ioc_hash_1way(ioste, io_address), | ||
304 | get_ioc_tag(ioste, io_address), | ||
305 | get_iopt_entry(real_address, ioid, IOPT_PROT_RW)); | ||
306 | } | ||
307 | } | 405 | } |
308 | 406 | ||
309 | static void iommu_devnode_setup(struct device_node *d) | 407 | #if 0/* Unused for now */ |
408 | static struct iommu_window *find_window(struct cbe_iommu *iommu, | ||
409 | unsigned long offset, unsigned long size) | ||
310 | { | 410 | { |
311 | const unsigned int *ioid; | 411 | struct iommu_window *window; |
312 | unsigned long map_start, map_size, token; | ||
313 | const unsigned long *dma_window; | ||
314 | struct cell_iommu *iommu; | ||
315 | 412 | ||
316 | ioid = get_property(d, "ioid", NULL); | 413 | /* todo: check for overlapping (but not equal) windows) */ |
317 | if (!ioid) | ||
318 | pr_debug("No ioid entry found !\n"); | ||
319 | 414 | ||
320 | dma_window = get_property(d, "ibm,dma-window", NULL); | 415 | list_for_each_entry(window, &(iommu->windows), list) { |
321 | if (!dma_window) | 416 | if (window->offset == offset && window->size == size) |
322 | pr_debug("No ibm,dma-window entry found !\n"); | 417 | return window; |
418 | } | ||
323 | 419 | ||
324 | map_start = dma_window[1]; | 420 | return NULL; |
325 | map_size = dma_window[2]; | 421 | } |
326 | token = dma_window[0] >> 32; | 422 | #endif |
327 | 423 | ||
328 | iommu = &cell_iommus[token]; | 424 | static struct iommu_window * __init |
425 | cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, | ||
426 | unsigned long offset, unsigned long size, | ||
427 | unsigned long pte_offset) | ||
428 | { | ||
429 | struct iommu_window *window; | ||
430 | const unsigned int *ioid; | ||
329 | 431 | ||
330 | cell_do_map_iommu(iommu, *ioid, map_start, map_size); | 432 | ioid = get_property(np, "ioid", NULL); |
433 | if (ioid == NULL) | ||
434 | printk(KERN_WARNING "iommu: missing ioid for %s using 0\n", | ||
435 | np->full_name); | ||
436 | |||
437 | window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid); | ||
438 | BUG_ON(window == NULL); | ||
439 | |||
440 | window->offset = offset; | ||
441 | window->size = size; | ||
442 | window->ioid = ioid ? *ioid : 0; | ||
443 | window->iommu = iommu; | ||
444 | window->pte_offset = pte_offset; | ||
445 | |||
446 | window->table.it_blocksize = 16; | ||
447 | window->table.it_base = (unsigned long)iommu->ptab; | ||
448 | window->table.it_index = iommu->nid; | ||
449 | window->table.it_offset = (offset >> IOMMU_PAGE_SHIFT) + | ||
450 | window->pte_offset; | ||
451 | window->table.it_size = size >> IOMMU_PAGE_SHIFT; | ||
452 | |||
453 | iommu_init_table(&window->table, iommu->nid); | ||
454 | |||
455 | pr_debug("\tioid %d\n", window->ioid); | ||
456 | pr_debug("\tblocksize %ld\n", window->table.it_blocksize); | ||
457 | pr_debug("\tbase 0x%016lx\n", window->table.it_base); | ||
458 | pr_debug("\toffset 0x%lx\n", window->table.it_offset); | ||
459 | pr_debug("\tsize %ld\n", window->table.it_size); | ||
460 | |||
461 | list_add(&window->list, &iommu->windows); | ||
462 | |||
463 | if (offset != 0) | ||
464 | return window; | ||
465 | |||
466 | /* We need to map and reserve the first IOMMU page since it's used | ||
467 | * by the spider workaround. In theory, we only need to do that when | ||
468 | * running on spider but it doesn't really matter. | ||
469 | * | ||
470 | * This code also assumes that we have a window that starts at 0, | ||
471 | * which is the case on all spider based blades. | ||
472 | */ | ||
473 | __set_bit(0, window->table.it_map); | ||
474 | tce_build_cell(&window->table, window->table.it_offset, 1, | ||
475 | (unsigned long)iommu->pad_page, DMA_TO_DEVICE); | ||
476 | window->table.it_hint = window->table.it_blocksize; | ||
477 | |||
478 | return window; | ||
331 | } | 479 | } |
332 | 480 | ||
333 | static void iommu_bus_setup(struct pci_bus *b) | 481 | static struct cbe_iommu *cell_iommu_for_node(int nid) |
334 | { | 482 | { |
335 | struct device_node *d = (struct device_node *)b->sysdata; | 483 | int i; |
336 | iommu_devnode_setup(d); | ||
337 | } | ||
338 | 484 | ||
485 | for (i = 0; i < cbe_nr_iommus; i++) | ||
486 | if (iommus[i].nid == nid) | ||
487 | return &iommus[i]; | ||
488 | return NULL; | ||
489 | } | ||
339 | 490 | ||
340 | static int cell_map_iommu_hardcoded(int num_nodes) | 491 | static void cell_dma_dev_setup(struct device *dev) |
341 | { | 492 | { |
342 | struct cell_iommu *iommu = NULL; | 493 | struct iommu_window *window; |
343 | 494 | struct cbe_iommu *iommu; | |
344 | pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); | 495 | struct dev_archdata *archdata = &dev->archdata; |
496 | |||
497 | /* If we run without iommu, no need to do anything */ | ||
498 | if (pci_dma_ops == &dma_direct_ops) | ||
499 | return; | ||
500 | |||
501 | /* Current implementation uses the first window available in that | ||
502 | * node's iommu. We -might- do something smarter later though it may | ||
503 | * never be necessary | ||
504 | */ | ||
505 | iommu = cell_iommu_for_node(archdata->numa_node); | ||
506 | if (iommu == NULL || list_empty(&iommu->windows)) { | ||
507 | printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", | ||
508 | archdata->of_node ? archdata->of_node->full_name : "?", | ||
509 | archdata->numa_node); | ||
510 | return; | ||
511 | } | ||
512 | window = list_entry(iommu->windows.next, struct iommu_window, list); | ||
345 | 513 | ||
346 | /* node 0 */ | 514 | archdata->dma_data = &window->table; |
347 | iommu = &cell_iommus[0]; | 515 | } |
348 | iommu->mapped_base = ioremap(0x20000511000ul, 0x1000); | ||
349 | iommu->mapped_mmio_base = ioremap(0x20000510000ul, 0x1000); | ||
350 | 516 | ||
351 | enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); | 517 | static void cell_pci_dma_dev_setup(struct pci_dev *dev) |
518 | { | ||
519 | cell_dma_dev_setup(&dev->dev); | ||
520 | } | ||
352 | 521 | ||
353 | cell_do_map_iommu(iommu, 0x048a, | 522 | static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action, |
354 | 0x20000000ul,0x20000000ul); | 523 | void *data) |
524 | { | ||
525 | struct device *dev = data; | ||
355 | 526 | ||
356 | if (num_nodes < 2) | 527 | /* We are only intereted in device addition */ |
528 | if (action != BUS_NOTIFY_ADD_DEVICE) | ||
357 | return 0; | 529 | return 0; |
358 | 530 | ||
359 | /* node 1 */ | 531 | /* We use the PCI DMA ops */ |
360 | iommu = &cell_iommus[1]; | 532 | dev->archdata.dma_ops = pci_dma_ops; |
361 | iommu->mapped_base = ioremap(0x30000511000ul, 0x1000); | ||
362 | iommu->mapped_mmio_base = ioremap(0x30000510000ul, 0x1000); | ||
363 | |||
364 | enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); | ||
365 | 533 | ||
366 | cell_do_map_iommu(iommu, 0x048a, | 534 | cell_dma_dev_setup(dev); |
367 | 0x20000000,0x20000000ul); | ||
368 | 535 | ||
369 | return 0; | 536 | return 0; |
370 | } | 537 | } |
371 | 538 | ||
539 | static struct notifier_block cell_of_bus_notifier = { | ||
540 | .notifier_call = cell_of_bus_notify | ||
541 | }; | ||
372 | 542 | ||
373 | static int cell_map_iommu(void) | 543 | static int __init cell_iommu_get_window(struct device_node *np, |
544 | unsigned long *base, | ||
545 | unsigned long *size) | ||
374 | { | 546 | { |
375 | unsigned int num_nodes = 0; | 547 | const void *dma_window; |
376 | const unsigned int *node_id; | 548 | unsigned long index; |
377 | const unsigned long *base, *mmio_base; | ||
378 | struct device_node *dn; | ||
379 | struct cell_iommu *iommu = NULL; | ||
380 | |||
381 | /* determine number of nodes (=iommus) */ | ||
382 | pr_debug("%s(%d): determining number of nodes...", __FUNCTION__, __LINE__); | ||
383 | for(dn = of_find_node_by_type(NULL, "cpu"); | ||
384 | dn; | ||
385 | dn = of_find_node_by_type(dn, "cpu")) { | ||
386 | node_id = get_property(dn, "node-id", NULL); | ||
387 | |||
388 | if (num_nodes < *node_id) | ||
389 | num_nodes = *node_id; | ||
390 | } | ||
391 | |||
392 | num_nodes++; | ||
393 | pr_debug("%i found.\n", num_nodes); | ||
394 | 549 | ||
395 | /* map the iommu registers for each node */ | 550 | /* Use ibm,dma-window if available, else, hard code ! */ |
396 | pr_debug("%s(%d): Looping through nodes\n", __FUNCTION__, __LINE__); | 551 | dma_window = get_property(np, "ibm,dma-window", NULL); |
397 | for(dn = of_find_node_by_type(NULL, "cpu"); | 552 | if (dma_window == NULL) { |
398 | dn; | 553 | *base = 0; |
399 | dn = of_find_node_by_type(dn, "cpu")) { | 554 | *size = 0x80000000u; |
555 | return -ENODEV; | ||
556 | } | ||
400 | 557 | ||
401 | node_id = get_property(dn, "node-id", NULL); | 558 | of_parse_dma_window(np, dma_window, &index, base, size); |
402 | base = get_property(dn, "ioc-cache", NULL); | 559 | return 0; |
403 | mmio_base = get_property(dn, "ioc-translation", NULL); | 560 | } |
404 | 561 | ||
405 | if (!base || !mmio_base || !node_id) | 562 | static void __init cell_iommu_init_one(struct device_node *np, unsigned long offset) |
406 | return cell_map_iommu_hardcoded(num_nodes); | 563 | { |
564 | struct cbe_iommu *iommu; | ||
565 | unsigned long base, size; | ||
566 | int nid, i; | ||
567 | |||
568 | /* Get node ID */ | ||
569 | nid = of_node_to_nid(np); | ||
570 | if (nid < 0) { | ||
571 | printk(KERN_ERR "iommu: failed to get node for %s\n", | ||
572 | np->full_name); | ||
573 | return; | ||
574 | } | ||
575 | pr_debug("iommu: setting up iommu for node %d (%s)\n", | ||
576 | nid, np->full_name); | ||
577 | |||
578 | /* XXX todo: If we can have multiple windows on the same IOMMU, which | ||
579 | * isn't the case today, we probably want here to check wether the | ||
580 | * iommu for that node is already setup. | ||
581 | * However, there might be issue with getting the size right so let's | ||
582 | * ignore that for now. We might want to completely get rid of the | ||
583 | * multiple window support since the cell iommu supports per-page ioids | ||
584 | */ | ||
585 | |||
586 | if (cbe_nr_iommus >= NR_IOMMUS) { | ||
587 | printk(KERN_ERR "iommu: too many IOMMUs detected ! (%s)\n", | ||
588 | np->full_name); | ||
589 | return; | ||
590 | } | ||
407 | 591 | ||
408 | iommu = &cell_iommus[*node_id]; | 592 | /* Init base fields */ |
409 | iommu->base = *base; | 593 | i = cbe_nr_iommus++; |
410 | iommu->mmio_base = *mmio_base; | 594 | iommu = &iommus[i]; |
595 | iommu->stab = 0; | ||
596 | iommu->nid = nid; | ||
597 | snprintf(iommu->name, sizeof(iommu->name), "iommu%d", i); | ||
598 | INIT_LIST_HEAD(&iommu->windows); | ||
411 | 599 | ||
412 | iommu->mapped_base = ioremap(*base, 0x1000); | 600 | /* Obtain a window for it */ |
413 | iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000); | 601 | cell_iommu_get_window(np, &base, &size); |
414 | 602 | ||
415 | enable_mapping(iommu->mapped_base, | 603 | pr_debug("\ttranslating window 0x%lx...0x%lx\n", |
416 | iommu->mapped_mmio_base); | 604 | base, base + size - 1); |
417 | 605 | ||
418 | /* everything else will be done in iommu_bus_setup */ | 606 | /* Initialize the hardware */ |
419 | } | 607 | cell_iommu_setup_hardware(iommu, size); |
420 | 608 | ||
421 | return 1; | 609 | /* Setup the iommu_table */ |
610 | cell_iommu_setup_window(iommu, np, base, size, | ||
611 | offset >> IOMMU_PAGE_SHIFT); | ||
422 | } | 612 | } |
423 | 613 | ||
424 | static void *cell_alloc_coherent(struct device *hwdev, size_t size, | 614 | static void __init cell_disable_iommus(void) |
425 | dma_addr_t *dma_handle, gfp_t flag) | ||
426 | { | 615 | { |
427 | void *ret; | 616 | int node; |
428 | 617 | unsigned long base, val; | |
429 | ret = (void *)__get_free_pages(flag, get_order(size)); | 618 | void __iomem *xregs, *cregs; |
430 | if (ret != NULL) { | 619 | |
431 | memset(ret, 0, size); | 620 | /* Make sure IOC translation is disabled on all nodes */ |
432 | *dma_handle = virt_to_abs(ret) | CELL_DMA_VALID; | 621 | for_each_online_node(node) { |
622 | if (cell_iommu_find_ioc(node, &base)) | ||
623 | continue; | ||
624 | xregs = ioremap(base, IOC_Reg_Size); | ||
625 | if (xregs == NULL) | ||
626 | continue; | ||
627 | cregs = xregs + IOC_IOCmd_Offset; | ||
628 | |||
629 | pr_debug("iommu: cleaning up iommu on node %d\n", node); | ||
630 | |||
631 | out_be64(xregs + IOC_IOST_Origin, 0); | ||
632 | (void)in_be64(xregs + IOC_IOST_Origin); | ||
633 | val = in_be64(cregs + IOC_IOCmd_Cfg); | ||
634 | val &= ~IOC_IOCmd_Cfg_TE; | ||
635 | out_be64(cregs + IOC_IOCmd_Cfg, val); | ||
636 | (void)in_be64(cregs + IOC_IOCmd_Cfg); | ||
637 | |||
638 | iounmap(xregs); | ||
433 | } | 639 | } |
434 | return ret; | ||
435 | } | 640 | } |
436 | 641 | ||
437 | static void cell_free_coherent(struct device *hwdev, size_t size, | 642 | static int __init cell_iommu_init_disabled(void) |
438 | void *vaddr, dma_addr_t dma_handle) | ||
439 | { | 643 | { |
440 | free_pages((unsigned long)vaddr, get_order(size)); | 644 | struct device_node *np = NULL; |
441 | } | 645 | unsigned long base = 0, size; |
646 | |||
647 | /* When no iommu is present, we use direct DMA ops */ | ||
648 | pci_dma_ops = &dma_direct_ops; | ||
649 | |||
650 | /* First make sure all IOC translation is turned off */ | ||
651 | cell_disable_iommus(); | ||
652 | |||
653 | /* If we have no Axon, we set up the spider DMA magic offset */ | ||
654 | if (of_find_node_by_name(NULL, "axon") == NULL) | ||
655 | dma_direct_offset = SPIDER_DMA_OFFSET; | ||
656 | |||
657 | /* Now we need to check to see where the memory is mapped | ||
658 | * in PCI space. We assume that all busses use the same dma | ||
659 | * window which is always the case so far on Cell, thus we | ||
660 | * pick up the first pci-internal node we can find and check | ||
661 | * the DMA window from there. | ||
662 | */ | ||
663 | for_each_node_by_name(np, "axon") { | ||
664 | if (np->parent == NULL || np->parent->parent != NULL) | ||
665 | continue; | ||
666 | if (cell_iommu_get_window(np, &base, &size) == 0) | ||
667 | break; | ||
668 | } | ||
669 | if (np == NULL) { | ||
670 | for_each_node_by_name(np, "pci-internal") { | ||
671 | if (np->parent == NULL || np->parent->parent != NULL) | ||
672 | continue; | ||
673 | if (cell_iommu_get_window(np, &base, &size) == 0) | ||
674 | break; | ||
675 | } | ||
676 | } | ||
677 | of_node_put(np); | ||
678 | |||
679 | /* If we found a DMA window, we check if it's big enough to enclose | ||
680 | * all of physical memory. If not, we force enable IOMMU | ||
681 | */ | ||
682 | if (np && size < lmb_end_of_DRAM()) { | ||
683 | printk(KERN_WARNING "iommu: force-enabled, dma window" | ||
684 | " (%ldMB) smaller than total memory (%ldMB)\n", | ||
685 | size >> 20, lmb_end_of_DRAM() >> 20); | ||
686 | return -ENODEV; | ||
687 | } | ||
442 | 688 | ||
443 | static dma_addr_t cell_map_single(struct device *hwdev, void *ptr, | 689 | dma_direct_offset += base; |
444 | size_t size, enum dma_data_direction direction) | ||
445 | { | ||
446 | return virt_to_abs(ptr) | CELL_DMA_VALID; | ||
447 | } | ||
448 | 690 | ||
449 | static void cell_unmap_single(struct device *hwdev, dma_addr_t dma_addr, | 691 | printk("iommu: disabled, direct DMA offset is 0x%lx\n", |
450 | size_t size, enum dma_data_direction direction) | 692 | dma_direct_offset); |
451 | { | 693 | |
694 | return 0; | ||
452 | } | 695 | } |
453 | 696 | ||
454 | static int cell_map_sg(struct device *hwdev, struct scatterlist *sg, | 697 | static int __init cell_iommu_init(void) |
455 | int nents, enum dma_data_direction direction) | ||
456 | { | 698 | { |
457 | int i; | 699 | struct device_node *np; |
700 | |||
701 | if (!machine_is(cell)) | ||
702 | return -ENODEV; | ||
703 | |||
704 | /* If IOMMU is disabled or we have little enough RAM to not need | ||
705 | * to enable it, we setup a direct mapping. | ||
706 | * | ||
707 | * Note: should we make sure we have the IOMMU actually disabled ? | ||
708 | */ | ||
709 | if (iommu_is_off || | ||
710 | (!iommu_force_on && lmb_end_of_DRAM() <= 0x80000000ull)) | ||
711 | if (cell_iommu_init_disabled() == 0) | ||
712 | goto bail; | ||
713 | |||
714 | /* Setup various ppc_md. callbacks */ | ||
715 | ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup; | ||
716 | ppc_md.tce_build = tce_build_cell; | ||
717 | ppc_md.tce_free = tce_free_cell; | ||
718 | |||
719 | /* Create an iommu for each /axon node. */ | ||
720 | for_each_node_by_name(np, "axon") { | ||
721 | if (np->parent == NULL || np->parent->parent != NULL) | ||
722 | continue; | ||
723 | cell_iommu_init_one(np, 0); | ||
724 | } | ||
458 | 725 | ||
459 | for (i = 0; i < nents; i++, sg++) { | 726 | /* Create an iommu for each toplevel /pci-internal node for |
460 | sg->dma_address = (page_to_phys(sg->page) + sg->offset) | 727 | * old hardware/firmware |
461 | | CELL_DMA_VALID; | 728 | */ |
462 | sg->dma_length = sg->length; | 729 | for_each_node_by_name(np, "pci-internal") { |
730 | if (np->parent == NULL || np->parent->parent != NULL) | ||
731 | continue; | ||
732 | cell_iommu_init_one(np, SPIDER_DMA_OFFSET); | ||
463 | } | 733 | } |
464 | 734 | ||
465 | return nents; | 735 | /* Setup default PCI iommu ops */ |
466 | } | 736 | pci_dma_ops = &dma_iommu_ops; |
467 | 737 | ||
468 | static void cell_unmap_sg(struct device *hwdev, struct scatterlist *sg, | 738 | bail: |
469 | int nents, enum dma_data_direction direction) | 739 | /* Register callbacks on OF platform device addition/removal |
470 | { | 740 | * to handle linking them to the right DMA operations |
471 | } | 741 | */ |
742 | bus_register_notifier(&of_platform_bus_type, &cell_of_bus_notifier); | ||
472 | 743 | ||
473 | static int cell_dma_supported(struct device *dev, u64 mask) | 744 | return 0; |
474 | { | ||
475 | return mask < 0x100000000ull; | ||
476 | } | 745 | } |
746 | arch_initcall(cell_iommu_init); | ||
477 | 747 | ||
478 | static struct dma_mapping_ops cell_iommu_ops = { | ||
479 | .alloc_coherent = cell_alloc_coherent, | ||
480 | .free_coherent = cell_free_coherent, | ||
481 | .map_single = cell_map_single, | ||
482 | .unmap_single = cell_unmap_single, | ||
483 | .map_sg = cell_map_sg, | ||
484 | .unmap_sg = cell_unmap_sg, | ||
485 | .dma_supported = cell_dma_supported, | ||
486 | }; | ||
487 | |||
488 | void cell_init_iommu(void) | ||
489 | { | ||
490 | int setup_bus = 0; | ||
491 | |||
492 | if (of_find_node_by_path("/mambo")) { | ||
493 | pr_info("Not using iommu on systemsim\n"); | ||
494 | } else { | ||
495 | |||
496 | if (!(of_chosen && | ||
497 | get_property(of_chosen, "linux,iommu-off", NULL))) | ||
498 | setup_bus = cell_map_iommu(); | ||
499 | |||
500 | if (setup_bus) { | ||
501 | pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__); | ||
502 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | ||
503 | ppc_md.iommu_bus_setup = iommu_bus_setup; | ||
504 | } else { | ||
505 | pr_debug("%s: IOMMU mapping activated, " | ||
506 | "no device action necessary\n", __FUNCTION__); | ||
507 | /* Direct I/O, IOMMU off */ | ||
508 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | ||
509 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | pci_dma_ops = cell_iommu_ops; | ||
514 | } | ||
diff --git a/arch/powerpc/platforms/cell/iommu.h b/arch/powerpc/platforms/cell/iommu.h deleted file mode 100644 index 490d77abfe8..00000000000 --- a/arch/powerpc/platforms/cell/iommu.h +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | #ifndef CELL_IOMMU_H | ||
2 | #define CELL_IOMMU_H | ||
3 | |||
4 | /* some constants */ | ||
5 | enum { | ||
6 | /* segment table entries */ | ||
7 | IOST_VALID_MASK = 0x8000000000000000ul, | ||
8 | IOST_TAG_MASK = 0x3000000000000000ul, | ||
9 | IOST_PT_BASE_MASK = 0x000003fffffff000ul, | ||
10 | IOST_NNPT_MASK = 0x0000000000000fe0ul, | ||
11 | IOST_PS_MASK = 0x000000000000000ful, | ||
12 | |||
13 | IOST_PS_4K = 0x1, | ||
14 | IOST_PS_64K = 0x3, | ||
15 | IOST_PS_1M = 0x5, | ||
16 | IOST_PS_16M = 0x7, | ||
17 | |||
18 | /* iopt tag register */ | ||
19 | IOPT_VALID_MASK = 0x0000000200000000ul, | ||
20 | IOPT_TAG_MASK = 0x00000001fffffffful, | ||
21 | |||
22 | /* iopt cache register */ | ||
23 | IOPT_PROT_MASK = 0xc000000000000000ul, | ||
24 | IOPT_PROT_NONE = 0x0000000000000000ul, | ||
25 | IOPT_PROT_READ = 0x4000000000000000ul, | ||
26 | IOPT_PROT_WRITE = 0x8000000000000000ul, | ||
27 | IOPT_PROT_RW = 0xc000000000000000ul, | ||
28 | IOPT_COHERENT = 0x2000000000000000ul, | ||
29 | |||
30 | IOPT_ORDER_MASK = 0x1800000000000000ul, | ||
31 | /* order access to same IOID/VC on same address */ | ||
32 | IOPT_ORDER_ADDR = 0x0800000000000000ul, | ||
33 | /* similar, but only after a write access */ | ||
34 | IOPT_ORDER_WRITES = 0x1000000000000000ul, | ||
35 | /* Order all accesses to same IOID/VC */ | ||
36 | IOPT_ORDER_VC = 0x1800000000000000ul, | ||
37 | |||
38 | IOPT_RPN_MASK = 0x000003fffffff000ul, | ||
39 | IOPT_HINT_MASK = 0x0000000000000800ul, | ||
40 | IOPT_IOID_MASK = 0x00000000000007fful, | ||
41 | |||
42 | IOSTO_ENABLE = 0x8000000000000000ul, | ||
43 | IOSTO_ORIGIN = 0x000003fffffff000ul, | ||
44 | IOSTO_HW = 0x0000000000000800ul, | ||
45 | IOSTO_SW = 0x0000000000000400ul, | ||
46 | |||
47 | IOCMD_CONF_TE = 0x0000800000000000ul, | ||
48 | |||
49 | /* memory mapped registers */ | ||
50 | IOC_PT_CACHE_DIR = 0x000, | ||
51 | IOC_ST_CACHE_DIR = 0x800, | ||
52 | IOC_PT_CACHE_REG = 0x910, | ||
53 | IOC_ST_ORIGIN = 0x918, | ||
54 | IOC_CONF = 0x930, | ||
55 | |||
56 | /* The high bit needs to be set on every DMA address, | ||
57 | only 2GB are addressable */ | ||
58 | CELL_DMA_VALID = 0x80000000, | ||
59 | CELL_DMA_MASK = 0x7fffffff, | ||
60 | }; | ||
61 | |||
62 | |||
63 | void cell_init_iommu(void); | ||
64 | |||
65 | #endif | ||
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 9f2e4ed20a5..8c20f0fb865 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c | |||
@@ -38,32 +38,25 @@ | |||
38 | #include "pervasive.h" | 38 | #include "pervasive.h" |
39 | #include "cbe_regs.h" | 39 | #include "cbe_regs.h" |
40 | 40 | ||
41 | static DEFINE_SPINLOCK(cbe_pervasive_lock); | 41 | static void cbe_power_save(void) |
42 | |||
43 | static void __init cbe_enable_pause_zero(void) | ||
44 | { | 42 | { |
45 | unsigned long thread_switch_control; | 43 | unsigned long ctrl, thread_switch_control; |
46 | unsigned long temp_register; | ||
47 | struct cbe_pmd_regs __iomem *pregs; | ||
48 | |||
49 | spin_lock_irq(&cbe_pervasive_lock); | ||
50 | pregs = cbe_get_cpu_pmd_regs(smp_processor_id()); | ||
51 | if (pregs == NULL) | ||
52 | goto out; | ||
53 | 44 | ||
54 | pr_debug("Power Management: CPU %d\n", smp_processor_id()); | 45 | /* |
55 | 46 | * We need to hard disable interrupts, but we also need to mark them | |
56 | /* Enable Pause(0) control bit */ | 47 | * hard disabled in the PACA so that the local_irq_enable() done by |
57 | temp_register = in_be64(&pregs->pm_control); | 48 | * our caller upon return propertly hard enables. |
49 | */ | ||
50 | hard_irq_disable(); | ||
51 | get_paca()->hard_enabled = 0; | ||
58 | 52 | ||
59 | out_be64(&pregs->pm_control, | 53 | ctrl = mfspr(SPRN_CTRLF); |
60 | temp_register | CBE_PMD_PAUSE_ZERO_CONTROL); | ||
61 | 54 | ||
62 | /* Enable DEC and EE interrupt request */ | 55 | /* Enable DEC and EE interrupt request */ |
63 | thread_switch_control = mfspr(SPRN_TSC_CELL); | 56 | thread_switch_control = mfspr(SPRN_TSC_CELL); |
64 | thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; | 57 | thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; |
65 | 58 | ||
66 | switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) { | 59 | switch (ctrl & CTRL_CT) { |
67 | case CTRL_CT0: | 60 | case CTRL_CT0: |
68 | thread_switch_control |= TSC_CELL_DEC_ENABLE_0; | 61 | thread_switch_control |= TSC_CELL_DEC_ENABLE_0; |
69 | break; | 62 | break; |
@@ -75,58 +68,21 @@ static void __init cbe_enable_pause_zero(void) | |||
75 | __FUNCTION__); | 68 | __FUNCTION__); |
76 | break; | 69 | break; |
77 | } | 70 | } |
78 | |||
79 | mtspr(SPRN_TSC_CELL, thread_switch_control); | 71 | mtspr(SPRN_TSC_CELL, thread_switch_control); |
80 | 72 | ||
81 | out: | 73 | /* |
82 | spin_unlock_irq(&cbe_pervasive_lock); | 74 | * go into low thread priority, medium priority will be |
83 | } | 75 | * restored for us after wake-up. |
84 | 76 | */ | |
85 | static void cbe_idle(void) | 77 | HMT_low(); |
86 | { | ||
87 | unsigned long ctrl; | ||
88 | 78 | ||
89 | /* Why do we do that on every idle ? Couldn't that be done once for | 79 | /* |
90 | * all or do we lose the state some way ? Also, the pm_control | 80 | * atomically disable thread execution and runlatch. |
91 | * register setting, that can't be set once at boot ? We really want | 81 | * External and Decrementer exceptions are still handled when the |
92 | * to move that away in order to implement a simple powersave | 82 | * thread is disabled but now enter in cbe_system_reset_exception() |
93 | */ | 83 | */ |
94 | cbe_enable_pause_zero(); | 84 | ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); |
95 | 85 | mtspr(SPRN_CTRLT, ctrl); | |
96 | while (1) { | ||
97 | if (!need_resched()) { | ||
98 | local_irq_disable(); | ||
99 | while (!need_resched()) { | ||
100 | /* go into low thread priority */ | ||
101 | HMT_low(); | ||
102 | |||
103 | /* | ||
104 | * atomically disable thread execution | ||
105 | * and runlatch. | ||
106 | * External and Decrementer exceptions | ||
107 | * are still handled when the thread | ||
108 | * is disabled but now enter in | ||
109 | * cbe_system_reset_exception() | ||
110 | */ | ||
111 | ctrl = mfspr(SPRN_CTRLF); | ||
112 | ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); | ||
113 | mtspr(SPRN_CTRLT, ctrl); | ||
114 | } | ||
115 | /* restore thread prio */ | ||
116 | HMT_medium(); | ||
117 | local_irq_enable(); | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * turn runlatch on again before scheduling the | ||
122 | * process we just woke up | ||
123 | */ | ||
124 | ppc64_runlatch_on(); | ||
125 | |||
126 | preempt_enable_no_resched(); | ||
127 | schedule(); | ||
128 | preempt_disable(); | ||
129 | } | ||
130 | } | 86 | } |
131 | 87 | ||
132 | static int cbe_system_reset_exception(struct pt_regs *regs) | 88 | static int cbe_system_reset_exception(struct pt_regs *regs) |
@@ -158,9 +114,20 @@ static int cbe_system_reset_exception(struct pt_regs *regs) | |||
158 | 114 | ||
159 | void __init cbe_pervasive_init(void) | 115 | void __init cbe_pervasive_init(void) |
160 | { | 116 | { |
117 | int cpu; | ||
161 | if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) | 118 | if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) |
162 | return; | 119 | return; |
163 | 120 | ||
164 | ppc_md.idle_loop = cbe_idle; | 121 | for_each_possible_cpu(cpu) { |
122 | struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); | ||
123 | if (!regs) | ||
124 | continue; | ||
125 | |||
126 | /* Enable Pause(0) control bit */ | ||
127 | out_be64(®s->pmcr, in_be64(®s->pmcr) | | ||
128 | CBE_PMD_PAUSE_ZERO_CONTROL); | ||
129 | } | ||
130 | |||
131 | ppc_md.power_save = cbe_power_save; | ||
165 | ppc_md.system_reset_exception = cbe_system_reset_exception; | 132 | ppc_md.system_reset_exception = cbe_system_reset_exception; |
166 | } | 133 | } |
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c new file mode 100644 index 00000000000..99c612025e8 --- /dev/null +++ b/arch/powerpc/platforms/cell/pmu.c | |||
@@ -0,0 +1,429 @@ | |||
1 | /* | ||
2 | * Cell Broadband Engine Performance Monitor | ||
3 | * | ||
4 | * (C) Copyright IBM Corporation 2001,2006 | ||
5 | * | ||
6 | * Author: | ||
7 | * David Erb (djerb@us.ibm.com) | ||
8 | * Kevin Corry (kevcorry@us.ibm.com) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2, or (at your option) | ||
13 | * any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/irq_regs.h> | ||
29 | #include <asm/machdep.h> | ||
30 | #include <asm/pmc.h> | ||
31 | #include <asm/reg.h> | ||
32 | #include <asm/spu.h> | ||
33 | |||
34 | #include "cbe_regs.h" | ||
35 | #include "interrupt.h" | ||
36 | |||
37 | /* | ||
38 | * When writing to write-only mmio addresses, save a shadow copy. All of the | ||
39 | * registers are 32-bit, but stored in the upper-half of a 64-bit field in | ||
40 | * pmd_regs. | ||
41 | */ | ||
42 | |||
43 | #define WRITE_WO_MMIO(reg, x) \ | ||
44 | do { \ | ||
45 | u32 _x = (x); \ | ||
46 | struct cbe_pmd_regs __iomem *pmd_regs; \ | ||
47 | struct cbe_pmd_shadow_regs *shadow_regs; \ | ||
48 | pmd_regs = cbe_get_cpu_pmd_regs(cpu); \ | ||
49 | shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \ | ||
50 | out_be64(&(pmd_regs->reg), (((u64)_x) << 32)); \ | ||
51 | shadow_regs->reg = _x; \ | ||
52 | } while (0) | ||
53 | |||
54 | #define READ_SHADOW_REG(val, reg) \ | ||
55 | do { \ | ||
56 | struct cbe_pmd_shadow_regs *shadow_regs; \ | ||
57 | shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); \ | ||
58 | (val) = shadow_regs->reg; \ | ||
59 | } while (0) | ||
60 | |||
61 | #define READ_MMIO_UPPER32(val, reg) \ | ||
62 | do { \ | ||
63 | struct cbe_pmd_regs __iomem *pmd_regs; \ | ||
64 | pmd_regs = cbe_get_cpu_pmd_regs(cpu); \ | ||
65 | (val) = (u32)(in_be64(&pmd_regs->reg) >> 32); \ | ||
66 | } while (0) | ||
67 | |||
68 | /* | ||
69 | * Physical counter registers. | ||
70 | * Each physical counter can act as one 32-bit counter or two 16-bit counters. | ||
71 | */ | ||
72 | |||
73 | u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr) | ||
74 | { | ||
75 | u32 val_in_latch, val = 0; | ||
76 | |||
77 | if (phys_ctr < NR_PHYS_CTRS) { | ||
78 | READ_SHADOW_REG(val_in_latch, counter_value_in_latch); | ||
79 | |||
80 | /* Read the latch or the actual counter, whichever is newer. */ | ||
81 | if (val_in_latch & (1 << phys_ctr)) { | ||
82 | READ_SHADOW_REG(val, pm_ctr[phys_ctr]); | ||
83 | } else { | ||
84 | READ_MMIO_UPPER32(val, pm_ctr[phys_ctr]); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | return val; | ||
89 | } | ||
90 | EXPORT_SYMBOL_GPL(cbe_read_phys_ctr); | ||
91 | |||
92 | void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val) | ||
93 | { | ||
94 | struct cbe_pmd_shadow_regs *shadow_regs; | ||
95 | u32 pm_ctrl; | ||
96 | |||
97 | if (phys_ctr < NR_PHYS_CTRS) { | ||
98 | /* Writing to a counter only writes to a hardware latch. | ||
99 | * The new value is not propagated to the actual counter | ||
100 | * until the performance monitor is enabled. | ||
101 | */ | ||
102 | WRITE_WO_MMIO(pm_ctr[phys_ctr], val); | ||
103 | |||
104 | pm_ctrl = cbe_read_pm(cpu, pm_control); | ||
105 | if (pm_ctrl & CBE_PM_ENABLE_PERF_MON) { | ||
106 | /* The counters are already active, so we need to | ||
107 | * rewrite the pm_control register to "re-enable" | ||
108 | * the PMU. | ||
109 | */ | ||
110 | cbe_write_pm(cpu, pm_control, pm_ctrl); | ||
111 | } else { | ||
112 | shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); | ||
113 | shadow_regs->counter_value_in_latch |= (1 << phys_ctr); | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(cbe_write_phys_ctr); | ||
118 | |||
119 | /* | ||
120 | * "Logical" counter registers. | ||
121 | * These will read/write 16-bits or 32-bits depending on the | ||
122 | * current size of the counter. Counters 4 - 7 are always 16-bit. | ||
123 | */ | ||
124 | |||
125 | u32 cbe_read_ctr(u32 cpu, u32 ctr) | ||
126 | { | ||
127 | u32 val; | ||
128 | u32 phys_ctr = ctr & (NR_PHYS_CTRS - 1); | ||
129 | |||
130 | val = cbe_read_phys_ctr(cpu, phys_ctr); | ||
131 | |||
132 | if (cbe_get_ctr_size(cpu, phys_ctr) == 16) | ||
133 | val = (ctr < NR_PHYS_CTRS) ? (val >> 16) : (val & 0xffff); | ||
134 | |||
135 | return val; | ||
136 | } | ||
137 | EXPORT_SYMBOL_GPL(cbe_read_ctr); | ||
138 | |||
139 | void cbe_write_ctr(u32 cpu, u32 ctr, u32 val) | ||
140 | { | ||
141 | u32 phys_ctr; | ||
142 | u32 phys_val; | ||
143 | |||
144 | phys_ctr = ctr & (NR_PHYS_CTRS - 1); | ||
145 | |||
146 | if (cbe_get_ctr_size(cpu, phys_ctr) == 16) { | ||
147 | phys_val = cbe_read_phys_ctr(cpu, phys_ctr); | ||
148 | |||
149 | if (ctr < NR_PHYS_CTRS) | ||
150 | val = (val << 16) | (phys_val & 0xffff); | ||
151 | else | ||
152 | val = (val & 0xffff) | (phys_val & 0xffff0000); | ||
153 | } | ||
154 | |||
155 | cbe_write_phys_ctr(cpu, phys_ctr, val); | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(cbe_write_ctr); | ||
158 | |||
159 | /* | ||
160 | * Counter-control registers. | ||
161 | * Each "logical" counter has a corresponding control register. | ||
162 | */ | ||
163 | |||
164 | u32 cbe_read_pm07_control(u32 cpu, u32 ctr) | ||
165 | { | ||
166 | u32 pm07_control = 0; | ||
167 | |||
168 | if (ctr < NR_CTRS) | ||
169 | READ_SHADOW_REG(pm07_control, pm07_control[ctr]); | ||
170 | |||
171 | return pm07_control; | ||
172 | } | ||
173 | EXPORT_SYMBOL_GPL(cbe_read_pm07_control); | ||
174 | |||
175 | void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val) | ||
176 | { | ||
177 | if (ctr < NR_CTRS) | ||
178 | WRITE_WO_MMIO(pm07_control[ctr], val); | ||
179 | } | ||
180 | EXPORT_SYMBOL_GPL(cbe_write_pm07_control); | ||
181 | |||
182 | /* | ||
183 | * Other PMU control registers. Most of these are write-only. | ||
184 | */ | ||
185 | |||
186 | u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg) | ||
187 | { | ||
188 | u32 val = 0; | ||
189 | |||
190 | switch (reg) { | ||
191 | case group_control: | ||
192 | READ_SHADOW_REG(val, group_control); | ||
193 | break; | ||
194 | |||
195 | case debug_bus_control: | ||
196 | READ_SHADOW_REG(val, debug_bus_control); | ||
197 | break; | ||
198 | |||
199 | case trace_address: | ||
200 | READ_MMIO_UPPER32(val, trace_address); | ||
201 | break; | ||
202 | |||
203 | case ext_tr_timer: | ||
204 | READ_SHADOW_REG(val, ext_tr_timer); | ||
205 | break; | ||
206 | |||
207 | case pm_status: | ||
208 | READ_MMIO_UPPER32(val, pm_status); | ||
209 | break; | ||
210 | |||
211 | case pm_control: | ||
212 | READ_SHADOW_REG(val, pm_control); | ||
213 | break; | ||
214 | |||
215 | case pm_interval: | ||
216 | READ_SHADOW_REG(val, pm_interval); | ||
217 | break; | ||
218 | |||
219 | case pm_start_stop: | ||
220 | READ_SHADOW_REG(val, pm_start_stop); | ||
221 | break; | ||
222 | } | ||
223 | |||
224 | return val; | ||
225 | } | ||
226 | EXPORT_SYMBOL_GPL(cbe_read_pm); | ||
227 | |||
228 | void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val) | ||
229 | { | ||
230 | switch (reg) { | ||
231 | case group_control: | ||
232 | WRITE_WO_MMIO(group_control, val); | ||
233 | break; | ||
234 | |||
235 | case debug_bus_control: | ||
236 | WRITE_WO_MMIO(debug_bus_control, val); | ||
237 | break; | ||
238 | |||
239 | case trace_address: | ||
240 | WRITE_WO_MMIO(trace_address, val); | ||
241 | break; | ||
242 | |||
243 | case ext_tr_timer: | ||
244 | WRITE_WO_MMIO(ext_tr_timer, val); | ||
245 | break; | ||
246 | |||
247 | case pm_status: | ||
248 | WRITE_WO_MMIO(pm_status, val); | ||
249 | break; | ||
250 | |||
251 | case pm_control: | ||
252 | WRITE_WO_MMIO(pm_control, val); | ||
253 | break; | ||
254 | |||
255 | case pm_interval: | ||
256 | WRITE_WO_MMIO(pm_interval, val); | ||
257 | break; | ||
258 | |||
259 | case pm_start_stop: | ||
260 | WRITE_WO_MMIO(pm_start_stop, val); | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | EXPORT_SYMBOL_GPL(cbe_write_pm); | ||
265 | |||
266 | /* | ||
267 | * Get/set the size of a physical counter to either 16 or 32 bits. | ||
268 | */ | ||
269 | |||
270 | u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr) | ||
271 | { | ||
272 | u32 pm_ctrl, size = 0; | ||
273 | |||
274 | if (phys_ctr < NR_PHYS_CTRS) { | ||
275 | pm_ctrl = cbe_read_pm(cpu, pm_control); | ||
276 | size = (pm_ctrl & CBE_PM_16BIT_CTR(phys_ctr)) ? 16 : 32; | ||
277 | } | ||
278 | |||
279 | return size; | ||
280 | } | ||
281 | EXPORT_SYMBOL_GPL(cbe_get_ctr_size); | ||
282 | |||
283 | void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size) | ||
284 | { | ||
285 | u32 pm_ctrl; | ||
286 | |||
287 | if (phys_ctr < NR_PHYS_CTRS) { | ||
288 | pm_ctrl = cbe_read_pm(cpu, pm_control); | ||
289 | switch (ctr_size) { | ||
290 | case 16: | ||
291 | pm_ctrl |= CBE_PM_16BIT_CTR(phys_ctr); | ||
292 | break; | ||
293 | |||
294 | case 32: | ||
295 | pm_ctrl &= ~CBE_PM_16BIT_CTR(phys_ctr); | ||
296 | break; | ||
297 | } | ||
298 | cbe_write_pm(cpu, pm_control, pm_ctrl); | ||
299 | } | ||
300 | } | ||
301 | EXPORT_SYMBOL_GPL(cbe_set_ctr_size); | ||
302 | |||
303 | /* | ||
304 | * Enable/disable the entire performance monitoring unit. | ||
305 | * When we enable the PMU, all pending writes to counters get committed. | ||
306 | */ | ||
307 | |||
308 | void cbe_enable_pm(u32 cpu) | ||
309 | { | ||
310 | struct cbe_pmd_shadow_regs *shadow_regs; | ||
311 | u32 pm_ctrl; | ||
312 | |||
313 | shadow_regs = cbe_get_cpu_pmd_shadow_regs(cpu); | ||
314 | shadow_regs->counter_value_in_latch = 0; | ||
315 | |||
316 | pm_ctrl = cbe_read_pm(cpu, pm_control) | CBE_PM_ENABLE_PERF_MON; | ||
317 | cbe_write_pm(cpu, pm_control, pm_ctrl); | ||
318 | } | ||
319 | EXPORT_SYMBOL_GPL(cbe_enable_pm); | ||
320 | |||
321 | void cbe_disable_pm(u32 cpu) | ||
322 | { | ||
323 | u32 pm_ctrl; | ||
324 | pm_ctrl = cbe_read_pm(cpu, pm_control) & ~CBE_PM_ENABLE_PERF_MON; | ||
325 | cbe_write_pm(cpu, pm_control, pm_ctrl); | ||
326 | } | ||
327 | EXPORT_SYMBOL_GPL(cbe_disable_pm); | ||
328 | |||
329 | /* | ||
330 | * Reading from the trace_buffer. | ||
331 | * The trace buffer is two 64-bit registers. Reading from | ||
332 | * the second half automatically increments the trace_address. | ||
333 | */ | ||
334 | |||
335 | void cbe_read_trace_buffer(u32 cpu, u64 *buf) | ||
336 | { | ||
337 | struct cbe_pmd_regs __iomem *pmd_regs = cbe_get_cpu_pmd_regs(cpu); | ||
338 | |||
339 | *buf++ = in_be64(&pmd_regs->trace_buffer_0_63); | ||
340 | *buf++ = in_be64(&pmd_regs->trace_buffer_64_127); | ||
341 | } | ||
342 | EXPORT_SYMBOL_GPL(cbe_read_trace_buffer); | ||
343 | |||
344 | /* | ||
345 | * Enabling/disabling interrupts for the entire performance monitoring unit. | ||
346 | */ | ||
347 | |||
348 | u32 cbe_query_pm_interrupts(u32 cpu) | ||
349 | { | ||
350 | return cbe_read_pm(cpu, pm_status); | ||
351 | } | ||
352 | EXPORT_SYMBOL_GPL(cbe_query_pm_interrupts); | ||
353 | |||
354 | u32 cbe_clear_pm_interrupts(u32 cpu) | ||
355 | { | ||
356 | /* Reading pm_status clears the interrupt bits. */ | ||
357 | return cbe_query_pm_interrupts(cpu); | ||
358 | } | ||
359 | EXPORT_SYMBOL_GPL(cbe_clear_pm_interrupts); | ||
360 | |||
361 | void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask) | ||
362 | { | ||
363 | /* Set which node and thread will handle the next interrupt. */ | ||
364 | iic_set_interrupt_routing(cpu, thread, 0); | ||
365 | |||
366 | /* Enable the interrupt bits in the pm_status register. */ | ||
367 | if (mask) | ||
368 | cbe_write_pm(cpu, pm_status, mask); | ||
369 | } | ||
370 | EXPORT_SYMBOL_GPL(cbe_enable_pm_interrupts); | ||
371 | |||
372 | void cbe_disable_pm_interrupts(u32 cpu) | ||
373 | { | ||
374 | cbe_clear_pm_interrupts(cpu); | ||
375 | cbe_write_pm(cpu, pm_status, 0); | ||
376 | } | ||
377 | EXPORT_SYMBOL_GPL(cbe_disable_pm_interrupts); | ||
378 | |||
379 | static irqreturn_t cbe_pm_irq(int irq, void *dev_id) | ||
380 | { | ||
381 | perf_irq(get_irq_regs()); | ||
382 | return IRQ_HANDLED; | ||
383 | } | ||
384 | |||
385 | int __init cbe_init_pm_irq(void) | ||
386 | { | ||
387 | unsigned int irq; | ||
388 | int rc, node; | ||
389 | |||
390 | for_each_node(node) { | ||
391 | irq = irq_create_mapping(NULL, IIC_IRQ_IOEX_PMI | | ||
392 | (node << IIC_IRQ_NODE_SHIFT)); | ||
393 | if (irq == NO_IRQ) { | ||
394 | printk("ERROR: Unable to allocate irq for node %d\n", | ||
395 | node); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | rc = request_irq(irq, cbe_pm_irq, | ||
400 | IRQF_DISABLED, "cbe-pmu-0", NULL); | ||
401 | if (rc) { | ||
402 | printk("ERROR: Request for irq on node %d failed\n", | ||
403 | node); | ||
404 | return rc; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | arch_initcall(cbe_init_pm_irq); | ||
411 | |||
412 | void cbe_sync_irq(int node) | ||
413 | { | ||
414 | unsigned int irq; | ||
415 | |||
416 | irq = irq_find_mapping(NULL, | ||
417 | IIC_IRQ_IOEX_PMI | ||
418 | | (node << IIC_IRQ_NODE_SHIFT)); | ||
419 | |||
420 | if (irq == NO_IRQ) { | ||
421 | printk(KERN_WARNING "ERROR, unable to get existing irq %d " \ | ||
422 | "for node %d\n", irq, node); | ||
423 | return; | ||
424 | } | ||
425 | |||
426 | synchronize_irq(irq); | ||
427 | } | ||
428 | EXPORT_SYMBOL_GPL(cbe_sync_irq); | ||
429 | |||
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 22c228a49c3..36989c2eee6 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -50,9 +50,10 @@ | |||
50 | #include <asm/spu.h> | 50 | #include <asm/spu.h> |
51 | #include <asm/spu_priv1.h> | 51 | #include <asm/spu_priv1.h> |
52 | #include <asm/udbg.h> | 52 | #include <asm/udbg.h> |
53 | #include <asm/mpic.h> | ||
54 | #include <asm/of_platform.h> | ||
53 | 55 | ||
54 | #include "interrupt.h" | 56 | #include "interrupt.h" |
55 | #include "iommu.h" | ||
56 | #include "cbe_regs.h" | 57 | #include "cbe_regs.h" |
57 | #include "pervasive.h" | 58 | #include "pervasive.h" |
58 | #include "ras.h" | 59 | #include "ras.h" |
@@ -80,24 +81,72 @@ static void cell_progress(char *s, unsigned short hex) | |||
80 | printk("*** %04x : %s\n", hex, s ? s : ""); | 81 | printk("*** %04x : %s\n", hex, s ? s : ""); |
81 | } | 82 | } |
82 | 83 | ||
83 | static void __init cell_pcibios_fixup(void) | 84 | static int __init cell_publish_devices(void) |
84 | { | 85 | { |
85 | struct pci_dev *dev = NULL; | 86 | if (!machine_is(cell)) |
87 | return 0; | ||
88 | |||
89 | /* Publish OF platform devices for southbridge IOs */ | ||
90 | of_platform_bus_probe(NULL, NULL, NULL); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | device_initcall(cell_publish_devices); | ||
95 | |||
96 | static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc) | ||
97 | { | ||
98 | struct mpic *mpic = desc->handler_data; | ||
99 | unsigned int virq; | ||
100 | |||
101 | virq = mpic_get_one_irq(mpic); | ||
102 | if (virq != NO_IRQ) | ||
103 | generic_handle_irq(virq); | ||
104 | desc->chip->eoi(irq); | ||
105 | } | ||
86 | 106 | ||
87 | for_each_pci_dev(dev) | 107 | static void __init mpic_init_IRQ(void) |
88 | pci_read_irq_line(dev); | 108 | { |
109 | struct device_node *dn; | ||
110 | struct mpic *mpic; | ||
111 | unsigned int virq; | ||
112 | |||
113 | for (dn = NULL; | ||
114 | (dn = of_find_node_by_name(dn, "interrupt-controller"));) { | ||
115 | if (!device_is_compatible(dn, "CBEA,platform-open-pic")) | ||
116 | continue; | ||
117 | |||
118 | /* The MPIC driver will get everything it needs from the | ||
119 | * device-tree, just pass 0 to all arguments | ||
120 | */ | ||
121 | mpic = mpic_alloc(dn, 0, 0, 0, 0, " MPIC "); | ||
122 | if (mpic == NULL) | ||
123 | continue; | ||
124 | mpic_init(mpic); | ||
125 | |||
126 | virq = irq_of_parse_and_map(dn, 0); | ||
127 | if (virq == NO_IRQ) | ||
128 | continue; | ||
129 | |||
130 | printk(KERN_INFO "%s : hooking up to IRQ %d\n", | ||
131 | dn->full_name, virq); | ||
132 | set_irq_data(virq, mpic); | ||
133 | set_irq_chained_handler(virq, cell_mpic_cascade); | ||
134 | } | ||
89 | } | 135 | } |
90 | 136 | ||
137 | |||
91 | static void __init cell_init_irq(void) | 138 | static void __init cell_init_irq(void) |
92 | { | 139 | { |
93 | iic_init_IRQ(); | 140 | iic_init_IRQ(); |
94 | spider_init_IRQ(); | 141 | spider_init_IRQ(); |
142 | mpic_init_IRQ(); | ||
95 | } | 143 | } |
96 | 144 | ||
97 | static void __init cell_setup_arch(void) | 145 | static void __init cell_setup_arch(void) |
98 | { | 146 | { |
99 | #ifdef CONFIG_SPU_BASE | 147 | #ifdef CONFIG_SPU_BASE |
100 | spu_priv1_ops = &spu_priv1_mmio_ops; | 148 | spu_priv1_ops = &spu_priv1_mmio_ops; |
149 | spu_management_ops = &spu_management_of_ops; | ||
101 | #endif | 150 | #endif |
102 | 151 | ||
103 | cbe_regs_init(); | 152 | cbe_regs_init(); |
@@ -109,7 +158,6 @@ static void __init cell_setup_arch(void) | |||
109 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
110 | smp_init_cell(); | 159 | smp_init_cell(); |
111 | #endif | 160 | #endif |
112 | |||
113 | /* init to some ~sane value until calibrate_delay() runs */ | 161 | /* init to some ~sane value until calibrate_delay() runs */ |
114 | loops_per_jiffy = 50000000; | 162 | loops_per_jiffy = 50000000; |
115 | 163 | ||
@@ -129,19 +177,6 @@ static void __init cell_setup_arch(void) | |||
129 | mmio_nvram_init(); | 177 | mmio_nvram_init(); |
130 | } | 178 | } |
131 | 179 | ||
132 | /* | ||
133 | * Early initialization. Relocation is on but do not reference unbolted pages | ||
134 | */ | ||
135 | static void __init cell_init_early(void) | ||
136 | { | ||
137 | DBG(" -> cell_init_early()\n"); | ||
138 | |||
139 | cell_init_iommu(); | ||
140 | |||
141 | DBG(" <- cell_init_early()\n"); | ||
142 | } | ||
143 | |||
144 | |||
145 | static int __init cell_probe(void) | 180 | static int __init cell_probe(void) |
146 | { | 181 | { |
147 | unsigned long root = of_get_flat_dt_root(); | 182 | unsigned long root = of_get_flat_dt_root(); |
@@ -168,7 +203,6 @@ define_machine(cell) { | |||
168 | .name = "Cell", | 203 | .name = "Cell", |
169 | .probe = cell_probe, | 204 | .probe = cell_probe, |
170 | .setup_arch = cell_setup_arch, | 205 | .setup_arch = cell_setup_arch, |
171 | .init_early = cell_init_early, | ||
172 | .show_cpuinfo = cell_show_cpuinfo, | 206 | .show_cpuinfo = cell_show_cpuinfo, |
173 | .restart = rtas_restart, | 207 | .restart = rtas_restart, |
174 | .power_off = rtas_power_off, | 208 | .power_off = rtas_power_off, |
@@ -180,7 +214,7 @@ define_machine(cell) { | |||
180 | .check_legacy_ioport = cell_check_legacy_ioport, | 214 | .check_legacy_ioport = cell_check_legacy_ioport, |
181 | .progress = cell_progress, | 215 | .progress = cell_progress, |
182 | .init_IRQ = cell_init_irq, | 216 | .init_IRQ = cell_init_irq, |
183 | .pcibios_fixup = cell_pcibios_fixup, | 217 | .pci_setup_phb = rtas_setup_phb, |
184 | #ifdef CONFIG_KEXEC | 218 | #ifdef CONFIG_KEXEC |
185 | .machine_kexec = default_machine_kexec, | 219 | .machine_kexec = default_machine_kexec, |
186 | .machine_kexec_prepare = default_machine_kexec_prepare, | 220 | .machine_kexec_prepare = default_machine_kexec_prepare, |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 7aa809d5a24..bd7bffc3ddd 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -25,22 +25,17 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/pci.h> | ||
29 | #include <linux/poll.h> | ||
30 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
31 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
32 | #include <linux/wait.h> | 30 | #include <linux/wait.h> |
33 | 31 | #include <linux/mm.h> | |
34 | #include <asm/firmware.h> | 32 | #include <linux/io.h> |
35 | #include <asm/io.h> | ||
36 | #include <asm/prom.h> | ||
37 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
38 | #include <asm/spu.h> | 34 | #include <asm/spu.h> |
39 | #include <asm/spu_priv1.h> | 35 | #include <asm/spu_priv1.h> |
40 | #include <asm/mmu_context.h> | 36 | #include <asm/xmon.h> |
41 | |||
42 | #include "interrupt.h" | ||
43 | 37 | ||
38 | const struct spu_management_ops *spu_management_ops; | ||
44 | const struct spu_priv1_ops *spu_priv1_ops; | 39 | const struct spu_priv1_ops *spu_priv1_ops; |
45 | 40 | ||
46 | EXPORT_SYMBOL_GPL(spu_priv1_ops); | 41 | EXPORT_SYMBOL_GPL(spu_priv1_ops); |
@@ -89,7 +84,30 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
89 | printk("%s: invalid access during switch!\n", __func__); | 84 | printk("%s: invalid access during switch!\n", __func__); |
90 | return 1; | 85 | return 1; |
91 | } | 86 | } |
92 | if (!mm || (REGION_ID(ea) != USER_REGION_ID)) { | 87 | esid = (ea & ESID_MASK) | SLB_ESID_V; |
88 | |||
89 | switch(REGION_ID(ea)) { | ||
90 | case USER_REGION_ID: | ||
91 | #ifdef CONFIG_HUGETLB_PAGE | ||
92 | if (in_hugepage_area(mm->context, ea)) | ||
93 | llp = mmu_psize_defs[mmu_huge_psize].sllp; | ||
94 | else | ||
95 | #endif | ||
96 | llp = mmu_psize_defs[mmu_virtual_psize].sllp; | ||
97 | vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | | ||
98 | SLB_VSID_USER | llp; | ||
99 | break; | ||
100 | case VMALLOC_REGION_ID: | ||
101 | llp = mmu_psize_defs[mmu_virtual_psize].sllp; | ||
102 | vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | | ||
103 | SLB_VSID_KERNEL | llp; | ||
104 | break; | ||
105 | case KERNEL_REGION_ID: | ||
106 | llp = mmu_psize_defs[mmu_linear_psize].sllp; | ||
107 | vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | | ||
108 | SLB_VSID_KERNEL | llp; | ||
109 | break; | ||
110 | default: | ||
93 | /* Future: support kernel segments so that drivers | 111 | /* Future: support kernel segments so that drivers |
94 | * can use SPUs. | 112 | * can use SPUs. |
95 | */ | 113 | */ |
@@ -97,16 +115,6 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
97 | return 1; | 115 | return 1; |
98 | } | 116 | } |
99 | 117 | ||
100 | esid = (ea & ESID_MASK) | SLB_ESID_V; | ||
101 | #ifdef CONFIG_HUGETLB_PAGE | ||
102 | if (in_hugepage_area(mm->context, ea)) | ||
103 | llp = mmu_psize_defs[mmu_huge_psize].sllp; | ||
104 | else | ||
105 | #endif | ||
106 | llp = mmu_psize_defs[mmu_virtual_psize].sllp; | ||
107 | vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | | ||
108 | SLB_VSID_USER | llp; | ||
109 | |||
110 | out_be64(&priv2->slb_index_W, spu->slb_replace); | 118 | out_be64(&priv2->slb_index_W, spu->slb_replace); |
111 | out_be64(&priv2->slb_vsid_RW, vsid); | 119 | out_be64(&priv2->slb_vsid_RW, vsid); |
112 | out_be64(&priv2->slb_esid_RW, esid); | 120 | out_be64(&priv2->slb_esid_RW, esid); |
@@ -320,6 +328,7 @@ static void spu_free_irqs(struct spu *spu) | |||
320 | } | 328 | } |
321 | 329 | ||
322 | static struct list_head spu_list[MAX_NUMNODES]; | 330 | static struct list_head spu_list[MAX_NUMNODES]; |
331 | static LIST_HEAD(spu_full_list); | ||
323 | static DEFINE_MUTEX(spu_mutex); | 332 | static DEFINE_MUTEX(spu_mutex); |
324 | 333 | ||
325 | static void spu_init_channels(struct spu *spu) | 334 | static void spu_init_channels(struct spu *spu) |
@@ -364,8 +373,7 @@ struct spu *spu_alloc_node(int node) | |||
364 | if (!list_empty(&spu_list[node])) { | 373 | if (!list_empty(&spu_list[node])) { |
365 | spu = list_entry(spu_list[node].next, struct spu, list); | 374 | spu = list_entry(spu_list[node].next, struct spu, list); |
366 | list_del_init(&spu->list); | 375 | list_del_init(&spu->list); |
367 | pr_debug("Got SPU %x %d %d\n", | 376 | pr_debug("Got SPU %d %d\n", spu->number, spu->node); |
368 | spu->isrc, spu->number, spu->node); | ||
369 | spu_init_channels(spu); | 377 | spu_init_channels(spu); |
370 | } | 378 | } |
371 | mutex_unlock(&spu_mutex); | 379 | mutex_unlock(&spu_mutex); |
@@ -493,280 +501,65 @@ int spu_irq_class_1_bottom(struct spu *spu) | |||
493 | if (!error) { | 501 | if (!error) { |
494 | spu_restart_dma(spu); | 502 | spu_restart_dma(spu); |
495 | } else { | 503 | } else { |
496 | __spu_trap_invalid_dma(spu); | 504 | spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE); |
497 | } | 505 | } |
498 | return ret; | 506 | return ret; |
499 | } | 507 | } |
500 | 508 | ||
501 | static int __init find_spu_node_id(struct device_node *spe) | 509 | struct sysdev_class spu_sysdev_class = { |
502 | { | 510 | set_kset_name("spu") |
503 | const unsigned int *id; | 511 | }; |
504 | struct device_node *cpu; | ||
505 | cpu = spe->parent->parent; | ||
506 | id = get_property(cpu, "node-id", NULL); | ||
507 | return id ? *id : 0; | ||
508 | } | ||
509 | |||
510 | static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe, | ||
511 | const char *prop) | ||
512 | { | ||
513 | static DEFINE_MUTEX(add_spumem_mutex); | ||
514 | |||
515 | const struct address_prop { | ||
516 | unsigned long address; | ||
517 | unsigned int len; | ||
518 | } __attribute__((packed)) *p; | ||
519 | int proplen; | ||
520 | |||
521 | unsigned long start_pfn, nr_pages; | ||
522 | struct pglist_data *pgdata; | ||
523 | struct zone *zone; | ||
524 | int ret; | ||
525 | |||
526 | p = get_property(spe, prop, &proplen); | ||
527 | WARN_ON(proplen != sizeof (*p)); | ||
528 | |||
529 | start_pfn = p->address >> PAGE_SHIFT; | ||
530 | nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
531 | |||
532 | pgdata = NODE_DATA(spu->nid); | ||
533 | zone = pgdata->node_zones; | ||
534 | |||
535 | /* XXX rethink locking here */ | ||
536 | mutex_lock(&add_spumem_mutex); | ||
537 | ret = __add_pages(zone, start_pfn, nr_pages); | ||
538 | mutex_unlock(&add_spumem_mutex); | ||
539 | |||
540 | return ret; | ||
541 | } | ||
542 | 512 | ||
543 | static void __iomem * __init map_spe_prop(struct spu *spu, | 513 | int spu_add_sysdev_attr(struct sysdev_attribute *attr) |
544 | struct device_node *n, const char *name) | ||
545 | { | 514 | { |
546 | const struct address_prop { | 515 | struct spu *spu; |
547 | unsigned long address; | 516 | mutex_lock(&spu_mutex); |
548 | unsigned int len; | ||
549 | } __attribute__((packed)) *prop; | ||
550 | |||
551 | const void *p; | ||
552 | int proplen; | ||
553 | void __iomem *ret = NULL; | ||
554 | int err = 0; | ||
555 | |||
556 | p = get_property(n, name, &proplen); | ||
557 | if (proplen != sizeof (struct address_prop)) | ||
558 | return NULL; | ||
559 | |||
560 | prop = p; | ||
561 | |||
562 | err = cell_spuprop_present(spu, n, name); | ||
563 | if (err && (err != -EEXIST)) | ||
564 | goto out; | ||
565 | |||
566 | ret = ioremap(prop->address, prop->len); | ||
567 | |||
568 | out: | ||
569 | return ret; | ||
570 | } | ||
571 | 517 | ||
572 | static void spu_unmap(struct spu *spu) | 518 | list_for_each_entry(spu, &spu_full_list, full_list) |
573 | { | 519 | sysdev_create_file(&spu->sysdev, attr); |
574 | iounmap(spu->priv2); | ||
575 | iounmap(spu->priv1); | ||
576 | iounmap(spu->problem); | ||
577 | iounmap((__force u8 __iomem *)spu->local_store); | ||
578 | } | ||
579 | 520 | ||
580 | /* This function shall be abstracted for HV platforms */ | 521 | mutex_unlock(&spu_mutex); |
581 | static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np) | 522 | return 0; |
582 | { | ||
583 | unsigned int isrc; | ||
584 | const u32 *tmp; | ||
585 | |||
586 | /* Get the interrupt source unit from the device-tree */ | ||
587 | tmp = get_property(np, "isrc", NULL); | ||
588 | if (!tmp) | ||
589 | return -ENODEV; | ||
590 | isrc = tmp[0]; | ||
591 | |||
592 | /* Add the node number */ | ||
593 | isrc |= spu->node << IIC_IRQ_NODE_SHIFT; | ||
594 | spu->isrc = isrc; | ||
595 | |||
596 | /* Now map interrupts of all 3 classes */ | ||
597 | spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); | ||
598 | spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc); | ||
599 | spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc); | ||
600 | |||
601 | /* Right now, we only fail if class 2 failed */ | ||
602 | return spu->irqs[2] == NO_IRQ ? -EINVAL : 0; | ||
603 | } | 523 | } |
524 | EXPORT_SYMBOL_GPL(spu_add_sysdev_attr); | ||
604 | 525 | ||
605 | static int __init spu_map_device_old(struct spu *spu, struct device_node *node) | 526 | int spu_add_sysdev_attr_group(struct attribute_group *attrs) |
606 | { | 527 | { |
607 | const char *prop; | 528 | struct spu *spu; |
608 | int ret; | 529 | mutex_lock(&spu_mutex); |
609 | |||
610 | ret = -ENODEV; | ||
611 | spu->name = get_property(node, "name", NULL); | ||
612 | if (!spu->name) | ||
613 | goto out; | ||
614 | |||
615 | prop = get_property(node, "local-store", NULL); | ||
616 | if (!prop) | ||
617 | goto out; | ||
618 | spu->local_store_phys = *(unsigned long *)prop; | ||
619 | |||
620 | /* we use local store as ram, not io memory */ | ||
621 | spu->local_store = (void __force *) | ||
622 | map_spe_prop(spu, node, "local-store"); | ||
623 | if (!spu->local_store) | ||
624 | goto out; | ||
625 | |||
626 | prop = get_property(node, "problem", NULL); | ||
627 | if (!prop) | ||
628 | goto out_unmap; | ||
629 | spu->problem_phys = *(unsigned long *)prop; | ||
630 | |||
631 | spu->problem= map_spe_prop(spu, node, "problem"); | ||
632 | if (!spu->problem) | ||
633 | goto out_unmap; | ||
634 | |||
635 | spu->priv1= map_spe_prop(spu, node, "priv1"); | ||
636 | /* priv1 is not available on a hypervisor */ | ||
637 | |||
638 | spu->priv2= map_spe_prop(spu, node, "priv2"); | ||
639 | if (!spu->priv2) | ||
640 | goto out_unmap; | ||
641 | ret = 0; | ||
642 | goto out; | ||
643 | |||
644 | out_unmap: | ||
645 | spu_unmap(spu); | ||
646 | out: | ||
647 | return ret; | ||
648 | } | ||
649 | 530 | ||
650 | static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) | 531 | list_for_each_entry(spu, &spu_full_list, full_list) |
651 | { | 532 | sysfs_create_group(&spu->sysdev.kobj, attrs); |
652 | struct of_irq oirq; | ||
653 | int ret; | ||
654 | int i; | ||
655 | 533 | ||
656 | for (i=0; i < 3; i++) { | 534 | mutex_unlock(&spu_mutex); |
657 | ret = of_irq_map_one(np, i, &oirq); | ||
658 | if (ret) { | ||
659 | pr_debug("spu_new: failed to get irq %d\n", i); | ||
660 | goto err; | ||
661 | } | ||
662 | ret = -EINVAL; | ||
663 | pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], | ||
664 | oirq.controller->full_name); | ||
665 | spu->irqs[i] = irq_create_of_mapping(oirq.controller, | ||
666 | oirq.specifier, oirq.size); | ||
667 | if (spu->irqs[i] == NO_IRQ) { | ||
668 | pr_debug("spu_new: failed to map it !\n"); | ||
669 | goto err; | ||
670 | } | ||
671 | } | ||
672 | return 0; | 535 | return 0; |
673 | |||
674 | err: | ||
675 | pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name); | ||
676 | for (; i >= 0; i--) { | ||
677 | if (spu->irqs[i] != NO_IRQ) | ||
678 | irq_dispose_mapping(spu->irqs[i]); | ||
679 | } | ||
680 | return ret; | ||
681 | } | 536 | } |
537 | EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group); | ||
682 | 538 | ||
683 | static int spu_map_resource(struct device_node *node, int nr, | ||
684 | void __iomem** virt, unsigned long *phys) | ||
685 | { | ||
686 | struct resource resource = { }; | ||
687 | int ret; | ||
688 | |||
689 | ret = of_address_to_resource(node, nr, &resource); | ||
690 | if (ret) | ||
691 | goto out; | ||
692 | 539 | ||
693 | if (phys) | 540 | void spu_remove_sysdev_attr(struct sysdev_attribute *attr) |
694 | *phys = resource.start; | ||
695 | *virt = ioremap(resource.start, resource.end - resource.start); | ||
696 | if (!*virt) | ||
697 | ret = -EINVAL; | ||
698 | |||
699 | out: | ||
700 | return ret; | ||
701 | } | ||
702 | |||
703 | static int __init spu_map_device(struct spu *spu, struct device_node *node) | ||
704 | { | 541 | { |
705 | int ret = -ENODEV; | 542 | struct spu *spu; |
706 | spu->name = get_property(node, "name", NULL); | 543 | mutex_lock(&spu_mutex); |
707 | if (!spu->name) | ||
708 | goto out; | ||
709 | |||
710 | ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, | ||
711 | &spu->local_store_phys); | ||
712 | if (ret) { | ||
713 | pr_debug("spu_new: failed to map %s resource 0\n", | ||
714 | node->full_name); | ||
715 | goto out; | ||
716 | } | ||
717 | ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, | ||
718 | &spu->problem_phys); | ||
719 | if (ret) { | ||
720 | pr_debug("spu_new: failed to map %s resource 1\n", | ||
721 | node->full_name); | ||
722 | goto out_unmap; | ||
723 | } | ||
724 | ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, | ||
725 | NULL); | ||
726 | if (ret) { | ||
727 | pr_debug("spu_new: failed to map %s resource 2\n", | ||
728 | node->full_name); | ||
729 | goto out_unmap; | ||
730 | } | ||
731 | |||
732 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | ||
733 | ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1, | ||
734 | NULL); | ||
735 | if (ret) { | ||
736 | pr_debug("spu_new: failed to map %s resource 3\n", | ||
737 | node->full_name); | ||
738 | goto out_unmap; | ||
739 | } | ||
740 | pr_debug("spu_new: %s maps:\n", node->full_name); | ||
741 | pr_debug(" local store : 0x%016lx -> 0x%p\n", | ||
742 | spu->local_store_phys, spu->local_store); | ||
743 | pr_debug(" problem state : 0x%016lx -> 0x%p\n", | ||
744 | spu->problem_phys, spu->problem); | ||
745 | pr_debug(" priv2 : 0x%p\n", spu->priv2); | ||
746 | pr_debug(" priv1 : 0x%p\n", spu->priv1); | ||
747 | 544 | ||
748 | return 0; | 545 | list_for_each_entry(spu, &spu_full_list, full_list) |
546 | sysdev_remove_file(&spu->sysdev, attr); | ||
749 | 547 | ||
750 | out_unmap: | 548 | mutex_unlock(&spu_mutex); |
751 | spu_unmap(spu); | ||
752 | out: | ||
753 | pr_debug("failed to map spe %s: %d\n", spu->name, ret); | ||
754 | return ret; | ||
755 | } | 549 | } |
550 | EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr); | ||
756 | 551 | ||
757 | struct sysdev_class spu_sysdev_class = { | 552 | void spu_remove_sysdev_attr_group(struct attribute_group *attrs) |
758 | set_kset_name("spu") | ||
759 | }; | ||
760 | |||
761 | static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf) | ||
762 | { | 553 | { |
763 | struct spu *spu = container_of(sysdev, struct spu, sysdev); | 554 | struct spu *spu; |
764 | return sprintf(buf, "%d\n", spu->isrc); | 555 | mutex_lock(&spu_mutex); |
765 | 556 | ||
766 | } | 557 | list_for_each_entry(spu, &spu_full_list, full_list) |
767 | static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); | 558 | sysfs_remove_group(&spu->sysdev.kobj, attrs); |
768 | 559 | ||
769 | extern int attach_sysdev_to_node(struct sys_device *dev, int nid); | 560 | mutex_unlock(&spu_mutex); |
561 | } | ||
562 | EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group); | ||
770 | 563 | ||
771 | static int spu_create_sysdev(struct spu *spu) | 564 | static int spu_create_sysdev(struct spu *spu) |
772 | { | 565 | { |
@@ -781,21 +574,18 @@ static int spu_create_sysdev(struct spu *spu) | |||
781 | return ret; | 574 | return ret; |
782 | } | 575 | } |
783 | 576 | ||
784 | if (spu->isrc != 0) | 577 | sysfs_add_device_to_node(&spu->sysdev, spu->node); |
785 | sysdev_create_file(&spu->sysdev, &attr_isrc); | ||
786 | sysfs_add_device_to_node(&spu->sysdev, spu->nid); | ||
787 | 578 | ||
788 | return 0; | 579 | return 0; |
789 | } | 580 | } |
790 | 581 | ||
791 | static void spu_destroy_sysdev(struct spu *spu) | 582 | static void spu_destroy_sysdev(struct spu *spu) |
792 | { | 583 | { |
793 | sysdev_remove_file(&spu->sysdev, &attr_isrc); | 584 | sysfs_remove_device_from_node(&spu->sysdev, spu->node); |
794 | sysfs_remove_device_from_node(&spu->sysdev, spu->nid); | ||
795 | sysdev_unregister(&spu->sysdev); | 585 | sysdev_unregister(&spu->sysdev); |
796 | } | 586 | } |
797 | 587 | ||
798 | static int __init create_spu(struct device_node *spe) | 588 | static int __init create_spu(void *data) |
799 | { | 589 | { |
800 | struct spu *spu; | 590 | struct spu *spu; |
801 | int ret; | 591 | int ret; |
@@ -806,57 +596,37 @@ static int __init create_spu(struct device_node *spe) | |||
806 | if (!spu) | 596 | if (!spu) |
807 | goto out; | 597 | goto out; |
808 | 598 | ||
809 | spu->node = find_spu_node_id(spe); | 599 | spin_lock_init(&spu->register_lock); |
810 | if (spu->node >= MAX_NUMNODES) { | 600 | mutex_lock(&spu_mutex); |
811 | printk(KERN_WARNING "SPE %s on node %d ignored," | 601 | spu->number = number++; |
812 | " node number too big\n", spe->full_name, spu->node); | 602 | mutex_unlock(&spu_mutex); |
813 | printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); | 603 | |
814 | return -ENODEV; | 604 | ret = spu_create_spu(spu, data); |
815 | } | ||
816 | spu->nid = of_node_to_nid(spe); | ||
817 | if (spu->nid == -1) | ||
818 | spu->nid = 0; | ||
819 | 605 | ||
820 | ret = spu_map_device(spu, spe); | ||
821 | /* try old method */ | ||
822 | if (ret) | ||
823 | ret = spu_map_device_old(spu, spe); | ||
824 | if (ret) | 606 | if (ret) |
825 | goto out_free; | 607 | goto out_free; |
826 | 608 | ||
827 | ret = spu_map_interrupts(spu, spe); | 609 | spu_mfc_sdr_setup(spu); |
828 | if (ret) | ||
829 | ret = spu_map_interrupts_old(spu, spe); | ||
830 | if (ret) | ||
831 | goto out_unmap; | ||
832 | spin_lock_init(&spu->register_lock); | ||
833 | spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); | ||
834 | spu_mfc_sr1_set(spu, 0x33); | 610 | spu_mfc_sr1_set(spu, 0x33); |
835 | mutex_lock(&spu_mutex); | ||
836 | |||
837 | spu->number = number++; | ||
838 | ret = spu_request_irqs(spu); | 611 | ret = spu_request_irqs(spu); |
839 | if (ret) | 612 | if (ret) |
840 | goto out_unlock; | 613 | goto out_destroy; |
841 | 614 | ||
842 | ret = spu_create_sysdev(spu); | 615 | ret = spu_create_sysdev(spu); |
843 | if (ret) | 616 | if (ret) |
844 | goto out_free_irqs; | 617 | goto out_free_irqs; |
845 | 618 | ||
619 | mutex_lock(&spu_mutex); | ||
846 | list_add(&spu->list, &spu_list[spu->node]); | 620 | list_add(&spu->list, &spu_list[spu->node]); |
621 | list_add(&spu->full_list, &spu_full_list); | ||
847 | mutex_unlock(&spu_mutex); | 622 | mutex_unlock(&spu_mutex); |
848 | 623 | ||
849 | pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", | ||
850 | spu->name, spu->isrc, spu->local_store, | ||
851 | spu->problem, spu->priv1, spu->priv2, spu->number); | ||
852 | goto out; | 624 | goto out; |
853 | 625 | ||
854 | out_free_irqs: | 626 | out_free_irqs: |
855 | spu_free_irqs(spu); | 627 | spu_free_irqs(spu); |
856 | out_unlock: | 628 | out_destroy: |
857 | mutex_unlock(&spu_mutex); | 629 | spu_destroy_spu(spu); |
858 | out_unmap: | ||
859 | spu_unmap(spu); | ||
860 | out_free: | 630 | out_free: |
861 | kfree(spu); | 631 | kfree(spu); |
862 | out: | 632 | out: |
@@ -866,10 +636,11 @@ out: | |||
866 | static void destroy_spu(struct spu *spu) | 636 | static void destroy_spu(struct spu *spu) |
867 | { | 637 | { |
868 | list_del_init(&spu->list); | 638 | list_del_init(&spu->list); |
639 | list_del_init(&spu->full_list); | ||
869 | 640 | ||
870 | spu_destroy_sysdev(spu); | 641 | spu_destroy_sysdev(spu); |
871 | spu_free_irqs(spu); | 642 | spu_free_irqs(spu); |
872 | spu_unmap(spu); | 643 | spu_destroy_spu(spu); |
873 | kfree(spu); | 644 | kfree(spu); |
874 | } | 645 | } |
875 | 646 | ||
@@ -890,9 +661,11 @@ module_exit(cleanup_spu_base); | |||
890 | 661 | ||
891 | static int __init init_spu_base(void) | 662 | static int __init init_spu_base(void) |
892 | { | 663 | { |
893 | struct device_node *node; | ||
894 | int i, ret; | 664 | int i, ret; |
895 | 665 | ||
666 | if (!spu_management_ops) | ||
667 | return 0; | ||
668 | |||
896 | /* create sysdev class for spus */ | 669 | /* create sysdev class for spus */ |
897 | ret = sysdev_class_register(&spu_sysdev_class); | 670 | ret = sysdev_class_register(&spu_sysdev_class); |
898 | if (ret) | 671 | if (ret) |
@@ -901,17 +674,17 @@ static int __init init_spu_base(void) | |||
901 | for (i = 0; i < MAX_NUMNODES; i++) | 674 | for (i = 0; i < MAX_NUMNODES; i++) |
902 | INIT_LIST_HEAD(&spu_list[i]); | 675 | INIT_LIST_HEAD(&spu_list[i]); |
903 | 676 | ||
904 | ret = -ENODEV; | 677 | ret = spu_enumerate_spus(create_spu); |
905 | for (node = of_find_node_by_type(NULL, "spe"); | 678 | |
906 | node; node = of_find_node_by_type(node, "spe")) { | 679 | if (ret) { |
907 | ret = create_spu(node); | 680 | printk(KERN_WARNING "%s: Error initializing spus\n", |
908 | if (ret) { | 681 | __FUNCTION__); |
909 | printk(KERN_WARNING "%s: Error initializing %s\n", | 682 | cleanup_spu_base(); |
910 | __FUNCTION__, node->name); | 683 | return ret; |
911 | cleanup_spu_base(); | ||
912 | break; | ||
913 | } | ||
914 | } | 684 | } |
685 | |||
686 | xmon_register_spus(&spu_full_list); | ||
687 | |||
915 | return ret; | 688 | return ret; |
916 | } | 689 | } |
917 | module_init(init_spu_base); | 690 | module_init(init_spu_base); |
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c new file mode 100644 index 00000000000..6915b418ee7 --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_coredump.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * SPU core dump code | ||
3 | * | ||
4 | * (C) Copyright 2006 IBM Corp. | ||
5 | * | ||
6 | * Author: Dwayne Grant McConnell <decimal@us.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/file.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/syscalls.h> | ||
26 | |||
27 | #include <asm/spu.h> | ||
28 | |||
29 | static struct spu_coredump_calls spu_coredump_calls; | ||
30 | static DEFINE_MUTEX(spu_coredump_mutex); | ||
31 | |||
32 | int arch_notes_size(void) | ||
33 | { | ||
34 | long ret; | ||
35 | struct module *owner = spu_coredump_calls.owner; | ||
36 | |||
37 | ret = -ENOSYS; | ||
38 | mutex_lock(&spu_coredump_mutex); | ||
39 | if (owner && try_module_get(owner)) { | ||
40 | ret = spu_coredump_calls.arch_notes_size(); | ||
41 | module_put(owner); | ||
42 | } | ||
43 | mutex_unlock(&spu_coredump_mutex); | ||
44 | return ret; | ||
45 | } | ||
46 | |||
47 | void arch_write_notes(struct file *file) | ||
48 | { | ||
49 | struct module *owner = spu_coredump_calls.owner; | ||
50 | |||
51 | mutex_lock(&spu_coredump_mutex); | ||
52 | if (owner && try_module_get(owner)) { | ||
53 | spu_coredump_calls.arch_write_notes(file); | ||
54 | module_put(owner); | ||
55 | } | ||
56 | mutex_unlock(&spu_coredump_mutex); | ||
57 | } | ||
58 | |||
59 | int register_arch_coredump_calls(struct spu_coredump_calls *calls) | ||
60 | { | ||
61 | if (spu_coredump_calls.owner) | ||
62 | return -EBUSY; | ||
63 | |||
64 | mutex_lock(&spu_coredump_mutex); | ||
65 | spu_coredump_calls.arch_notes_size = calls->arch_notes_size; | ||
66 | spu_coredump_calls.arch_write_notes = calls->arch_write_notes; | ||
67 | spu_coredump_calls.owner = calls->owner; | ||
68 | mutex_unlock(&spu_coredump_mutex); | ||
69 | return 0; | ||
70 | } | ||
71 | EXPORT_SYMBOL_GPL(register_arch_coredump_calls); | ||
72 | |||
73 | void unregister_arch_coredump_calls(struct spu_coredump_calls *calls) | ||
74 | { | ||
75 | BUG_ON(spu_coredump_calls.owner != calls->owner); | ||
76 | |||
77 | mutex_lock(&spu_coredump_mutex); | ||
78 | spu_coredump_calls.owner = NULL; | ||
79 | mutex_unlock(&spu_coredump_mutex); | ||
80 | } | ||
81 | EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls); | ||
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 71b69f0a1a4..a5de0430c56 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c | |||
@@ -18,120 +18,498 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/list.h> | ||
21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/ptrace.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/device.h> | ||
22 | 31 | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/spu.h> | 32 | #include <asm/spu.h> |
25 | #include <asm/spu_priv1.h> | 33 | #include <asm/spu_priv1.h> |
34 | #include <asm/firmware.h> | ||
35 | #include <asm/prom.h> | ||
26 | 36 | ||
27 | #include "interrupt.h" | 37 | #include "interrupt.h" |
38 | #include "spu_priv1_mmio.h" | ||
39 | |||
40 | struct spu_pdata { | ||
41 | int nid; | ||
42 | struct device_node *devnode; | ||
43 | struct spu_priv1 __iomem *priv1; | ||
44 | }; | ||
45 | |||
46 | static struct spu_pdata *spu_get_pdata(struct spu *spu) | ||
47 | { | ||
48 | BUG_ON(!spu->pdata); | ||
49 | return spu->pdata; | ||
50 | } | ||
51 | |||
52 | struct device_node *spu_devnode(struct spu *spu) | ||
53 | { | ||
54 | return spu_get_pdata(spu)->devnode; | ||
55 | } | ||
56 | |||
57 | EXPORT_SYMBOL_GPL(spu_devnode); | ||
58 | |||
59 | static int __init find_spu_node_id(struct device_node *spe) | ||
60 | { | ||
61 | const unsigned int *id; | ||
62 | struct device_node *cpu; | ||
63 | cpu = spe->parent->parent; | ||
64 | id = get_property(cpu, "node-id", NULL); | ||
65 | return id ? *id : 0; | ||
66 | } | ||
67 | |||
68 | static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe, | ||
69 | const char *prop) | ||
70 | { | ||
71 | static DEFINE_MUTEX(add_spumem_mutex); | ||
72 | |||
73 | const struct address_prop { | ||
74 | unsigned long address; | ||
75 | unsigned int len; | ||
76 | } __attribute__((packed)) *p; | ||
77 | int proplen; | ||
78 | |||
79 | unsigned long start_pfn, nr_pages; | ||
80 | struct pglist_data *pgdata; | ||
81 | struct zone *zone; | ||
82 | int ret; | ||
83 | |||
84 | p = get_property(spe, prop, &proplen); | ||
85 | WARN_ON(proplen != sizeof (*p)); | ||
86 | |||
87 | start_pfn = p->address >> PAGE_SHIFT; | ||
88 | nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
89 | |||
90 | pgdata = NODE_DATA(spu_get_pdata(spu)->nid); | ||
91 | zone = pgdata->node_zones; | ||
92 | |||
93 | /* XXX rethink locking here */ | ||
94 | mutex_lock(&add_spumem_mutex); | ||
95 | ret = __add_pages(zone, start_pfn, nr_pages); | ||
96 | mutex_unlock(&add_spumem_mutex); | ||
97 | |||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | static void __iomem * __init map_spe_prop(struct spu *spu, | ||
102 | struct device_node *n, const char *name) | ||
103 | { | ||
104 | const struct address_prop { | ||
105 | unsigned long address; | ||
106 | unsigned int len; | ||
107 | } __attribute__((packed)) *prop; | ||
108 | |||
109 | const void *p; | ||
110 | int proplen; | ||
111 | void __iomem *ret = NULL; | ||
112 | int err = 0; | ||
113 | |||
114 | p = get_property(n, name, &proplen); | ||
115 | if (proplen != sizeof (struct address_prop)) | ||
116 | return NULL; | ||
117 | |||
118 | prop = p; | ||
119 | |||
120 | err = cell_spuprop_present(spu, n, name); | ||
121 | if (err && (err != -EEXIST)) | ||
122 | goto out; | ||
123 | |||
124 | ret = ioremap(prop->address, prop->len); | ||
125 | |||
126 | out: | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | static void spu_unmap(struct spu *spu) | ||
131 | { | ||
132 | iounmap(spu->priv2); | ||
133 | iounmap(spu_get_pdata(spu)->priv1); | ||
134 | iounmap(spu->problem); | ||
135 | iounmap((__force u8 __iomem *)spu->local_store); | ||
136 | } | ||
137 | |||
138 | static int __init spu_map_interrupts_old(struct spu *spu, | ||
139 | struct device_node *np) | ||
140 | { | ||
141 | unsigned int isrc; | ||
142 | const u32 *tmp; | ||
143 | |||
144 | /* Get the interrupt source unit from the device-tree */ | ||
145 | tmp = get_property(np, "isrc", NULL); | ||
146 | if (!tmp) | ||
147 | return -ENODEV; | ||
148 | isrc = tmp[0]; | ||
149 | |||
150 | /* Add the node number */ | ||
151 | isrc |= spu->node << IIC_IRQ_NODE_SHIFT; | ||
152 | |||
153 | /* Now map interrupts of all 3 classes */ | ||
154 | spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); | ||
155 | spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc); | ||
156 | spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc); | ||
157 | |||
158 | /* Right now, we only fail if class 2 failed */ | ||
159 | return spu->irqs[2] == NO_IRQ ? -EINVAL : 0; | ||
160 | } | ||
161 | |||
162 | static int __init spu_map_device_old(struct spu *spu, struct device_node *node) | ||
163 | { | ||
164 | const char *prop; | ||
165 | int ret; | ||
166 | |||
167 | ret = -ENODEV; | ||
168 | spu->name = get_property(node, "name", NULL); | ||
169 | if (!spu->name) | ||
170 | goto out; | ||
171 | |||
172 | prop = get_property(node, "local-store", NULL); | ||
173 | if (!prop) | ||
174 | goto out; | ||
175 | spu->local_store_phys = *(unsigned long *)prop; | ||
176 | |||
177 | /* we use local store as ram, not io memory */ | ||
178 | spu->local_store = (void __force *) | ||
179 | map_spe_prop(spu, node, "local-store"); | ||
180 | if (!spu->local_store) | ||
181 | goto out; | ||
182 | |||
183 | prop = get_property(node, "problem", NULL); | ||
184 | if (!prop) | ||
185 | goto out_unmap; | ||
186 | spu->problem_phys = *(unsigned long *)prop; | ||
187 | |||
188 | spu->problem= map_spe_prop(spu, node, "problem"); | ||
189 | if (!spu->problem) | ||
190 | goto out_unmap; | ||
191 | |||
192 | spu_get_pdata(spu)->priv1= map_spe_prop(spu, node, "priv1"); | ||
193 | |||
194 | spu->priv2= map_spe_prop(spu, node, "priv2"); | ||
195 | if (!spu->priv2) | ||
196 | goto out_unmap; | ||
197 | ret = 0; | ||
198 | goto out; | ||
199 | |||
200 | out_unmap: | ||
201 | spu_unmap(spu); | ||
202 | out: | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) | ||
207 | { | ||
208 | struct of_irq oirq; | ||
209 | int ret; | ||
210 | int i; | ||
211 | |||
212 | for (i=0; i < 3; i++) { | ||
213 | ret = of_irq_map_one(np, i, &oirq); | ||
214 | if (ret) { | ||
215 | pr_debug("spu_new: failed to get irq %d\n", i); | ||
216 | goto err; | ||
217 | } | ||
218 | ret = -EINVAL; | ||
219 | pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], | ||
220 | oirq.controller->full_name); | ||
221 | spu->irqs[i] = irq_create_of_mapping(oirq.controller, | ||
222 | oirq.specifier, oirq.size); | ||
223 | if (spu->irqs[i] == NO_IRQ) { | ||
224 | pr_debug("spu_new: failed to map it !\n"); | ||
225 | goto err; | ||
226 | } | ||
227 | } | ||
228 | return 0; | ||
229 | |||
230 | err: | ||
231 | pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, | ||
232 | spu->name); | ||
233 | for (; i >= 0; i--) { | ||
234 | if (spu->irqs[i] != NO_IRQ) | ||
235 | irq_dispose_mapping(spu->irqs[i]); | ||
236 | } | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static int spu_map_resource(struct device_node *node, int nr, | ||
241 | void __iomem** virt, unsigned long *phys) | ||
242 | { | ||
243 | struct resource resource = { }; | ||
244 | int ret; | ||
245 | |||
246 | ret = of_address_to_resource(node, nr, &resource); | ||
247 | if (ret) | ||
248 | goto out; | ||
249 | |||
250 | if (phys) | ||
251 | *phys = resource.start; | ||
252 | *virt = ioremap(resource.start, resource.end - resource.start); | ||
253 | if (!*virt) | ||
254 | ret = -EINVAL; | ||
255 | |||
256 | out: | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | static int __init spu_map_device(struct spu *spu, struct device_node *node) | ||
261 | { | ||
262 | int ret = -ENODEV; | ||
263 | spu->name = get_property(node, "name", NULL); | ||
264 | if (!spu->name) | ||
265 | goto out; | ||
266 | |||
267 | ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, | ||
268 | &spu->local_store_phys); | ||
269 | if (ret) { | ||
270 | pr_debug("spu_new: failed to map %s resource 0\n", | ||
271 | node->full_name); | ||
272 | goto out; | ||
273 | } | ||
274 | ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, | ||
275 | &spu->problem_phys); | ||
276 | if (ret) { | ||
277 | pr_debug("spu_new: failed to map %s resource 1\n", | ||
278 | node->full_name); | ||
279 | goto out_unmap; | ||
280 | } | ||
281 | ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, | ||
282 | NULL); | ||
283 | if (ret) { | ||
284 | pr_debug("spu_new: failed to map %s resource 2\n", | ||
285 | node->full_name); | ||
286 | goto out_unmap; | ||
287 | } | ||
288 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | ||
289 | ret = spu_map_resource(node, 3, | ||
290 | (void __iomem**)&spu_get_pdata(spu)->priv1, NULL); | ||
291 | if (ret) { | ||
292 | pr_debug("spu_new: failed to map %s resource 3\n", | ||
293 | node->full_name); | ||
294 | goto out_unmap; | ||
295 | } | ||
296 | pr_debug("spu_new: %s maps:\n", node->full_name); | ||
297 | pr_debug(" local store : 0x%016lx -> 0x%p\n", | ||
298 | spu->local_store_phys, spu->local_store); | ||
299 | pr_debug(" problem state : 0x%016lx -> 0x%p\n", | ||
300 | spu->problem_phys, spu->problem); | ||
301 | pr_debug(" priv2 : 0x%p\n", spu->priv2); | ||
302 | pr_debug(" priv1 : 0x%p\n", | ||
303 | spu_get_pdata(spu)->priv1); | ||
304 | |||
305 | return 0; | ||
306 | |||
307 | out_unmap: | ||
308 | spu_unmap(spu); | ||
309 | out: | ||
310 | pr_debug("failed to map spe %s: %d\n", spu->name, ret); | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static int __init of_enumerate_spus(int (*fn)(void *data)) | ||
315 | { | ||
316 | int ret; | ||
317 | struct device_node *node; | ||
318 | |||
319 | ret = -ENODEV; | ||
320 | for (node = of_find_node_by_type(NULL, "spe"); | ||
321 | node; node = of_find_node_by_type(node, "spe")) { | ||
322 | ret = fn(node); | ||
323 | if (ret) { | ||
324 | printk(KERN_WARNING "%s: Error initializing %s\n", | ||
325 | __FUNCTION__, node->name); | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | static int __init of_create_spu(struct spu *spu, void *data) | ||
333 | { | ||
334 | int ret; | ||
335 | struct device_node *spe = (struct device_node *)data; | ||
336 | |||
337 | spu->pdata = kzalloc(sizeof(struct spu_pdata), | ||
338 | GFP_KERNEL); | ||
339 | if (!spu->pdata) { | ||
340 | ret = -ENOMEM; | ||
341 | goto out; | ||
342 | } | ||
343 | |||
344 | spu->node = find_spu_node_id(spe); | ||
345 | if (spu->node >= MAX_NUMNODES) { | ||
346 | printk(KERN_WARNING "SPE %s on node %d ignored," | ||
347 | " node number too big\n", spe->full_name, spu->node); | ||
348 | printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); | ||
349 | ret = -ENODEV; | ||
350 | goto out_free; | ||
351 | } | ||
352 | |||
353 | spu_get_pdata(spu)->nid = of_node_to_nid(spe); | ||
354 | if (spu_get_pdata(spu)->nid == -1) | ||
355 | spu_get_pdata(spu)->nid = 0; | ||
356 | |||
357 | ret = spu_map_device(spu, spe); | ||
358 | /* try old method */ | ||
359 | if (ret) | ||
360 | ret = spu_map_device_old(spu, spe); | ||
361 | if (ret) | ||
362 | goto out_free; | ||
363 | |||
364 | ret = spu_map_interrupts(spu, spe); | ||
365 | if (ret) | ||
366 | ret = spu_map_interrupts_old(spu, spe); | ||
367 | if (ret) | ||
368 | goto out_unmap; | ||
369 | |||
370 | spu_get_pdata(spu)->devnode = of_node_get(spe); | ||
371 | |||
372 | pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n", spu->name, | ||
373 | spu->local_store, spu->problem, spu_get_pdata(spu)->priv1, | ||
374 | spu->priv2, spu->number); | ||
375 | goto out; | ||
376 | |||
377 | out_unmap: | ||
378 | spu_unmap(spu); | ||
379 | out_free: | ||
380 | kfree(spu->pdata); | ||
381 | spu->pdata = NULL; | ||
382 | out: | ||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | static int of_destroy_spu(struct spu *spu) | ||
387 | { | ||
388 | spu_unmap(spu); | ||
389 | of_node_put(spu_get_pdata(spu)->devnode); | ||
390 | kfree(spu->pdata); | ||
391 | spu->pdata = NULL; | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | const struct spu_management_ops spu_management_of_ops = { | ||
396 | .enumerate_spus = of_enumerate_spus, | ||
397 | .create_spu = of_create_spu, | ||
398 | .destroy_spu = of_destroy_spu, | ||
399 | }; | ||
28 | 400 | ||
29 | static void int_mask_and(struct spu *spu, int class, u64 mask) | 401 | static void int_mask_and(struct spu *spu, int class, u64 mask) |
30 | { | 402 | { |
31 | u64 old_mask; | 403 | u64 old_mask; |
32 | 404 | ||
33 | old_mask = in_be64(&spu->priv1->int_mask_RW[class]); | 405 | old_mask = in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]); |
34 | out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); | 406 | out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class], |
407 | old_mask & mask); | ||
35 | } | 408 | } |
36 | 409 | ||
37 | static void int_mask_or(struct spu *spu, int class, u64 mask) | 410 | static void int_mask_or(struct spu *spu, int class, u64 mask) |
38 | { | 411 | { |
39 | u64 old_mask; | 412 | u64 old_mask; |
40 | 413 | ||
41 | old_mask = in_be64(&spu->priv1->int_mask_RW[class]); | 414 | old_mask = in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]); |
42 | out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); | 415 | out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class], |
416 | old_mask | mask); | ||
43 | } | 417 | } |
44 | 418 | ||
45 | static void int_mask_set(struct spu *spu, int class, u64 mask) | 419 | static void int_mask_set(struct spu *spu, int class, u64 mask) |
46 | { | 420 | { |
47 | out_be64(&spu->priv1->int_mask_RW[class], mask); | 421 | out_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class], mask); |
48 | } | 422 | } |
49 | 423 | ||
50 | static u64 int_mask_get(struct spu *spu, int class) | 424 | static u64 int_mask_get(struct spu *spu, int class) |
51 | { | 425 | { |
52 | return in_be64(&spu->priv1->int_mask_RW[class]); | 426 | return in_be64(&spu_get_pdata(spu)->priv1->int_mask_RW[class]); |
53 | } | 427 | } |
54 | 428 | ||
55 | static void int_stat_clear(struct spu *spu, int class, u64 stat) | 429 | static void int_stat_clear(struct spu *spu, int class, u64 stat) |
56 | { | 430 | { |
57 | out_be64(&spu->priv1->int_stat_RW[class], stat); | 431 | out_be64(&spu_get_pdata(spu)->priv1->int_stat_RW[class], stat); |
58 | } | 432 | } |
59 | 433 | ||
60 | static u64 int_stat_get(struct spu *spu, int class) | 434 | static u64 int_stat_get(struct spu *spu, int class) |
61 | { | 435 | { |
62 | return in_be64(&spu->priv1->int_stat_RW[class]); | 436 | return in_be64(&spu_get_pdata(spu)->priv1->int_stat_RW[class]); |
63 | } | 437 | } |
64 | 438 | ||
65 | static void cpu_affinity_set(struct spu *spu, int cpu) | 439 | static void cpu_affinity_set(struct spu *spu, int cpu) |
66 | { | 440 | { |
67 | u64 target = iic_get_target_id(cpu); | 441 | u64 target = iic_get_target_id(cpu); |
68 | u64 route = target << 48 | target << 32 | target << 16; | 442 | u64 route = target << 48 | target << 32 | target << 16; |
69 | out_be64(&spu->priv1->int_route_RW, route); | 443 | out_be64(&spu_get_pdata(spu)->priv1->int_route_RW, route); |
70 | } | 444 | } |
71 | 445 | ||
72 | static u64 mfc_dar_get(struct spu *spu) | 446 | static u64 mfc_dar_get(struct spu *spu) |
73 | { | 447 | { |
74 | return in_be64(&spu->priv1->mfc_dar_RW); | 448 | return in_be64(&spu_get_pdata(spu)->priv1->mfc_dar_RW); |
75 | } | 449 | } |
76 | 450 | ||
77 | static u64 mfc_dsisr_get(struct spu *spu) | 451 | static u64 mfc_dsisr_get(struct spu *spu) |
78 | { | 452 | { |
79 | return in_be64(&spu->priv1->mfc_dsisr_RW); | 453 | return in_be64(&spu_get_pdata(spu)->priv1->mfc_dsisr_RW); |
80 | } | 454 | } |
81 | 455 | ||
82 | static void mfc_dsisr_set(struct spu *spu, u64 dsisr) | 456 | static void mfc_dsisr_set(struct spu *spu, u64 dsisr) |
83 | { | 457 | { |
84 | out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); | 458 | out_be64(&spu_get_pdata(spu)->priv1->mfc_dsisr_RW, dsisr); |
85 | } | 459 | } |
86 | 460 | ||
87 | static void mfc_sdr_set(struct spu *spu, u64 sdr) | 461 | static void mfc_sdr_setup(struct spu *spu) |
88 | { | 462 | { |
89 | out_be64(&spu->priv1->mfc_sdr_RW, sdr); | 463 | out_be64(&spu_get_pdata(spu)->priv1->mfc_sdr_RW, mfspr(SPRN_SDR1)); |
90 | } | 464 | } |
91 | 465 | ||
92 | static void mfc_sr1_set(struct spu *spu, u64 sr1) | 466 | static void mfc_sr1_set(struct spu *spu, u64 sr1) |
93 | { | 467 | { |
94 | out_be64(&spu->priv1->mfc_sr1_RW, sr1); | 468 | out_be64(&spu_get_pdata(spu)->priv1->mfc_sr1_RW, sr1); |
95 | } | 469 | } |
96 | 470 | ||
97 | static u64 mfc_sr1_get(struct spu *spu) | 471 | static u64 mfc_sr1_get(struct spu *spu) |
98 | { | 472 | { |
99 | return in_be64(&spu->priv1->mfc_sr1_RW); | 473 | return in_be64(&spu_get_pdata(spu)->priv1->mfc_sr1_RW); |
100 | } | 474 | } |
101 | 475 | ||
102 | static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) | 476 | static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) |
103 | { | 477 | { |
104 | out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); | 478 | out_be64(&spu_get_pdata(spu)->priv1->mfc_tclass_id_RW, tclass_id); |
105 | } | 479 | } |
106 | 480 | ||
107 | static u64 mfc_tclass_id_get(struct spu *spu) | 481 | static u64 mfc_tclass_id_get(struct spu *spu) |
108 | { | 482 | { |
109 | return in_be64(&spu->priv1->mfc_tclass_id_RW); | 483 | return in_be64(&spu_get_pdata(spu)->priv1->mfc_tclass_id_RW); |
110 | } | 484 | } |
111 | 485 | ||
112 | static void tlb_invalidate(struct spu *spu) | 486 | static void tlb_invalidate(struct spu *spu) |
113 | { | 487 | { |
114 | out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); | 488 | out_be64(&spu_get_pdata(spu)->priv1->tlb_invalidate_entry_W, 0ul); |
115 | } | 489 | } |
116 | 490 | ||
117 | static void resource_allocation_groupID_set(struct spu *spu, u64 id) | 491 | static void resource_allocation_groupID_set(struct spu *spu, u64 id) |
118 | { | 492 | { |
119 | out_be64(&spu->priv1->resource_allocation_groupID_RW, id); | 493 | out_be64(&spu_get_pdata(spu)->priv1->resource_allocation_groupID_RW, |
494 | id); | ||
120 | } | 495 | } |
121 | 496 | ||
122 | static u64 resource_allocation_groupID_get(struct spu *spu) | 497 | static u64 resource_allocation_groupID_get(struct spu *spu) |
123 | { | 498 | { |
124 | return in_be64(&spu->priv1->resource_allocation_groupID_RW); | 499 | return in_be64( |
500 | &spu_get_pdata(spu)->priv1->resource_allocation_groupID_RW); | ||
125 | } | 501 | } |
126 | 502 | ||
127 | static void resource_allocation_enable_set(struct spu *spu, u64 enable) | 503 | static void resource_allocation_enable_set(struct spu *spu, u64 enable) |
128 | { | 504 | { |
129 | out_be64(&spu->priv1->resource_allocation_enable_RW, enable); | 505 | out_be64(&spu_get_pdata(spu)->priv1->resource_allocation_enable_RW, |
506 | enable); | ||
130 | } | 507 | } |
131 | 508 | ||
132 | static u64 resource_allocation_enable_get(struct spu *spu) | 509 | static u64 resource_allocation_enable_get(struct spu *spu) |
133 | { | 510 | { |
134 | return in_be64(&spu->priv1->resource_allocation_enable_RW); | 511 | return in_be64( |
512 | &spu_get_pdata(spu)->priv1->resource_allocation_enable_RW); | ||
135 | } | 513 | } |
136 | 514 | ||
137 | const struct spu_priv1_ops spu_priv1_mmio_ops = | 515 | const struct spu_priv1_ops spu_priv1_mmio_ops = |
@@ -146,7 +524,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops = | |||
146 | .mfc_dar_get = mfc_dar_get, | 524 | .mfc_dar_get = mfc_dar_get, |
147 | .mfc_dsisr_get = mfc_dsisr_get, | 525 | .mfc_dsisr_get = mfc_dsisr_get, |
148 | .mfc_dsisr_set = mfc_dsisr_set, | 526 | .mfc_dsisr_set = mfc_dsisr_set, |
149 | .mfc_sdr_set = mfc_sdr_set, | 527 | .mfc_sdr_setup = mfc_sdr_setup, |
150 | .mfc_sr1_set = mfc_sr1_set, | 528 | .mfc_sr1_set = mfc_sr1_set, |
151 | .mfc_sr1_get = mfc_sr1_get, | 529 | .mfc_sr1_get = mfc_sr1_get, |
152 | .mfc_tclass_id_set = mfc_tclass_id_set, | 530 | .mfc_tclass_id_set = mfc_tclass_id_set, |
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.h b/arch/powerpc/platforms/cell/spu_priv1_mmio.h new file mode 100644 index 00000000000..7b62bd1cc25 --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * spu hypervisor abstraction for direct hardware access. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef SPU_PRIV1_MMIO_H | ||
22 | #define SPU_PRIV1_MMIO_H | ||
23 | |||
24 | struct device_node *spu_devnode(struct spu *spu); | ||
25 | |||
26 | #endif /* SPU_PRIV1_MMIO_H */ | ||
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index ecdfbb35f82..472217d19fa 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | obj-y += switch.o | 1 | obj-y += switch.o |
2 | 2 | ||
3 | obj-$(CONFIG_SPU_FS) += spufs.o | 3 | obj-$(CONFIG_SPU_FS) += spufs.o |
4 | spufs-y += inode.o file.o context.o syscalls.o | 4 | spufs-y += inode.o file.o context.o syscalls.o coredump.o |
5 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o | 5 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o |
6 | 6 | ||
7 | # Rules to build switch.o with the help of SPU tool chain | 7 | # Rules to build switch.o with the help of SPU tool chain |
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index 2d22cd59d6f..1898f0d3a8b 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | #include <asm/spu.h> | 37 | #include <asm/spu.h> |
38 | #include <asm/spu_csa.h> | 38 | #include <asm/spu_csa.h> |
39 | #include <asm/spu_info.h> | ||
39 | #include <asm/mmu_context.h> | 40 | #include <asm/mmu_context.h> |
40 | #include "spufs.h" | 41 | #include "spufs.h" |
41 | 42 | ||
@@ -267,6 +268,11 @@ static char *spu_backing_get_ls(struct spu_context *ctx) | |||
267 | return ctx->csa.lscsa->ls; | 268 | return ctx->csa.lscsa->ls; |
268 | } | 269 | } |
269 | 270 | ||
271 | static u32 spu_backing_runcntl_read(struct spu_context *ctx) | ||
272 | { | ||
273 | return ctx->csa.prob.spu_runcntl_RW; | ||
274 | } | ||
275 | |||
270 | static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val) | 276 | static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val) |
271 | { | 277 | { |
272 | spin_lock(&ctx->csa.register_lock); | 278 | spin_lock(&ctx->csa.register_lock); |
@@ -279,9 +285,26 @@ static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val) | |||
279 | spin_unlock(&ctx->csa.register_lock); | 285 | spin_unlock(&ctx->csa.register_lock); |
280 | } | 286 | } |
281 | 287 | ||
282 | static void spu_backing_runcntl_stop(struct spu_context *ctx) | 288 | static void spu_backing_master_start(struct spu_context *ctx) |
289 | { | ||
290 | struct spu_state *csa = &ctx->csa; | ||
291 | u64 sr1; | ||
292 | |||
293 | spin_lock(&csa->register_lock); | ||
294 | sr1 = csa->priv1.mfc_sr1_RW | MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
295 | csa->priv1.mfc_sr1_RW = sr1; | ||
296 | spin_unlock(&csa->register_lock); | ||
297 | } | ||
298 | |||
299 | static void spu_backing_master_stop(struct spu_context *ctx) | ||
283 | { | 300 | { |
284 | spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP); | 301 | struct spu_state *csa = &ctx->csa; |
302 | u64 sr1; | ||
303 | |||
304 | spin_lock(&csa->register_lock); | ||
305 | sr1 = csa->priv1.mfc_sr1_RW & ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
306 | csa->priv1.mfc_sr1_RW = sr1; | ||
307 | spin_unlock(&csa->register_lock); | ||
285 | } | 308 | } |
286 | 309 | ||
287 | static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, | 310 | static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, |
@@ -345,8 +368,10 @@ struct spu_context_ops spu_backing_ops = { | |||
345 | .npc_write = spu_backing_npc_write, | 368 | .npc_write = spu_backing_npc_write, |
346 | .status_read = spu_backing_status_read, | 369 | .status_read = spu_backing_status_read, |
347 | .get_ls = spu_backing_get_ls, | 370 | .get_ls = spu_backing_get_ls, |
371 | .runcntl_read = spu_backing_runcntl_read, | ||
348 | .runcntl_write = spu_backing_runcntl_write, | 372 | .runcntl_write = spu_backing_runcntl_write, |
349 | .runcntl_stop = spu_backing_runcntl_stop, | 373 | .master_start = spu_backing_master_start, |
374 | .master_stop = spu_backing_master_stop, | ||
350 | .set_mfc_query = spu_backing_set_mfc_query, | 375 | .set_mfc_query = spu_backing_set_mfc_query, |
351 | .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, | 376 | .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, |
352 | .get_mfc_free_elements = spu_backing_get_mfc_free_elements, | 377 | .get_mfc_free_elements = spu_backing_get_mfc_free_elements, |
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 034cf6af53a..0870009f56d 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -120,6 +120,33 @@ void spu_unmap_mappings(struct spu_context *ctx) | |||
120 | unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); | 120 | unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); |
121 | } | 121 | } |
122 | 122 | ||
123 | int spu_acquire_exclusive(struct spu_context *ctx) | ||
124 | { | ||
125 | int ret = 0; | ||
126 | |||
127 | down_write(&ctx->state_sema); | ||
128 | /* ctx is about to be freed, can't acquire any more */ | ||
129 | if (!ctx->owner) { | ||
130 | ret = -EINVAL; | ||
131 | goto out; | ||
132 | } | ||
133 | |||
134 | if (ctx->state == SPU_STATE_SAVED) { | ||
135 | ret = spu_activate(ctx, 0); | ||
136 | if (ret) | ||
137 | goto out; | ||
138 | ctx->state = SPU_STATE_RUNNABLE; | ||
139 | } else { | ||
140 | /* We need to exclude userspace access to the context. */ | ||
141 | spu_unmap_mappings(ctx); | ||
142 | } | ||
143 | |||
144 | out: | ||
145 | if (ret) | ||
146 | up_write(&ctx->state_sema); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
123 | int spu_acquire_runnable(struct spu_context *ctx) | 150 | int spu_acquire_runnable(struct spu_context *ctx) |
124 | { | 151 | { |
125 | int ret = 0; | 152 | int ret = 0; |
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c new file mode 100644 index 00000000000..26945c491f6 --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/coredump.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * SPU core dump code | ||
3 | * | ||
4 | * (C) Copyright 2006 IBM Corp. | ||
5 | * | ||
6 | * Author: Dwayne Grant McConnell <decimal@us.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/elf.h> | ||
24 | #include <linux/file.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/syscalls.h> | ||
29 | |||
30 | #include <asm/uaccess.h> | ||
31 | |||
32 | #include "spufs.h" | ||
33 | |||
34 | struct spufs_ctx_info { | ||
35 | struct list_head list; | ||
36 | int dfd; | ||
37 | int memsize; /* in bytes */ | ||
38 | struct spu_context *ctx; | ||
39 | }; | ||
40 | |||
41 | static LIST_HEAD(ctx_info_list); | ||
42 | |||
43 | static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer, | ||
44 | size_t size, loff_t *off) | ||
45 | { | ||
46 | u64 data; | ||
47 | int ret; | ||
48 | |||
49 | if (spufs_coredump_read[num].read) | ||
50 | return spufs_coredump_read[num].read(ctx, buffer, size, off); | ||
51 | |||
52 | data = spufs_coredump_read[num].get(ctx); | ||
53 | ret = copy_to_user(buffer, &data, 8); | ||
54 | return ret ? -EFAULT : 8; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * These are the only things you should do on a core-file: use only these | ||
59 | * functions to write out all the necessary info. | ||
60 | */ | ||
61 | static int spufs_dump_write(struct file *file, const void *addr, int nr) | ||
62 | { | ||
63 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; | ||
64 | } | ||
65 | |||
66 | static int spufs_dump_seek(struct file *file, loff_t off) | ||
67 | { | ||
68 | if (file->f_op->llseek) { | ||
69 | if (file->f_op->llseek(file, off, 0) != off) | ||
70 | return 0; | ||
71 | } else | ||
72 | file->f_pos = off; | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info) | ||
77 | { | ||
78 | struct spu_context *ctx; | ||
79 | unsigned long long lslr; | ||
80 | |||
81 | ctx = ctx_info->ctx; | ||
82 | lslr = ctx->csa.priv2.spu_lslr_RW; | ||
83 | ctx_info->memsize = lslr + 1; | ||
84 | } | ||
85 | |||
86 | static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) | ||
87 | { | ||
88 | int dfd, memsize, i, sz, total = 0; | ||
89 | char *name; | ||
90 | char fullname[80]; | ||
91 | |||
92 | dfd = ctx_info->dfd; | ||
93 | memsize = ctx_info->memsize; | ||
94 | |||
95 | for (i = 0; spufs_coredump_read[i].name; i++) { | ||
96 | name = spufs_coredump_read[i].name; | ||
97 | sz = spufs_coredump_read[i].size; | ||
98 | |||
99 | sprintf(fullname, "SPU/%d/%s", dfd, name); | ||
100 | |||
101 | total += sizeof(struct elf_note); | ||
102 | total += roundup(strlen(fullname) + 1, 4); | ||
103 | if (!strcmp(name, "mem")) | ||
104 | total += roundup(memsize, 4); | ||
105 | else | ||
106 | total += roundup(sz, 4); | ||
107 | } | ||
108 | |||
109 | return total; | ||
110 | } | ||
111 | |||
112 | static int spufs_add_one_context(struct file *file, int dfd) | ||
113 | { | ||
114 | struct spu_context *ctx; | ||
115 | struct spufs_ctx_info *ctx_info; | ||
116 | int size; | ||
117 | |||
118 | ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx; | ||
119 | if (ctx->flags & SPU_CREATE_NOSCHED) | ||
120 | return 0; | ||
121 | |||
122 | ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL); | ||
123 | if (unlikely(!ctx_info)) | ||
124 | return -ENOMEM; | ||
125 | |||
126 | ctx_info->dfd = dfd; | ||
127 | ctx_info->ctx = ctx; | ||
128 | |||
129 | spufs_fill_memsize(ctx_info); | ||
130 | |||
131 | size = spufs_ctx_note_size(ctx_info); | ||
132 | list_add(&ctx_info->list, &ctx_info_list); | ||
133 | return size; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * The additional architecture-specific notes for Cell are various | ||
138 | * context files in the spu context. | ||
139 | * | ||
140 | * This function iterates over all open file descriptors and sees | ||
141 | * if they are a directory in spufs. In that case we use spufs | ||
142 | * internal functionality to dump them without needing to actually | ||
143 | * open the files. | ||
144 | */ | ||
145 | static int spufs_arch_notes_size(void) | ||
146 | { | ||
147 | struct fdtable *fdt = files_fdtable(current->files); | ||
148 | int size = 0, fd; | ||
149 | |||
150 | for (fd = 0; fd < fdt->max_fdset && fd < fdt->max_fds; fd++) { | ||
151 | if (FD_ISSET(fd, fdt->open_fds)) { | ||
152 | struct file *file = fcheck(fd); | ||
153 | |||
154 | if (file && file->f_op == &spufs_context_fops) { | ||
155 | int rval = spufs_add_one_context(file, fd); | ||
156 | if (rval < 0) | ||
157 | break; | ||
158 | size += rval; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return size; | ||
164 | } | ||
165 | |||
166 | static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, | ||
167 | struct file *file) | ||
168 | { | ||
169 | struct spu_context *ctx; | ||
170 | loff_t pos = 0; | ||
171 | int sz, dfd, rc, total = 0; | ||
172 | const int bufsz = 4096; | ||
173 | char *name; | ||
174 | char fullname[80], *buf; | ||
175 | struct elf_note en; | ||
176 | |||
177 | buf = kmalloc(bufsz, GFP_KERNEL); | ||
178 | if (!buf) | ||
179 | return; | ||
180 | |||
181 | dfd = ctx_info->dfd; | ||
182 | name = spufs_coredump_read[i].name; | ||
183 | |||
184 | if (!strcmp(name, "mem")) | ||
185 | sz = ctx_info->memsize; | ||
186 | else | ||
187 | sz = spufs_coredump_read[i].size; | ||
188 | |||
189 | ctx = ctx_info->ctx; | ||
190 | if (!ctx) { | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | sprintf(fullname, "SPU/%d/%s", dfd, name); | ||
195 | en.n_namesz = strlen(fullname) + 1; | ||
196 | en.n_descsz = sz; | ||
197 | en.n_type = NT_SPU; | ||
198 | |||
199 | if (!spufs_dump_write(file, &en, sizeof(en))) | ||
200 | return; | ||
201 | if (!spufs_dump_write(file, fullname, en.n_namesz)) | ||
202 | return; | ||
203 | if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4))) | ||
204 | return; | ||
205 | |||
206 | do { | ||
207 | rc = do_coredump_read(i, ctx, buf, bufsz, &pos); | ||
208 | if (rc > 0) { | ||
209 | if (!spufs_dump_write(file, buf, rc)) | ||
210 | return; | ||
211 | total += rc; | ||
212 | } | ||
213 | } while (rc == bufsz && total < sz); | ||
214 | |||
215 | spufs_dump_seek(file, roundup((unsigned long)file->f_pos | ||
216 | - total + sz, 4)); | ||
217 | } | ||
218 | |||
219 | static void spufs_arch_write_notes(struct file *file) | ||
220 | { | ||
221 | int j; | ||
222 | struct spufs_ctx_info *ctx_info, *next; | ||
223 | |||
224 | list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) { | ||
225 | spu_acquire_saved(ctx_info->ctx); | ||
226 | for (j = 0; j < spufs_coredump_num_notes; j++) | ||
227 | spufs_arch_write_note(ctx_info, j, file); | ||
228 | spu_release(ctx_info->ctx); | ||
229 | list_del(&ctx_info->list); | ||
230 | kfree(ctx_info); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | struct spu_coredump_calls spufs_coredump_calls = { | ||
235 | .arch_notes_size = spufs_arch_notes_size, | ||
236 | .arch_write_notes = spufs_arch_write_notes, | ||
237 | .owner = THIS_MODULE, | ||
238 | }; | ||
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 533e2723e18..347eff56fcb 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -32,13 +32,13 @@ | |||
32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
33 | #include <asm/semaphore.h> | 33 | #include <asm/semaphore.h> |
34 | #include <asm/spu.h> | 34 | #include <asm/spu.h> |
35 | #include <asm/spu_info.h> | ||
35 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
36 | 37 | ||
37 | #include "spufs.h" | 38 | #include "spufs.h" |
38 | 39 | ||
39 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) | 40 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) |
40 | 41 | ||
41 | |||
42 | static int | 42 | static int |
43 | spufs_mem_open(struct inode *inode, struct file *file) | 43 | spufs_mem_open(struct inode *inode, struct file *file) |
44 | { | 44 | { |
@@ -51,18 +51,23 @@ spufs_mem_open(struct inode *inode, struct file *file) | |||
51 | } | 51 | } |
52 | 52 | ||
53 | static ssize_t | 53 | static ssize_t |
54 | __spufs_mem_read(struct spu_context *ctx, char __user *buffer, | ||
55 | size_t size, loff_t *pos) | ||
56 | { | ||
57 | char *local_store = ctx->ops->get_ls(ctx); | ||
58 | return simple_read_from_buffer(buffer, size, pos, local_store, | ||
59 | LS_SIZE); | ||
60 | } | ||
61 | |||
62 | static ssize_t | ||
54 | spufs_mem_read(struct file *file, char __user *buffer, | 63 | spufs_mem_read(struct file *file, char __user *buffer, |
55 | size_t size, loff_t *pos) | 64 | size_t size, loff_t *pos) |
56 | { | 65 | { |
57 | struct spu_context *ctx = file->private_data; | ||
58 | char *local_store; | ||
59 | int ret; | 66 | int ret; |
67 | struct spu_context *ctx = file->private_data; | ||
60 | 68 | ||
61 | spu_acquire(ctx); | 69 | spu_acquire(ctx); |
62 | 70 | ret = __spufs_mem_read(ctx, buffer, size, pos); | |
63 | local_store = ctx->ops->get_ls(ctx); | ||
64 | ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE); | ||
65 | |||
66 | spu_release(ctx); | 71 | spu_release(ctx); |
67 | return ret; | 72 | return ret; |
68 | } | 73 | } |
@@ -104,11 +109,11 @@ spufs_mem_mmap_nopage(struct vm_area_struct *vma, | |||
104 | 109 | ||
105 | if (ctx->state == SPU_STATE_SAVED) { | 110 | if (ctx->state == SPU_STATE_SAVED) { |
106 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 111 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
107 | & ~(_PAGE_NO_CACHE | _PAGE_GUARDED)); | 112 | & ~_PAGE_NO_CACHE); |
108 | page = vmalloc_to_page(ctx->csa.lscsa->ls + offset); | 113 | page = vmalloc_to_page(ctx->csa.lscsa->ls + offset); |
109 | } else { | 114 | } else { |
110 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 115 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
111 | | _PAGE_NO_CACHE | _PAGE_GUARDED); | 116 | | _PAGE_NO_CACHE); |
112 | page = pfn_to_page((ctx->spu->local_store_phys + offset) | 117 | page = pfn_to_page((ctx->spu->local_store_phys + offset) |
113 | >> PAGE_SHIFT); | 118 | >> PAGE_SHIFT); |
114 | } | 119 | } |
@@ -131,7 +136,7 @@ spufs_mem_mmap(struct file *file, struct vm_area_struct *vma) | |||
131 | if (!(vma->vm_flags & VM_SHARED)) | 136 | if (!(vma->vm_flags & VM_SHARED)) |
132 | return -EINVAL; | 137 | return -EINVAL; |
133 | 138 | ||
134 | /* FIXME: */ | 139 | vma->vm_flags |= VM_IO; |
135 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 140 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
136 | | _PAGE_NO_CACHE); | 141 | | _PAGE_NO_CACHE); |
137 | 142 | ||
@@ -200,7 +205,7 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma) | |||
200 | if (!(vma->vm_flags & VM_SHARED)) | 205 | if (!(vma->vm_flags & VM_SHARED)) |
201 | return -EINVAL; | 206 | return -EINVAL; |
202 | 207 | ||
203 | vma->vm_flags |= VM_RESERVED; | 208 | vma->vm_flags |= VM_IO; |
204 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 209 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
205 | | _PAGE_NO_CACHE | _PAGE_GUARDED); | 210 | | _PAGE_NO_CACHE | _PAGE_GUARDED); |
206 | 211 | ||
@@ -261,18 +266,23 @@ spufs_regs_open(struct inode *inode, struct file *file) | |||
261 | } | 266 | } |
262 | 267 | ||
263 | static ssize_t | 268 | static ssize_t |
269 | __spufs_regs_read(struct spu_context *ctx, char __user *buffer, | ||
270 | size_t size, loff_t *pos) | ||
271 | { | ||
272 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | ||
273 | return simple_read_from_buffer(buffer, size, pos, | ||
274 | lscsa->gprs, sizeof lscsa->gprs); | ||
275 | } | ||
276 | |||
277 | static ssize_t | ||
264 | spufs_regs_read(struct file *file, char __user *buffer, | 278 | spufs_regs_read(struct file *file, char __user *buffer, |
265 | size_t size, loff_t *pos) | 279 | size_t size, loff_t *pos) |
266 | { | 280 | { |
267 | struct spu_context *ctx = file->private_data; | ||
268 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | ||
269 | int ret; | 281 | int ret; |
282 | struct spu_context *ctx = file->private_data; | ||
270 | 283 | ||
271 | spu_acquire_saved(ctx); | 284 | spu_acquire_saved(ctx); |
272 | 285 | ret = __spufs_regs_read(ctx, buffer, size, pos); | |
273 | ret = simple_read_from_buffer(buffer, size, pos, | ||
274 | lscsa->gprs, sizeof lscsa->gprs); | ||
275 | |||
276 | spu_release(ctx); | 286 | spu_release(ctx); |
277 | return ret; | 287 | return ret; |
278 | } | 288 | } |
@@ -307,18 +317,23 @@ static struct file_operations spufs_regs_fops = { | |||
307 | }; | 317 | }; |
308 | 318 | ||
309 | static ssize_t | 319 | static ssize_t |
320 | __spufs_fpcr_read(struct spu_context *ctx, char __user * buffer, | ||
321 | size_t size, loff_t * pos) | ||
322 | { | ||
323 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | ||
324 | return simple_read_from_buffer(buffer, size, pos, | ||
325 | &lscsa->fpcr, sizeof(lscsa->fpcr)); | ||
326 | } | ||
327 | |||
328 | static ssize_t | ||
310 | spufs_fpcr_read(struct file *file, char __user * buffer, | 329 | spufs_fpcr_read(struct file *file, char __user * buffer, |
311 | size_t size, loff_t * pos) | 330 | size_t size, loff_t * pos) |
312 | { | 331 | { |
313 | struct spu_context *ctx = file->private_data; | ||
314 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | ||
315 | int ret; | 332 | int ret; |
333 | struct spu_context *ctx = file->private_data; | ||
316 | 334 | ||
317 | spu_acquire_saved(ctx); | 335 | spu_acquire_saved(ctx); |
318 | 336 | ret = __spufs_fpcr_read(ctx, buffer, size, pos); | |
319 | ret = simple_read_from_buffer(buffer, size, pos, | ||
320 | &lscsa->fpcr, sizeof(lscsa->fpcr)); | ||
321 | |||
322 | spu_release(ctx); | 337 | spu_release(ctx); |
323 | return ret; | 338 | return ret; |
324 | } | 339 | } |
@@ -718,23 +733,41 @@ static int spufs_signal1_open(struct inode *inode, struct file *file) | |||
718 | return nonseekable_open(inode, file); | 733 | return nonseekable_open(inode, file); |
719 | } | 734 | } |
720 | 735 | ||
721 | static ssize_t spufs_signal1_read(struct file *file, char __user *buf, | 736 | static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf, |
722 | size_t len, loff_t *pos) | 737 | size_t len, loff_t *pos) |
723 | { | 738 | { |
724 | struct spu_context *ctx = file->private_data; | 739 | int ret = 0; |
725 | u32 data; | 740 | u32 data; |
726 | 741 | ||
727 | if (len < 4) | 742 | if (len < 4) |
728 | return -EINVAL; | 743 | return -EINVAL; |
729 | 744 | ||
730 | spu_acquire(ctx); | 745 | if (ctx->csa.spu_chnlcnt_RW[3]) { |
731 | data = ctx->ops->signal1_read(ctx); | 746 | data = ctx->csa.spu_chnldata_RW[3]; |
732 | spu_release(ctx); | 747 | ret = 4; |
748 | } | ||
749 | |||
750 | if (!ret) | ||
751 | goto out; | ||
733 | 752 | ||
734 | if (copy_to_user(buf, &data, 4)) | 753 | if (copy_to_user(buf, &data, 4)) |
735 | return -EFAULT; | 754 | return -EFAULT; |
736 | 755 | ||
737 | return 4; | 756 | out: |
757 | return ret; | ||
758 | } | ||
759 | |||
760 | static ssize_t spufs_signal1_read(struct file *file, char __user *buf, | ||
761 | size_t len, loff_t *pos) | ||
762 | { | ||
763 | int ret; | ||
764 | struct spu_context *ctx = file->private_data; | ||
765 | |||
766 | spu_acquire_saved(ctx); | ||
767 | ret = __spufs_signal1_read(ctx, buf, len, pos); | ||
768 | spu_release(ctx); | ||
769 | |||
770 | return ret; | ||
738 | } | 771 | } |
739 | 772 | ||
740 | static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, | 773 | static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, |
@@ -782,7 +815,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) | |||
782 | if (!(vma->vm_flags & VM_SHARED)) | 815 | if (!(vma->vm_flags & VM_SHARED)) |
783 | return -EINVAL; | 816 | return -EINVAL; |
784 | 817 | ||
785 | vma->vm_flags |= VM_RESERVED; | 818 | vma->vm_flags |= VM_IO; |
786 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 819 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
787 | | _PAGE_NO_CACHE | _PAGE_GUARDED); | 820 | | _PAGE_NO_CACHE | _PAGE_GUARDED); |
788 | 821 | ||
@@ -807,25 +840,41 @@ static int spufs_signal2_open(struct inode *inode, struct file *file) | |||
807 | return nonseekable_open(inode, file); | 840 | return nonseekable_open(inode, file); |
808 | } | 841 | } |
809 | 842 | ||
810 | static ssize_t spufs_signal2_read(struct file *file, char __user *buf, | 843 | static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf, |
811 | size_t len, loff_t *pos) | 844 | size_t len, loff_t *pos) |
812 | { | 845 | { |
813 | struct spu_context *ctx; | 846 | int ret = 0; |
814 | u32 data; | 847 | u32 data; |
815 | 848 | ||
816 | ctx = file->private_data; | ||
817 | |||
818 | if (len < 4) | 849 | if (len < 4) |
819 | return -EINVAL; | 850 | return -EINVAL; |
820 | 851 | ||
821 | spu_acquire(ctx); | 852 | if (ctx->csa.spu_chnlcnt_RW[4]) { |
822 | data = ctx->ops->signal2_read(ctx); | 853 | data = ctx->csa.spu_chnldata_RW[4]; |
823 | spu_release(ctx); | 854 | ret = 4; |
855 | } | ||
856 | |||
857 | if (!ret) | ||
858 | goto out; | ||
824 | 859 | ||
825 | if (copy_to_user(buf, &data, 4)) | 860 | if (copy_to_user(buf, &data, 4)) |
826 | return -EFAULT; | 861 | return -EFAULT; |
827 | 862 | ||
828 | return 4; | 863 | out: |
864 | return ret; | ||
865 | } | ||
866 | |||
867 | static ssize_t spufs_signal2_read(struct file *file, char __user *buf, | ||
868 | size_t len, loff_t *pos) | ||
869 | { | ||
870 | struct spu_context *ctx = file->private_data; | ||
871 | int ret; | ||
872 | |||
873 | spu_acquire_saved(ctx); | ||
874 | ret = __spufs_signal2_read(ctx, buf, len, pos); | ||
875 | spu_release(ctx); | ||
876 | |||
877 | return ret; | ||
829 | } | 878 | } |
830 | 879 | ||
831 | static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, | 880 | static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, |
@@ -874,8 +923,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) | |||
874 | if (!(vma->vm_flags & VM_SHARED)) | 923 | if (!(vma->vm_flags & VM_SHARED)) |
875 | return -EINVAL; | 924 | return -EINVAL; |
876 | 925 | ||
877 | /* FIXME: */ | 926 | vma->vm_flags |= VM_IO; |
878 | vma->vm_flags |= VM_RESERVED; | ||
879 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 927 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
880 | | _PAGE_NO_CACHE | _PAGE_GUARDED); | 928 | | _PAGE_NO_CACHE | _PAGE_GUARDED); |
881 | 929 | ||
@@ -902,13 +950,19 @@ static void spufs_signal1_type_set(void *data, u64 val) | |||
902 | spu_release(ctx); | 950 | spu_release(ctx); |
903 | } | 951 | } |
904 | 952 | ||
953 | static u64 __spufs_signal1_type_get(void *data) | ||
954 | { | ||
955 | struct spu_context *ctx = data; | ||
956 | return ctx->ops->signal1_type_get(ctx); | ||
957 | } | ||
958 | |||
905 | static u64 spufs_signal1_type_get(void *data) | 959 | static u64 spufs_signal1_type_get(void *data) |
906 | { | 960 | { |
907 | struct spu_context *ctx = data; | 961 | struct spu_context *ctx = data; |
908 | u64 ret; | 962 | u64 ret; |
909 | 963 | ||
910 | spu_acquire(ctx); | 964 | spu_acquire(ctx); |
911 | ret = ctx->ops->signal1_type_get(ctx); | 965 | ret = __spufs_signal1_type_get(data); |
912 | spu_release(ctx); | 966 | spu_release(ctx); |
913 | 967 | ||
914 | return ret; | 968 | return ret; |
@@ -925,13 +979,19 @@ static void spufs_signal2_type_set(void *data, u64 val) | |||
925 | spu_release(ctx); | 979 | spu_release(ctx); |
926 | } | 980 | } |
927 | 981 | ||
982 | static u64 __spufs_signal2_type_get(void *data) | ||
983 | { | ||
984 | struct spu_context *ctx = data; | ||
985 | return ctx->ops->signal2_type_get(ctx); | ||
986 | } | ||
987 | |||
928 | static u64 spufs_signal2_type_get(void *data) | 988 | static u64 spufs_signal2_type_get(void *data) |
929 | { | 989 | { |
930 | struct spu_context *ctx = data; | 990 | struct spu_context *ctx = data; |
931 | u64 ret; | 991 | u64 ret; |
932 | 992 | ||
933 | spu_acquire(ctx); | 993 | spu_acquire(ctx); |
934 | ret = ctx->ops->signal2_type_get(ctx); | 994 | ret = __spufs_signal2_type_get(data); |
935 | spu_release(ctx); | 995 | spu_release(ctx); |
936 | 996 | ||
937 | return ret; | 997 | return ret; |
@@ -958,7 +1018,7 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma) | |||
958 | if (!(vma->vm_flags & VM_SHARED)) | 1018 | if (!(vma->vm_flags & VM_SHARED)) |
959 | return -EINVAL; | 1019 | return -EINVAL; |
960 | 1020 | ||
961 | vma->vm_flags |= VM_RESERVED; | 1021 | vma->vm_flags |= VM_IO; |
962 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 1022 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
963 | | _PAGE_NO_CACHE | _PAGE_GUARDED); | 1023 | | _PAGE_NO_CACHE | _PAGE_GUARDED); |
964 | 1024 | ||
@@ -1000,7 +1060,7 @@ static int spufs_psmap_mmap(struct file *file, struct vm_area_struct *vma) | |||
1000 | if (!(vma->vm_flags & VM_SHARED)) | 1060 | if (!(vma->vm_flags & VM_SHARED)) |
1001 | return -EINVAL; | 1061 | return -EINVAL; |
1002 | 1062 | ||
1003 | vma->vm_flags |= VM_RESERVED; | 1063 | vma->vm_flags |= VM_IO; |
1004 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 1064 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
1005 | | _PAGE_NO_CACHE | _PAGE_GUARDED); | 1065 | | _PAGE_NO_CACHE | _PAGE_GUARDED); |
1006 | 1066 | ||
@@ -1041,7 +1101,7 @@ static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma) | |||
1041 | if (!(vma->vm_flags & VM_SHARED)) | 1101 | if (!(vma->vm_flags & VM_SHARED)) |
1042 | return -EINVAL; | 1102 | return -EINVAL; |
1043 | 1103 | ||
1044 | vma->vm_flags |= VM_RESERVED; | 1104 | vma->vm_flags |= VM_IO; |
1045 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | 1105 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
1046 | | _PAGE_NO_CACHE | _PAGE_GUARDED); | 1106 | | _PAGE_NO_CACHE | _PAGE_GUARDED); |
1047 | 1107 | ||
@@ -1265,6 +1325,7 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, | |||
1265 | goto out; | 1325 | goto out; |
1266 | 1326 | ||
1267 | ctx->tagwait |= 1 << cmd.tag; | 1327 | ctx->tagwait |= 1 << cmd.tag; |
1328 | ret = size; | ||
1268 | 1329 | ||
1269 | out: | 1330 | out: |
1270 | return ret; | 1331 | return ret; |
@@ -1360,7 +1421,8 @@ static u64 spufs_npc_get(void *data) | |||
1360 | spu_release(ctx); | 1421 | spu_release(ctx); |
1361 | return ret; | 1422 | return ret; |
1362 | } | 1423 | } |
1363 | DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n") | 1424 | DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, |
1425 | "0x%llx\n") | ||
1364 | 1426 | ||
1365 | static void spufs_decr_set(void *data, u64 val) | 1427 | static void spufs_decr_set(void *data, u64 val) |
1366 | { | 1428 | { |
@@ -1371,18 +1433,24 @@ static void spufs_decr_set(void *data, u64 val) | |||
1371 | spu_release(ctx); | 1433 | spu_release(ctx); |
1372 | } | 1434 | } |
1373 | 1435 | ||
1374 | static u64 spufs_decr_get(void *data) | 1436 | static u64 __spufs_decr_get(void *data) |
1375 | { | 1437 | { |
1376 | struct spu_context *ctx = data; | 1438 | struct spu_context *ctx = data; |
1377 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1439 | struct spu_lscsa *lscsa = ctx->csa.lscsa; |
1440 | return lscsa->decr.slot[0]; | ||
1441 | } | ||
1442 | |||
1443 | static u64 spufs_decr_get(void *data) | ||
1444 | { | ||
1445 | struct spu_context *ctx = data; | ||
1378 | u64 ret; | 1446 | u64 ret; |
1379 | spu_acquire_saved(ctx); | 1447 | spu_acquire_saved(ctx); |
1380 | ret = lscsa->decr.slot[0]; | 1448 | ret = __spufs_decr_get(data); |
1381 | spu_release(ctx); | 1449 | spu_release(ctx); |
1382 | return ret; | 1450 | return ret; |
1383 | } | 1451 | } |
1384 | DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, | 1452 | DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set, |
1385 | "%llx\n") | 1453 | "0x%llx\n") |
1386 | 1454 | ||
1387 | static void spufs_decr_status_set(void *data, u64 val) | 1455 | static void spufs_decr_status_set(void *data, u64 val) |
1388 | { | 1456 | { |
@@ -1393,62 +1461,76 @@ static void spufs_decr_status_set(void *data, u64 val) | |||
1393 | spu_release(ctx); | 1461 | spu_release(ctx); |
1394 | } | 1462 | } |
1395 | 1463 | ||
1396 | static u64 spufs_decr_status_get(void *data) | 1464 | static u64 __spufs_decr_status_get(void *data) |
1397 | { | 1465 | { |
1398 | struct spu_context *ctx = data; | 1466 | struct spu_context *ctx = data; |
1399 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1467 | struct spu_lscsa *lscsa = ctx->csa.lscsa; |
1468 | return lscsa->decr_status.slot[0]; | ||
1469 | } | ||
1470 | |||
1471 | static u64 spufs_decr_status_get(void *data) | ||
1472 | { | ||
1473 | struct spu_context *ctx = data; | ||
1400 | u64 ret; | 1474 | u64 ret; |
1401 | spu_acquire_saved(ctx); | 1475 | spu_acquire_saved(ctx); |
1402 | ret = lscsa->decr_status.slot[0]; | 1476 | ret = __spufs_decr_status_get(data); |
1403 | spu_release(ctx); | 1477 | spu_release(ctx); |
1404 | return ret; | 1478 | return ret; |
1405 | } | 1479 | } |
1406 | DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, | 1480 | DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get, |
1407 | spufs_decr_status_set, "%llx\n") | 1481 | spufs_decr_status_set, "0x%llx\n") |
1408 | 1482 | ||
1409 | static void spufs_spu_tag_mask_set(void *data, u64 val) | 1483 | static void spufs_event_mask_set(void *data, u64 val) |
1410 | { | 1484 | { |
1411 | struct spu_context *ctx = data; | 1485 | struct spu_context *ctx = data; |
1412 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1486 | struct spu_lscsa *lscsa = ctx->csa.lscsa; |
1413 | spu_acquire_saved(ctx); | 1487 | spu_acquire_saved(ctx); |
1414 | lscsa->tag_mask.slot[0] = (u32) val; | 1488 | lscsa->event_mask.slot[0] = (u32) val; |
1415 | spu_release(ctx); | 1489 | spu_release(ctx); |
1416 | } | 1490 | } |
1417 | 1491 | ||
1418 | static u64 spufs_spu_tag_mask_get(void *data) | 1492 | static u64 __spufs_event_mask_get(void *data) |
1419 | { | 1493 | { |
1420 | struct spu_context *ctx = data; | 1494 | struct spu_context *ctx = data; |
1421 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1495 | struct spu_lscsa *lscsa = ctx->csa.lscsa; |
1496 | return lscsa->event_mask.slot[0]; | ||
1497 | } | ||
1498 | |||
1499 | static u64 spufs_event_mask_get(void *data) | ||
1500 | { | ||
1501 | struct spu_context *ctx = data; | ||
1422 | u64 ret; | 1502 | u64 ret; |
1423 | spu_acquire_saved(ctx); | 1503 | spu_acquire_saved(ctx); |
1424 | ret = lscsa->tag_mask.slot[0]; | 1504 | ret = __spufs_event_mask_get(data); |
1425 | spu_release(ctx); | 1505 | spu_release(ctx); |
1426 | return ret; | 1506 | return ret; |
1427 | } | 1507 | } |
1428 | DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get, | 1508 | DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, |
1429 | spufs_spu_tag_mask_set, "%llx\n") | 1509 | spufs_event_mask_set, "0x%llx\n") |
1430 | 1510 | ||
1431 | static void spufs_event_mask_set(void *data, u64 val) | 1511 | static u64 __spufs_event_status_get(void *data) |
1432 | { | 1512 | { |
1433 | struct spu_context *ctx = data; | 1513 | struct spu_context *ctx = data; |
1434 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1514 | struct spu_state *state = &ctx->csa; |
1435 | spu_acquire_saved(ctx); | 1515 | u64 stat; |
1436 | lscsa->event_mask.slot[0] = (u32) val; | 1516 | stat = state->spu_chnlcnt_RW[0]; |
1437 | spu_release(ctx); | 1517 | if (stat) |
1518 | return state->spu_chnldata_RW[0]; | ||
1519 | return 0; | ||
1438 | } | 1520 | } |
1439 | 1521 | ||
1440 | static u64 spufs_event_mask_get(void *data) | 1522 | static u64 spufs_event_status_get(void *data) |
1441 | { | 1523 | { |
1442 | struct spu_context *ctx = data; | 1524 | struct spu_context *ctx = data; |
1443 | struct spu_lscsa *lscsa = ctx->csa.lscsa; | 1525 | u64 ret = 0; |
1444 | u64 ret; | 1526 | |
1445 | spu_acquire_saved(ctx); | 1527 | spu_acquire_saved(ctx); |
1446 | ret = lscsa->event_mask.slot[0]; | 1528 | ret = __spufs_event_status_get(data); |
1447 | spu_release(ctx); | 1529 | spu_release(ctx); |
1448 | return ret; | 1530 | return ret; |
1449 | } | 1531 | } |
1450 | DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get, | 1532 | DEFINE_SIMPLE_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get, |
1451 | spufs_event_mask_set, "%llx\n") | 1533 | NULL, "0x%llx\n") |
1452 | 1534 | ||
1453 | static void spufs_srr0_set(void *data, u64 val) | 1535 | static void spufs_srr0_set(void *data, u64 val) |
1454 | { | 1536 | { |
@@ -1470,7 +1552,7 @@ static u64 spufs_srr0_get(void *data) | |||
1470 | return ret; | 1552 | return ret; |
1471 | } | 1553 | } |
1472 | DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, | 1554 | DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, |
1473 | "%llx\n") | 1555 | "0x%llx\n") |
1474 | 1556 | ||
1475 | static u64 spufs_id_get(void *data) | 1557 | static u64 spufs_id_get(void *data) |
1476 | { | 1558 | { |
@@ -1488,12 +1570,18 @@ static u64 spufs_id_get(void *data) | |||
1488 | } | 1570 | } |
1489 | DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") | 1571 | DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n") |
1490 | 1572 | ||
1491 | static u64 spufs_object_id_get(void *data) | 1573 | static u64 __spufs_object_id_get(void *data) |
1492 | { | 1574 | { |
1493 | struct spu_context *ctx = data; | 1575 | struct spu_context *ctx = data; |
1494 | return ctx->object_id; | 1576 | return ctx->object_id; |
1495 | } | 1577 | } |
1496 | 1578 | ||
1579 | static u64 spufs_object_id_get(void *data) | ||
1580 | { | ||
1581 | /* FIXME: Should there really be no locking here? */ | ||
1582 | return __spufs_object_id_get(data); | ||
1583 | } | ||
1584 | |||
1497 | static void spufs_object_id_set(void *data, u64 id) | 1585 | static void spufs_object_id_set(void *data, u64 id) |
1498 | { | 1586 | { |
1499 | struct spu_context *ctx = data; | 1587 | struct spu_context *ctx = data; |
@@ -1503,6 +1591,250 @@ static void spufs_object_id_set(void *data, u64 id) | |||
1503 | DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, | 1591 | DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get, |
1504 | spufs_object_id_set, "0x%llx\n"); | 1592 | spufs_object_id_set, "0x%llx\n"); |
1505 | 1593 | ||
1594 | static u64 __spufs_lslr_get(void *data) | ||
1595 | { | ||
1596 | struct spu_context *ctx = data; | ||
1597 | return ctx->csa.priv2.spu_lslr_RW; | ||
1598 | } | ||
1599 | |||
1600 | static u64 spufs_lslr_get(void *data) | ||
1601 | { | ||
1602 | struct spu_context *ctx = data; | ||
1603 | u64 ret; | ||
1604 | |||
1605 | spu_acquire_saved(ctx); | ||
1606 | ret = __spufs_lslr_get(data); | ||
1607 | spu_release(ctx); | ||
1608 | |||
1609 | return ret; | ||
1610 | } | ||
1611 | DEFINE_SIMPLE_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n") | ||
1612 | |||
1613 | static int spufs_info_open(struct inode *inode, struct file *file) | ||
1614 | { | ||
1615 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
1616 | struct spu_context *ctx = i->i_ctx; | ||
1617 | file->private_data = ctx; | ||
1618 | return 0; | ||
1619 | } | ||
1620 | |||
1621 | static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, | ||
1622 | char __user *buf, size_t len, loff_t *pos) | ||
1623 | { | ||
1624 | u32 mbox_stat; | ||
1625 | u32 data; | ||
1626 | |||
1627 | mbox_stat = ctx->csa.prob.mb_stat_R; | ||
1628 | if (mbox_stat & 0x0000ff) { | ||
1629 | data = ctx->csa.prob.pu_mb_R; | ||
1630 | } | ||
1631 | |||
1632 | return simple_read_from_buffer(buf, len, pos, &data, sizeof data); | ||
1633 | } | ||
1634 | |||
1635 | static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf, | ||
1636 | size_t len, loff_t *pos) | ||
1637 | { | ||
1638 | int ret; | ||
1639 | struct spu_context *ctx = file->private_data; | ||
1640 | |||
1641 | if (!access_ok(VERIFY_WRITE, buf, len)) | ||
1642 | return -EFAULT; | ||
1643 | |||
1644 | spu_acquire_saved(ctx); | ||
1645 | spin_lock(&ctx->csa.register_lock); | ||
1646 | ret = __spufs_mbox_info_read(ctx, buf, len, pos); | ||
1647 | spin_unlock(&ctx->csa.register_lock); | ||
1648 | spu_release(ctx); | ||
1649 | |||
1650 | return ret; | ||
1651 | } | ||
1652 | |||
1653 | static struct file_operations spufs_mbox_info_fops = { | ||
1654 | .open = spufs_info_open, | ||
1655 | .read = spufs_mbox_info_read, | ||
1656 | .llseek = generic_file_llseek, | ||
1657 | }; | ||
1658 | |||
1659 | static ssize_t __spufs_ibox_info_read(struct spu_context *ctx, | ||
1660 | char __user *buf, size_t len, loff_t *pos) | ||
1661 | { | ||
1662 | u32 ibox_stat; | ||
1663 | u32 data; | ||
1664 | |||
1665 | ibox_stat = ctx->csa.prob.mb_stat_R; | ||
1666 | if (ibox_stat & 0xff0000) { | ||
1667 | data = ctx->csa.priv2.puint_mb_R; | ||
1668 | } | ||
1669 | |||
1670 | return simple_read_from_buffer(buf, len, pos, &data, sizeof data); | ||
1671 | } | ||
1672 | |||
1673 | static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf, | ||
1674 | size_t len, loff_t *pos) | ||
1675 | { | ||
1676 | struct spu_context *ctx = file->private_data; | ||
1677 | int ret; | ||
1678 | |||
1679 | if (!access_ok(VERIFY_WRITE, buf, len)) | ||
1680 | return -EFAULT; | ||
1681 | |||
1682 | spu_acquire_saved(ctx); | ||
1683 | spin_lock(&ctx->csa.register_lock); | ||
1684 | ret = __spufs_ibox_info_read(ctx, buf, len, pos); | ||
1685 | spin_unlock(&ctx->csa.register_lock); | ||
1686 | spu_release(ctx); | ||
1687 | |||
1688 | return ret; | ||
1689 | } | ||
1690 | |||
1691 | static struct file_operations spufs_ibox_info_fops = { | ||
1692 | .open = spufs_info_open, | ||
1693 | .read = spufs_ibox_info_read, | ||
1694 | .llseek = generic_file_llseek, | ||
1695 | }; | ||
1696 | |||
1697 | static ssize_t __spufs_wbox_info_read(struct spu_context *ctx, | ||
1698 | char __user *buf, size_t len, loff_t *pos) | ||
1699 | { | ||
1700 | int i, cnt; | ||
1701 | u32 data[4]; | ||
1702 | u32 wbox_stat; | ||
1703 | |||
1704 | wbox_stat = ctx->csa.prob.mb_stat_R; | ||
1705 | cnt = 4 - ((wbox_stat & 0x00ff00) >> 8); | ||
1706 | for (i = 0; i < cnt; i++) { | ||
1707 | data[i] = ctx->csa.spu_mailbox_data[i]; | ||
1708 | } | ||
1709 | |||
1710 | return simple_read_from_buffer(buf, len, pos, &data, | ||
1711 | cnt * sizeof(u32)); | ||
1712 | } | ||
1713 | |||
1714 | static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf, | ||
1715 | size_t len, loff_t *pos) | ||
1716 | { | ||
1717 | struct spu_context *ctx = file->private_data; | ||
1718 | int ret; | ||
1719 | |||
1720 | if (!access_ok(VERIFY_WRITE, buf, len)) | ||
1721 | return -EFAULT; | ||
1722 | |||
1723 | spu_acquire_saved(ctx); | ||
1724 | spin_lock(&ctx->csa.register_lock); | ||
1725 | ret = __spufs_wbox_info_read(ctx, buf, len, pos); | ||
1726 | spin_unlock(&ctx->csa.register_lock); | ||
1727 | spu_release(ctx); | ||
1728 | |||
1729 | return ret; | ||
1730 | } | ||
1731 | |||
1732 | static struct file_operations spufs_wbox_info_fops = { | ||
1733 | .open = spufs_info_open, | ||
1734 | .read = spufs_wbox_info_read, | ||
1735 | .llseek = generic_file_llseek, | ||
1736 | }; | ||
1737 | |||
1738 | static ssize_t __spufs_dma_info_read(struct spu_context *ctx, | ||
1739 | char __user *buf, size_t len, loff_t *pos) | ||
1740 | { | ||
1741 | struct spu_dma_info info; | ||
1742 | struct mfc_cq_sr *qp, *spuqp; | ||
1743 | int i; | ||
1744 | |||
1745 | info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW; | ||
1746 | info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0]; | ||
1747 | info.dma_info_status = ctx->csa.spu_chnldata_RW[24]; | ||
1748 | info.dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25]; | ||
1749 | info.dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27]; | ||
1750 | for (i = 0; i < 16; i++) { | ||
1751 | qp = &info.dma_info_command_data[i]; | ||
1752 | spuqp = &ctx->csa.priv2.spuq[i]; | ||
1753 | |||
1754 | qp->mfc_cq_data0_RW = spuqp->mfc_cq_data0_RW; | ||
1755 | qp->mfc_cq_data1_RW = spuqp->mfc_cq_data1_RW; | ||
1756 | qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW; | ||
1757 | qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW; | ||
1758 | } | ||
1759 | |||
1760 | return simple_read_from_buffer(buf, len, pos, &info, | ||
1761 | sizeof info); | ||
1762 | } | ||
1763 | |||
1764 | static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, | ||
1765 | size_t len, loff_t *pos) | ||
1766 | { | ||
1767 | struct spu_context *ctx = file->private_data; | ||
1768 | int ret; | ||
1769 | |||
1770 | if (!access_ok(VERIFY_WRITE, buf, len)) | ||
1771 | return -EFAULT; | ||
1772 | |||
1773 | spu_acquire_saved(ctx); | ||
1774 | spin_lock(&ctx->csa.register_lock); | ||
1775 | ret = __spufs_dma_info_read(ctx, buf, len, pos); | ||
1776 | spin_unlock(&ctx->csa.register_lock); | ||
1777 | spu_release(ctx); | ||
1778 | |||
1779 | return ret; | ||
1780 | } | ||
1781 | |||
1782 | static struct file_operations spufs_dma_info_fops = { | ||
1783 | .open = spufs_info_open, | ||
1784 | .read = spufs_dma_info_read, | ||
1785 | }; | ||
1786 | |||
1787 | static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx, | ||
1788 | char __user *buf, size_t len, loff_t *pos) | ||
1789 | { | ||
1790 | struct spu_proxydma_info info; | ||
1791 | struct mfc_cq_sr *qp, *puqp; | ||
1792 | int ret = sizeof info; | ||
1793 | int i; | ||
1794 | |||
1795 | if (len < ret) | ||
1796 | return -EINVAL; | ||
1797 | |||
1798 | if (!access_ok(VERIFY_WRITE, buf, len)) | ||
1799 | return -EFAULT; | ||
1800 | |||
1801 | info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW; | ||
1802 | info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW; | ||
1803 | info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R; | ||
1804 | for (i = 0; i < 8; i++) { | ||
1805 | qp = &info.proxydma_info_command_data[i]; | ||
1806 | puqp = &ctx->csa.priv2.puq[i]; | ||
1807 | |||
1808 | qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW; | ||
1809 | qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW; | ||
1810 | qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW; | ||
1811 | qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW; | ||
1812 | } | ||
1813 | |||
1814 | return simple_read_from_buffer(buf, len, pos, &info, | ||
1815 | sizeof info); | ||
1816 | } | ||
1817 | |||
1818 | static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, | ||
1819 | size_t len, loff_t *pos) | ||
1820 | { | ||
1821 | struct spu_context *ctx = file->private_data; | ||
1822 | int ret; | ||
1823 | |||
1824 | spu_acquire_saved(ctx); | ||
1825 | spin_lock(&ctx->csa.register_lock); | ||
1826 | ret = __spufs_proxydma_info_read(ctx, buf, len, pos); | ||
1827 | spin_unlock(&ctx->csa.register_lock); | ||
1828 | spu_release(ctx); | ||
1829 | |||
1830 | return ret; | ||
1831 | } | ||
1832 | |||
1833 | static struct file_operations spufs_proxydma_info_fops = { | ||
1834 | .open = spufs_info_open, | ||
1835 | .read = spufs_proxydma_info_read, | ||
1836 | }; | ||
1837 | |||
1506 | struct tree_descr spufs_dir_contents[] = { | 1838 | struct tree_descr spufs_dir_contents[] = { |
1507 | { "mem", &spufs_mem_fops, 0666, }, | 1839 | { "mem", &spufs_mem_fops, 0666, }, |
1508 | { "regs", &spufs_regs_fops, 0666, }, | 1840 | { "regs", &spufs_regs_fops, 0666, }, |
@@ -1516,18 +1848,70 @@ struct tree_descr spufs_dir_contents[] = { | |||
1516 | { "signal2", &spufs_signal2_fops, 0666, }, | 1848 | { "signal2", &spufs_signal2_fops, 0666, }, |
1517 | { "signal1_type", &spufs_signal1_type, 0666, }, | 1849 | { "signal1_type", &spufs_signal1_type, 0666, }, |
1518 | { "signal2_type", &spufs_signal2_type, 0666, }, | 1850 | { "signal2_type", &spufs_signal2_type, 0666, }, |
1519 | { "mss", &spufs_mss_fops, 0666, }, | ||
1520 | { "mfc", &spufs_mfc_fops, 0666, }, | ||
1521 | { "cntl", &spufs_cntl_fops, 0666, }, | 1851 | { "cntl", &spufs_cntl_fops, 0666, }, |
1522 | { "npc", &spufs_npc_ops, 0666, }, | ||
1523 | { "fpcr", &spufs_fpcr_fops, 0666, }, | 1852 | { "fpcr", &spufs_fpcr_fops, 0666, }, |
1853 | { "lslr", &spufs_lslr_ops, 0444, }, | ||
1854 | { "mfc", &spufs_mfc_fops, 0666, }, | ||
1855 | { "mss", &spufs_mss_fops, 0666, }, | ||
1856 | { "npc", &spufs_npc_ops, 0666, }, | ||
1857 | { "srr0", &spufs_srr0_ops, 0666, }, | ||
1524 | { "decr", &spufs_decr_ops, 0666, }, | 1858 | { "decr", &spufs_decr_ops, 0666, }, |
1525 | { "decr_status", &spufs_decr_status_ops, 0666, }, | 1859 | { "decr_status", &spufs_decr_status_ops, 0666, }, |
1526 | { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, | ||
1527 | { "event_mask", &spufs_event_mask_ops, 0666, }, | 1860 | { "event_mask", &spufs_event_mask_ops, 0666, }, |
1528 | { "srr0", &spufs_srr0_ops, 0666, }, | 1861 | { "event_status", &spufs_event_status_ops, 0444, }, |
1862 | { "psmap", &spufs_psmap_fops, 0666, }, | ||
1863 | { "phys-id", &spufs_id_ops, 0666, }, | ||
1864 | { "object-id", &spufs_object_id_ops, 0666, }, | ||
1865 | { "mbox_info", &spufs_mbox_info_fops, 0444, }, | ||
1866 | { "ibox_info", &spufs_ibox_info_fops, 0444, }, | ||
1867 | { "wbox_info", &spufs_wbox_info_fops, 0444, }, | ||
1868 | { "dma_info", &spufs_dma_info_fops, 0444, }, | ||
1869 | { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, | ||
1870 | {}, | ||
1871 | }; | ||
1872 | |||
1873 | struct tree_descr spufs_dir_nosched_contents[] = { | ||
1874 | { "mem", &spufs_mem_fops, 0666, }, | ||
1875 | { "mbox", &spufs_mbox_fops, 0444, }, | ||
1876 | { "ibox", &spufs_ibox_fops, 0444, }, | ||
1877 | { "wbox", &spufs_wbox_fops, 0222, }, | ||
1878 | { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, | ||
1879 | { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, | ||
1880 | { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, | ||
1881 | { "signal1", &spufs_signal1_fops, 0666, }, | ||
1882 | { "signal2", &spufs_signal2_fops, 0666, }, | ||
1883 | { "signal1_type", &spufs_signal1_type, 0666, }, | ||
1884 | { "signal2_type", &spufs_signal2_type, 0666, }, | ||
1885 | { "mss", &spufs_mss_fops, 0666, }, | ||
1886 | { "mfc", &spufs_mfc_fops, 0666, }, | ||
1887 | { "cntl", &spufs_cntl_fops, 0666, }, | ||
1888 | { "npc", &spufs_npc_ops, 0666, }, | ||
1529 | { "psmap", &spufs_psmap_fops, 0666, }, | 1889 | { "psmap", &spufs_psmap_fops, 0666, }, |
1530 | { "phys-id", &spufs_id_ops, 0666, }, | 1890 | { "phys-id", &spufs_id_ops, 0666, }, |
1531 | { "object-id", &spufs_object_id_ops, 0666, }, | 1891 | { "object-id", &spufs_object_id_ops, 0666, }, |
1532 | {}, | 1892 | {}, |
1533 | }; | 1893 | }; |
1894 | |||
1895 | struct spufs_coredump_reader spufs_coredump_read[] = { | ||
1896 | { "regs", __spufs_regs_read, NULL, 128 * 16 }, | ||
1897 | { "fpcr", __spufs_fpcr_read, NULL, 16 }, | ||
1898 | { "lslr", NULL, __spufs_lslr_get, 11 }, | ||
1899 | { "decr", NULL, __spufs_decr_get, 11 }, | ||
1900 | { "decr_status", NULL, __spufs_decr_status_get, 11 }, | ||
1901 | { "mem", __spufs_mem_read, NULL, 256 * 1024, }, | ||
1902 | { "signal1", __spufs_signal1_read, NULL, 4 }, | ||
1903 | { "signal1_type", NULL, __spufs_signal1_type_get, 2 }, | ||
1904 | { "signal2", __spufs_signal2_read, NULL, 4 }, | ||
1905 | { "signal2_type", NULL, __spufs_signal2_type_get, 2 }, | ||
1906 | { "event_mask", NULL, __spufs_event_mask_get, 8 }, | ||
1907 | { "event_status", NULL, __spufs_event_status_get, 8 }, | ||
1908 | { "mbox_info", __spufs_mbox_info_read, NULL, 4 }, | ||
1909 | { "ibox_info", __spufs_ibox_info_read, NULL, 4 }, | ||
1910 | { "wbox_info", __spufs_wbox_info_read, NULL, 16 }, | ||
1911 | { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 }, | ||
1912 | { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 }, | ||
1913 | { "object-id", NULL, __spufs_object_id_get, 19 }, | ||
1914 | { }, | ||
1915 | }; | ||
1916 | int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1; | ||
1917 | |||
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index d805ffed892..ae42e03b8c8 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c | |||
@@ -135,21 +135,11 @@ static int spu_hw_wbox_write(struct spu_context *ctx, u32 data) | |||
135 | return ret; | 135 | return ret; |
136 | } | 136 | } |
137 | 137 | ||
138 | static u32 spu_hw_signal1_read(struct spu_context *ctx) | ||
139 | { | ||
140 | return in_be32(&ctx->spu->problem->signal_notify1); | ||
141 | } | ||
142 | |||
143 | static void spu_hw_signal1_write(struct spu_context *ctx, u32 data) | 138 | static void spu_hw_signal1_write(struct spu_context *ctx, u32 data) |
144 | { | 139 | { |
145 | out_be32(&ctx->spu->problem->signal_notify1, data); | 140 | out_be32(&ctx->spu->problem->signal_notify1, data); |
146 | } | 141 | } |
147 | 142 | ||
148 | static u32 spu_hw_signal2_read(struct spu_context *ctx) | ||
149 | { | ||
150 | return in_be32(&ctx->spu->problem->signal_notify2); | ||
151 | } | ||
152 | |||
153 | static void spu_hw_signal2_write(struct spu_context *ctx, u32 data) | 143 | static void spu_hw_signal2_write(struct spu_context *ctx, u32 data) |
154 | { | 144 | { |
155 | out_be32(&ctx->spu->problem->signal_notify2, data); | 145 | out_be32(&ctx->spu->problem->signal_notify2, data); |
@@ -217,21 +207,42 @@ static char *spu_hw_get_ls(struct spu_context *ctx) | |||
217 | return ctx->spu->local_store; | 207 | return ctx->spu->local_store; |
218 | } | 208 | } |
219 | 209 | ||
220 | static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) | 210 | static u32 spu_hw_runcntl_read(struct spu_context *ctx) |
221 | { | 211 | { |
222 | eieio(); | 212 | return in_be32(&ctx->spu->problem->spu_runcntl_RW); |
223 | out_be32(&ctx->spu->problem->spu_runcntl_RW, val); | ||
224 | } | 213 | } |
225 | 214 | ||
226 | static void spu_hw_runcntl_stop(struct spu_context *ctx) | 215 | static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val) |
227 | { | 216 | { |
228 | spin_lock_irq(&ctx->spu->register_lock); | 217 | spin_lock_irq(&ctx->spu->register_lock); |
229 | out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP); | 218 | if (val & SPU_RUNCNTL_ISOLATE) |
230 | while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING) | 219 | out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL); |
231 | cpu_relax(); | 220 | out_be32(&ctx->spu->problem->spu_runcntl_RW, val); |
232 | spin_unlock_irq(&ctx->spu->register_lock); | 221 | spin_unlock_irq(&ctx->spu->register_lock); |
233 | } | 222 | } |
234 | 223 | ||
224 | static void spu_hw_master_start(struct spu_context *ctx) | ||
225 | { | ||
226 | struct spu *spu = ctx->spu; | ||
227 | u64 sr1; | ||
228 | |||
229 | spin_lock_irq(&spu->register_lock); | ||
230 | sr1 = spu_mfc_sr1_get(spu) | MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
231 | spu_mfc_sr1_set(spu, sr1); | ||
232 | spin_unlock_irq(&spu->register_lock); | ||
233 | } | ||
234 | |||
235 | static void spu_hw_master_stop(struct spu_context *ctx) | ||
236 | { | ||
237 | struct spu *spu = ctx->spu; | ||
238 | u64 sr1; | ||
239 | |||
240 | spin_lock_irq(&spu->register_lock); | ||
241 | sr1 = spu_mfc_sr1_get(spu) & ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
242 | spu_mfc_sr1_set(spu, sr1); | ||
243 | spin_unlock_irq(&spu->register_lock); | ||
244 | } | ||
245 | |||
235 | static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode) | 246 | static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode) |
236 | { | 247 | { |
237 | struct spu_problem __iomem *prob = ctx->spu->problem; | 248 | struct spu_problem __iomem *prob = ctx->spu->problem; |
@@ -291,9 +302,7 @@ struct spu_context_ops spu_hw_ops = { | |||
291 | .mbox_stat_poll = spu_hw_mbox_stat_poll, | 302 | .mbox_stat_poll = spu_hw_mbox_stat_poll, |
292 | .ibox_read = spu_hw_ibox_read, | 303 | .ibox_read = spu_hw_ibox_read, |
293 | .wbox_write = spu_hw_wbox_write, | 304 | .wbox_write = spu_hw_wbox_write, |
294 | .signal1_read = spu_hw_signal1_read, | ||
295 | .signal1_write = spu_hw_signal1_write, | 305 | .signal1_write = spu_hw_signal1_write, |
296 | .signal2_read = spu_hw_signal2_read, | ||
297 | .signal2_write = spu_hw_signal2_write, | 306 | .signal2_write = spu_hw_signal2_write, |
298 | .signal1_type_set = spu_hw_signal1_type_set, | 307 | .signal1_type_set = spu_hw_signal1_type_set, |
299 | .signal1_type_get = spu_hw_signal1_type_get, | 308 | .signal1_type_get = spu_hw_signal1_type_get, |
@@ -303,8 +312,10 @@ struct spu_context_ops spu_hw_ops = { | |||
303 | .npc_write = spu_hw_npc_write, | 312 | .npc_write = spu_hw_npc_write, |
304 | .status_read = spu_hw_status_read, | 313 | .status_read = spu_hw_status_read, |
305 | .get_ls = spu_hw_get_ls, | 314 | .get_ls = spu_hw_get_ls, |
315 | .runcntl_read = spu_hw_runcntl_read, | ||
306 | .runcntl_write = spu_hw_runcntl_write, | 316 | .runcntl_write = spu_hw_runcntl_write, |
307 | .runcntl_stop = spu_hw_runcntl_stop, | 317 | .master_start = spu_hw_master_start, |
318 | .master_stop = spu_hw_master_stop, | ||
308 | .set_mfc_query = spu_hw_set_mfc_query, | 319 | .set_mfc_query = spu_hw_set_mfc_query, |
309 | .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, | 320 | .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, |
310 | .get_mfc_free_elements = spu_hw_get_mfc_free_elements, | 321 | .get_mfc_free_elements = spu_hw_get_mfc_free_elements, |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 427d00a4f6a..c7d010749a1 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/parser.h> | 34 | #include <linux/parser.h> |
35 | 35 | ||
36 | #include <asm/io.h> | 36 | #include <asm/prom.h> |
37 | #include <asm/semaphore.h> | 37 | #include <asm/semaphore.h> |
38 | #include <asm/spu.h> | 38 | #include <asm/spu.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
@@ -41,6 +41,7 @@ | |||
41 | #include "spufs.h" | 41 | #include "spufs.h" |
42 | 42 | ||
43 | static kmem_cache_t *spufs_inode_cache; | 43 | static kmem_cache_t *spufs_inode_cache; |
44 | char *isolated_loader; | ||
44 | 45 | ||
45 | static struct inode * | 46 | static struct inode * |
46 | spufs_alloc_inode(struct super_block *sb) | 47 | spufs_alloc_inode(struct super_block *sb) |
@@ -231,6 +232,7 @@ struct file_operations spufs_context_fops = { | |||
231 | .readdir = dcache_readdir, | 232 | .readdir = dcache_readdir, |
232 | .fsync = simple_sync_file, | 233 | .fsync = simple_sync_file, |
233 | }; | 234 | }; |
235 | EXPORT_SYMBOL_GPL(spufs_context_fops); | ||
234 | 236 | ||
235 | static int | 237 | static int |
236 | spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | 238 | spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, |
@@ -255,10 +257,14 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | |||
255 | goto out_iput; | 257 | goto out_iput; |
256 | 258 | ||
257 | ctx->flags = flags; | 259 | ctx->flags = flags; |
258 | |||
259 | inode->i_op = &spufs_dir_inode_operations; | 260 | inode->i_op = &spufs_dir_inode_operations; |
260 | inode->i_fop = &simple_dir_operations; | 261 | inode->i_fop = &simple_dir_operations; |
261 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); | 262 | if (flags & SPU_CREATE_NOSCHED) |
263 | ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, | ||
264 | mode, ctx); | ||
265 | else | ||
266 | ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); | ||
267 | |||
262 | if (ret) | 268 | if (ret) |
263 | goto out_free_ctx; | 269 | goto out_free_ctx; |
264 | 270 | ||
@@ -307,6 +313,20 @@ static int spufs_create_context(struct inode *inode, | |||
307 | { | 313 | { |
308 | int ret; | 314 | int ret; |
309 | 315 | ||
316 | ret = -EPERM; | ||
317 | if ((flags & SPU_CREATE_NOSCHED) && | ||
318 | !capable(CAP_SYS_NICE)) | ||
319 | goto out_unlock; | ||
320 | |||
321 | ret = -EINVAL; | ||
322 | if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) | ||
323 | == SPU_CREATE_ISOLATE) | ||
324 | goto out_unlock; | ||
325 | |||
326 | ret = -ENODEV; | ||
327 | if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) | ||
328 | goto out_unlock; | ||
329 | |||
310 | ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); | 330 | ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); |
311 | if (ret) | 331 | if (ret) |
312 | goto out_unlock; | 332 | goto out_unlock; |
@@ -540,6 +560,30 @@ spufs_parse_options(char *options, struct inode *root) | |||
540 | return 1; | 560 | return 1; |
541 | } | 561 | } |
542 | 562 | ||
563 | static void | ||
564 | spufs_init_isolated_loader(void) | ||
565 | { | ||
566 | struct device_node *dn; | ||
567 | const char *loader; | ||
568 | int size; | ||
569 | |||
570 | dn = of_find_node_by_path("/spu-isolation"); | ||
571 | if (!dn) | ||
572 | return; | ||
573 | |||
574 | loader = get_property(dn, "loader", &size); | ||
575 | if (!loader) | ||
576 | return; | ||
577 | |||
578 | /* kmalloc should align on a 16 byte boundary..* */ | ||
579 | isolated_loader = kmalloc(size, GFP_KERNEL); | ||
580 | if (!isolated_loader) | ||
581 | return; | ||
582 | |||
583 | memcpy(isolated_loader, loader, size); | ||
584 | printk(KERN_INFO "spufs: SPU isolation mode enabled\n"); | ||
585 | } | ||
586 | |||
543 | static int | 587 | static int |
544 | spufs_create_root(struct super_block *sb, void *data) | 588 | spufs_create_root(struct super_block *sb, void *data) |
545 | { | 589 | { |
@@ -608,6 +652,7 @@ static struct file_system_type spufs_type = { | |||
608 | static int __init spufs_init(void) | 652 | static int __init spufs_init(void) |
609 | { | 653 | { |
610 | int ret; | 654 | int ret; |
655 | |||
611 | ret = -ENOMEM; | 656 | ret = -ENOMEM; |
612 | spufs_inode_cache = kmem_cache_create("spufs_inode_cache", | 657 | spufs_inode_cache = kmem_cache_create("spufs_inode_cache", |
613 | sizeof(struct spufs_inode_info), 0, | 658 | sizeof(struct spufs_inode_info), 0, |
@@ -625,6 +670,12 @@ static int __init spufs_init(void) | |||
625 | ret = register_spu_syscalls(&spufs_calls); | 670 | ret = register_spu_syscalls(&spufs_calls); |
626 | if (ret) | 671 | if (ret) |
627 | goto out_fs; | 672 | goto out_fs; |
673 | ret = register_arch_coredump_calls(&spufs_coredump_calls); | ||
674 | if (ret) | ||
675 | goto out_fs; | ||
676 | |||
677 | spufs_init_isolated_loader(); | ||
678 | |||
628 | return 0; | 679 | return 0; |
629 | out_fs: | 680 | out_fs: |
630 | unregister_filesystem(&spufs_type); | 681 | unregister_filesystem(&spufs_type); |
@@ -638,6 +689,7 @@ module_init(spufs_init); | |||
638 | static void __exit spufs_exit(void) | 689 | static void __exit spufs_exit(void) |
639 | { | 690 | { |
640 | spu_sched_exit(); | 691 | spu_sched_exit(); |
692 | unregister_arch_coredump_calls(&spufs_coredump_calls); | ||
641 | unregister_spu_syscalls(&spufs_calls); | 693 | unregister_spu_syscalls(&spufs_calls); |
642 | unregister_filesystem(&spufs_type); | 694 | unregister_filesystem(&spufs_type); |
643 | kmem_cache_destroy(spufs_inode_cache); | 695 | kmem_cache_destroy(spufs_inode_cache); |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 63df8cf4ba1..1acc2ffef8c 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -1,7 +1,11 @@ | |||
1 | #define DEBUG | ||
2 | |||
1 | #include <linux/wait.h> | 3 | #include <linux/wait.h> |
2 | #include <linux/ptrace.h> | 4 | #include <linux/ptrace.h> |
3 | 5 | ||
4 | #include <asm/spu.h> | 6 | #include <asm/spu.h> |
7 | #include <asm/spu_priv1.h> | ||
8 | #include <asm/io.h> | ||
5 | #include <asm/unistd.h> | 9 | #include <asm/unistd.h> |
6 | 10 | ||
7 | #include "spufs.h" | 11 | #include "spufs.h" |
@@ -24,6 +28,7 @@ void spufs_dma_callback(struct spu *spu, int type) | |||
24 | } else { | 28 | } else { |
25 | switch (type) { | 29 | switch (type) { |
26 | case SPE_EVENT_DMA_ALIGNMENT: | 30 | case SPE_EVENT_DMA_ALIGNMENT: |
31 | case SPE_EVENT_SPE_DATA_STORAGE: | ||
27 | case SPE_EVENT_INVALID_DMA: | 32 | case SPE_EVENT_INVALID_DMA: |
28 | force_sig(SIGBUS, /* info, */ current); | 33 | force_sig(SIGBUS, /* info, */ current); |
29 | break; | 34 | break; |
@@ -48,15 +53,122 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) | |||
48 | return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; | 53 | return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; |
49 | } | 54 | } |
50 | 55 | ||
56 | static int spu_setup_isolated(struct spu_context *ctx) | ||
57 | { | ||
58 | int ret; | ||
59 | u64 __iomem *mfc_cntl; | ||
60 | u64 sr1; | ||
61 | u32 status; | ||
62 | unsigned long timeout; | ||
63 | const u32 status_loading = SPU_STATUS_RUNNING | ||
64 | | SPU_STATUS_ISOLATED_STATE | SPU_STATUS_ISOLATED_LOAD_STATUS; | ||
65 | |||
66 | if (!isolated_loader) | ||
67 | return -ENODEV; | ||
68 | |||
69 | ret = spu_acquire_exclusive(ctx); | ||
70 | if (ret) | ||
71 | goto out; | ||
72 | |||
73 | mfc_cntl = &ctx->spu->priv2->mfc_control_RW; | ||
74 | |||
75 | /* purge the MFC DMA queue to ensure no spurious accesses before we | ||
76 | * enter kernel mode */ | ||
77 | timeout = jiffies + HZ; | ||
78 | out_be64(mfc_cntl, MFC_CNTL_PURGE_DMA_REQUEST); | ||
79 | while ((in_be64(mfc_cntl) & MFC_CNTL_PURGE_DMA_STATUS_MASK) | ||
80 | != MFC_CNTL_PURGE_DMA_COMPLETE) { | ||
81 | if (time_after(jiffies, timeout)) { | ||
82 | printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n", | ||
83 | __FUNCTION__); | ||
84 | ret = -EIO; | ||
85 | goto out_unlock; | ||
86 | } | ||
87 | cond_resched(); | ||
88 | } | ||
89 | |||
90 | /* put the SPE in kernel mode to allow access to the loader */ | ||
91 | sr1 = spu_mfc_sr1_get(ctx->spu); | ||
92 | sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK; | ||
93 | spu_mfc_sr1_set(ctx->spu, sr1); | ||
94 | |||
95 | /* start the loader */ | ||
96 | ctx->ops->signal1_write(ctx, (unsigned long)isolated_loader >> 32); | ||
97 | ctx->ops->signal2_write(ctx, | ||
98 | (unsigned long)isolated_loader & 0xffffffff); | ||
99 | |||
100 | ctx->ops->runcntl_write(ctx, | ||
101 | SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); | ||
102 | |||
103 | ret = 0; | ||
104 | timeout = jiffies + HZ; | ||
105 | while (((status = ctx->ops->status_read(ctx)) & status_loading) == | ||
106 | status_loading) { | ||
107 | if (time_after(jiffies, timeout)) { | ||
108 | printk(KERN_ERR "%s: timeout waiting for loader\n", | ||
109 | __FUNCTION__); | ||
110 | ret = -EIO; | ||
111 | goto out_drop_priv; | ||
112 | } | ||
113 | cond_resched(); | ||
114 | } | ||
115 | |||
116 | if (!(status & SPU_STATUS_RUNNING)) { | ||
117 | /* If isolated LOAD has failed: run SPU, we will get a stop-and | ||
118 | * signal later. */ | ||
119 | pr_debug("%s: isolated LOAD failed\n", __FUNCTION__); | ||
120 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); | ||
121 | ret = -EACCES; | ||
122 | |||
123 | } else if (!(status & SPU_STATUS_ISOLATED_STATE)) { | ||
124 | /* This isn't allowed by the CBEA, but check anyway */ | ||
125 | pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__); | ||
126 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP); | ||
127 | ret = -EINVAL; | ||
128 | } | ||
129 | |||
130 | out_drop_priv: | ||
131 | /* Finished accessing the loader. Drop kernel mode */ | ||
132 | sr1 |= MFC_STATE1_PROBLEM_STATE_MASK; | ||
133 | spu_mfc_sr1_set(ctx->spu, sr1); | ||
134 | |||
135 | out_unlock: | ||
136 | spu_release_exclusive(ctx); | ||
137 | out: | ||
138 | return ret; | ||
139 | } | ||
140 | |||
51 | static inline int spu_run_init(struct spu_context *ctx, u32 * npc) | 141 | static inline int spu_run_init(struct spu_context *ctx, u32 * npc) |
52 | { | 142 | { |
53 | int ret; | 143 | int ret; |
144 | unsigned long runcntl = SPU_RUNCNTL_RUNNABLE; | ||
54 | 145 | ||
55 | if ((ret = spu_acquire_runnable(ctx)) != 0) | 146 | ret = spu_acquire_runnable(ctx); |
147 | if (ret) | ||
56 | return ret; | 148 | return ret; |
57 | ctx->ops->npc_write(ctx, *npc); | 149 | |
58 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); | 150 | if (ctx->flags & SPU_CREATE_ISOLATE) { |
59 | return 0; | 151 | if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) { |
152 | /* Need to release ctx, because spu_setup_isolated will | ||
153 | * acquire it exclusively. | ||
154 | */ | ||
155 | spu_release(ctx); | ||
156 | ret = spu_setup_isolated(ctx); | ||
157 | if (!ret) | ||
158 | ret = spu_acquire_runnable(ctx); | ||
159 | } | ||
160 | |||
161 | /* if userspace has set the runcntrl register (eg, to issue an | ||
162 | * isolated exit), we need to re-set it here */ | ||
163 | runcntl = ctx->ops->runcntl_read(ctx) & | ||
164 | (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE); | ||
165 | if (runcntl == 0) | ||
166 | runcntl = SPU_RUNCNTL_RUNNABLE; | ||
167 | } else | ||
168 | ctx->ops->npc_write(ctx, *npc); | ||
169 | |||
170 | ctx->ops->runcntl_write(ctx, runcntl); | ||
171 | return ret; | ||
60 | } | 172 | } |
61 | 173 | ||
62 | static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, | 174 | static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, |
@@ -70,13 +182,7 @@ static inline int spu_run_fini(struct spu_context *ctx, u32 * npc, | |||
70 | 182 | ||
71 | if (signal_pending(current)) | 183 | if (signal_pending(current)) |
72 | ret = -ERESTARTSYS; | 184 | ret = -ERESTARTSYS; |
73 | if (unlikely(current->ptrace & PT_PTRACED)) { | 185 | |
74 | if ((*status & SPU_STATUS_STOPPED_BY_STOP) | ||
75 | && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { | ||
76 | force_sig(SIGTRAP, current); | ||
77 | ret = -ERESTARTSYS; | ||
78 | } | ||
79 | } | ||
80 | return ret; | 186 | return ret; |
81 | } | 187 | } |
82 | 188 | ||
@@ -204,6 +310,7 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
204 | if (down_interruptible(&ctx->run_sema)) | 310 | if (down_interruptible(&ctx->run_sema)) |
205 | return -ERESTARTSYS; | 311 | return -ERESTARTSYS; |
206 | 312 | ||
313 | ctx->ops->master_start(ctx); | ||
207 | ctx->event_return = 0; | 314 | ctx->event_return = 0; |
208 | ret = spu_run_init(ctx, npc); | 315 | ret = spu_run_init(ctx, npc); |
209 | if (ret) | 316 | if (ret) |
@@ -223,7 +330,7 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
223 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { | 330 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { |
224 | ret = spu_reacquire_runnable(ctx, npc, &status); | 331 | ret = spu_reacquire_runnable(ctx, npc, &status); |
225 | if (ret) | 332 | if (ret) |
226 | goto out; | 333 | goto out2; |
227 | continue; | 334 | continue; |
228 | } | 335 | } |
229 | ret = spu_process_events(ctx); | 336 | ret = spu_process_events(ctx); |
@@ -231,12 +338,24 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
231 | } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | | 338 | } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | |
232 | SPU_STATUS_STOPPED_BY_HALT))); | 339 | SPU_STATUS_STOPPED_BY_HALT))); |
233 | 340 | ||
234 | ctx->ops->runcntl_stop(ctx); | 341 | ctx->ops->master_stop(ctx); |
235 | ret = spu_run_fini(ctx, npc, &status); | 342 | ret = spu_run_fini(ctx, npc, &status); |
236 | if (!ret) | ||
237 | ret = status; | ||
238 | spu_yield(ctx); | 343 | spu_yield(ctx); |
239 | 344 | ||
345 | out2: | ||
346 | if ((ret == 0) || | ||
347 | ((ret == -ERESTARTSYS) && | ||
348 | ((status & SPU_STATUS_STOPPED_BY_HALT) || | ||
349 | ((status & SPU_STATUS_STOPPED_BY_STOP) && | ||
350 | (status >> SPU_STOP_STATUS_SHIFT != 0x2104))))) | ||
351 | ret = status; | ||
352 | |||
353 | if ((status & SPU_STATUS_STOPPED_BY_STOP) | ||
354 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { | ||
355 | force_sig(SIGTRAP, current); | ||
356 | ret = -ERESTARTSYS; | ||
357 | } | ||
358 | |||
240 | out: | 359 | out: |
241 | *event = ctx->event_return; | 360 | *event = ctx->event_return; |
242 | up(&ctx->run_sema); | 361 | up(&ctx->run_sema); |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index a0f55ca2d48..70fb13395c0 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <asm/spu.h> | 30 | #include <asm/spu.h> |
31 | #include <asm/spu_csa.h> | 31 | #include <asm/spu_csa.h> |
32 | #include <asm/spu_info.h> | ||
32 | 33 | ||
33 | /* The magic number for our file system */ | 34 | /* The magic number for our file system */ |
34 | enum { | 35 | enum { |
@@ -114,13 +115,19 @@ struct spu_context_ops { | |||
114 | void (*npc_write) (struct spu_context * ctx, u32 data); | 115 | void (*npc_write) (struct spu_context * ctx, u32 data); |
115 | u32(*status_read) (struct spu_context * ctx); | 116 | u32(*status_read) (struct spu_context * ctx); |
116 | char*(*get_ls) (struct spu_context * ctx); | 117 | char*(*get_ls) (struct spu_context * ctx); |
118 | u32 (*runcntl_read) (struct spu_context * ctx); | ||
117 | void (*runcntl_write) (struct spu_context * ctx, u32 data); | 119 | void (*runcntl_write) (struct spu_context * ctx, u32 data); |
118 | void (*runcntl_stop) (struct spu_context * ctx); | 120 | void (*master_start) (struct spu_context * ctx); |
121 | void (*master_stop) (struct spu_context * ctx); | ||
119 | int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); | 122 | int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); |
120 | u32 (*read_mfc_tagstatus)(struct spu_context * ctx); | 123 | u32 (*read_mfc_tagstatus)(struct spu_context * ctx); |
121 | u32 (*get_mfc_free_elements)(struct spu_context *ctx); | 124 | u32 (*get_mfc_free_elements)(struct spu_context *ctx); |
122 | int (*send_mfc_command)(struct spu_context *ctx, | 125 | int (*send_mfc_command)(struct spu_context * ctx, |
123 | struct mfc_dma_command *cmd); | 126 | struct mfc_dma_command * cmd); |
127 | void (*dma_info_read) (struct spu_context * ctx, | ||
128 | struct spu_dma_info * info); | ||
129 | void (*proxydma_info_read) (struct spu_context * ctx, | ||
130 | struct spu_proxydma_info * info); | ||
124 | }; | 131 | }; |
125 | 132 | ||
126 | extern struct spu_context_ops spu_hw_ops; | 133 | extern struct spu_context_ops spu_hw_ops; |
@@ -135,6 +142,7 @@ struct spufs_inode_info { | |||
135 | container_of(inode, struct spufs_inode_info, vfs_inode) | 142 | container_of(inode, struct spufs_inode_info, vfs_inode) |
136 | 143 | ||
137 | extern struct tree_descr spufs_dir_contents[]; | 144 | extern struct tree_descr spufs_dir_contents[]; |
145 | extern struct tree_descr spufs_dir_nosched_contents[]; | ||
138 | 146 | ||
139 | /* system call implementation */ | 147 | /* system call implementation */ |
140 | long spufs_run_spu(struct file *file, | 148 | long spufs_run_spu(struct file *file, |
@@ -162,6 +170,12 @@ void spu_acquire(struct spu_context *ctx); | |||
162 | void spu_release(struct spu_context *ctx); | 170 | void spu_release(struct spu_context *ctx); |
163 | int spu_acquire_runnable(struct spu_context *ctx); | 171 | int spu_acquire_runnable(struct spu_context *ctx); |
164 | void spu_acquire_saved(struct spu_context *ctx); | 172 | void spu_acquire_saved(struct spu_context *ctx); |
173 | int spu_acquire_exclusive(struct spu_context *ctx); | ||
174 | |||
175 | static inline void spu_release_exclusive(struct spu_context *ctx) | ||
176 | { | ||
177 | up_write(&ctx->state_sema); | ||
178 | } | ||
165 | 179 | ||
166 | int spu_activate(struct spu_context *ctx, u64 flags); | 180 | int spu_activate(struct spu_context *ctx, u64 flags); |
167 | void spu_deactivate(struct spu_context *ctx); | 181 | void spu_deactivate(struct spu_context *ctx); |
@@ -169,6 +183,8 @@ void spu_yield(struct spu_context *ctx); | |||
169 | int __init spu_sched_init(void); | 183 | int __init spu_sched_init(void); |
170 | void __exit spu_sched_exit(void); | 184 | void __exit spu_sched_exit(void); |
171 | 185 | ||
186 | extern char *isolated_loader; | ||
187 | |||
172 | /* | 188 | /* |
173 | * spufs_wait | 189 | * spufs_wait |
174 | * Same as wait_event_interruptible(), except that here | 190 | * Same as wait_event_interruptible(), except that here |
@@ -207,4 +223,15 @@ void spufs_stop_callback(struct spu *spu); | |||
207 | void spufs_mfc_callback(struct spu *spu); | 223 | void spufs_mfc_callback(struct spu *spu); |
208 | void spufs_dma_callback(struct spu *spu, int type); | 224 | void spufs_dma_callback(struct spu *spu, int type); |
209 | 225 | ||
226 | extern struct spu_coredump_calls spufs_coredump_calls; | ||
227 | struct spufs_coredump_reader { | ||
228 | char *name; | ||
229 | ssize_t (*read)(struct spu_context *ctx, | ||
230 | char __user *buffer, size_t size, loff_t *pos); | ||
231 | u64 (*get)(void *data); | ||
232 | size_t size; | ||
233 | }; | ||
234 | extern struct spufs_coredump_reader spufs_coredump_read[]; | ||
235 | extern int spufs_coredump_num_notes; | ||
236 | |||
210 | #endif | 237 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 0f782ca662b..c08981ff7fc 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
@@ -102,7 +102,7 @@ static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu) | |||
102 | * saved at this time. | 102 | * saved at this time. |
103 | */ | 103 | */ |
104 | isolate_state = SPU_STATUS_ISOLATED_STATE | | 104 | isolate_state = SPU_STATUS_ISOLATED_STATE | |
105 | SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS; | 105 | SPU_STATUS_ISOLATED_LOAD_STATUS | SPU_STATUS_ISOLATED_EXIT_STATUS; |
106 | return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; | 106 | return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; |
107 | } | 107 | } |
108 | 108 | ||
@@ -1046,12 +1046,12 @@ static inline int suspend_spe(struct spu_state *csa, struct spu *spu) | |||
1046 | */ | 1046 | */ |
1047 | if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { | 1047 | if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { |
1048 | if (in_be32(&prob->spu_status_R) & | 1048 | if (in_be32(&prob->spu_status_R) & |
1049 | SPU_STATUS_ISOLATED_EXIT_STAUTUS) { | 1049 | SPU_STATUS_ISOLATED_EXIT_STATUS) { |
1050 | POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & | 1050 | POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & |
1051 | SPU_STATUS_RUNNING); | 1051 | SPU_STATUS_RUNNING); |
1052 | } | 1052 | } |
1053 | if ((in_be32(&prob->spu_status_R) & | 1053 | if ((in_be32(&prob->spu_status_R) & |
1054 | SPU_STATUS_ISOLATED_LOAD_STAUTUS) | 1054 | SPU_STATUS_ISOLATED_LOAD_STATUS) |
1055 | || (in_be32(&prob->spu_status_R) & | 1055 | || (in_be32(&prob->spu_status_R) & |
1056 | SPU_STATUS_ISOLATED_STATE)) { | 1056 | SPU_STATUS_ISOLATED_STATE)) { |
1057 | out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); | 1057 | out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); |
@@ -1085,7 +1085,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) | |||
1085 | */ | 1085 | */ |
1086 | if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { | 1086 | if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { |
1087 | if (in_be32(&prob->spu_status_R) & | 1087 | if (in_be32(&prob->spu_status_R) & |
1088 | SPU_STATUS_ISOLATED_EXIT_STAUTUS) { | 1088 | SPU_STATUS_ISOLATED_EXIT_STATUS) { |
1089 | spu_mfc_sr1_set(spu, | 1089 | spu_mfc_sr1_set(spu, |
1090 | MFC_STATE1_MASTER_RUN_CONTROL_MASK); | 1090 | MFC_STATE1_MASTER_RUN_CONTROL_MASK); |
1091 | eieio(); | 1091 | eieio(); |
@@ -1095,7 +1095,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) | |||
1095 | SPU_STATUS_RUNNING); | 1095 | SPU_STATUS_RUNNING); |
1096 | } | 1096 | } |
1097 | if ((in_be32(&prob->spu_status_R) & | 1097 | if ((in_be32(&prob->spu_status_R) & |
1098 | SPU_STATUS_ISOLATED_LOAD_STAUTUS) | 1098 | SPU_STATUS_ISOLATED_LOAD_STATUS) |
1099 | || (in_be32(&prob->spu_status_R) & | 1099 | || (in_be32(&prob->spu_status_R) & |
1100 | SPU_STATUS_ISOLATED_STATE)) { | 1100 | SPU_STATUS_ISOLATED_STATE)) { |
1101 | spu_mfc_sr1_set(spu, | 1101 | spu_mfc_sr1_set(spu, |
@@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu) | |||
1916 | wait_spu_stopped(prev, spu); /* Step 57. */ | 1916 | wait_spu_stopped(prev, spu); /* Step 57. */ |
1917 | } | 1917 | } |
1918 | 1918 | ||
1919 | static void force_spu_isolate_exit(struct spu *spu) | ||
1920 | { | ||
1921 | struct spu_problem __iomem *prob = spu->problem; | ||
1922 | struct spu_priv2 __iomem *priv2 = spu->priv2; | ||
1923 | |||
1924 | /* Stop SPE execution and wait for completion. */ | ||
1925 | out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); | ||
1926 | iobarrier_rw(); | ||
1927 | POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); | ||
1928 | |||
1929 | /* Restart SPE master runcntl. */ | ||
1930 | spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK); | ||
1931 | iobarrier_w(); | ||
1932 | |||
1933 | /* Initiate isolate exit request and wait for completion. */ | ||
1934 | out_be64(&priv2->spu_privcntl_RW, 4LL); | ||
1935 | iobarrier_w(); | ||
1936 | out_be32(&prob->spu_runcntl_RW, 2); | ||
1937 | iobarrier_rw(); | ||
1938 | POLL_WHILE_FALSE((in_be32(&prob->spu_status_R) | ||
1939 | & SPU_STATUS_STOPPED_BY_STOP)); | ||
1940 | |||
1941 | /* Reset load request to normal. */ | ||
1942 | out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL); | ||
1943 | iobarrier_w(); | ||
1944 | } | ||
1945 | |||
1946 | /** | ||
1947 | * stop_spu_isolate | ||
1948 | * Check SPU run-control state and force isolated | ||
1949 | * exit function as necessary. | ||
1950 | */ | ||
1951 | static void stop_spu_isolate(struct spu *spu) | ||
1952 | { | ||
1953 | struct spu_problem __iomem *prob = spu->problem; | ||
1954 | |||
1955 | if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) { | ||
1956 | /* The SPU is in isolated state; the only way | ||
1957 | * to get it out is to perform an isolated | ||
1958 | * exit (clean) operation. | ||
1959 | */ | ||
1960 | force_spu_isolate_exit(spu); | ||
1961 | } | ||
1962 | } | ||
1963 | |||
1919 | static void harvest(struct spu_state *prev, struct spu *spu) | 1964 | static void harvest(struct spu_state *prev, struct spu *spu) |
1920 | { | 1965 | { |
1921 | /* | 1966 | /* |
@@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) | |||
1928 | inhibit_user_access(prev, spu); /* Step 3. */ | 1973 | inhibit_user_access(prev, spu); /* Step 3. */ |
1929 | terminate_spu_app(prev, spu); /* Step 4. */ | 1974 | terminate_spu_app(prev, spu); /* Step 4. */ |
1930 | set_switch_pending(prev, spu); /* Step 5. */ | 1975 | set_switch_pending(prev, spu); /* Step 5. */ |
1976 | stop_spu_isolate(spu); /* NEW. */ | ||
1931 | remove_other_spu_access(prev, spu); /* Step 6. */ | 1977 | remove_other_spu_access(prev, spu); /* Step 6. */ |
1932 | suspend_mfc(prev, spu); /* Step 7. */ | 1978 | suspend_mfc(prev, spu); /* Step 7. */ |
1933 | wait_suspend_mfc_complete(prev, spu); /* Step 8. */ | 1979 | wait_suspend_mfc_complete(prev, spu); /* Step 8. */ |
@@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu) | |||
2096 | acquire_spu_lock(spu); /* Step 1. */ | 2142 | acquire_spu_lock(spu); /* Step 1. */ |
2097 | rc = __do_spu_save(prev, spu); /* Steps 2-53. */ | 2143 | rc = __do_spu_save(prev, spu); /* Steps 2-53. */ |
2098 | release_spu_lock(spu); | 2144 | release_spu_lock(spu); |
2099 | if (rc) { | 2145 | if (rc != 0 && rc != 2 && rc != 6) { |
2100 | panic("%s failed on SPU[%d], rc=%d.\n", | 2146 | panic("%s failed on SPU[%d], rc=%d.\n", |
2101 | __func__, spu->number, rc); | 2147 | __func__, spu->number, rc); |
2102 | } | 2148 | } |
2103 | return rc; | 2149 | return 0; |
2104 | } | 2150 | } |
2105 | EXPORT_SYMBOL_GPL(spu_save); | 2151 | EXPORT_SYMBOL_GPL(spu_save); |
2106 | 2152 | ||
@@ -2165,9 +2211,6 @@ static void init_priv1(struct spu_state *csa) | |||
2165 | MFC_STATE1_PROBLEM_STATE_MASK | | 2211 | MFC_STATE1_PROBLEM_STATE_MASK | |
2166 | MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; | 2212 | MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; |
2167 | 2213 | ||
2168 | /* Set storage description. */ | ||
2169 | csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1); | ||
2170 | |||
2171 | /* Enable OS-specific set of interrupts. */ | 2214 | /* Enable OS-specific set of interrupts. */ |
2172 | csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | | 2215 | csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | |
2173 | CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | | 2216 | CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | |
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h index 996c28744e9..63f0aee4c15 100644 --- a/arch/powerpc/platforms/chrp/chrp.h +++ b/arch/powerpc/platforms/chrp/chrp.h | |||
@@ -9,4 +9,3 @@ extern long chrp_time_init(void); | |||
9 | 9 | ||
10 | extern void chrp_find_bridges(void); | 10 | extern void chrp_find_bridges(void); |
11 | extern void chrp_event_scan(unsigned long); | 11 | extern void chrp_event_scan(unsigned long); |
12 | extern void chrp_pcibios_fixup(void); | ||
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 0f4340506c7..ddb4a116ea8 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
@@ -156,15 +156,6 @@ hydra_init(void) | |||
156 | return 1; | 156 | return 1; |
157 | } | 157 | } |
158 | 158 | ||
159 | void __init | ||
160 | chrp_pcibios_fixup(void) | ||
161 | { | ||
162 | struct pci_dev *dev = NULL; | ||
163 | |||
164 | for_each_pci_dev(dev) | ||
165 | pci_read_irq_line(dev); | ||
166 | } | ||
167 | |||
168 | #define PRG_CL_RESET_VALID 0x00010000 | 159 | #define PRG_CL_RESET_VALID 0x00010000 |
169 | 160 | ||
170 | static void __init | 161 | static void __init |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 49b8dabcbc9..e1f51d45598 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -588,7 +588,6 @@ static int __init chrp_probe(void) | |||
588 | ISA_DMA_THRESHOLD = ~0L; | 588 | ISA_DMA_THRESHOLD = ~0L; |
589 | DMA_MODE_READ = 0x44; | 589 | DMA_MODE_READ = 0x44; |
590 | DMA_MODE_WRITE = 0x48; | 590 | DMA_MODE_WRITE = 0x48; |
591 | isa_io_base = CHRP_ISA_IO_BASE; /* default value */ | ||
592 | 591 | ||
593 | return 1; | 592 | return 1; |
594 | } | 593 | } |
@@ -600,7 +599,6 @@ define_machine(chrp) { | |||
600 | .init = chrp_init2, | 599 | .init = chrp_init2, |
601 | .show_cpuinfo = chrp_show_cpuinfo, | 600 | .show_cpuinfo = chrp_show_cpuinfo, |
602 | .init_IRQ = chrp_init_IRQ, | 601 | .init_IRQ = chrp_init_IRQ, |
603 | .pcibios_fixup = chrp_pcibios_fixup, | ||
604 | .restart = rtas_restart, | 602 | .restart = rtas_restart, |
605 | .power_off = rtas_power_off, | 603 | .power_off = rtas_power_off, |
606 | .halt = rtas_halt, | 604 | .halt = rtas_halt, |
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 234a861870a..ddbe398fbd4 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
@@ -74,6 +74,18 @@ config SANDPOINT | |||
74 | Select SANDPOINT if configuring for a Motorola Sandpoint X3 | 74 | Select SANDPOINT if configuring for a Motorola Sandpoint X3 |
75 | (any flavor). | 75 | (any flavor). |
76 | 76 | ||
77 | config LINKSTATION | ||
78 | bool "Linkstation / Kurobox(HG) from Buffalo" | ||
79 | select MPIC | ||
80 | select FSL_SOC | ||
81 | select PPC_UDBG_16550 if SERIAL_8250 | ||
82 | help | ||
83 | Select LINKSTATION if configuring for one of PPC- (MPC8241) | ||
84 | based NAS systems from Buffalo Technology. So far only | ||
85 | KuroboxHG has been tested. In the future classical Kurobox, | ||
86 | Linkstation-I HD-HLAN and HD-HGLAN versions, and PPC-based | ||
87 | Terastation systems should be supported too. | ||
88 | |||
77 | config MPC7448HPC2 | 89 | config MPC7448HPC2 |
78 | bool "Freescale MPC7448HPC2(Taiga)" | 90 | bool "Freescale MPC7448HPC2(Taiga)" |
79 | select TSI108_BRIDGE | 91 | select TSI108_BRIDGE |
@@ -146,15 +158,6 @@ config PQ2FADS | |||
146 | Select PQ2FADS if you wish to configure for a Freescale | 158 | Select PQ2FADS if you wish to configure for a Freescale |
147 | PQ2FADS board (-VR or -ZU). | 159 | PQ2FADS board (-VR or -ZU). |
148 | 160 | ||
149 | config LITE5200 | ||
150 | bool "Freescale LITE5200 / (IceCube)" | ||
151 | select PPC_MPC52xx | ||
152 | help | ||
153 | Support for the LITE5200 dev board for the MPC5200 from Freescale. | ||
154 | This is for the LITE5200 version 2.0 board. Don't know if it changes | ||
155 | much but it's only been tested on this board version. I think this | ||
156 | board is also known as IceCube. | ||
157 | |||
158 | config EV64360 | 161 | config EV64360 |
159 | bool "Marvell-EV64360BP" | 162 | bool "Marvell-EV64360BP" |
160 | help | 163 | help |
@@ -172,9 +175,6 @@ config TQM8xxL | |||
172 | depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L) | 175 | depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L) |
173 | default y | 176 | default y |
174 | 177 | ||
175 | config PPC_MPC52xx | ||
176 | bool | ||
177 | |||
178 | config 8260 | 178 | config 8260 |
179 | bool "CPM2 Support" if WILLOW | 179 | bool "CPM2 Support" if WILLOW |
180 | depends on 6xx | 180 | depends on 6xx |
@@ -208,7 +208,7 @@ config PPC_GEN550 | |||
208 | depends on SANDPOINT || SPRUCE || PPLUS || \ | 208 | depends on SANDPOINT || SPRUCE || PPLUS || \ |
209 | PRPMC750 || PRPMC800 || LOPEC || \ | 209 | PRPMC750 || PRPMC800 || LOPEC || \ |
210 | (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \ | 210 | (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \ |
211 | 83xx | 211 | 83xx || LINKSTATION |
212 | default y | 212 | default y |
213 | 213 | ||
214 | config FORCE | 214 | config FORCE |
@@ -282,13 +282,13 @@ config EPIC_SERIAL_MODE | |||
282 | 282 | ||
283 | config MPC10X_BRIDGE | 283 | config MPC10X_BRIDGE |
284 | bool | 284 | bool |
285 | depends on POWERPMC250 || LOPEC || SANDPOINT | 285 | depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION |
286 | select PPC_INDIRECT_PCI | 286 | select PPC_INDIRECT_PCI |
287 | default y | 287 | default y |
288 | 288 | ||
289 | config MPC10X_OPENPIC | 289 | config MPC10X_OPENPIC |
290 | bool | 290 | bool |
291 | depends on POWERPMC250 || LOPEC || SANDPOINT | 291 | depends on POWERPMC250 || LOPEC || SANDPOINT || LINKSTATION |
292 | default y | 292 | default y |
293 | 293 | ||
294 | config MPC10X_STORE_GATHERING | 294 | config MPC10X_STORE_GATHERING |
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile index fa499fe5929..d3d11a3cd65 100644 --- a/arch/powerpc/platforms/embedded6xx/Makefile +++ b/arch/powerpc/platforms/embedded6xx/Makefile | |||
@@ -2,3 +2,4 @@ | |||
2 | # Makefile for the 6xx/7xx/7xxxx linux kernel. | 2 | # Makefile for the 6xx/7xx/7xxxx linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o | 4 | obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o |
5 | obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o | ||
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c new file mode 100644 index 00000000000..61599d919ea --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * Board setup routines for the Buffalo Linkstation / Kurobox Platform. | ||
3 | * | ||
4 | * Copyright (C) 2006 G. Liakhovetski (g.liakhovetski@gmx.de) | ||
5 | * | ||
6 | * Based on sandpoint.c by Mark A. Greer | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of | ||
10 | * any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/initrd.h> | ||
16 | #include <linux/root_dev.h> | ||
17 | #include <linux/mtd/physmap.h> | ||
18 | |||
19 | #include <asm/time.h> | ||
20 | #include <asm/prom.h> | ||
21 | #include <asm/mpic.h> | ||
22 | #include <asm/mpc10x.h> | ||
23 | #include <asm/pci-bridge.h> | ||
24 | |||
25 | static struct mtd_partition linkstation_physmap_partitions[] = { | ||
26 | { | ||
27 | .name = "mtd_firmimg", | ||
28 | .offset = 0x000000, | ||
29 | .size = 0x300000, | ||
30 | }, | ||
31 | { | ||
32 | .name = "mtd_bootcode", | ||
33 | .offset = 0x300000, | ||
34 | .size = 0x070000, | ||
35 | }, | ||
36 | { | ||
37 | .name = "mtd_status", | ||
38 | .offset = 0x370000, | ||
39 | .size = 0x010000, | ||
40 | }, | ||
41 | { | ||
42 | .name = "mtd_conf", | ||
43 | .offset = 0x380000, | ||
44 | .size = 0x080000, | ||
45 | }, | ||
46 | { | ||
47 | .name = "mtd_allflash", | ||
48 | .offset = 0x000000, | ||
49 | .size = 0x400000, | ||
50 | }, | ||
51 | { | ||
52 | .name = "mtd_data", | ||
53 | .offset = 0x310000, | ||
54 | .size = 0x0f0000, | ||
55 | }, | ||
56 | }; | ||
57 | |||
58 | static int __init add_bridge(struct device_node *dev) | ||
59 | { | ||
60 | int len; | ||
61 | struct pci_controller *hose; | ||
62 | int *bus_range; | ||
63 | |||
64 | printk("Adding PCI host bridge %s\n", dev->full_name); | ||
65 | |||
66 | bus_range = (int *) get_property(dev, "bus-range", &len); | ||
67 | if (bus_range == NULL || len < 2 * sizeof(int)) | ||
68 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | ||
69 | " bus 0\n", dev->full_name); | ||
70 | |||
71 | hose = pcibios_alloc_controller(); | ||
72 | if (hose == NULL) | ||
73 | return -ENOMEM; | ||
74 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
75 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
76 | hose->arch_data = dev; | ||
77 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | ||
78 | |||
79 | /* Interpret the "ranges" property */ | ||
80 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
81 | pci_process_bridge_OF_ranges(hose, dev, 1); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static void __init linkstation_setup_arch(void) | ||
87 | { | ||
88 | struct device_node *np; | ||
89 | #ifdef CONFIG_MTD_PHYSMAP | ||
90 | physmap_set_partitions(linkstation_physmap_partitions, | ||
91 | ARRAY_SIZE(linkstation_physmap_partitions)); | ||
92 | #endif | ||
93 | |||
94 | #ifdef CONFIG_BLK_DEV_INITRD | ||
95 | if (initrd_start) | ||
96 | ROOT_DEV = Root_RAM0; | ||
97 | else | ||
98 | #endif | ||
99 | #ifdef CONFIG_ROOT_NFS | ||
100 | ROOT_DEV = Root_NFS; | ||
101 | #else | ||
102 | ROOT_DEV = Root_HDA1; | ||
103 | #endif | ||
104 | |||
105 | /* Lookup PCI host bridges */ | ||
106 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | ||
107 | add_bridge(np); | ||
108 | |||
109 | printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); | ||
110 | printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n"); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Interrupt setup and service. Interrrupts on the linkstation come | ||
115 | * from the four PCI slots plus onboard 8241 devices: I2C, DUART. | ||
116 | */ | ||
117 | static void __init linkstation_init_IRQ(void) | ||
118 | { | ||
119 | struct mpic *mpic; | ||
120 | struct device_node *dnp; | ||
121 | void *prop; | ||
122 | int size; | ||
123 | phys_addr_t paddr; | ||
124 | |||
125 | dnp = of_find_node_by_type(NULL, "open-pic"); | ||
126 | if (dnp == NULL) | ||
127 | return; | ||
128 | |||
129 | prop = (struct device_node *)get_property(dnp, "reg", &size); | ||
130 | paddr = (phys_addr_t)of_translate_address(dnp, prop); | ||
131 | |||
132 | mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, 4, 32, " EPIC "); | ||
133 | BUG_ON(mpic == NULL); | ||
134 | |||
135 | /* PCI IRQs */ | ||
136 | mpic_assign_isu(mpic, 0, paddr + 0x10200); | ||
137 | |||
138 | /* I2C */ | ||
139 | mpic_assign_isu(mpic, 1, paddr + 0x11000); | ||
140 | |||
141 | /* ttyS0, ttyS1 */ | ||
142 | mpic_assign_isu(mpic, 2, paddr + 0x11100); | ||
143 | |||
144 | mpic_init(mpic); | ||
145 | } | ||
146 | |||
147 | extern void avr_uart_configure(void); | ||
148 | extern void avr_uart_send(const char); | ||
149 | |||
150 | static void linkstation_restart(char *cmd) | ||
151 | { | ||
152 | local_irq_disable(); | ||
153 | |||
154 | /* Reset system via AVR */ | ||
155 | avr_uart_configure(); | ||
156 | /* Send reboot command */ | ||
157 | avr_uart_send('C'); | ||
158 | |||
159 | for(;;) /* Spin until reset happens */ | ||
160 | avr_uart_send('G'); /* "kick" */ | ||
161 | } | ||
162 | |||
163 | static void linkstation_power_off(void) | ||
164 | { | ||
165 | local_irq_disable(); | ||
166 | |||
167 | /* Power down system via AVR */ | ||
168 | avr_uart_configure(); | ||
169 | /* send shutdown command */ | ||
170 | avr_uart_send('E'); | ||
171 | |||
172 | for(;;) /* Spin until power-off happens */ | ||
173 | avr_uart_send('G'); /* "kick" */ | ||
174 | /* NOTREACHED */ | ||
175 | } | ||
176 | |||
177 | static void linkstation_halt(void) | ||
178 | { | ||
179 | linkstation_power_off(); | ||
180 | /* NOTREACHED */ | ||
181 | } | ||
182 | |||
183 | static void linkstation_show_cpuinfo(struct seq_file *m) | ||
184 | { | ||
185 | seq_printf(m, "vendor\t\t: Buffalo Technology\n"); | ||
186 | seq_printf(m, "machine\t\t: Linkstation I/Kurobox(HG)\n"); | ||
187 | } | ||
188 | |||
189 | static int __init linkstation_probe(void) | ||
190 | { | ||
191 | unsigned long root; | ||
192 | |||
193 | root = of_get_flat_dt_root(); | ||
194 | |||
195 | if (!of_flat_dt_is_compatible(root, "linkstation")) | ||
196 | return 0; | ||
197 | return 1; | ||
198 | } | ||
199 | |||
200 | define_machine(linkstation){ | ||
201 | .name = "Buffalo Linkstation", | ||
202 | .probe = linkstation_probe, | ||
203 | .setup_arch = linkstation_setup_arch, | ||
204 | .init_IRQ = linkstation_init_IRQ, | ||
205 | .show_cpuinfo = linkstation_show_cpuinfo, | ||
206 | .get_irq = mpic_get_irq, | ||
207 | .restart = linkstation_restart, | ||
208 | .power_off = linkstation_power_off, | ||
209 | .halt = linkstation_halt, | ||
210 | .calibrate_decr = generic_calibrate_decr, | ||
211 | }; | ||
diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c new file mode 100644 index 00000000000..31bcdae8482 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c | |||
@@ -0,0 +1,131 @@ | |||
1 | #include <linux/workqueue.h> | ||
2 | #include <linux/string.h> | ||
3 | #include <linux/delay.h> | ||
4 | #include <linux/serial_reg.h> | ||
5 | #include <linux/serial_8250.h> | ||
6 | #include <asm/io.h> | ||
7 | #include <asm/mpc10x.h> | ||
8 | #include <asm/ppc_sys.h> | ||
9 | #include <asm/prom.h> | ||
10 | #include <asm/termbits.h> | ||
11 | |||
12 | static void __iomem *avr_addr; | ||
13 | static unsigned long avr_clock; | ||
14 | |||
15 | static struct work_struct wd_work; | ||
16 | |||
17 | static void wd_stop(void *unused) | ||
18 | { | ||
19 | const char string[] = "AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK"; | ||
20 | int i = 0, rescue = 8; | ||
21 | int len = strlen(string); | ||
22 | |||
23 | while (rescue--) { | ||
24 | int j; | ||
25 | char lsr = in_8(avr_addr + UART_LSR); | ||
26 | |||
27 | if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) { | ||
28 | for (j = 0; j < 16 && i < len; j++, i++) | ||
29 | out_8(avr_addr + UART_TX, string[i]); | ||
30 | if (i == len) { | ||
31 | /* Read "OK" back: 4ms for the last "KKKK" | ||
32 | plus a couple bytes back */ | ||
33 | msleep(7); | ||
34 | printk("linkstation: disarming the AVR watchdog: "); | ||
35 | while (in_8(avr_addr + UART_LSR) & UART_LSR_DR) | ||
36 | printk("%c", in_8(avr_addr + UART_RX)); | ||
37 | break; | ||
38 | } | ||
39 | } | ||
40 | msleep(17); | ||
41 | } | ||
42 | printk("\n"); | ||
43 | } | ||
44 | |||
45 | #define AVR_QUOT(clock) ((clock) + 8 * 9600) / (16 * 9600) | ||
46 | |||
47 | void avr_uart_configure(void) | ||
48 | { | ||
49 | unsigned char cval = UART_LCR_WLEN8; | ||
50 | unsigned int quot = AVR_QUOT(avr_clock); | ||
51 | |||
52 | if (!avr_addr || !avr_clock) | ||
53 | return; | ||
54 | |||
55 | out_8(avr_addr + UART_LCR, cval); /* initialise UART */ | ||
56 | out_8(avr_addr + UART_MCR, 0); | ||
57 | out_8(avr_addr + UART_IER, 0); | ||
58 | |||
59 | cval |= UART_LCR_STOP | UART_LCR_PARITY | UART_LCR_EPAR; | ||
60 | |||
61 | out_8(avr_addr + UART_LCR, cval); /* Set character format */ | ||
62 | |||
63 | out_8(avr_addr + UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ | ||
64 | out_8(avr_addr + UART_DLL, quot & 0xff); /* LS of divisor */ | ||
65 | out_8(avr_addr + UART_DLM, quot >> 8); /* MS of divisor */ | ||
66 | out_8(avr_addr + UART_LCR, cval); /* reset DLAB */ | ||
67 | out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO); /* enable FIFO */ | ||
68 | } | ||
69 | |||
70 | void avr_uart_send(const char c) | ||
71 | { | ||
72 | if (!avr_addr || !avr_clock) | ||
73 | return; | ||
74 | |||
75 | out_8(avr_addr + UART_TX, c); | ||
76 | out_8(avr_addr + UART_TX, c); | ||
77 | out_8(avr_addr + UART_TX, c); | ||
78 | out_8(avr_addr + UART_TX, c); | ||
79 | } | ||
80 | |||
81 | static void __init ls_uart_init(void) | ||
82 | { | ||
83 | local_irq_disable(); | ||
84 | |||
85 | #ifndef CONFIG_SERIAL_8250 | ||
86 | out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO); /* enable FIFO */ | ||
87 | out_8(avr_addr + UART_FCR, UART_FCR_ENABLE_FIFO | | ||
88 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); /* clear FIFOs */ | ||
89 | out_8(avr_addr + UART_FCR, 0); | ||
90 | out_8(avr_addr + UART_IER, 0); | ||
91 | |||
92 | /* Clear up interrupts */ | ||
93 | (void) in_8(avr_addr + UART_LSR); | ||
94 | (void) in_8(avr_addr + UART_RX); | ||
95 | (void) in_8(avr_addr + UART_IIR); | ||
96 | (void) in_8(avr_addr + UART_MSR); | ||
97 | #endif | ||
98 | avr_uart_configure(); | ||
99 | |||
100 | local_irq_enable(); | ||
101 | } | ||
102 | |||
103 | static int __init ls_uarts_init(void) | ||
104 | { | ||
105 | struct device_node *avr; | ||
106 | phys_addr_t phys_addr; | ||
107 | int len; | ||
108 | |||
109 | avr = of_find_node_by_path("/soc10x/serial@80004500"); | ||
110 | if (!avr) | ||
111 | return -EINVAL; | ||
112 | |||
113 | avr_clock = *(u32*)get_property(avr, "clock-frequency", &len); | ||
114 | phys_addr = ((u32*)get_property(avr, "reg", &len))[0]; | ||
115 | |||
116 | if (!avr_clock || !phys_addr) | ||
117 | return -EINVAL; | ||
118 | |||
119 | avr_addr = ioremap(phys_addr, 32); | ||
120 | if (!avr_addr) | ||
121 | return -EFAULT; | ||
122 | |||
123 | ls_uart_init(); | ||
124 | |||
125 | INIT_WORK(&wd_work, wd_stop, NULL); | ||
126 | schedule_work(&wd_work); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | late_initcall(ls_uarts_init); | ||
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index bdb475c65cb..3fcc85f60fb 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | |||
@@ -60,7 +60,7 @@ pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; | |||
60 | 60 | ||
61 | extern int tsi108_setup_pci(struct device_node *dev); | 61 | extern int tsi108_setup_pci(struct device_node *dev); |
62 | extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); | 62 | extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); |
63 | extern void tsi108_pci_int_init(void); | 63 | extern void tsi108_pci_int_init(struct device_node *node); |
64 | extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc); | 64 | extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc); |
65 | 65 | ||
66 | int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) | 66 | int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) |
@@ -71,65 +71,6 @@ int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) | |||
71 | return PCIBIOS_SUCCESSFUL; | 71 | return PCIBIOS_SUCCESSFUL; |
72 | } | 72 | } |
73 | 73 | ||
74 | /* | ||
75 | * find pci slot by devfn in interrupt map of OF tree | ||
76 | */ | ||
77 | u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn) | ||
78 | { | ||
79 | int i; | ||
80 | unsigned int tmp; | ||
81 | for (i = 0; i < 4; i++){ | ||
82 | tmp = interrupt_map[i*4*7]; | ||
83 | if ((tmp >> 11) == (devfn >> 3)) | ||
84 | return i; | ||
85 | } | ||
86 | return i; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Scans the interrupt map for pci device | ||
91 | */ | ||
92 | void mpc7448_hpc2_fixup_irq(struct pci_dev *dev) | ||
93 | { | ||
94 | struct pci_controller *hose; | ||
95 | struct device_node *node; | ||
96 | const unsigned int *interrupt; | ||
97 | int busnr; | ||
98 | int len; | ||
99 | u8 slot; | ||
100 | u8 pin; | ||
101 | |||
102 | /* Lookup the hose */ | ||
103 | busnr = dev->bus->number; | ||
104 | hose = pci_bus_to_hose(busnr); | ||
105 | if (!hose) | ||
106 | printk(KERN_ERR "No pci hose found\n"); | ||
107 | |||
108 | /* Check it has an OF node associated */ | ||
109 | node = (struct device_node *) hose->arch_data; | ||
110 | if (!node) | ||
111 | printk(KERN_ERR "No pci node found\n"); | ||
112 | |||
113 | interrupt = get_property(node, "interrupt-map", &len); | ||
114 | slot = find_slot_by_devfn(interrupt, dev->devfn); | ||
115 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
116 | if (pin == 0 || pin > 4) | ||
117 | pin = 1; | ||
118 | pin--; | ||
119 | dev->irq = interrupt[slot*4*7 + pin*7 + 5]; | ||
120 | DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq); | ||
121 | } | ||
122 | /* temporary pci irq map fixup*/ | ||
123 | |||
124 | void __init mpc7448_hpc2_pcibios_fixup(void) | ||
125 | { | ||
126 | struct pci_dev *dev = NULL; | ||
127 | for_each_pci_dev(dev) { | ||
128 | mpc7448_hpc2_fixup_irq(dev); | ||
129 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | static void __init mpc7448_hpc2_setup_arch(void) | 74 | static void __init mpc7448_hpc2_setup_arch(void) |
134 | { | 75 | { |
135 | struct device_node *cpu; | 76 | struct device_node *cpu; |
@@ -192,9 +133,12 @@ static void __init mpc7448_hpc2_init_IRQ(void) | |||
192 | { | 133 | { |
193 | struct mpic *mpic; | 134 | struct mpic *mpic; |
194 | phys_addr_t mpic_paddr = 0; | 135 | phys_addr_t mpic_paddr = 0; |
136 | struct device_node *tsi_pic; | ||
137 | #ifdef CONFIG_PCI | ||
195 | unsigned int cascade_pci_irq; | 138 | unsigned int cascade_pci_irq; |
196 | struct device_node *tsi_pci; | 139 | struct device_node *tsi_pci; |
197 | struct device_node *tsi_pic; | 140 | struct device_node *cascade_node = NULL; |
141 | #endif | ||
198 | 142 | ||
199 | tsi_pic = of_find_node_by_type(NULL, "open-pic"); | 143 | tsi_pic = of_find_node_by_type(NULL, "open-pic"); |
200 | if (tsi_pic) { | 144 | if (tsi_pic) { |
@@ -208,31 +152,41 @@ static void __init mpc7448_hpc2_init_IRQ(void) | |||
208 | return; | 152 | return; |
209 | } | 153 | } |
210 | 154 | ||
211 | DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__, | 155 | DBG("%s: tsi108 pic phys_addr = 0x%x\n", __FUNCTION__, |
212 | (u32) mpic_paddr); | 156 | (u32) mpic_paddr); |
213 | 157 | ||
214 | mpic = mpic_alloc(tsi_pic, mpic_paddr, | 158 | mpic = mpic_alloc(tsi_pic, mpic_paddr, |
215 | MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | | 159 | MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | |
216 | MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, | 160 | MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, |
217 | 0, /* num_sources used */ | 161 | 24, |
218 | 0, /* num_sources used */ | 162 | NR_IRQS-4, /* num_sources used */ |
219 | "Tsi108_PIC"); | 163 | "Tsi108_PIC"); |
220 | 164 | ||
221 | BUG_ON(mpic == NULL); /* XXXX */ | 165 | BUG_ON(mpic == NULL); |
166 | |||
167 | mpic_assign_isu(mpic, 0, mpic_paddr + 0x100); | ||
168 | |||
222 | mpic_init(mpic); | 169 | mpic_init(mpic); |
223 | 170 | ||
171 | #ifdef CONFIG_PCI | ||
224 | tsi_pci = of_find_node_by_type(NULL, "pci"); | 172 | tsi_pci = of_find_node_by_type(NULL, "pci"); |
225 | if (tsi_pci == 0) { | 173 | if (tsi_pci == NULL) { |
226 | printk("%s: No tsi108 pci node found !\n", __FUNCTION__); | 174 | printk("%s: No tsi108 pci node found !\n", __FUNCTION__); |
227 | return; | 175 | return; |
228 | } | 176 | } |
177 | cascade_node = of_find_node_by_type(NULL, "pic-router"); | ||
178 | if (cascade_node == NULL) { | ||
179 | printk("%s: No tsi108 pci cascade node found !\n", __FUNCTION__); | ||
180 | return; | ||
181 | } | ||
229 | 182 | ||
230 | cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0); | 183 | cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0); |
184 | DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __FUNCTION__, | ||
185 | (u32) cascade_pci_irq); | ||
186 | tsi108_pci_int_init(cascade_node); | ||
231 | set_irq_data(cascade_pci_irq, mpic); | 187 | set_irq_data(cascade_pci_irq, mpic); |
232 | set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade); | 188 | set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade); |
233 | 189 | #endif | |
234 | tsi108_pci_int_init(); | ||
235 | |||
236 | /* Configure MPIC outputs to CPU0 */ | 190 | /* Configure MPIC outputs to CPU0 */ |
237 | tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0); | 191 | tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0); |
238 | of_node_put(tsi_pic); | 192 | of_node_put(tsi_pic); |
@@ -290,7 +244,6 @@ static int mpc7448_machine_check_exception(struct pt_regs *regs) | |||
290 | return 1; | 244 | return 1; |
291 | } | 245 | } |
292 | return 0; | 246 | return 0; |
293 | |||
294 | } | 247 | } |
295 | 248 | ||
296 | define_machine(mpc7448_hpc2){ | 249 | define_machine(mpc7448_hpc2){ |
@@ -300,7 +253,6 @@ define_machine(mpc7448_hpc2){ | |||
300 | .init_IRQ = mpc7448_hpc2_init_IRQ, | 253 | .init_IRQ = mpc7448_hpc2_init_IRQ, |
301 | .show_cpuinfo = mpc7448_hpc2_show_cpuinfo, | 254 | .show_cpuinfo = mpc7448_hpc2_show_cpuinfo, |
302 | .get_irq = mpic_get_irq, | 255 | .get_irq = mpic_get_irq, |
303 | .pcibios_fixup = mpc7448_hpc2_pcibios_fixup, | ||
304 | .restart = mpc7448_hpc2_restart, | 256 | .restart = mpc7448_hpc2_restart, |
305 | .calibrate_decr = generic_calibrate_decr, | 257 | .calibrate_decr = generic_calibrate_decr, |
306 | .machine_check_exception= mpc7448_machine_check_exception, | 258 | .machine_check_exception= mpc7448_machine_check_exception, |
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index dee4eb4d8be..13ac3015d91 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | EXTRA_CFLAGS += -mno-minimal-toc | 1 | EXTRA_CFLAGS += -mno-minimal-toc |
2 | 2 | ||
3 | extra-y += dt.o | ||
4 | |||
3 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ | 5 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ |
4 | hvcall.o proc.o htab.o iommu.o misc.o irq.o | 6 | hvcall.o proc.o htab.o iommu.o misc.o irq.o |
5 | obj-$(CONFIG_PCI) += pci.o vpdinfo.o | 7 | obj-$(CONFIG_PCI) += pci.o vpdinfo.o |
@@ -7,5 +9,9 @@ obj-$(CONFIG_SMP) += smp.o | |||
7 | obj-$(CONFIG_VIOPATH) += viopath.o | 9 | obj-$(CONFIG_VIOPATH) += viopath.o |
8 | obj-$(CONFIG_MODULES) += ksyms.o | 10 | obj-$(CONFIG_MODULES) += ksyms.o |
9 | 11 | ||
12 | quiet_cmd_dt_strings = DT_STR $@ | ||
13 | cmd_dt_strings = $(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings \ | ||
14 | $< $@ | ||
15 | |||
10 | $(obj)/dt_mod.o: $(obj)/dt.o | 16 | $(obj)/dt_mod.o: $(obj)/dt.o |
11 | @$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o | 17 | $(call if_changed,dt_strings) |
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index e305deee7f4..9e8a334a518 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "call_pci.h" | 41 | #include "call_pci.h" |
42 | #include "pci.h" | 42 | #include "pci.h" |
43 | #include "it_exp_vpd_panel.h" | 43 | #include "it_exp_vpd_panel.h" |
44 | #include "naca.h" | ||
44 | 45 | ||
45 | #ifdef DEBUG | 46 | #ifdef DEBUG |
46 | #define DBG(fmt...) udbg_printf(fmt) | 47 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -205,13 +206,11 @@ static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name, | |||
205 | dt_prop(dt, name, &data, sizeof(u32)); | 206 | dt_prop(dt, name, &data, sizeof(u32)); |
206 | } | 207 | } |
207 | 208 | ||
208 | #ifdef notyet | ||
209 | static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, | 209 | static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, |
210 | u64 data) | 210 | u64 data) |
211 | { | 211 | { |
212 | dt_prop(dt, name, &data, sizeof(u64)); | 212 | dt_prop(dt, name, &data, sizeof(u64)); |
213 | } | 213 | } |
214 | #endif | ||
215 | 214 | ||
216 | static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, | 215 | static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, |
217 | const char *name, u64 *data, int n) | 216 | const char *name, u64 *data, int n) |
@@ -306,6 +305,17 @@ static void __init dt_model(struct iseries_flat_dt *dt) | |||
306 | dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex()); | 305 | dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex()); |
307 | } | 306 | } |
308 | 307 | ||
308 | static void __init dt_initrd(struct iseries_flat_dt *dt) | ||
309 | { | ||
310 | #ifdef CONFIG_BLK_DEV_INITRD | ||
311 | if (naca.xRamDisk) { | ||
312 | dt_prop_u64(dt, "linux,initrd-start", (u64)naca.xRamDisk); | ||
313 | dt_prop_u64(dt, "linux,initrd-end", | ||
314 | (u64)naca.xRamDisk + naca.xRamDiskSize * HW_PAGE_SIZE); | ||
315 | } | ||
316 | #endif | ||
317 | } | ||
318 | |||
309 | static void __init dt_do_vdevice(struct iseries_flat_dt *dt, | 319 | static void __init dt_do_vdevice(struct iseries_flat_dt *dt, |
310 | const char *name, u32 reg, int unit, | 320 | const char *name, u32 reg, int unit, |
311 | const char *type, const char *compat, int end) | 321 | const char *type, const char *compat, int end) |
@@ -641,6 +651,7 @@ void * __init build_flat_dt(unsigned long phys_mem_size) | |||
641 | /* /chosen */ | 651 | /* /chosen */ |
642 | dt_start_node(iseries_dt, "chosen"); | 652 | dt_start_node(iseries_dt, "chosen"); |
643 | dt_prop_str(iseries_dt, "bootargs", cmd_line); | 653 | dt_prop_str(iseries_dt, "bootargs", cmd_line); |
654 | dt_initrd(iseries_dt); | ||
644 | dt_end_node(iseries_dt); | 655 | dt_end_node(iseries_dt); |
645 | 656 | ||
646 | dt_cpus(iseries_dt); | 657 | dt_cpus(iseries_dt); |
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 218817d13c5..d7a756d5135 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/pci.h> | ||
30 | 31 | ||
31 | #include <asm/iommu.h> | 32 | #include <asm/iommu.h> |
32 | #include <asm/tce.h> | 33 | #include <asm/tce.h> |
@@ -114,12 +115,10 @@ void iommu_table_getparms_iSeries(unsigned long busno, | |||
114 | { | 115 | { |
115 | struct iommu_table_cb *parms; | 116 | struct iommu_table_cb *parms; |
116 | 117 | ||
117 | parms = kmalloc(sizeof(*parms), GFP_KERNEL); | 118 | parms = kzalloc(sizeof(*parms), GFP_KERNEL); |
118 | if (parms == NULL) | 119 | if (parms == NULL) |
119 | panic("PCI_DMA: TCE Table Allocation failed."); | 120 | panic("PCI_DMA: TCE Table Allocation failed."); |
120 | 121 | ||
121 | memset(parms, 0, sizeof(*parms)); | ||
122 | |||
123 | parms->itc_busno = busno; | 122 | parms->itc_busno = busno; |
124 | parms->itc_slotno = slotno; | 123 | parms->itc_slotno = slotno; |
125 | parms->itc_virtbus = virtbus; | 124 | parms->itc_virtbus = virtbus; |
@@ -168,7 +167,7 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) | |||
168 | } | 167 | } |
169 | 168 | ||
170 | 169 | ||
171 | void iommu_devnode_init_iSeries(struct device_node *dn) | 170 | void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn) |
172 | { | 171 | { |
173 | struct iommu_table *tbl; | 172 | struct iommu_table *tbl; |
174 | struct pci_dn *pdn = PCI_DN(dn); | 173 | struct pci_dn *pdn = PCI_DN(dn); |
@@ -186,19 +185,14 @@ void iommu_devnode_init_iSeries(struct device_node *dn) | |||
186 | pdn->iommu_table = iommu_init_table(tbl, -1); | 185 | pdn->iommu_table = iommu_init_table(tbl, -1); |
187 | else | 186 | else |
188 | kfree(tbl); | 187 | kfree(tbl); |
188 | pdev->dev.archdata.dma_data = pdn->iommu_table; | ||
189 | } | 189 | } |
190 | #endif | 190 | #endif |
191 | 191 | ||
192 | static void iommu_dev_setup_iSeries(struct pci_dev *dev) { } | ||
193 | static void iommu_bus_setup_iSeries(struct pci_bus *bus) { } | ||
194 | |||
195 | void iommu_init_early_iSeries(void) | 192 | void iommu_init_early_iSeries(void) |
196 | { | 193 | { |
197 | ppc_md.tce_build = tce_build_iSeries; | 194 | ppc_md.tce_build = tce_build_iSeries; |
198 | ppc_md.tce_free = tce_free_iSeries; | 195 | ppc_md.tce_free = tce_free_iSeries; |
199 | 196 | ||
200 | ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries; | 197 | pci_dma_ops = &dma_iommu_ops; |
201 | ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries; | ||
202 | |||
203 | pci_iommu_init(); | ||
204 | } | 198 | } |
diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c index a2200842f4e..2430848b98e 100644 --- a/arch/powerpc/platforms/iseries/ksyms.c +++ b/arch/powerpc/platforms/iseries/ksyms.c | |||
@@ -19,9 +19,3 @@ EXPORT_SYMBOL(HvCall4); | |||
19 | EXPORT_SYMBOL(HvCall5); | 19 | EXPORT_SYMBOL(HvCall5); |
20 | EXPORT_SYMBOL(HvCall6); | 20 | EXPORT_SYMBOL(HvCall6); |
21 | EXPORT_SYMBOL(HvCall7); | 21 | EXPORT_SYMBOL(HvCall7); |
22 | |||
23 | #ifdef CONFIG_SMP | ||
24 | EXPORT_SYMBOL(local_get_flags); | ||
25 | EXPORT_SYMBOL(local_irq_disable); | ||
26 | EXPORT_SYMBOL(local_irq_restore); | ||
27 | #endif | ||
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index 7641fc7e550..2c6ff0fdac9 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S | |||
@@ -19,39 +19,8 @@ | |||
19 | 19 | ||
20 | .text | 20 | .text |
21 | 21 | ||
22 | /* unsigned long local_save_flags(void) */ | 22 | /* Handle pending interrupts in interrupt context */ |
23 | _GLOBAL(local_get_flags) | 23 | _GLOBAL(iseries_handle_interrupts) |
24 | lbz r3,PACAPROCENABLED(r13) | ||
25 | blr | ||
26 | |||
27 | /* unsigned long local_irq_disable(void) */ | ||
28 | _GLOBAL(local_irq_disable) | ||
29 | lbz r3,PACAPROCENABLED(r13) | ||
30 | li r4,0 | ||
31 | stb r4,PACAPROCENABLED(r13) | ||
32 | blr /* Done */ | ||
33 | |||
34 | /* void local_irq_restore(unsigned long flags) */ | ||
35 | _GLOBAL(local_irq_restore) | ||
36 | lbz r5,PACAPROCENABLED(r13) | ||
37 | /* Check if things are setup the way we want _already_. */ | ||
38 | cmpw 0,r3,r5 | ||
39 | beqlr | ||
40 | /* are we enabling interrupts? */ | ||
41 | cmpdi 0,r3,0 | ||
42 | stb r3,PACAPROCENABLED(r13) | ||
43 | beqlr | ||
44 | /* Check pending interrupts */ | ||
45 | /* A decrementer, IPI or PMC interrupt may have occurred | ||
46 | * while we were in the hypervisor (which enables) */ | ||
47 | ld r4,PACALPPACAPTR(r13) | ||
48 | ld r4,LPPACAANYINT(r4) | ||
49 | cmpdi r4,0 | ||
50 | beqlr | ||
51 | |||
52 | /* | ||
53 | * Handle pending interrupts in interrupt context | ||
54 | */ | ||
55 | li r0,0x5555 | 24 | li r0,0x5555 |
56 | sc | 25 | sc |
57 | blr | 26 | blr |
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4aa165e010d..4a06d9c3498 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
@@ -156,53 +156,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * iSeries_pcibios_init | ||
160 | * | ||
161 | * Description: | ||
162 | * This function checks for all possible system PCI host bridges that connect | ||
163 | * PCI buses. The system hypervisor is queried as to the guest partition | ||
164 | * ownership status. A pci_controller is built for any bus which is partially | ||
165 | * owned or fully owned by this guest partition. | ||
166 | */ | ||
167 | void iSeries_pcibios_init(void) | ||
168 | { | ||
169 | struct pci_controller *phb; | ||
170 | struct device_node *root = of_find_node_by_path("/"); | ||
171 | struct device_node *node = NULL; | ||
172 | |||
173 | if (root == NULL) { | ||
174 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " | ||
175 | "of device tree\n"); | ||
176 | return; | ||
177 | } | ||
178 | while ((node = of_get_next_child(root, node)) != NULL) { | ||
179 | HvBusNumber bus; | ||
180 | const u32 *busp; | ||
181 | |||
182 | if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) | ||
183 | continue; | ||
184 | |||
185 | busp = get_property(node, "bus-range", NULL); | ||
186 | if (busp == NULL) | ||
187 | continue; | ||
188 | bus = *busp; | ||
189 | printk("bus %d appears to exist\n", bus); | ||
190 | phb = pcibios_alloc_controller(node); | ||
191 | if (phb == NULL) | ||
192 | continue; | ||
193 | |||
194 | phb->pci_mem_offset = phb->local_number = bus; | ||
195 | phb->first_busno = bus; | ||
196 | phb->last_busno = bus; | ||
197 | phb->ops = &iSeries_pci_ops; | ||
198 | } | ||
199 | |||
200 | of_node_put(root); | ||
201 | |||
202 | pci_devs_phb_init(); | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * iSeries_pci_final_fixup(void) | 159 | * iSeries_pci_final_fixup(void) |
207 | */ | 160 | */ |
208 | void __init iSeries_pci_final_fixup(void) | 161 | void __init iSeries_pci_final_fixup(void) |
@@ -253,7 +206,7 @@ void __init iSeries_pci_final_fixup(void) | |||
253 | PCI_DN(node)->pcidev = pdev; | 206 | PCI_DN(node)->pcidev = pdev; |
254 | allocate_device_bars(pdev); | 207 | allocate_device_bars(pdev); |
255 | iSeries_Device_Information(pdev, DeviceCount); | 208 | iSeries_Device_Information(pdev, DeviceCount); |
256 | iommu_devnode_init_iSeries(node); | 209 | iommu_devnode_init_iSeries(pdev, node); |
257 | } else | 210 | } else |
258 | printk("PCI: Device Tree not found for 0x%016lX\n", | 211 | printk("PCI: Device Tree not found for 0x%016lX\n", |
259 | (unsigned long)pdev); | 212 | (unsigned long)pdev); |
@@ -438,11 +391,7 @@ static inline struct device_node *xlate_iomm_address( | |||
438 | /* | 391 | /* |
439 | * Read MM I/O Instructions for the iSeries | 392 | * Read MM I/O Instructions for the iSeries |
440 | * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal | 393 | * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal |
441 | * else, data is returned in big Endian format. | 394 | * else, data is returned in Big Endian format. |
442 | * | ||
443 | * iSeries_Read_Byte = Read Byte ( 8 bit) | ||
444 | * iSeries_Read_Word = Read Word (16 bit) | ||
445 | * iSeries_Read_Long = Read Long (32 bit) | ||
446 | */ | 395 | */ |
447 | static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) | 396 | static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) |
448 | { | 397 | { |
@@ -462,14 +411,15 @@ static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) | |||
462 | num_printed = 0; | 411 | num_printed = 0; |
463 | } | 412 | } |
464 | if (num_printed++ < 10) | 413 | if (num_printed++ < 10) |
465 | printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); | 414 | printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", |
415 | IoAddress); | ||
466 | return 0xff; | 416 | return 0xff; |
467 | } | 417 | } |
468 | do { | 418 | do { |
469 | HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); | 419 | HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); |
470 | } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); | 420 | } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); |
471 | 421 | ||
472 | return (u8)ret.value; | 422 | return ret.value; |
473 | } | 423 | } |
474 | 424 | ||
475 | static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) | 425 | static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) |
@@ -490,7 +440,8 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) | |||
490 | num_printed = 0; | 440 | num_printed = 0; |
491 | } | 441 | } |
492 | if (num_printed++ < 10) | 442 | if (num_printed++ < 10) |
493 | printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); | 443 | printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", |
444 | IoAddress); | ||
494 | return 0xffff; | 445 | return 0xffff; |
495 | } | 446 | } |
496 | do { | 447 | do { |
@@ -498,7 +449,7 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) | |||
498 | BarOffset, 0); | 449 | BarOffset, 0); |
499 | } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); | 450 | } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); |
500 | 451 | ||
501 | return swab16((u16)ret.value); | 452 | return ret.value; |
502 | } | 453 | } |
503 | 454 | ||
504 | static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) | 455 | static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) |
@@ -519,7 +470,8 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) | |||
519 | num_printed = 0; | 470 | num_printed = 0; |
520 | } | 471 | } |
521 | if (num_printed++ < 10) | 472 | if (num_printed++ < 10) |
522 | printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); | 473 | printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", |
474 | IoAddress); | ||
523 | return 0xffffffff; | 475 | return 0xffffffff; |
524 | } | 476 | } |
525 | do { | 477 | do { |
@@ -527,15 +479,12 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) | |||
527 | BarOffset, 0); | 479 | BarOffset, 0); |
528 | } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); | 480 | } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); |
529 | 481 | ||
530 | return swab32((u32)ret.value); | 482 | return ret.value; |
531 | } | 483 | } |
532 | 484 | ||
533 | /* | 485 | /* |
534 | * Write MM I/O Instructions for the iSeries | 486 | * Write MM I/O Instructions for the iSeries |
535 | * | 487 | * |
536 | * iSeries_Write_Byte = Write Byte (8 bit) | ||
537 | * iSeries_Write_Word = Write Word(16 bit) | ||
538 | * iSeries_Write_Long = Write Long(32 bit) | ||
539 | */ | 488 | */ |
540 | static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) | 489 | static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) |
541 | { | 490 | { |
@@ -581,11 +530,12 @@ static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) | |||
581 | num_printed = 0; | 530 | num_printed = 0; |
582 | } | 531 | } |
583 | if (num_printed++ < 10) | 532 | if (num_printed++ < 10) |
584 | printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); | 533 | printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", |
534 | IoAddress); | ||
585 | return; | 535 | return; |
586 | } | 536 | } |
587 | do { | 537 | do { |
588 | rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); | 538 | rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0); |
589 | } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); | 539 | } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); |
590 | } | 540 | } |
591 | 541 | ||
@@ -607,231 +557,221 @@ static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) | |||
607 | num_printed = 0; | 557 | num_printed = 0; |
608 | } | 558 | } |
609 | if (num_printed++ < 10) | 559 | if (num_printed++ < 10) |
610 | printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); | 560 | printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", |
561 | IoAddress); | ||
611 | return; | 562 | return; |
612 | } | 563 | } |
613 | do { | 564 | do { |
614 | rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); | 565 | rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0); |
615 | } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); | 566 | } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); |
616 | } | 567 | } |
617 | 568 | ||
618 | extern unsigned char __raw_readb(const volatile void __iomem *addr) | 569 | static u8 iseries_readb(const volatile void __iomem *addr) |
619 | { | 570 | { |
620 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 571 | return iSeries_Read_Byte(addr); |
621 | |||
622 | return *(volatile unsigned char __force *)addr; | ||
623 | } | 572 | } |
624 | EXPORT_SYMBOL(__raw_readb); | ||
625 | 573 | ||
626 | extern unsigned short __raw_readw(const volatile void __iomem *addr) | 574 | static u16 iseries_readw(const volatile void __iomem *addr) |
627 | { | 575 | { |
628 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 576 | return le16_to_cpu(iSeries_Read_Word(addr)); |
629 | |||
630 | return *(volatile unsigned short __force *)addr; | ||
631 | } | 577 | } |
632 | EXPORT_SYMBOL(__raw_readw); | ||
633 | 578 | ||
634 | extern unsigned int __raw_readl(const volatile void __iomem *addr) | 579 | static u32 iseries_readl(const volatile void __iomem *addr) |
635 | { | 580 | { |
636 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 581 | return le32_to_cpu(iSeries_Read_Long(addr)); |
637 | |||
638 | return *(volatile unsigned int __force *)addr; | ||
639 | } | 582 | } |
640 | EXPORT_SYMBOL(__raw_readl); | ||
641 | 583 | ||
642 | extern unsigned long __raw_readq(const volatile void __iomem *addr) | 584 | static u16 iseries_readw_be(const volatile void __iomem *addr) |
643 | { | 585 | { |
644 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 586 | return iSeries_Read_Word(addr); |
645 | |||
646 | return *(volatile unsigned long __force *)addr; | ||
647 | } | 587 | } |
648 | EXPORT_SYMBOL(__raw_readq); | ||
649 | 588 | ||
650 | extern void __raw_writeb(unsigned char v, volatile void __iomem *addr) | 589 | static u32 iseries_readl_be(const volatile void __iomem *addr) |
651 | { | 590 | { |
652 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 591 | return iSeries_Read_Long(addr); |
653 | |||
654 | *(volatile unsigned char __force *)addr = v; | ||
655 | } | 592 | } |
656 | EXPORT_SYMBOL(__raw_writeb); | ||
657 | 593 | ||
658 | extern void __raw_writew(unsigned short v, volatile void __iomem *addr) | 594 | static void iseries_writeb(u8 data, volatile void __iomem *addr) |
659 | { | 595 | { |
660 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 596 | iSeries_Write_Byte(data, addr); |
661 | |||
662 | *(volatile unsigned short __force *)addr = v; | ||
663 | } | 597 | } |
664 | EXPORT_SYMBOL(__raw_writew); | ||
665 | 598 | ||
666 | extern void __raw_writel(unsigned int v, volatile void __iomem *addr) | 599 | static void iseries_writew(u16 data, volatile void __iomem *addr) |
667 | { | 600 | { |
668 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 601 | iSeries_Write_Word(cpu_to_le16(data), addr); |
669 | |||
670 | *(volatile unsigned int __force *)addr = v; | ||
671 | } | 602 | } |
672 | EXPORT_SYMBOL(__raw_writel); | ||
673 | 603 | ||
674 | extern void __raw_writeq(unsigned long v, volatile void __iomem *addr) | 604 | static void iseries_writel(u32 data, volatile void __iomem *addr) |
675 | { | 605 | { |
676 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 606 | iSeries_Write_Long(cpu_to_le32(data), addr); |
677 | |||
678 | *(volatile unsigned long __force *)addr = v; | ||
679 | } | 607 | } |
680 | EXPORT_SYMBOL(__raw_writeq); | ||
681 | 608 | ||
682 | int in_8(const volatile unsigned char __iomem *addr) | 609 | static void iseries_writew_be(u16 data, volatile void __iomem *addr) |
683 | { | 610 | { |
684 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 611 | iSeries_Write_Word(data, addr); |
685 | return iSeries_Read_Byte(addr); | ||
686 | return __in_8(addr); | ||
687 | } | 612 | } |
688 | EXPORT_SYMBOL(in_8); | ||
689 | 613 | ||
690 | void out_8(volatile unsigned char __iomem *addr, int val) | 614 | static void iseries_writel_be(u32 data, volatile void __iomem *addr) |
691 | { | 615 | { |
692 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 616 | iSeries_Write_Long(data, addr); |
693 | iSeries_Write_Byte(val, addr); | ||
694 | else | ||
695 | __out_8(addr, val); | ||
696 | } | 617 | } |
697 | EXPORT_SYMBOL(out_8); | ||
698 | 618 | ||
699 | int in_le16(const volatile unsigned short __iomem *addr) | 619 | static void iseries_readsb(const volatile void __iomem *addr, void *buf, |
620 | unsigned long count) | ||
700 | { | 621 | { |
701 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 622 | u8 *dst = buf; |
702 | return iSeries_Read_Word(addr); | 623 | while(count-- > 0) |
703 | return __in_le16(addr); | 624 | *(dst++) = iSeries_Read_Byte(addr); |
704 | } | 625 | } |
705 | EXPORT_SYMBOL(in_le16); | ||
706 | 626 | ||
707 | int in_be16(const volatile unsigned short __iomem *addr) | 627 | static void iseries_readsw(const volatile void __iomem *addr, void *buf, |
628 | unsigned long count) | ||
708 | { | 629 | { |
709 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 630 | u16 *dst = buf; |
710 | 631 | while(count-- > 0) | |
711 | return __in_be16(addr); | 632 | *(dst++) = iSeries_Read_Word(addr); |
712 | } | 633 | } |
713 | EXPORT_SYMBOL(in_be16); | ||
714 | 634 | ||
715 | void out_le16(volatile unsigned short __iomem *addr, int val) | 635 | static void iseries_readsl(const volatile void __iomem *addr, void *buf, |
636 | unsigned long count) | ||
716 | { | 637 | { |
717 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 638 | u32 *dst = buf; |
718 | iSeries_Write_Word(val, addr); | 639 | while(count-- > 0) |
719 | else | 640 | *(dst++) = iSeries_Read_Long(addr); |
720 | __out_le16(addr, val); | ||
721 | } | 641 | } |
722 | EXPORT_SYMBOL(out_le16); | ||
723 | 642 | ||
724 | void out_be16(volatile unsigned short __iomem *addr, int val) | 643 | static void iseries_writesb(volatile void __iomem *addr, const void *buf, |
644 | unsigned long count) | ||
725 | { | 645 | { |
726 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 646 | const u8 *src = buf; |
727 | 647 | while(count-- > 0) | |
728 | __out_be16(addr, val); | 648 | iSeries_Write_Byte(*(src++), addr); |
729 | } | 649 | } |
730 | EXPORT_SYMBOL(out_be16); | ||
731 | 650 | ||
732 | unsigned in_le32(const volatile unsigned __iomem *addr) | 651 | static void iseries_writesw(volatile void __iomem *addr, const void *buf, |
652 | unsigned long count) | ||
733 | { | 653 | { |
734 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 654 | const u16 *src = buf; |
735 | return iSeries_Read_Long(addr); | 655 | while(count-- > 0) |
736 | return __in_le32(addr); | 656 | iSeries_Write_Word(*(src++), addr); |
737 | } | 657 | } |
738 | EXPORT_SYMBOL(in_le32); | ||
739 | 658 | ||
740 | unsigned in_be32(const volatile unsigned __iomem *addr) | 659 | static void iseries_writesl(volatile void __iomem *addr, const void *buf, |
660 | unsigned long count) | ||
741 | { | 661 | { |
742 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 662 | const u32 *src = buf; |
743 | 663 | while(count-- > 0) | |
744 | return __in_be32(addr); | 664 | iSeries_Write_Long(*(src++), addr); |
745 | } | 665 | } |
746 | EXPORT_SYMBOL(in_be32); | ||
747 | 666 | ||
748 | void out_le32(volatile unsigned __iomem *addr, int val) | 667 | static void iseries_memset_io(volatile void __iomem *addr, int c, |
668 | unsigned long n) | ||
749 | { | 669 | { |
750 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 670 | volatile char __iomem *d = addr; |
751 | iSeries_Write_Long(val, addr); | ||
752 | else | ||
753 | __out_le32(addr, val); | ||
754 | } | ||
755 | EXPORT_SYMBOL(out_le32); | ||
756 | 671 | ||
757 | void out_be32(volatile unsigned __iomem *addr, int val) | 672 | while (n-- > 0) |
758 | { | 673 | iSeries_Write_Byte(c, d++); |
759 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
760 | |||
761 | __out_be32(addr, val); | ||
762 | } | 674 | } |
763 | EXPORT_SYMBOL(out_be32); | ||
764 | 675 | ||
765 | unsigned long in_le64(const volatile unsigned long __iomem *addr) | 676 | static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src, |
677 | unsigned long n) | ||
766 | { | 678 | { |
767 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 679 | char *d = dest; |
680 | const volatile char __iomem *s = src; | ||
768 | 681 | ||
769 | return __in_le64(addr); | 682 | while (n-- > 0) |
683 | *d++ = iSeries_Read_Byte(s++); | ||
770 | } | 684 | } |
771 | EXPORT_SYMBOL(in_le64); | ||
772 | 685 | ||
773 | unsigned long in_be64(const volatile unsigned long __iomem *addr) | 686 | static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src, |
687 | unsigned long n) | ||
774 | { | 688 | { |
775 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 689 | const char *s = src; |
690 | volatile char __iomem *d = dest; | ||
776 | 691 | ||
777 | return __in_be64(addr); | 692 | while (n-- > 0) |
693 | iSeries_Write_Byte(*s++, d++); | ||
778 | } | 694 | } |
779 | EXPORT_SYMBOL(in_be64); | ||
780 | |||
781 | void out_le64(volatile unsigned long __iomem *addr, unsigned long val) | ||
782 | { | ||
783 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
784 | 695 | ||
785 | __out_le64(addr, val); | 696 | /* We only set MMIO ops. The default PIO ops will be default |
786 | } | 697 | * to the MMIO ops + pci_io_base which is 0 on iSeries as |
787 | EXPORT_SYMBOL(out_le64); | 698 | * expected so both should work. |
699 | * | ||
700 | * Note that we don't implement the readq/writeq versions as | ||
701 | * I don't know of an HV call for doing so. Thus, the default | ||
702 | * operation will be used instead, which will fault a the value | ||
703 | * return by iSeries for MMIO addresses always hits a non mapped | ||
704 | * area. This is as good as the BUG() we used to have there. | ||
705 | */ | ||
706 | static struct ppc_pci_io __initdata iseries_pci_io = { | ||
707 | .readb = iseries_readb, | ||
708 | .readw = iseries_readw, | ||
709 | .readl = iseries_readl, | ||
710 | .readw_be = iseries_readw_be, | ||
711 | .readl_be = iseries_readl_be, | ||
712 | .writeb = iseries_writeb, | ||
713 | .writew = iseries_writew, | ||
714 | .writel = iseries_writel, | ||
715 | .writew_be = iseries_writew_be, | ||
716 | .writel_be = iseries_writel_be, | ||
717 | .readsb = iseries_readsb, | ||
718 | .readsw = iseries_readsw, | ||
719 | .readsl = iseries_readsl, | ||
720 | .writesb = iseries_writesb, | ||
721 | .writesw = iseries_writesw, | ||
722 | .writesl = iseries_writesl, | ||
723 | .memset_io = iseries_memset_io, | ||
724 | .memcpy_fromio = iseries_memcpy_fromio, | ||
725 | .memcpy_toio = iseries_memcpy_toio, | ||
726 | }; | ||
788 | 727 | ||
789 | void out_be64(volatile unsigned long __iomem *addr, unsigned long val) | 728 | /* |
729 | * iSeries_pcibios_init | ||
730 | * | ||
731 | * Description: | ||
732 | * This function checks for all possible system PCI host bridges that connect | ||
733 | * PCI buses. The system hypervisor is queried as to the guest partition | ||
734 | * ownership status. A pci_controller is built for any bus which is partially | ||
735 | * owned or fully owned by this guest partition. | ||
736 | */ | ||
737 | void __init iSeries_pcibios_init(void) | ||
790 | { | 738 | { |
791 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 739 | struct pci_controller *phb; |
740 | struct device_node *root = of_find_node_by_path("/"); | ||
741 | struct device_node *node = NULL; | ||
792 | 742 | ||
793 | __out_be64(addr, val); | 743 | /* Install IO hooks */ |
794 | } | 744 | ppc_pci_io = iseries_pci_io; |
795 | EXPORT_SYMBOL(out_be64); | ||
796 | 745 | ||
797 | void memset_io(volatile void __iomem *addr, int c, unsigned long n) | 746 | if (root == NULL) { |
798 | { | 747 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " |
799 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | 748 | "of device tree\n"); |
800 | volatile char __iomem *d = addr; | 749 | return; |
750 | } | ||
751 | while ((node = of_get_next_child(root, node)) != NULL) { | ||
752 | HvBusNumber bus; | ||
753 | const u32 *busp; | ||
801 | 754 | ||
802 | while (n-- > 0) { | 755 | if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) |
803 | iSeries_Write_Byte(c, d++); | 756 | continue; |
804 | } | ||
805 | } else | ||
806 | eeh_memset_io(addr, c, n); | ||
807 | } | ||
808 | EXPORT_SYMBOL(memset_io); | ||
809 | 757 | ||
810 | void memcpy_fromio(void *dest, const volatile void __iomem *src, | 758 | busp = get_property(node, "bus-range", NULL); |
811 | unsigned long n) | 759 | if (busp == NULL) |
812 | { | 760 | continue; |
813 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | 761 | bus = *busp; |
814 | char *d = dest; | 762 | printk("bus %d appears to exist\n", bus); |
815 | const volatile char __iomem *s = src; | 763 | phb = pcibios_alloc_controller(node); |
764 | if (phb == NULL) | ||
765 | continue; | ||
816 | 766 | ||
817 | while (n-- > 0) { | 767 | phb->pci_mem_offset = phb->local_number = bus; |
818 | *d++ = iSeries_Read_Byte(s++); | 768 | phb->first_busno = bus; |
819 | } | 769 | phb->last_busno = bus; |
820 | } else | 770 | phb->ops = &iSeries_pci_ops; |
821 | eeh_memcpy_fromio(dest, src, n); | 771 | } |
822 | } | ||
823 | EXPORT_SYMBOL(memcpy_fromio); | ||
824 | 772 | ||
825 | void memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) | 773 | of_node_put(root); |
826 | { | ||
827 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
828 | const char *s = src; | ||
829 | volatile char __iomem *d = dest; | ||
830 | 774 | ||
831 | while (n-- > 0) { | 775 | pci_devs_phb_init(); |
832 | iSeries_Write_Byte(*s++, d++); | ||
833 | } | ||
834 | } else | ||
835 | eeh_memcpy_toio(dest, src, n); | ||
836 | } | 776 | } |
837 | EXPORT_SYMBOL(memcpy_toio); | 777 | |
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 6f73469fd3b..bdf2afbb60c 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/param.h> | 22 | #include <linux/param.h> |
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/initrd.h> | ||
25 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
26 | #include <linux/kdev_t.h> | 25 | #include <linux/kdev_t.h> |
27 | #include <linux/major.h> | 26 | #include <linux/major.h> |
@@ -80,8 +79,6 @@ extern void iSeries_pci_final_fixup(void); | |||
80 | static void iSeries_pci_final_fixup(void) { } | 79 | static void iSeries_pci_final_fixup(void) { } |
81 | #endif | 80 | #endif |
82 | 81 | ||
83 | extern int rd_size; /* Defined in drivers/block/rd.c */ | ||
84 | |||
85 | extern unsigned long iSeries_recal_tb; | 82 | extern unsigned long iSeries_recal_tb; |
86 | extern unsigned long iSeries_recal_titan; | 83 | extern unsigned long iSeries_recal_titan; |
87 | 84 | ||
@@ -295,24 +292,6 @@ static void __init iSeries_init_early(void) | |||
295 | { | 292 | { |
296 | DBG(" -> iSeries_init_early()\n"); | 293 | DBG(" -> iSeries_init_early()\n"); |
297 | 294 | ||
298 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
299 | /* | ||
300 | * If the init RAM disk has been configured and there is | ||
301 | * a non-zero starting address for it, set it up | ||
302 | */ | ||
303 | if (naca.xRamDisk) { | ||
304 | initrd_start = (unsigned long)__va(naca.xRamDisk); | ||
305 | initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE; | ||
306 | initrd_below_start_ok = 1; // ramdisk in kernel space | ||
307 | ROOT_DEV = Root_RAM0; | ||
308 | if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize) | ||
309 | rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024; | ||
310 | } else | ||
311 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
312 | { | ||
313 | /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */ | ||
314 | } | ||
315 | |||
316 | iSeries_recal_tb = get_tb(); | 295 | iSeries_recal_tb = get_tb(); |
317 | iSeries_recal_titan = HvCallXm_loadTod(); | 296 | iSeries_recal_titan = HvCallXm_loadTod(); |
318 | 297 | ||
@@ -331,17 +310,6 @@ static void __init iSeries_init_early(void) | |||
331 | 310 | ||
332 | mf_init(); | 311 | mf_init(); |
333 | 312 | ||
334 | /* If we were passed an initrd, set the ROOT_DEV properly if the values | ||
335 | * look sensible. If not, clear initrd reference. | ||
336 | */ | ||
337 | #ifdef CONFIG_BLK_DEV_INITRD | ||
338 | if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE && | ||
339 | initrd_end > initrd_start) | ||
340 | ROOT_DEV = Root_RAM0; | ||
341 | else | ||
342 | initrd_start = initrd_end = 0; | ||
343 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
344 | |||
345 | DBG(" <- iSeries_init_early()\n"); | 313 | DBG(" <- iSeries_init_early()\n"); |
346 | } | 314 | } |
347 | 315 | ||
@@ -649,6 +617,16 @@ static void iseries_dedicated_idle(void) | |||
649 | void __init iSeries_init_IRQ(void) { } | 617 | void __init iSeries_init_IRQ(void) { } |
650 | #endif | 618 | #endif |
651 | 619 | ||
620 | static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size, | ||
621 | unsigned long flags) | ||
622 | { | ||
623 | return (void __iomem *)address; | ||
624 | } | ||
625 | |||
626 | static void iseries_iounmap(volatile void __iomem *token) | ||
627 | { | ||
628 | } | ||
629 | |||
652 | /* | 630 | /* |
653 | * iSeries has no legacy IO, anything calling this function has to | 631 | * iSeries has no legacy IO, anything calling this function has to |
654 | * fail or bad things will happen | 632 | * fail or bad things will happen |
@@ -665,6 +643,8 @@ static int __init iseries_probe(void) | |||
665 | return 0; | 643 | return 0; |
666 | 644 | ||
667 | hpte_init_iSeries(); | 645 | hpte_init_iSeries(); |
646 | /* iSeries does not support 16M pages */ | ||
647 | cur_cpu_spec->cpu_features &= ~CPU_FTR_16M_PAGE; | ||
668 | 648 | ||
669 | return 1; | 649 | return 1; |
670 | } | 650 | } |
@@ -687,6 +667,8 @@ define_machine(iseries) { | |||
687 | .progress = iSeries_progress, | 667 | .progress = iSeries_progress, |
688 | .probe = iseries_probe, | 668 | .probe = iseries_probe, |
689 | .check_legacy_ioport = iseries_check_legacy_ioport, | 669 | .check_legacy_ioport = iseries_check_legacy_ioport, |
670 | .ioremap = iseries_ioremap, | ||
671 | .iounmap = iseries_iounmap, | ||
690 | /* XXX Implement enable_pmcs for iSeries */ | 672 | /* XXX Implement enable_pmcs for iSeries */ |
691 | }; | 673 | }; |
692 | 674 | ||
@@ -697,7 +679,7 @@ void * __init iSeries_early_setup(void) | |||
697 | /* Identify CPU type. This is done again by the common code later | 679 | /* Identify CPU type. This is done again by the common code later |
698 | * on but calling this function multiple times is fine. | 680 | * on but calling this function multiple times is fine. |
699 | */ | 681 | */ |
700 | identify_cpu(0); | 682 | identify_cpu(0, mfspr(SPRN_PVR)); |
701 | 683 | ||
702 | powerpc_firmware_features |= FW_FEATURE_ISERIES; | 684 | powerpc_firmware_features |= FW_FEATURE_ISERIES; |
703 | powerpc_firmware_features |= FW_FEATURE_LPAR; | 685 | powerpc_firmware_features |= FW_FEATURE_LPAR; |
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 04e07e5da0c..84e7ee2c086 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c | |||
@@ -119,10 +119,9 @@ static int proc_viopath_show(struct seq_file *m, void *v) | |||
119 | struct device_node *node; | 119 | struct device_node *node; |
120 | const char *sysid; | 120 | const char *sysid; |
121 | 121 | ||
122 | buf = kmalloc(HW_PAGE_SIZE, GFP_KERNEL); | 122 | buf = kzalloc(HW_PAGE_SIZE, GFP_KERNEL); |
123 | if (!buf) | 123 | if (!buf) |
124 | return 0; | 124 | return 0; |
125 | memset(buf, 0, HW_PAGE_SIZE); | ||
126 | 125 | ||
127 | handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, | 126 | handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, |
128 | DMA_FROM_DEVICE); | 127 | DMA_FROM_DEVICE); |
diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h index 0657c579b84..c6911ddc479 100644 --- a/arch/powerpc/platforms/maple/maple.h +++ b/arch/powerpc/platforms/maple/maple.h | |||
@@ -8,5 +8,5 @@ extern void maple_get_rtc_time(struct rtc_time *tm); | |||
8 | extern unsigned long maple_get_boot_time(void); | 8 | extern unsigned long maple_get_boot_time(void); |
9 | extern void maple_calibrate_decr(void); | 9 | extern void maple_calibrate_decr(void); |
10 | extern void maple_pci_init(void); | 10 | extern void maple_pci_init(void); |
11 | extern void maple_pcibios_fixup(void); | 11 | extern void maple_pci_irq_fixup(struct pci_dev *dev); |
12 | extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel); | 12 | extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel); |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 63b4d1bff35..3a32deda765 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -502,38 +502,29 @@ static int __init add_bridge(struct device_node *dev) | |||
502 | } | 502 | } |
503 | 503 | ||
504 | 504 | ||
505 | void __init maple_pcibios_fixup(void) | 505 | void __devinit maple_pci_irq_fixup(struct pci_dev *dev) |
506 | { | 506 | { |
507 | struct pci_dev *dev = NULL; | 507 | DBG(" -> maple_pci_irq_fixup\n"); |
508 | 508 | ||
509 | DBG(" -> maple_pcibios_fixup\n"); | 509 | /* Fixup IRQ for PCIe host */ |
510 | 510 | if (u4_pcie != NULL && dev->bus->number == 0 && | |
511 | for_each_pci_dev(dev) { | 511 | pci_bus_to_host(dev->bus) == u4_pcie) { |
512 | /* Fixup IRQ for PCIe host */ | 512 | printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n"); |
513 | if (u4_pcie != NULL && dev->bus->number == 0 && | 513 | dev->irq = irq_create_mapping(NULL, 1); |
514 | pci_bus_to_host(dev->bus) == u4_pcie) { | 514 | if (dev->irq != NO_IRQ) |
515 | printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n"); | 515 | set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); |
516 | dev->irq = irq_create_mapping(NULL, 1); | 516 | } |
517 | if (dev->irq != NO_IRQ) | ||
518 | set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); | ||
519 | continue; | ||
520 | } | ||
521 | |||
522 | /* Hide AMD8111 IDE interrupt when in legacy mode so | ||
523 | * the driver calls pci_get_legacy_ide_irq() | ||
524 | */ | ||
525 | if (dev->vendor == PCI_VENDOR_ID_AMD && | ||
526 | dev->device == PCI_DEVICE_ID_AMD_8111_IDE && | ||
527 | (dev->class & 5) != 5) { | ||
528 | dev->irq = NO_IRQ; | ||
529 | continue; | ||
530 | } | ||
531 | 517 | ||
532 | /* For all others, map the interrupt from the device-tree */ | 518 | /* Hide AMD8111 IDE interrupt when in legacy mode so |
533 | pci_read_irq_line(dev); | 519 | * the driver calls pci_get_legacy_ide_irq() |
520 | */ | ||
521 | if (dev->vendor == PCI_VENDOR_ID_AMD && | ||
522 | dev->device == PCI_DEVICE_ID_AMD_8111_IDE && | ||
523 | (dev->class & 5) != 5) { | ||
524 | dev->irq = NO_IRQ; | ||
534 | } | 525 | } |
535 | 526 | ||
536 | DBG(" <- maple_pcibios_fixup\n"); | 527 | DBG(" <- maple_pci_irq_fixup\n"); |
537 | } | 528 | } |
538 | 529 | ||
539 | static void __init maple_fixup_phb_resources(void) | 530 | static void __init maple_fixup_phb_resources(void) |
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index fe6b9bff61b..094989d50ba 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c | |||
@@ -312,7 +312,7 @@ define_machine(maple_md) { | |||
312 | .setup_arch = maple_setup_arch, | 312 | .setup_arch = maple_setup_arch, |
313 | .init_early = maple_init_early, | 313 | .init_early = maple_init_early, |
314 | .init_IRQ = maple_init_IRQ, | 314 | .init_IRQ = maple_init_IRQ, |
315 | .pcibios_fixup = maple_pcibios_fixup, | 315 | .pci_irq_fixup = maple_pci_irq_fixup, |
316 | .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, | 316 | .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, |
317 | .restart = maple_restart, | 317 | .restart = maple_restart, |
318 | .power_off = maple_power_off, | 318 | .power_off = maple_power_off, |
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index fd71d72736b..51c2a2397ec 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h | |||
@@ -3,6 +3,5 @@ | |||
3 | 3 | ||
4 | extern unsigned long pas_get_boot_time(void); | 4 | extern unsigned long pas_get_boot_time(void); |
5 | extern void pas_pci_init(void); | 5 | extern void pas_pci_init(void); |
6 | extern void pas_pcibios_fixup(void); | ||
7 | 6 | ||
8 | #endif /* _PASEMI_PASEMI_H */ | 7 | #endif /* _PASEMI_PASEMI_H */ |
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index 39020c1fa13..faa618e0404 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c | |||
@@ -148,14 +148,6 @@ static int __init add_bridge(struct device_node *dev) | |||
148 | } | 148 | } |
149 | 149 | ||
150 | 150 | ||
151 | void __init pas_pcibios_fixup(void) | ||
152 | { | ||
153 | struct pci_dev *dev = NULL; | ||
154 | |||
155 | for_each_pci_dev(dev) | ||
156 | pci_read_irq_line(dev); | ||
157 | } | ||
158 | |||
159 | static void __init pas_fixup_phb_resources(void) | 151 | static void __init pas_fixup_phb_resources(void) |
160 | { | 152 | { |
161 | struct pci_controller *hose, *tmp; | 153 | struct pci_controller *hose, *tmp; |
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 106896c3b60..89d6e295dbf 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/pci.h> | ||
29 | 30 | ||
30 | #include <asm/prom.h> | 31 | #include <asm/prom.h> |
31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
@@ -71,6 +72,9 @@ void __init pas_setup_arch(void) | |||
71 | /* Setup SMP callback */ | 72 | /* Setup SMP callback */ |
72 | smp_ops = &pas_smp_ops; | 73 | smp_ops = &pas_smp_ops; |
73 | #endif | 74 | #endif |
75 | /* no iommu yet */ | ||
76 | pci_dma_ops = &dma_direct_ops; | ||
77 | |||
74 | /* Lookup PCI hosts */ | 78 | /* Lookup PCI hosts */ |
75 | pas_pci_init(); | 79 | pas_pci_init(); |
76 | 80 | ||
@@ -81,17 +85,6 @@ void __init pas_setup_arch(void) | |||
81 | printk(KERN_DEBUG "Using default idle loop\n"); | 85 | printk(KERN_DEBUG "Using default idle loop\n"); |
82 | } | 86 | } |
83 | 87 | ||
84 | static void iommu_dev_setup_null(struct pci_dev *dev) { } | ||
85 | static void iommu_bus_setup_null(struct pci_bus *bus) { } | ||
86 | |||
87 | static void __init pas_init_early(void) | ||
88 | { | ||
89 | /* No iommu code yet */ | ||
90 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | ||
91 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | ||
92 | pci_direct_iommu_init(); | ||
93 | } | ||
94 | |||
95 | /* No legacy IO on our parts */ | 88 | /* No legacy IO on our parts */ |
96 | static int pas_check_legacy_ioport(unsigned int baseport) | 89 | static int pas_check_legacy_ioport(unsigned int baseport) |
97 | { | 90 | { |
@@ -173,10 +166,8 @@ define_machine(pas) { | |||
173 | .name = "PA Semi PA6T-1682M", | 166 | .name = "PA Semi PA6T-1682M", |
174 | .probe = pas_probe, | 167 | .probe = pas_probe, |
175 | .setup_arch = pas_setup_arch, | 168 | .setup_arch = pas_setup_arch, |
176 | .init_early = pas_init_early, | ||
177 | .init_IRQ = pas_init_IRQ, | 169 | .init_IRQ = pas_init_IRQ, |
178 | .get_irq = mpic_get_irq, | 170 | .get_irq = mpic_get_irq, |
179 | .pcibios_fixup = pas_pcibios_fixup, | ||
180 | .restart = pas_restart, | 171 | .restart = pas_restart, |
181 | .power_off = pas_power_off, | 172 | .power_off = pas_power_off, |
182 | .halt = pas_halt, | 173 | .halt = pas_halt, |
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index e49621be664..c29a6a064d2 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -486,10 +486,6 @@ static long heathrow_sound_enable(struct device_node *node, long param, | |||
486 | 486 | ||
487 | static u32 save_fcr[6]; | 487 | static u32 save_fcr[6]; |
488 | static u32 save_mbcr; | 488 | static u32 save_mbcr; |
489 | static u32 save_gpio_levels[2]; | ||
490 | static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; | ||
491 | static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; | ||
492 | static u32 save_unin_clock_ctl; | ||
493 | static struct dbdma_regs save_dbdma[13]; | 489 | static struct dbdma_regs save_dbdma[13]; |
494 | static struct dbdma_regs save_alt_dbdma[13]; | 490 | static struct dbdma_regs save_alt_dbdma[13]; |
495 | 491 | ||
@@ -1548,6 +1544,10 @@ void g5_phy_disable_cpu1(void) | |||
1548 | 1544 | ||
1549 | 1545 | ||
1550 | #ifdef CONFIG_PM | 1546 | #ifdef CONFIG_PM |
1547 | static u32 save_gpio_levels[2]; | ||
1548 | static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; | ||
1549 | static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; | ||
1550 | static u32 save_unin_clock_ctl; | ||
1551 | 1551 | ||
1552 | static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode) | 1552 | static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode) |
1553 | { | 1553 | { |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 257dc906846..f42475b27c1 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -984,30 +984,23 @@ static int __init add_bridge(struct device_node *dev) | |||
984 | return 0; | 984 | return 0; |
985 | } | 985 | } |
986 | 986 | ||
987 | void __init pmac_pcibios_fixup(void) | 987 | void __devinit pmac_pci_irq_fixup(struct pci_dev *dev) |
988 | { | 988 | { |
989 | struct pci_dev* dev = NULL; | ||
990 | |||
991 | for_each_pci_dev(dev) { | ||
992 | /* Read interrupt from the device-tree */ | ||
993 | pci_read_irq_line(dev); | ||
994 | |||
995 | #ifdef CONFIG_PPC32 | 989 | #ifdef CONFIG_PPC32 |
996 | /* Fixup interrupt for the modem/ethernet combo controller. | 990 | /* Fixup interrupt for the modem/ethernet combo controller. |
997 | * on machines with a second ohare chip. | 991 | * on machines with a second ohare chip. |
998 | * The number in the device tree (27) is bogus (correct for | 992 | * The number in the device tree (27) is bogus (correct for |
999 | * the ethernet-only board but not the combo ethernet/modem | 993 | * the ethernet-only board but not the combo ethernet/modem |
1000 | * board). The real interrupt is 28 on the second controller | 994 | * board). The real interrupt is 28 on the second controller |
1001 | * -> 28+32 = 60. | 995 | * -> 28+32 = 60. |
1002 | */ | 996 | */ |
1003 | if (has_second_ohare && | 997 | if (has_second_ohare && |
1004 | dev->vendor == PCI_VENDOR_ID_DEC && | 998 | dev->vendor == PCI_VENDOR_ID_DEC && |
1005 | dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) { | 999 | dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) { |
1006 | dev->irq = irq_create_mapping(NULL, 60); | 1000 | dev->irq = irq_create_mapping(NULL, 60); |
1007 | set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); | 1001 | set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW); |
1008 | } | ||
1009 | #endif /* CONFIG_PPC32 */ | ||
1010 | } | 1002 | } |
1003 | #endif /* CONFIG_PPC32 */ | ||
1011 | } | 1004 | } |
1012 | 1005 | ||
1013 | #ifdef CONFIG_PPC64 | 1006 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 94e7b24b840..6e090a7dea8 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h | |||
@@ -20,7 +20,7 @@ extern void pmac_get_rtc_time(struct rtc_time *); | |||
20 | extern int pmac_set_rtc_time(struct rtc_time *); | 20 | extern int pmac_set_rtc_time(struct rtc_time *); |
21 | extern void pmac_read_rtc_time(void); | 21 | extern void pmac_read_rtc_time(void); |
22 | extern void pmac_calibrate_decr(void); | 22 | extern void pmac_calibrate_decr(void); |
23 | extern void pmac_pcibios_fixup(void); | 23 | extern void pmac_pci_irq_fixup(struct pci_dev *); |
24 | extern void pmac_pci_init(void); | 24 | extern void pmac_pci_init(void); |
25 | extern unsigned long pmac_ide_get_base(int index); | 25 | extern unsigned long pmac_ide_get_base(int index); |
26 | extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, | 26 | extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, |
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 824a618396a..d949e9df41e 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -70,6 +70,7 @@ | |||
70 | #include <asm/pmac_feature.h> | 70 | #include <asm/pmac_feature.h> |
71 | #include <asm/time.h> | 71 | #include <asm/time.h> |
72 | #include <asm/of_device.h> | 72 | #include <asm/of_device.h> |
73 | #include <asm/of_platform.h> | ||
73 | #include <asm/mmu_context.h> | 74 | #include <asm/mmu_context.h> |
74 | #include <asm/iommu.h> | 75 | #include <asm/iommu.h> |
75 | #include <asm/smu.h> | 76 | #include <asm/smu.h> |
@@ -361,7 +362,7 @@ char *bootdevice; | |||
361 | void *boot_host; | 362 | void *boot_host; |
362 | int boot_target; | 363 | int boot_target; |
363 | int boot_part; | 364 | int boot_part; |
364 | extern dev_t boot_dev; | 365 | static dev_t boot_dev; |
365 | 366 | ||
366 | #ifdef CONFIG_SCSI | 367 | #ifdef CONFIG_SCSI |
367 | void __init note_scsi_host(struct device_node *node, void *host) | 368 | void __init note_scsi_host(struct device_node *node, void *host) |
@@ -676,8 +677,6 @@ static int __init pmac_probe(void) | |||
676 | 677 | ||
677 | #ifdef CONFIG_PPC32 | 678 | #ifdef CONFIG_PPC32 |
678 | /* isa_io_base gets set in pmac_pci_init */ | 679 | /* isa_io_base gets set in pmac_pci_init */ |
679 | isa_mem_base = PMAC_ISA_MEM_BASE; | ||
680 | pci_dram_offset = PMAC_PCI_DRAM_OFFSET; | ||
681 | ISA_DMA_THRESHOLD = ~0L; | 680 | ISA_DMA_THRESHOLD = ~0L; |
682 | DMA_MODE_READ = 1; | 681 | DMA_MODE_READ = 1; |
683 | DMA_MODE_WRITE = 2; | 682 | DMA_MODE_WRITE = 2; |
@@ -727,7 +726,7 @@ define_machine(powermac) { | |||
727 | .show_cpuinfo = pmac_show_cpuinfo, | 726 | .show_cpuinfo = pmac_show_cpuinfo, |
728 | .init_IRQ = pmac_pic_init, | 727 | .init_IRQ = pmac_pic_init, |
729 | .get_irq = NULL, /* changed later */ | 728 | .get_irq = NULL, /* changed later */ |
730 | .pcibios_fixup = pmac_pcibios_fixup, | 729 | .pci_irq_fixup = pmac_pci_irq_fixup, |
731 | .restart = pmac_restart, | 730 | .restart = pmac_restart, |
732 | .power_off = pmac_power_off, | 731 | .power_off = pmac_power_off, |
733 | .halt = pmac_halt, | 732 | .halt = pmac_halt, |
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig new file mode 100644 index 00000000000..451bfcd5502 --- /dev/null +++ b/arch/powerpc/platforms/ps3/Kconfig | |||
@@ -0,0 +1,43 @@ | |||
1 | menu "PS3 Platform Options" | ||
2 | depends on PPC_PS3 | ||
3 | |||
4 | config PS3_HTAB_SIZE | ||
5 | depends on PPC_PS3 | ||
6 | int "PS3 Platform pagetable size" | ||
7 | range 18 20 | ||
8 | default 20 | ||
9 | help | ||
10 | This option is only for experts who may have the desire to fine | ||
11 | tune the pagetable size on their system. The value here is | ||
12 | expressed as the log2 of the page table size. Valid values are | ||
13 | 18, 19, and 20, corresponding to 256KB, 512KB and 1MB respectively. | ||
14 | |||
15 | If unsure, choose the default (20) with the confidence that your | ||
16 | system will have optimal runtime performance. | ||
17 | |||
18 | config PS3_DYNAMIC_DMA | ||
19 | depends on PPC_PS3 && EXPERIMENTAL | ||
20 | bool "PS3 Platform dynamic DMA page table management" | ||
21 | default n | ||
22 | help | ||
23 | This option will enable kernel support to take advantage of the | ||
24 | per device dynamic DMA page table management provided by the Cell | ||
25 | processor's IO Controller. This support incurs some runtime | ||
26 | overhead and also slightly increases kernel memory usage. The | ||
27 | current implementation should be considered experimental. | ||
28 | |||
29 | This support is mainly for Linux kernel development. If unsure, | ||
30 | say N. | ||
31 | |||
32 | config PS3_USE_LPAR_ADDR | ||
33 | depends on PPC_PS3 && EXPERIMENTAL | ||
34 | bool "PS3 use lpar address space" | ||
35 | default y | ||
36 | help | ||
37 | This option is solely for experimentation by experts. Disables | ||
38 | translation of lpar addresses. SPE support currently won't work | ||
39 | without this set to y. | ||
40 | |||
41 | If you have any doubt, choose the default y. | ||
42 | |||
43 | endmenu | ||
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile new file mode 100644 index 00000000000..3757cfabc8c --- /dev/null +++ b/arch/powerpc/platforms/ps3/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | obj-y += setup.o mm.o smp.o time.o hvcall.o htab.o repository.o | ||
2 | obj-y += interrupt.o exports.o os-area.o | ||
3 | |||
4 | obj-$(CONFIG_SPU_BASE) += spu.o | ||
diff --git a/arch/powerpc/platforms/ps3/exports.c b/arch/powerpc/platforms/ps3/exports.c new file mode 100644 index 00000000000..a7e8ffd24a6 --- /dev/null +++ b/arch/powerpc/platforms/ps3/exports.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * PS3 hvcall exports for modules. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | |||
23 | #define LV1_CALL(name, in, out, num) \ | ||
24 | extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \ | ||
25 | EXPORT_SYMBOL(_lv1_##name); | ||
26 | |||
27 | #include <asm/lv1call.h> | ||
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c new file mode 100644 index 00000000000..8fe1769655a --- /dev/null +++ b/arch/powerpc/platforms/ps3/htab.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * PS3 pagetable management routines. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | |||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/lmb.h> | ||
25 | #include <asm/udbg.h> | ||
26 | #include <asm/ps3.h> | ||
27 | #include <asm/lv1call.h> | ||
28 | |||
29 | #include "platform.h" | ||
30 | |||
31 | #if defined(DEBUG) | ||
32 | #define DBG(fmt...) udbg_printf(fmt) | ||
33 | #else | ||
34 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | ||
35 | #endif | ||
36 | |||
37 | static hpte_t *htab; | ||
38 | static unsigned long htab_addr; | ||
39 | static unsigned char *bolttab; | ||
40 | static unsigned char *inusetab; | ||
41 | |||
42 | static spinlock_t ps3_bolttab_lock = SPIN_LOCK_UNLOCKED; | ||
43 | |||
44 | #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ | ||
45 | _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) | ||
46 | static void _debug_dump_hpte(unsigned long pa, unsigned long va, | ||
47 | unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize, | ||
48 | unsigned long slot, const char* func, int line) | ||
49 | { | ||
50 | DBG("%s:%d: pa = %lxh\n", func, line, pa); | ||
51 | DBG("%s:%d: lpar = %lxh\n", func, line, | ||
52 | ps3_mm_phys_to_lpar(pa)); | ||
53 | DBG("%s:%d: va = %lxh\n", func, line, va); | ||
54 | DBG("%s:%d: group = %lxh\n", func, line, group); | ||
55 | DBG("%s:%d: bitmap = %lxh\n", func, line, bitmap); | ||
56 | DBG("%s:%d: hpte.v = %lxh\n", func, line, lhpte.v); | ||
57 | DBG("%s:%d: hpte.r = %lxh\n", func, line, lhpte.r); | ||
58 | DBG("%s:%d: psize = %xh\n", func, line, psize); | ||
59 | DBG("%s:%d: slot = %lxh\n", func, line, slot); | ||
60 | } | ||
61 | |||
62 | static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, | ||
63 | unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) | ||
64 | { | ||
65 | unsigned long slot; | ||
66 | hpte_t lhpte; | ||
67 | int secondary = 0; | ||
68 | unsigned long result; | ||
69 | unsigned long bitmap; | ||
70 | unsigned long flags; | ||
71 | unsigned long p_pteg, s_pteg, b_index, b_mask, cb, ci; | ||
72 | |||
73 | vflags &= ~HPTE_V_SECONDARY; /* this bit is ignored */ | ||
74 | |||
75 | lhpte.v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID; | ||
76 | lhpte.r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags; | ||
77 | |||
78 | p_pteg = hpte_group / HPTES_PER_GROUP; | ||
79 | s_pteg = ~p_pteg & htab_hash_mask; | ||
80 | |||
81 | spin_lock_irqsave(&ps3_bolttab_lock, flags); | ||
82 | |||
83 | BUG_ON(bolttab[p_pteg] == 0xff && bolttab[s_pteg] == 0xff); | ||
84 | |||
85 | bitmap = (inusetab[p_pteg] << 8) | inusetab[s_pteg]; | ||
86 | |||
87 | if (bitmap == 0xffff) { | ||
88 | /* | ||
89 | * PTEG is full. Search for victim. | ||
90 | */ | ||
91 | bitmap &= ~((bolttab[p_pteg] << 8) | bolttab[s_pteg]); | ||
92 | do { | ||
93 | ci = mftb() & 15; | ||
94 | cb = 0x8000UL >> ci; | ||
95 | } while ((cb & bitmap) == 0); | ||
96 | } else { | ||
97 | /* | ||
98 | * search free slot in hardware order | ||
99 | * [primary] 0, 2, 4, 6, 1, 3, 5, 7 | ||
100 | * [secondary] 0, 2, 4, 6, 1, 3, 5, 7 | ||
101 | */ | ||
102 | for (ci = 0; ci < HPTES_PER_GROUP; ci += 2) { | ||
103 | cb = 0x8000UL >> ci; | ||
104 | if ((cb & bitmap) == 0) | ||
105 | goto found; | ||
106 | } | ||
107 | for (ci = 1; ci < HPTES_PER_GROUP; ci += 2) { | ||
108 | cb = 0x8000UL >> ci; | ||
109 | if ((cb & bitmap) == 0) | ||
110 | goto found; | ||
111 | } | ||
112 | for (ci = HPTES_PER_GROUP; ci < HPTES_PER_GROUP*2; ci += 2) { | ||
113 | cb = 0x8000UL >> ci; | ||
114 | if ((cb & bitmap) == 0) | ||
115 | goto found; | ||
116 | } | ||
117 | for (ci = HPTES_PER_GROUP+1; ci < HPTES_PER_GROUP*2; ci += 2) { | ||
118 | cb = 0x8000UL >> ci; | ||
119 | if ((cb & bitmap) == 0) | ||
120 | goto found; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | found: | ||
125 | if (ci < HPTES_PER_GROUP) { | ||
126 | slot = p_pteg * HPTES_PER_GROUP + ci; | ||
127 | } else { | ||
128 | slot = s_pteg * HPTES_PER_GROUP + (ci & 7); | ||
129 | /* lhpte.dw0.dw0.h = 1; */ | ||
130 | vflags |= HPTE_V_SECONDARY; | ||
131 | lhpte.v |= HPTE_V_SECONDARY; | ||
132 | } | ||
133 | |||
134 | result = lv1_write_htab_entry(0, slot, lhpte.v, lhpte.r); | ||
135 | |||
136 | if (result) { | ||
137 | debug_dump_hpte(pa, va, hpte_group, bitmap, lhpte, psize, slot); | ||
138 | BUG(); | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * If used slot is not in primary HPTE group, | ||
143 | * the slot should be in secondary HPTE group. | ||
144 | */ | ||
145 | |||
146 | if ((hpte_group ^ slot) & ~(HPTES_PER_GROUP - 1)) { | ||
147 | secondary = 1; | ||
148 | b_index = s_pteg; | ||
149 | } else { | ||
150 | secondary = 0; | ||
151 | b_index = p_pteg; | ||
152 | } | ||
153 | |||
154 | b_mask = (lhpte.v & HPTE_V_BOLTED) ? 1 << 7 : 0 << 7; | ||
155 | bolttab[b_index] |= b_mask >> (slot & 7); | ||
156 | b_mask = 1 << 7; | ||
157 | inusetab[b_index] |= b_mask >> (slot & 7); | ||
158 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | ||
159 | |||
160 | return (slot & 7) | (secondary << 3); | ||
161 | } | ||
162 | |||
163 | static long ps3_hpte_remove(unsigned long hpte_group) | ||
164 | { | ||
165 | panic("ps3_hpte_remove() not implemented"); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | ||
170 | unsigned long va, int psize, int local) | ||
171 | { | ||
172 | unsigned long flags; | ||
173 | unsigned long result; | ||
174 | unsigned long pteg, bit; | ||
175 | unsigned long hpte_v, want_v; | ||
176 | |||
177 | want_v = hpte_encode_v(va, psize); | ||
178 | |||
179 | spin_lock_irqsave(&ps3_bolttab_lock, flags); | ||
180 | |||
181 | hpte_v = htab[slot].v; | ||
182 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { | ||
183 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | ||
184 | |||
185 | /* ps3_hpte_insert() will be used to update PTE */ | ||
186 | return -1; | ||
187 | } | ||
188 | |||
189 | result = lv1_write_htab_entry(0, slot, 0, 0); | ||
190 | |||
191 | if (result) { | ||
192 | DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n", | ||
193 | __func__, va, slot, psize, result, result); | ||
194 | BUG(); | ||
195 | } | ||
196 | |||
197 | pteg = slot / HPTES_PER_GROUP; | ||
198 | bit = slot % HPTES_PER_GROUP; | ||
199 | inusetab[pteg] &= ~(0x80 >> bit); | ||
200 | |||
201 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | ||
202 | |||
203 | /* ps3_hpte_insert() will be used to update PTE */ | ||
204 | return -1; | ||
205 | } | ||
206 | |||
207 | static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | ||
208 | int psize) | ||
209 | { | ||
210 | panic("ps3_hpte_updateboltedpp() not implemented"); | ||
211 | } | ||
212 | |||
213 | static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, | ||
214 | int psize, int local) | ||
215 | { | ||
216 | unsigned long flags; | ||
217 | unsigned long result; | ||
218 | unsigned long pteg, bit; | ||
219 | |||
220 | spin_lock_irqsave(&ps3_bolttab_lock, flags); | ||
221 | result = lv1_write_htab_entry(0, slot, 0, 0); | ||
222 | |||
223 | if (result) { | ||
224 | DBG("%s: va=%lx slot=%lx psize=%d result = %ld (0x%lx)\n", | ||
225 | __func__, va, slot, psize, result, result); | ||
226 | BUG(); | ||
227 | } | ||
228 | |||
229 | pteg = slot / HPTES_PER_GROUP; | ||
230 | bit = slot % HPTES_PER_GROUP; | ||
231 | inusetab[pteg] &= ~(0x80 >> bit); | ||
232 | spin_unlock_irqrestore(&ps3_bolttab_lock, flags); | ||
233 | } | ||
234 | |||
235 | static void ps3_hpte_clear(void) | ||
236 | { | ||
237 | lv1_unmap_htab(htab_addr); | ||
238 | } | ||
239 | |||
240 | void __init ps3_hpte_init(unsigned long htab_size) | ||
241 | { | ||
242 | long bitmap_size; | ||
243 | |||
244 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
245 | |||
246 | ppc_md.hpte_invalidate = ps3_hpte_invalidate; | ||
247 | ppc_md.hpte_updatepp = ps3_hpte_updatepp; | ||
248 | ppc_md.hpte_updateboltedpp = ps3_hpte_updateboltedpp; | ||
249 | ppc_md.hpte_insert = ps3_hpte_insert; | ||
250 | ppc_md.hpte_remove = ps3_hpte_remove; | ||
251 | ppc_md.hpte_clear_all = ps3_hpte_clear; | ||
252 | |||
253 | ppc64_pft_size = __ilog2(htab_size); | ||
254 | |||
255 | bitmap_size = htab_size / sizeof(hpte_t) / 8; | ||
256 | |||
257 | bolttab = __va(lmb_alloc(bitmap_size, 1)); | ||
258 | inusetab = __va(lmb_alloc(bitmap_size, 1)); | ||
259 | |||
260 | memset(bolttab, 0, bitmap_size); | ||
261 | memset(inusetab, 0, bitmap_size); | ||
262 | |||
263 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
264 | } | ||
265 | |||
266 | void __init ps3_map_htab(void) | ||
267 | { | ||
268 | long result; | ||
269 | unsigned long htab_size = (1UL << ppc64_pft_size); | ||
270 | |||
271 | result = lv1_map_htab(0, &htab_addr); | ||
272 | |||
273 | htab = (hpte_t *)__ioremap(htab_addr, htab_size, PAGE_READONLY_X); | ||
274 | |||
275 | DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, | ||
276 | htab_addr, (unsigned long)htab); | ||
277 | } | ||
diff --git a/arch/powerpc/platforms/ps3/hvcall.S b/arch/powerpc/platforms/ps3/hvcall.S new file mode 100644 index 00000000000..54be6523a0e --- /dev/null +++ b/arch/powerpc/platforms/ps3/hvcall.S | |||
@@ -0,0 +1,804 @@ | |||
1 | /* | ||
2 | * PS3 hvcall interface. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * Copyright 2003, 2004 (c) MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <asm/processor.h> | ||
23 | #include <asm/ppc_asm.h> | ||
24 | |||
25 | #define lv1call .long 0x44000022; extsw r3, r3 | ||
26 | |||
27 | #define LV1_N_IN_0_OUT(API_NAME, API_NUMBER) \ | ||
28 | _GLOBAL(_##API_NAME) \ | ||
29 | \ | ||
30 | mflr r0; \ | ||
31 | std r0, 16(r1); \ | ||
32 | \ | ||
33 | li r11, API_NUMBER; \ | ||
34 | lv1call; \ | ||
35 | \ | ||
36 | ld r0, 16(r1); \ | ||
37 | mtlr r0; \ | ||
38 | blr | ||
39 | |||
40 | #define LV1_0_IN_0_OUT LV1_N_IN_0_OUT | ||
41 | #define LV1_1_IN_0_OUT LV1_N_IN_0_OUT | ||
42 | #define LV1_2_IN_0_OUT LV1_N_IN_0_OUT | ||
43 | #define LV1_3_IN_0_OUT LV1_N_IN_0_OUT | ||
44 | #define LV1_4_IN_0_OUT LV1_N_IN_0_OUT | ||
45 | #define LV1_5_IN_0_OUT LV1_N_IN_0_OUT | ||
46 | #define LV1_6_IN_0_OUT LV1_N_IN_0_OUT | ||
47 | #define LV1_7_IN_0_OUT LV1_N_IN_0_OUT | ||
48 | |||
49 | #define LV1_0_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
50 | _GLOBAL(_##API_NAME) \ | ||
51 | \ | ||
52 | mflr r0; \ | ||
53 | std r0, 16(r1); \ | ||
54 | \ | ||
55 | stdu r3, -8(r1); \ | ||
56 | \ | ||
57 | li r11, API_NUMBER; \ | ||
58 | lv1call; \ | ||
59 | \ | ||
60 | addi r1, r1, 8; \ | ||
61 | ld r11, -8(r1); \ | ||
62 | std r4, 0(r11); \ | ||
63 | \ | ||
64 | ld r0, 16(r1); \ | ||
65 | mtlr r0; \ | ||
66 | blr | ||
67 | |||
68 | #define LV1_0_IN_2_OUT(API_NAME, API_NUMBER) \ | ||
69 | _GLOBAL(_##API_NAME) \ | ||
70 | \ | ||
71 | mflr r0; \ | ||
72 | std r0, 16(r1); \ | ||
73 | \ | ||
74 | std r3, -8(r1); \ | ||
75 | stdu r4, -16(r1); \ | ||
76 | \ | ||
77 | li r11, API_NUMBER; \ | ||
78 | lv1call; \ | ||
79 | \ | ||
80 | addi r1, r1, 16; \ | ||
81 | ld r11, -8(r1); \ | ||
82 | std r4, 0(r11); \ | ||
83 | ld r11, -16(r1); \ | ||
84 | std r5, 0(r11); \ | ||
85 | \ | ||
86 | ld r0, 16(r1); \ | ||
87 | mtlr r0; \ | ||
88 | blr | ||
89 | |||
90 | #define LV1_0_IN_3_OUT(API_NAME, API_NUMBER) \ | ||
91 | _GLOBAL(_##API_NAME) \ | ||
92 | \ | ||
93 | mflr r0; \ | ||
94 | std r0, 16(r1); \ | ||
95 | \ | ||
96 | std r3, -8(r1); \ | ||
97 | std r4, -16(r1); \ | ||
98 | stdu r5, -24(r1); \ | ||
99 | \ | ||
100 | li r11, API_NUMBER; \ | ||
101 | lv1call; \ | ||
102 | \ | ||
103 | addi r1, r1, 24; \ | ||
104 | ld r11, -8(r1); \ | ||
105 | std r4, 0(r11); \ | ||
106 | ld r11, -16(r1); \ | ||
107 | std r5, 0(r11); \ | ||
108 | ld r11, -24(r1); \ | ||
109 | std r6, 0(r11); \ | ||
110 | \ | ||
111 | ld r0, 16(r1); \ | ||
112 | mtlr r0; \ | ||
113 | blr | ||
114 | |||
115 | #define LV1_0_IN_7_OUT(API_NAME, API_NUMBER) \ | ||
116 | _GLOBAL(_##API_NAME) \ | ||
117 | \ | ||
118 | mflr r0; \ | ||
119 | std r0, 16(r1); \ | ||
120 | \ | ||
121 | std r3, -8(r1); \ | ||
122 | std r4, -16(r1); \ | ||
123 | std r5, -24(r1); \ | ||
124 | std r6, -32(r1); \ | ||
125 | std r7, -40(r1); \ | ||
126 | std r8, -48(r1); \ | ||
127 | stdu r9, -56(r1); \ | ||
128 | \ | ||
129 | li r11, API_NUMBER; \ | ||
130 | lv1call; \ | ||
131 | \ | ||
132 | addi r1, r1, 56; \ | ||
133 | ld r11, -8(r1); \ | ||
134 | std r4, 0(r11); \ | ||
135 | ld r11, -16(r1); \ | ||
136 | std r5, 0(r11); \ | ||
137 | ld r11, -24(r1); \ | ||
138 | std r6, 0(r11); \ | ||
139 | ld r11, -32(r1); \ | ||
140 | std r7, 0(r11); \ | ||
141 | ld r11, -40(r1); \ | ||
142 | std r8, 0(r11); \ | ||
143 | ld r11, -48(r1); \ | ||
144 | std r9, 0(r11); \ | ||
145 | ld r11, -56(r1); \ | ||
146 | std r10, 0(r11); \ | ||
147 | \ | ||
148 | ld r0, 16(r1); \ | ||
149 | mtlr r0; \ | ||
150 | blr | ||
151 | |||
152 | #define LV1_1_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
153 | _GLOBAL(_##API_NAME) \ | ||
154 | \ | ||
155 | mflr r0; \ | ||
156 | std r0, 16(r1); \ | ||
157 | \ | ||
158 | stdu r4, -8(r1); \ | ||
159 | \ | ||
160 | li r11, API_NUMBER; \ | ||
161 | lv1call; \ | ||
162 | \ | ||
163 | addi r1, r1, 8; \ | ||
164 | ld r11, -8(r1); \ | ||
165 | std r4, 0(r11); \ | ||
166 | \ | ||
167 | ld r0, 16(r1); \ | ||
168 | mtlr r0; \ | ||
169 | blr | ||
170 | |||
171 | #define LV1_1_IN_2_OUT(API_NAME, API_NUMBER) \ | ||
172 | _GLOBAL(_##API_NAME) \ | ||
173 | \ | ||
174 | mflr r0; \ | ||
175 | std r0, 16(r1); \ | ||
176 | \ | ||
177 | std r4, -8(r1); \ | ||
178 | stdu r5, -16(r1); \ | ||
179 | \ | ||
180 | li r11, API_NUMBER; \ | ||
181 | lv1call; \ | ||
182 | \ | ||
183 | addi r1, r1, 16; \ | ||
184 | ld r11, -8(r1); \ | ||
185 | std r4, 0(r11); \ | ||
186 | ld r11, -16(r1); \ | ||
187 | std r5, 0(r11); \ | ||
188 | \ | ||
189 | ld r0, 16(r1); \ | ||
190 | mtlr r0; \ | ||
191 | blr | ||
192 | |||
193 | #define LV1_1_IN_3_OUT(API_NAME, API_NUMBER) \ | ||
194 | _GLOBAL(_##API_NAME) \ | ||
195 | \ | ||
196 | mflr r0; \ | ||
197 | std r0, 16(r1); \ | ||
198 | \ | ||
199 | std r4, -8(r1); \ | ||
200 | std r5, -16(r1); \ | ||
201 | stdu r6, -24(r1); \ | ||
202 | \ | ||
203 | li r11, API_NUMBER; \ | ||
204 | lv1call; \ | ||
205 | \ | ||
206 | addi r1, r1, 24; \ | ||
207 | ld r11, -8(r1); \ | ||
208 | std r4, 0(r11); \ | ||
209 | ld r11, -16(r1); \ | ||
210 | std r5, 0(r11); \ | ||
211 | ld r11, -24(r1); \ | ||
212 | std r6, 0(r11); \ | ||
213 | \ | ||
214 | ld r0, 16(r1); \ | ||
215 | mtlr r0; \ | ||
216 | blr | ||
217 | |||
218 | #define LV1_1_IN_4_OUT(API_NAME, API_NUMBER) \ | ||
219 | _GLOBAL(_##API_NAME) \ | ||
220 | \ | ||
221 | mflr r0; \ | ||
222 | std r0, 16(r1); \ | ||
223 | \ | ||
224 | std r4, -8(r1); \ | ||
225 | std r5, -16(r1); \ | ||
226 | std r6, -24(r1); \ | ||
227 | stdu r7, -32(r1); \ | ||
228 | \ | ||
229 | li r11, API_NUMBER; \ | ||
230 | lv1call; \ | ||
231 | \ | ||
232 | addi r1, r1, 32; \ | ||
233 | ld r11, -8(r1); \ | ||
234 | std r4, 0(r11); \ | ||
235 | ld r11, -16(r1); \ | ||
236 | std r5, 0(r11); \ | ||
237 | ld r11, -24(r1); \ | ||
238 | std r6, 0(r11); \ | ||
239 | ld r11, -32(r1); \ | ||
240 | std r7, 0(r11); \ | ||
241 | \ | ||
242 | ld r0, 16(r1); \ | ||
243 | mtlr r0; \ | ||
244 | blr | ||
245 | |||
246 | #define LV1_1_IN_5_OUT(API_NAME, API_NUMBER) \ | ||
247 | _GLOBAL(_##API_NAME) \ | ||
248 | \ | ||
249 | mflr r0; \ | ||
250 | std r0, 16(r1); \ | ||
251 | \ | ||
252 | std r4, -8(r1); \ | ||
253 | std r5, -16(r1); \ | ||
254 | std r6, -24(r1); \ | ||
255 | std r7, -32(r1); \ | ||
256 | stdu r8, -40(r1); \ | ||
257 | \ | ||
258 | li r11, API_NUMBER; \ | ||
259 | lv1call; \ | ||
260 | \ | ||
261 | addi r1, r1, 40; \ | ||
262 | ld r11, -8(r1); \ | ||
263 | std r4, 0(r11); \ | ||
264 | ld r11, -16(r1); \ | ||
265 | std r5, 0(r11); \ | ||
266 | ld r11, -24(r1); \ | ||
267 | std r6, 0(r11); \ | ||
268 | ld r11, -32(r1); \ | ||
269 | std r7, 0(r11); \ | ||
270 | ld r11, -40(r1); \ | ||
271 | std r8, 0(r11); \ | ||
272 | \ | ||
273 | ld r0, 16(r1); \ | ||
274 | mtlr r0; \ | ||
275 | blr | ||
276 | |||
277 | #define LV1_1_IN_6_OUT(API_NAME, API_NUMBER) \ | ||
278 | _GLOBAL(_##API_NAME) \ | ||
279 | \ | ||
280 | mflr r0; \ | ||
281 | std r0, 16(r1); \ | ||
282 | \ | ||
283 | std r4, -8(r1); \ | ||
284 | std r5, -16(r1); \ | ||
285 | std r6, -24(r1); \ | ||
286 | std r7, -32(r1); \ | ||
287 | std r8, -40(r1); \ | ||
288 | stdu r9, -48(r1); \ | ||
289 | \ | ||
290 | li r11, API_NUMBER; \ | ||
291 | lv1call; \ | ||
292 | \ | ||
293 | addi r1, r1, 48; \ | ||
294 | ld r11, -8(r1); \ | ||
295 | std r4, 0(r11); \ | ||
296 | ld r11, -16(r1); \ | ||
297 | std r5, 0(r11); \ | ||
298 | ld r11, -24(r1); \ | ||
299 | std r6, 0(r11); \ | ||
300 | ld r11, -32(r1); \ | ||
301 | std r7, 0(r11); \ | ||
302 | ld r11, -40(r1); \ | ||
303 | std r8, 0(r11); \ | ||
304 | ld r11, -48(r1); \ | ||
305 | std r9, 0(r11); \ | ||
306 | \ | ||
307 | ld r0, 16(r1); \ | ||
308 | mtlr r0; \ | ||
309 | blr | ||
310 | |||
311 | #define LV1_1_IN_7_OUT(API_NAME, API_NUMBER) \ | ||
312 | _GLOBAL(_##API_NAME) \ | ||
313 | \ | ||
314 | mflr r0; \ | ||
315 | std r0, 16(r1); \ | ||
316 | \ | ||
317 | std r4, -8(r1); \ | ||
318 | std r5, -16(r1); \ | ||
319 | std r6, -24(r1); \ | ||
320 | std r7, -32(r1); \ | ||
321 | std r8, -40(r1); \ | ||
322 | std r9, -48(r1); \ | ||
323 | stdu r10, -56(r1); \ | ||
324 | \ | ||
325 | li r11, API_NUMBER; \ | ||
326 | lv1call; \ | ||
327 | \ | ||
328 | addi r1, r1, 56; \ | ||
329 | ld r11, -8(r1); \ | ||
330 | std r4, 0(r11); \ | ||
331 | ld r11, -16(r1); \ | ||
332 | std r5, 0(r11); \ | ||
333 | ld r11, -24(r1); \ | ||
334 | std r6, 0(r11); \ | ||
335 | ld r11, -32(r1); \ | ||
336 | std r7, 0(r11); \ | ||
337 | ld r11, -40(r1); \ | ||
338 | std r8, 0(r11); \ | ||
339 | ld r11, -48(r1); \ | ||
340 | std r9, 0(r11); \ | ||
341 | ld r11, -56(r1); \ | ||
342 | std r10, 0(r11); \ | ||
343 | \ | ||
344 | ld r0, 16(r1); \ | ||
345 | mtlr r0; \ | ||
346 | blr | ||
347 | |||
348 | #define LV1_2_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
349 | _GLOBAL(_##API_NAME) \ | ||
350 | \ | ||
351 | mflr r0; \ | ||
352 | std r0, 16(r1); \ | ||
353 | \ | ||
354 | stdu r5, -8(r1); \ | ||
355 | \ | ||
356 | li r11, API_NUMBER; \ | ||
357 | lv1call; \ | ||
358 | \ | ||
359 | addi r1, r1, 8; \ | ||
360 | ld r11, -8(r1); \ | ||
361 | std r4, 0(r11); \ | ||
362 | \ | ||
363 | ld r0, 16(r1); \ | ||
364 | mtlr r0; \ | ||
365 | blr | ||
366 | |||
367 | #define LV1_2_IN_2_OUT(API_NAME, API_NUMBER) \ | ||
368 | _GLOBAL(_##API_NAME) \ | ||
369 | \ | ||
370 | mflr r0; \ | ||
371 | std r0, 16(r1); \ | ||
372 | \ | ||
373 | std r5, -8(r1); \ | ||
374 | stdu r6, -16(r1); \ | ||
375 | \ | ||
376 | li r11, API_NUMBER; \ | ||
377 | lv1call; \ | ||
378 | \ | ||
379 | addi r1, r1, 16; \ | ||
380 | ld r11, -8(r1); \ | ||
381 | std r4, 0(r11); \ | ||
382 | ld r11, -16(r1); \ | ||
383 | std r5, 0(r11); \ | ||
384 | \ | ||
385 | ld r0, 16(r1); \ | ||
386 | mtlr r0; \ | ||
387 | blr | ||
388 | |||
389 | #define LV1_2_IN_3_OUT(API_NAME, API_NUMBER) \ | ||
390 | _GLOBAL(_##API_NAME) \ | ||
391 | \ | ||
392 | mflr r0; \ | ||
393 | std r0, 16(r1); \ | ||
394 | \ | ||
395 | std r5, -8(r1); \ | ||
396 | std r6, -16(r1); \ | ||
397 | stdu r7, -24(r1); \ | ||
398 | \ | ||
399 | li r11, API_NUMBER; \ | ||
400 | lv1call; \ | ||
401 | \ | ||
402 | addi r1, r1, 24; \ | ||
403 | ld r11, -8(r1); \ | ||
404 | std r4, 0(r11); \ | ||
405 | ld r11, -16(r1); \ | ||
406 | std r5, 0(r11); \ | ||
407 | ld r11, -24(r1); \ | ||
408 | std r6, 0(r11); \ | ||
409 | \ | ||
410 | ld r0, 16(r1); \ | ||
411 | mtlr r0; \ | ||
412 | blr | ||
413 | |||
414 | #define LV1_2_IN_4_OUT(API_NAME, API_NUMBER) \ | ||
415 | _GLOBAL(_##API_NAME) \ | ||
416 | \ | ||
417 | mflr r0; \ | ||
418 | std r0, 16(r1); \ | ||
419 | \ | ||
420 | std r5, -8(r1); \ | ||
421 | std r6, -16(r1); \ | ||
422 | std r7, -24(r1); \ | ||
423 | stdu r8, -32(r1); \ | ||
424 | \ | ||
425 | li r11, API_NUMBER; \ | ||
426 | lv1call; \ | ||
427 | \ | ||
428 | addi r1, r1, 32; \ | ||
429 | ld r11, -8(r1); \ | ||
430 | std r4, 0(r11); \ | ||
431 | ld r11, -16(r1); \ | ||
432 | std r5, 0(r11); \ | ||
433 | ld r11, -24(r1); \ | ||
434 | std r6, 0(r11); \ | ||
435 | ld r11, -32(r1); \ | ||
436 | std r7, 0(r11); \ | ||
437 | \ | ||
438 | ld r0, 16(r1); \ | ||
439 | mtlr r0; \ | ||
440 | blr | ||
441 | |||
442 | #define LV1_2_IN_5_OUT(API_NAME, API_NUMBER) \ | ||
443 | _GLOBAL(_##API_NAME) \ | ||
444 | \ | ||
445 | mflr r0; \ | ||
446 | std r0, 16(r1); \ | ||
447 | \ | ||
448 | std r5, -8(r1); \ | ||
449 | std r6, -16(r1); \ | ||
450 | std r7, -24(r1); \ | ||
451 | std r8, -32(r1); \ | ||
452 | stdu r9, -40(r1); \ | ||
453 | \ | ||
454 | li r11, API_NUMBER; \ | ||
455 | lv1call; \ | ||
456 | \ | ||
457 | addi r1, r1, 40; \ | ||
458 | ld r11, -8(r1); \ | ||
459 | std r4, 0(r11); \ | ||
460 | ld r11, -16(r1); \ | ||
461 | std r5, 0(r11); \ | ||
462 | ld r11, -24(r1); \ | ||
463 | std r6, 0(r11); \ | ||
464 | ld r11, -32(r1); \ | ||
465 | std r7, 0(r11); \ | ||
466 | ld r11, -40(r1); \ | ||
467 | std r8, 0(r11); \ | ||
468 | \ | ||
469 | ld r0, 16(r1); \ | ||
470 | mtlr r0; \ | ||
471 | blr | ||
472 | |||
473 | #define LV1_3_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
474 | _GLOBAL(_##API_NAME) \ | ||
475 | \ | ||
476 | mflr r0; \ | ||
477 | std r0, 16(r1); \ | ||
478 | \ | ||
479 | stdu r6, -8(r1); \ | ||
480 | \ | ||
481 | li r11, API_NUMBER; \ | ||
482 | lv1call; \ | ||
483 | \ | ||
484 | addi r1, r1, 8; \ | ||
485 | ld r11, -8(r1); \ | ||
486 | std r4, 0(r11); \ | ||
487 | \ | ||
488 | ld r0, 16(r1); \ | ||
489 | mtlr r0; \ | ||
490 | blr | ||
491 | |||
492 | #define LV1_3_IN_2_OUT(API_NAME, API_NUMBER) \ | ||
493 | _GLOBAL(_##API_NAME) \ | ||
494 | \ | ||
495 | mflr r0; \ | ||
496 | std r0, 16(r1); \ | ||
497 | \ | ||
498 | std r6, -8(r1); \ | ||
499 | stdu r7, -16(r1); \ | ||
500 | \ | ||
501 | li r11, API_NUMBER; \ | ||
502 | lv1call; \ | ||
503 | \ | ||
504 | addi r1, r1, 16; \ | ||
505 | ld r11, -8(r1); \ | ||
506 | std r4, 0(r11); \ | ||
507 | ld r11, -16(r1); \ | ||
508 | std r5, 0(r11); \ | ||
509 | \ | ||
510 | ld r0, 16(r1); \ | ||
511 | mtlr r0; \ | ||
512 | blr | ||
513 | |||
514 | #define LV1_3_IN_3_OUT(API_NAME, API_NUMBER) \ | ||
515 | _GLOBAL(_##API_NAME) \ | ||
516 | \ | ||
517 | mflr r0; \ | ||
518 | std r0, 16(r1); \ | ||
519 | \ | ||
520 | std r6, -8(r1); \ | ||
521 | std r7, -16(r1); \ | ||
522 | stdu r8, -24(r1); \ | ||
523 | \ | ||
524 | li r11, API_NUMBER; \ | ||
525 | lv1call; \ | ||
526 | \ | ||
527 | addi r1, r1, 24; \ | ||
528 | ld r11, -8(r1); \ | ||
529 | std r4, 0(r11); \ | ||
530 | ld r11, -16(r1); \ | ||
531 | std r5, 0(r11); \ | ||
532 | ld r11, -24(r1); \ | ||
533 | std r6, 0(r11); \ | ||
534 | \ | ||
535 | ld r0, 16(r1); \ | ||
536 | mtlr r0; \ | ||
537 | blr | ||
538 | |||
539 | #define LV1_4_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
540 | _GLOBAL(_##API_NAME) \ | ||
541 | \ | ||
542 | mflr r0; \ | ||
543 | std r0, 16(r1); \ | ||
544 | \ | ||
545 | stdu r7, -8(r1); \ | ||
546 | \ | ||
547 | li r11, API_NUMBER; \ | ||
548 | lv1call; \ | ||
549 | \ | ||
550 | addi r1, r1, 8; \ | ||
551 | ld r11, -8(r1); \ | ||
552 | std r4, 0(r11); \ | ||
553 | \ | ||
554 | ld r0, 16(r1); \ | ||
555 | mtlr r0; \ | ||
556 | blr | ||
557 | |||
558 | #define LV1_4_IN_2_OUT(API_NAME, API_NUMBER) \ | ||
559 | _GLOBAL(_##API_NAME) \ | ||
560 | \ | ||
561 | mflr r0; \ | ||
562 | std r0, 16(r1); \ | ||
563 | \ | ||
564 | std r7, -8(r1); \ | ||
565 | stdu r8, -16(r1); \ | ||
566 | \ | ||
567 | li r11, API_NUMBER; \ | ||
568 | lv1call; \ | ||
569 | \ | ||
570 | addi r1, r1, 16; \ | ||
571 | ld r11, -8(r1); \ | ||
572 | std r4, 0(r11); \ | ||
573 | ld r11, -16(r1); \ | ||
574 | std r5, 0(r11); \ | ||
575 | \ | ||
576 | ld r0, 16(r1); \ | ||
577 | mtlr r0; \ | ||
578 | blr | ||
579 | |||
580 | #define LV1_4_IN_3_OUT(API_NAME, API_NUMBER) \ | ||
581 | _GLOBAL(_##API_NAME) \ | ||
582 | \ | ||
583 | mflr r0; \ | ||
584 | std r0, 16(r1); \ | ||
585 | \ | ||
586 | std r7, -8(r1); \ | ||
587 | std r8, -16(r1); \ | ||
588 | stdu r9, -24(r1); \ | ||
589 | \ | ||
590 | li r11, API_NUMBER; \ | ||
591 | lv1call; \ | ||
592 | \ | ||
593 | addi r1, r1, 24; \ | ||
594 | ld r11, -8(r1); \ | ||
595 | std r4, 0(r11); \ | ||
596 | ld r11, -16(r1); \ | ||
597 | std r5, 0(r11); \ | ||
598 | ld r11, -24(r1); \ | ||
599 | std r6, 0(r11); \ | ||
600 | \ | ||
601 | ld r0, 16(r1); \ | ||
602 | mtlr r0; \ | ||
603 | blr | ||
604 | |||
605 | #define LV1_5_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
606 | _GLOBAL(_##API_NAME) \ | ||
607 | \ | ||
608 | mflr r0; \ | ||
609 | std r0, 16(r1); \ | ||
610 | \ | ||
611 | stdu r8, -8(r1); \ | ||
612 | \ | ||
613 | li r11, API_NUMBER; \ | ||
614 | lv1call; \ | ||
615 | \ | ||
616 | addi r1, r1, 8; \ | ||
617 | ld r11, -8(r1); \ | ||
618 | std r4, 0(r11); \ | ||
619 | \ | ||
620 | ld r0, 16(r1); \ | ||
621 | mtlr r0; \ | ||
622 | blr | ||
623 | |||
624 | #define LV1_5_IN_2_OUT(API_NAME, API_NUMBER) \ | ||
625 | _GLOBAL(_##API_NAME) \ | ||
626 | \ | ||
627 | mflr r0; \ | ||
628 | std r0, 16(r1); \ | ||
629 | \ | ||
630 | std r8, -8(r1); \ | ||
631 | stdu r9, -16(r1); \ | ||
632 | \ | ||
633 | li r11, API_NUMBER; \ | ||
634 | lv1call; \ | ||
635 | \ | ||
636 | addi r1, r1, 16; \ | ||
637 | ld r11, -8(r1); \ | ||
638 | std r4, 0(r11); \ | ||
639 | ld r11, -16(r1); \ | ||
640 | std r5, 0(r11); \ | ||
641 | \ | ||
642 | ld r0, 16(r1); \ | ||
643 | mtlr r0; \ | ||
644 | blr | ||
645 | |||
646 | #define LV1_5_IN_3_OUT(API_NAME, API_NUMBER) \ | ||
647 | _GLOBAL(_##API_NAME) \ | ||
648 | \ | ||
649 | mflr r0; \ | ||
650 | std r0, 16(r1); \ | ||
651 | \ | ||
652 | std r8, -8(r1); \ | ||
653 | std r9, -16(r1); \ | ||
654 | stdu r10, -24(r1); \ | ||
655 | \ | ||
656 | li r11, API_NUMBER; \ | ||
657 | lv1call; \ | ||
658 | \ | ||
659 | addi r1, r1, 24; \ | ||
660 | ld r11, -8(r1); \ | ||
661 | std r4, 0(r11); \ | ||
662 | ld r11, -16(r1); \ | ||
663 | std r5, 0(r11); \ | ||
664 | ld r11, -24(r1); \ | ||
665 | std r6, 0(r11); \ | ||
666 | \ | ||
667 | ld r0, 16(r1); \ | ||
668 | mtlr r0; \ | ||
669 | blr | ||
670 | |||
671 | #define LV1_6_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
672 | _GLOBAL(_##API_NAME) \ | ||
673 | \ | ||
674 | mflr r0; \ | ||
675 | std r0, 16(r1); \ | ||
676 | \ | ||
677 | stdu r9, -8(r1); \ | ||
678 | \ | ||
679 | li r11, API_NUMBER; \ | ||
680 | lv1call; \ | ||
681 | \ | ||
682 | addi r1, r1, 8; \ | ||
683 | ld r11, -8(r1); \ | ||
684 | std r4, 0(r11); \ | ||
685 | \ | ||
686 | ld r0, 16(r1); \ | ||
687 | mtlr r0; \ | ||
688 | blr | ||
689 | |||
690 | #define LV1_6_IN_2_OUT(API_NAME, API_NUMBER) \ | ||
691 | _GLOBAL(_##API_NAME) \ | ||
692 | \ | ||
693 | mflr r0; \ | ||
694 | std r0, 16(r1); \ | ||
695 | \ | ||
696 | std r9, -8(r1); \ | ||
697 | stdu r10, -16(r1); \ | ||
698 | \ | ||
699 | li r11, API_NUMBER; \ | ||
700 | lv1call; \ | ||
701 | \ | ||
702 | addi r1, r1, 16; \ | ||
703 | ld r11, -8(r1); \ | ||
704 | std r4, 0(r11); \ | ||
705 | ld r11, -16(r1); \ | ||
706 | std r5, 0(r11); \ | ||
707 | \ | ||
708 | ld r0, 16(r1); \ | ||
709 | mtlr r0; \ | ||
710 | blr | ||
711 | |||
712 | #define LV1_6_IN_3_OUT(API_NAME, API_NUMBER) \ | ||
713 | _GLOBAL(_##API_NAME) \ | ||
714 | \ | ||
715 | mflr r0; \ | ||
716 | std r0, 16(r1); \ | ||
717 | \ | ||
718 | std r9, -8(r1); \ | ||
719 | stdu r10, -16(r1); \ | ||
720 | \ | ||
721 | li r11, API_NUMBER; \ | ||
722 | lv1call; \ | ||
723 | \ | ||
724 | addi r1, r1, 16; \ | ||
725 | ld r11, -8(r1); \ | ||
726 | std r4, 0(r11); \ | ||
727 | ld r11, -16(r1); \ | ||
728 | std r5, 0(r11); \ | ||
729 | ld r11, 48+8*8(r1); \ | ||
730 | std r6, 0(r11); \ | ||
731 | \ | ||
732 | ld r0, 16(r1); \ | ||
733 | mtlr r0; \ | ||
734 | blr | ||
735 | |||
736 | #define LV1_7_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
737 | _GLOBAL(_##API_NAME) \ | ||
738 | \ | ||
739 | mflr r0; \ | ||
740 | std r0, 16(r1); \ | ||
741 | \ | ||
742 | stdu r10, -8(r1); \ | ||
743 | \ | ||
744 | li r11, API_NUMBER; \ | ||
745 | lv1call; \ | ||
746 | \ | ||
747 | addi r1, r1, 8; \ | ||
748 | ld r11, -8(r1); \ | ||
749 | std r4, 0(r11); \ | ||
750 | \ | ||
751 | ld r0, 16(r1); \ | ||
752 | mtlr r0; \ | ||
753 | blr | ||
754 | |||
755 | #define LV1_7_IN_6_OUT(API_NAME, API_NUMBER) \ | ||
756 | _GLOBAL(_##API_NAME) \ | ||
757 | \ | ||
758 | mflr r0; \ | ||
759 | std r0, 16(r1); \ | ||
760 | \ | ||
761 | std r10, 48+8*7(r1); \ | ||
762 | \ | ||
763 | li r11, API_NUMBER; \ | ||
764 | lv1call; \ | ||
765 | \ | ||
766 | ld r11, 48+8*7(r1); \ | ||
767 | std r4, 0(r11); \ | ||
768 | ld r11, 48+8*8(r1); \ | ||
769 | std r5, 0(r11); \ | ||
770 | ld r11, 48+8*9(r1); \ | ||
771 | std r6, 0(r11); \ | ||
772 | ld r11, 48+8*10(r1); \ | ||
773 | std r7, 0(r11); \ | ||
774 | ld r11, 48+8*11(r1); \ | ||
775 | std r8, 0(r11); \ | ||
776 | ld r11, 48+8*12(r1); \ | ||
777 | std r9, 0(r11); \ | ||
778 | \ | ||
779 | ld r0, 16(r1); \ | ||
780 | mtlr r0; \ | ||
781 | blr | ||
782 | |||
783 | #define LV1_8_IN_1_OUT(API_NAME, API_NUMBER) \ | ||
784 | _GLOBAL(_##API_NAME) \ | ||
785 | \ | ||
786 | mflr r0; \ | ||
787 | std r0, 16(r1); \ | ||
788 | \ | ||
789 | li r11, API_NUMBER; \ | ||
790 | lv1call; \ | ||
791 | \ | ||
792 | ld r11, 48+8*8(r1); \ | ||
793 | std r4, 0(r11); \ | ||
794 | \ | ||
795 | ld r0, 16(r1); \ | ||
796 | mtlr r0; \ | ||
797 | blr | ||
798 | |||
799 | .text | ||
800 | |||
801 | /* the lv1 underscored call definitions expand here */ | ||
802 | |||
803 | #define LV1_CALL(name, in, out, num) LV1_##in##_IN_##out##_OUT(lv1_##name, num) | ||
804 | #include <asm/lv1call.h> | ||
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c new file mode 100644 index 00000000000..056c1e4141b --- /dev/null +++ b/arch/powerpc/platforms/ps3/interrupt.c | |||
@@ -0,0 +1,575 @@ | |||
1 | /* | ||
2 | * PS3 interrupt routines. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/irq.h> | ||
24 | |||
25 | #include <asm/machdep.h> | ||
26 | #include <asm/udbg.h> | ||
27 | #include <asm/ps3.h> | ||
28 | #include <asm/lv1call.h> | ||
29 | |||
30 | #include "platform.h" | ||
31 | |||
32 | #if defined(DEBUG) | ||
33 | #define DBG(fmt...) udbg_printf(fmt) | ||
34 | #else | ||
35 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | ||
36 | #endif | ||
37 | |||
38 | /** | ||
39 | * ps3_alloc_io_irq - Assign a virq to a system bus device. | ||
40 | * interrupt_id: The device interrupt id read from the system repository. | ||
41 | * @virq: The assigned Linux virq. | ||
42 | * | ||
43 | * An io irq represents a non-virtualized device interrupt. interrupt_id | ||
44 | * coresponds to the interrupt number of the interrupt controller. | ||
45 | */ | ||
46 | |||
47 | int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq) | ||
48 | { | ||
49 | int result; | ||
50 | unsigned long outlet; | ||
51 | |||
52 | result = lv1_construct_io_irq_outlet(interrupt_id, &outlet); | ||
53 | |||
54 | if (result) { | ||
55 | pr_debug("%s:%d: lv1_construct_io_irq_outlet failed: %s\n", | ||
56 | __func__, __LINE__, ps3_result(result)); | ||
57 | return result; | ||
58 | } | ||
59 | |||
60 | *virq = irq_create_mapping(NULL, outlet); | ||
61 | |||
62 | pr_debug("%s:%d: interrupt_id %u => outlet %lu, virq %u\n", | ||
63 | __func__, __LINE__, interrupt_id, outlet, *virq); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | int ps3_free_io_irq(unsigned int virq) | ||
69 | { | ||
70 | int result; | ||
71 | |||
72 | result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); | ||
73 | |||
74 | if (!result) | ||
75 | pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", | ||
76 | __func__, __LINE__, ps3_result(result)); | ||
77 | |||
78 | irq_dispose_mapping(virq); | ||
79 | |||
80 | return result; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * ps3_alloc_event_irq - Allocate a virq for use with a system event. | ||
85 | * @virq: The assigned Linux virq. | ||
86 | * | ||
87 | * The virq can be used with lv1_connect_interrupt_event_receive_port() to | ||
88 | * arrange to receive events, or with ps3_send_event_locally() to signal | ||
89 | * events. | ||
90 | */ | ||
91 | |||
92 | int ps3_alloc_event_irq(unsigned int *virq) | ||
93 | { | ||
94 | int result; | ||
95 | unsigned long outlet; | ||
96 | |||
97 | result = lv1_construct_event_receive_port(&outlet); | ||
98 | |||
99 | if (result) { | ||
100 | pr_debug("%s:%d: lv1_construct_event_receive_port failed: %s\n", | ||
101 | __func__, __LINE__, ps3_result(result)); | ||
102 | *virq = NO_IRQ; | ||
103 | return result; | ||
104 | } | ||
105 | |||
106 | *virq = irq_create_mapping(NULL, outlet); | ||
107 | |||
108 | pr_debug("%s:%d: outlet %lu, virq %u\n", __func__, __LINE__, outlet, | ||
109 | *virq); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | int ps3_free_event_irq(unsigned int virq) | ||
115 | { | ||
116 | int result; | ||
117 | |||
118 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
119 | |||
120 | result = lv1_destruct_event_receive_port(virq_to_hw(virq)); | ||
121 | |||
122 | if (result) | ||
123 | pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", | ||
124 | __func__, __LINE__, ps3_result(result)); | ||
125 | |||
126 | irq_dispose_mapping(virq); | ||
127 | |||
128 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
129 | return result; | ||
130 | } | ||
131 | |||
132 | int ps3_send_event_locally(unsigned int virq) | ||
133 | { | ||
134 | return lv1_send_event_locally(virq_to_hw(virq)); | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * ps3_connect_event_irq - Assign a virq to a system bus device. | ||
139 | * @did: The HV device identifier read from the system repository. | ||
140 | * @interrupt_id: The device interrupt id read from the system repository. | ||
141 | * @virq: The assigned Linux virq. | ||
142 | * | ||
143 | * An event irq represents a virtual device interrupt. The interrupt_id | ||
144 | * coresponds to the software interrupt number. | ||
145 | */ | ||
146 | |||
147 | int ps3_connect_event_irq(const struct ps3_device_id *did, | ||
148 | unsigned int interrupt_id, unsigned int *virq) | ||
149 | { | ||
150 | int result; | ||
151 | |||
152 | result = ps3_alloc_event_irq(virq); | ||
153 | |||
154 | if (result) | ||
155 | return result; | ||
156 | |||
157 | result = lv1_connect_interrupt_event_receive_port(did->bus_id, | ||
158 | did->dev_id, virq_to_hw(*virq), interrupt_id); | ||
159 | |||
160 | if (result) { | ||
161 | pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" | ||
162 | " failed: %s\n", __func__, __LINE__, | ||
163 | ps3_result(result)); | ||
164 | ps3_free_event_irq(*virq); | ||
165 | *virq = NO_IRQ; | ||
166 | return result; | ||
167 | } | ||
168 | |||
169 | pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, | ||
170 | interrupt_id, *virq); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | int ps3_disconnect_event_irq(const struct ps3_device_id *did, | ||
176 | unsigned int interrupt_id, unsigned int virq) | ||
177 | { | ||
178 | int result; | ||
179 | |||
180 | pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, | ||
181 | interrupt_id, virq); | ||
182 | |||
183 | result = lv1_disconnect_interrupt_event_receive_port(did->bus_id, | ||
184 | did->dev_id, virq_to_hw(virq), interrupt_id); | ||
185 | |||
186 | if (result) | ||
187 | pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" | ||
188 | " failed: %s\n", __func__, __LINE__, | ||
189 | ps3_result(result)); | ||
190 | |||
191 | ps3_free_event_irq(virq); | ||
192 | |||
193 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
194 | return result; | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * ps3_alloc_vuart_irq - Configure the system virtual uart virq. | ||
199 | * @virt_addr_bmp: The caller supplied virtual uart interrupt bitmap. | ||
200 | * @virq: The assigned Linux virq. | ||
201 | * | ||
202 | * The system supports only a single virtual uart, so multiple calls without | ||
203 | * freeing the interrupt will return a wrong state error. | ||
204 | */ | ||
205 | |||
206 | int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq) | ||
207 | { | ||
208 | int result; | ||
209 | unsigned long outlet; | ||
210 | unsigned long lpar_addr; | ||
211 | |||
212 | BUG_ON(!is_kernel_addr((unsigned long)virt_addr_bmp)); | ||
213 | |||
214 | lpar_addr = ps3_mm_phys_to_lpar(__pa(virt_addr_bmp)); | ||
215 | |||
216 | result = lv1_configure_virtual_uart_irq(lpar_addr, &outlet); | ||
217 | |||
218 | if (result) { | ||
219 | pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", | ||
220 | __func__, __LINE__, ps3_result(result)); | ||
221 | return result; | ||
222 | } | ||
223 | |||
224 | *virq = irq_create_mapping(NULL, outlet); | ||
225 | |||
226 | pr_debug("%s:%d: outlet %lu, virq %u\n", __func__, __LINE__, | ||
227 | outlet, *virq); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | int ps3_free_vuart_irq(unsigned int virq) | ||
233 | { | ||
234 | int result; | ||
235 | |||
236 | result = lv1_deconfigure_virtual_uart_irq(); | ||
237 | |||
238 | if (result) { | ||
239 | pr_debug("%s:%d: lv1_configure_virtual_uart_irq failed: %s\n", | ||
240 | __func__, __LINE__, ps3_result(result)); | ||
241 | return result; | ||
242 | } | ||
243 | |||
244 | irq_dispose_mapping(virq); | ||
245 | |||
246 | return result; | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * ps3_alloc_spe_irq - Configure an spe virq. | ||
251 | * @spe_id: The spe_id returned from lv1_construct_logical_spe(). | ||
252 | * @class: The spe interrupt class {0,1,2}. | ||
253 | * @virq: The assigned Linux virq. | ||
254 | * | ||
255 | */ | ||
256 | |||
257 | int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class, | ||
258 | unsigned int *virq) | ||
259 | { | ||
260 | int result; | ||
261 | unsigned long outlet; | ||
262 | |||
263 | BUG_ON(class > 2); | ||
264 | |||
265 | result = lv1_get_spe_irq_outlet(spe_id, class, &outlet); | ||
266 | |||
267 | if (result) { | ||
268 | pr_debug("%s:%d: lv1_get_spe_irq_outlet failed: %s\n", | ||
269 | __func__, __LINE__, ps3_result(result)); | ||
270 | return result; | ||
271 | } | ||
272 | |||
273 | *virq = irq_create_mapping(NULL, outlet); | ||
274 | |||
275 | pr_debug("%s:%d: spe_id %lu, class %u, outlet %lu, virq %u\n", | ||
276 | __func__, __LINE__, spe_id, class, outlet, *virq); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | int ps3_free_spe_irq(unsigned int virq) | ||
282 | { | ||
283 | irq_dispose_mapping(virq); | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | #define PS3_INVALID_OUTLET ((irq_hw_number_t)-1) | ||
288 | #define PS3_PLUG_MAX 63 | ||
289 | |||
290 | /** | ||
291 | * struct bmp - a per cpu irq status and mask bitmap structure | ||
292 | * @status: 256 bit status bitmap indexed by plug | ||
293 | * @unused_1: | ||
294 | * @mask: 256 bit mask bitmap indexed by plug | ||
295 | * @unused_2: | ||
296 | * @lock: | ||
297 | * @ipi_debug_brk_mask: | ||
298 | * | ||
299 | * The HV mantains per SMT thread mappings of HV outlet to HV plug on | ||
300 | * behalf of the guest. These mappings are implemented as 256 bit guest | ||
301 | * supplied bitmaps indexed by plug number. The address of the bitmaps are | ||
302 | * registered with the HV through lv1_configure_irq_state_bitmap(). | ||
303 | * | ||
304 | * The HV supports 256 plugs per thread, assigned as {0..255}, for a total | ||
305 | * of 512 plugs supported on a processor. To simplify the logic this | ||
306 | * implementation equates HV plug value to linux virq value, constrains each | ||
307 | * interrupt to have a system wide unique plug number, and limits the range | ||
308 | * of the plug values to map into the first dword of the bitmaps. This | ||
309 | * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note | ||
310 | * that there is no constraint on how many in this set an individual thread | ||
311 | * can aquire. | ||
312 | */ | ||
313 | |||
314 | struct bmp { | ||
315 | struct { | ||
316 | unsigned long status; | ||
317 | unsigned long unused_1[3]; | ||
318 | unsigned long mask; | ||
319 | unsigned long unused_2[3]; | ||
320 | } __attribute__ ((packed)); | ||
321 | spinlock_t lock; | ||
322 | unsigned long ipi_debug_brk_mask; | ||
323 | }; | ||
324 | |||
325 | /** | ||
326 | * struct private - a per cpu data structure | ||
327 | * @node: HV node id | ||
328 | * @cpu: HV thread id | ||
329 | * @bmp: an HV bmp structure | ||
330 | */ | ||
331 | |||
332 | struct private { | ||
333 | unsigned long node; | ||
334 | unsigned int cpu; | ||
335 | struct bmp bmp; | ||
336 | }; | ||
337 | |||
338 | #if defined(DEBUG) | ||
339 | static void _dump_64_bmp(const char *header, const unsigned long *p, unsigned cpu, | ||
340 | const char* func, int line) | ||
341 | { | ||
342 | pr_debug("%s:%d: %s %u {%04lx_%04lx_%04lx_%04lx}\n", | ||
343 | func, line, header, cpu, | ||
344 | *p >> 48, (*p >> 32) & 0xffff, (*p >> 16) & 0xffff, | ||
345 | *p & 0xffff); | ||
346 | } | ||
347 | |||
348 | static void __attribute__ ((unused)) _dump_256_bmp(const char *header, | ||
349 | const unsigned long *p, unsigned cpu, const char* func, int line) | ||
350 | { | ||
351 | pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", | ||
352 | func, line, header, cpu, p[0], p[1], p[2], p[3]); | ||
353 | } | ||
354 | |||
355 | #define dump_bmp(_x) _dump_bmp(_x, __func__, __LINE__) | ||
356 | static void _dump_bmp(struct private* pd, const char* func, int line) | ||
357 | { | ||
358 | unsigned long flags; | ||
359 | |||
360 | spin_lock_irqsave(&pd->bmp.lock, flags); | ||
361 | _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line); | ||
362 | _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); | ||
363 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | ||
364 | } | ||
365 | |||
366 | #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) | ||
367 | static void __attribute__ ((unused)) _dump_mask(struct private* pd, | ||
368 | const char* func, int line) | ||
369 | { | ||
370 | unsigned long flags; | ||
371 | |||
372 | spin_lock_irqsave(&pd->bmp.lock, flags); | ||
373 | _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); | ||
374 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | ||
375 | } | ||
376 | #else | ||
377 | static void dump_bmp(struct private* pd) {}; | ||
378 | #endif /* defined(DEBUG) */ | ||
379 | |||
380 | static void chip_mask(unsigned int virq) | ||
381 | { | ||
382 | unsigned long flags; | ||
383 | struct private *pd = get_irq_chip_data(virq); | ||
384 | |||
385 | pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); | ||
386 | |||
387 | BUG_ON(virq < NUM_ISA_INTERRUPTS); | ||
388 | BUG_ON(virq > PS3_PLUG_MAX); | ||
389 | |||
390 | spin_lock_irqsave(&pd->bmp.lock, flags); | ||
391 | pd->bmp.mask &= ~(0x8000000000000000UL >> virq); | ||
392 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | ||
393 | |||
394 | lv1_did_update_interrupt_mask(pd->node, pd->cpu); | ||
395 | } | ||
396 | |||
397 | static void chip_unmask(unsigned int virq) | ||
398 | { | ||
399 | unsigned long flags; | ||
400 | struct private *pd = get_irq_chip_data(virq); | ||
401 | |||
402 | pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); | ||
403 | |||
404 | BUG_ON(virq < NUM_ISA_INTERRUPTS); | ||
405 | BUG_ON(virq > PS3_PLUG_MAX); | ||
406 | |||
407 | spin_lock_irqsave(&pd->bmp.lock, flags); | ||
408 | pd->bmp.mask |= (0x8000000000000000UL >> virq); | ||
409 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | ||
410 | |||
411 | lv1_did_update_interrupt_mask(pd->node, pd->cpu); | ||
412 | } | ||
413 | |||
414 | static void chip_eoi(unsigned int virq) | ||
415 | { | ||
416 | lv1_end_of_interrupt(virq); | ||
417 | } | ||
418 | |||
419 | static struct irq_chip irq_chip = { | ||
420 | .typename = "ps3", | ||
421 | .mask = chip_mask, | ||
422 | .unmask = chip_unmask, | ||
423 | .eoi = chip_eoi, | ||
424 | }; | ||
425 | |||
426 | static void host_unmap(struct irq_host *h, unsigned int virq) | ||
427 | { | ||
428 | int result; | ||
429 | |||
430 | pr_debug("%s:%d: virq %d\n", __func__, __LINE__, virq); | ||
431 | |||
432 | lv1_disconnect_irq_plug(virq); | ||
433 | |||
434 | result = set_irq_chip_data(virq, NULL); | ||
435 | BUG_ON(result); | ||
436 | } | ||
437 | |||
438 | static DEFINE_PER_CPU(struct private, private); | ||
439 | |||
440 | static int host_map(struct irq_host *h, unsigned int virq, | ||
441 | irq_hw_number_t hwirq) | ||
442 | { | ||
443 | int result; | ||
444 | unsigned int cpu; | ||
445 | |||
446 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
447 | pr_debug("%s:%d: hwirq %lu => virq %u\n", __func__, __LINE__, hwirq, | ||
448 | virq); | ||
449 | |||
450 | /* bind this virq to a cpu */ | ||
451 | |||
452 | preempt_disable(); | ||
453 | cpu = smp_processor_id(); | ||
454 | result = lv1_connect_irq_plug(virq, hwirq); | ||
455 | preempt_enable(); | ||
456 | |||
457 | if (result) { | ||
458 | pr_info("%s:%d: lv1_connect_irq_plug failed:" | ||
459 | " %s\n", __func__, __LINE__, ps3_result(result)); | ||
460 | return -EPERM; | ||
461 | } | ||
462 | |||
463 | result = set_irq_chip_data(virq, &per_cpu(private, cpu)); | ||
464 | BUG_ON(result); | ||
465 | |||
466 | set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); | ||
467 | |||
468 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
469 | return result; | ||
470 | } | ||
471 | |||
472 | static struct irq_host_ops host_ops = { | ||
473 | .map = host_map, | ||
474 | .unmap = host_unmap, | ||
475 | }; | ||
476 | |||
477 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) | ||
478 | { | ||
479 | struct private *pd = &per_cpu(private, cpu); | ||
480 | |||
481 | pd->bmp.ipi_debug_brk_mask = 0x8000000000000000UL >> virq; | ||
482 | |||
483 | pr_debug("%s:%d: cpu %u, virq %u, mask %lxh\n", __func__, __LINE__, | ||
484 | cpu, virq, pd->bmp.ipi_debug_brk_mask); | ||
485 | } | ||
486 | |||
487 | static int bmp_get_and_clear_status_bit(struct bmp *m) | ||
488 | { | ||
489 | unsigned long flags; | ||
490 | unsigned int bit; | ||
491 | unsigned long x; | ||
492 | |||
493 | spin_lock_irqsave(&m->lock, flags); | ||
494 | |||
495 | /* check for ipi break first to stop this cpu ASAP */ | ||
496 | |||
497 | if (m->status & m->ipi_debug_brk_mask) { | ||
498 | m->status &= ~m->ipi_debug_brk_mask; | ||
499 | spin_unlock_irqrestore(&m->lock, flags); | ||
500 | return __ilog2(m->ipi_debug_brk_mask); | ||
501 | } | ||
502 | |||
503 | x = (m->status & m->mask); | ||
504 | |||
505 | for (bit = NUM_ISA_INTERRUPTS, x <<= bit; x; bit++, x <<= 1) | ||
506 | if (x & 0x8000000000000000UL) { | ||
507 | m->status &= ~(0x8000000000000000UL >> bit); | ||
508 | spin_unlock_irqrestore(&m->lock, flags); | ||
509 | return bit; | ||
510 | } | ||
511 | |||
512 | spin_unlock_irqrestore(&m->lock, flags); | ||
513 | |||
514 | pr_debug("%s:%d: not found\n", __func__, __LINE__); | ||
515 | return -1; | ||
516 | } | ||
517 | |||
518 | unsigned int ps3_get_irq(void) | ||
519 | { | ||
520 | int plug; | ||
521 | |||
522 | struct private *pd = &__get_cpu_var(private); | ||
523 | |||
524 | plug = bmp_get_and_clear_status_bit(&pd->bmp); | ||
525 | |||
526 | if (plug < 1) { | ||
527 | pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__, | ||
528 | pd->cpu); | ||
529 | dump_bmp(&per_cpu(private, 0)); | ||
530 | dump_bmp(&per_cpu(private, 1)); | ||
531 | return NO_IRQ; | ||
532 | } | ||
533 | |||
534 | #if defined(DEBUG) | ||
535 | if (plug < NUM_ISA_INTERRUPTS || plug > PS3_PLUG_MAX) { | ||
536 | dump_bmp(&per_cpu(private, 0)); | ||
537 | dump_bmp(&per_cpu(private, 1)); | ||
538 | BUG(); | ||
539 | } | ||
540 | #endif | ||
541 | return plug; | ||
542 | } | ||
543 | |||
544 | void __init ps3_init_IRQ(void) | ||
545 | { | ||
546 | int result; | ||
547 | unsigned long node; | ||
548 | unsigned cpu; | ||
549 | struct irq_host *host; | ||
550 | |||
551 | lv1_get_logical_ppe_id(&node); | ||
552 | |||
553 | host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &host_ops, | ||
554 | PS3_INVALID_OUTLET); | ||
555 | irq_set_default_host(host); | ||
556 | irq_set_virq_count(PS3_PLUG_MAX + 1); | ||
557 | |||
558 | for_each_possible_cpu(cpu) { | ||
559 | struct private *pd = &per_cpu(private, cpu); | ||
560 | |||
561 | pd->node = node; | ||
562 | pd->cpu = cpu; | ||
563 | spin_lock_init(&pd->bmp.lock); | ||
564 | |||
565 | result = lv1_configure_irq_state_bitmap(node, cpu, | ||
566 | ps3_mm_phys_to_lpar(__pa(&pd->bmp.status))); | ||
567 | |||
568 | if (result) | ||
569 | pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" | ||
570 | " %s\n", __func__, __LINE__, | ||
571 | ps3_result(result)); | ||
572 | } | ||
573 | |||
574 | ppc_md.get_irq = ps3_get_irq; | ||
575 | } | ||
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c new file mode 100644 index 00000000000..49c0d010d49 --- /dev/null +++ b/arch/powerpc/platforms/ps3/mm.c | |||
@@ -0,0 +1,831 @@ | |||
1 | /* | ||
2 | * PS3 address space management. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/memory_hotplug.h> | ||
24 | |||
25 | #include <asm/firmware.h> | ||
26 | #include <asm/lmb.h> | ||
27 | #include <asm/udbg.h> | ||
28 | #include <asm/ps3.h> | ||
29 | #include <asm/lv1call.h> | ||
30 | |||
31 | #include "platform.h" | ||
32 | |||
33 | #if defined(DEBUG) | ||
34 | #define DBG(fmt...) udbg_printf(fmt) | ||
35 | #else | ||
36 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | ||
37 | #endif | ||
38 | |||
39 | enum { | ||
40 | #if defined(CONFIG_PS3_USE_LPAR_ADDR) | ||
41 | USE_LPAR_ADDR = 1, | ||
42 | #else | ||
43 | USE_LPAR_ADDR = 0, | ||
44 | #endif | ||
45 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | ||
46 | USE_DYNAMIC_DMA = 1, | ||
47 | #else | ||
48 | USE_DYNAMIC_DMA = 0, | ||
49 | #endif | ||
50 | }; | ||
51 | |||
52 | enum { | ||
53 | PAGE_SHIFT_4K = 12U, | ||
54 | PAGE_SHIFT_64K = 16U, | ||
55 | PAGE_SHIFT_16M = 24U, | ||
56 | }; | ||
57 | |||
58 | static unsigned long make_page_sizes(unsigned long a, unsigned long b) | ||
59 | { | ||
60 | return (a << 56) | (b << 48); | ||
61 | } | ||
62 | |||
63 | enum { | ||
64 | ALLOCATE_MEMORY_TRY_ALT_UNIT = 0X04, | ||
65 | ALLOCATE_MEMORY_ADDR_ZERO = 0X08, | ||
66 | }; | ||
67 | |||
68 | /* valid htab sizes are {18,19,20} = 256K, 512K, 1M */ | ||
69 | |||
70 | enum { | ||
71 | HTAB_SIZE_MAX = 20U, /* HV limit of 1MB */ | ||
72 | HTAB_SIZE_MIN = 18U, /* CPU limit of 256KB */ | ||
73 | }; | ||
74 | |||
75 | /*============================================================================*/ | ||
76 | /* virtual address space routines */ | ||
77 | /*============================================================================*/ | ||
78 | |||
79 | /** | ||
80 | * struct mem_region - memory region structure | ||
81 | * @base: base address | ||
82 | * @size: size in bytes | ||
83 | * @offset: difference between base and rm.size | ||
84 | */ | ||
85 | |||
86 | struct mem_region { | ||
87 | unsigned long base; | ||
88 | unsigned long size; | ||
89 | unsigned long offset; | ||
90 | }; | ||
91 | |||
92 | /** | ||
93 | * struct map - address space state variables holder | ||
94 | * @total: total memory available as reported by HV | ||
95 | * @vas_id - HV virtual address space id | ||
96 | * @htab_size: htab size in bytes | ||
97 | * | ||
98 | * The HV virtual address space (vas) allows for hotplug memory regions. | ||
99 | * Memory regions can be created and destroyed in the vas at runtime. | ||
100 | * @rm: real mode (bootmem) region | ||
101 | * @r1: hotplug memory region(s) | ||
102 | * | ||
103 | * ps3 addresses | ||
104 | * virt_addr: a cpu 'translated' effective address | ||
105 | * phys_addr: an address in what Linux thinks is the physical address space | ||
106 | * lpar_addr: an address in the HV virtual address space | ||
107 | * bus_addr: an io controller 'translated' address on a device bus | ||
108 | */ | ||
109 | |||
110 | struct map { | ||
111 | unsigned long total; | ||
112 | unsigned long vas_id; | ||
113 | unsigned long htab_size; | ||
114 | struct mem_region rm; | ||
115 | struct mem_region r1; | ||
116 | }; | ||
117 | |||
118 | #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__) | ||
119 | static void _debug_dump_map(const struct map* m, const char* func, int line) | ||
120 | { | ||
121 | DBG("%s:%d: map.total = %lxh\n", func, line, m->total); | ||
122 | DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size); | ||
123 | DBG("%s:%d: map.vas_id = %lu\n", func, line, m->vas_id); | ||
124 | DBG("%s:%d: map.htab_size = %lxh\n", func, line, m->htab_size); | ||
125 | DBG("%s:%d: map.r1.base = %lxh\n", func, line, m->r1.base); | ||
126 | DBG("%s:%d: map.r1.offset = %lxh\n", func, line, m->r1.offset); | ||
127 | DBG("%s:%d: map.r1.size = %lxh\n", func, line, m->r1.size); | ||
128 | } | ||
129 | |||
130 | static struct map map; | ||
131 | |||
132 | /** | ||
133 | * ps3_mm_phys_to_lpar - translate a linux physical address to lpar address | ||
134 | * @phys_addr: linux physical address | ||
135 | */ | ||
136 | |||
137 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr) | ||
138 | { | ||
139 | BUG_ON(is_kernel_addr(phys_addr)); | ||
140 | if (USE_LPAR_ADDR) | ||
141 | return phys_addr; | ||
142 | else | ||
143 | return (phys_addr < map.rm.size || phys_addr >= map.total) | ||
144 | ? phys_addr : phys_addr + map.r1.offset; | ||
145 | } | ||
146 | |||
147 | EXPORT_SYMBOL(ps3_mm_phys_to_lpar); | ||
148 | |||
149 | /** | ||
150 | * ps3_mm_vas_create - create the virtual address space | ||
151 | */ | ||
152 | |||
153 | void __init ps3_mm_vas_create(unsigned long* htab_size) | ||
154 | { | ||
155 | int result; | ||
156 | unsigned long start_address; | ||
157 | unsigned long size; | ||
158 | unsigned long access_right; | ||
159 | unsigned long max_page_size; | ||
160 | unsigned long flags; | ||
161 | |||
162 | result = lv1_query_logical_partition_address_region_info(0, | ||
163 | &start_address, &size, &access_right, &max_page_size, | ||
164 | &flags); | ||
165 | |||
166 | if (result) { | ||
167 | DBG("%s:%d: lv1_query_logical_partition_address_region_info " | ||
168 | "failed: %s\n", __func__, __LINE__, | ||
169 | ps3_result(result)); | ||
170 | goto fail; | ||
171 | } | ||
172 | |||
173 | if (max_page_size < PAGE_SHIFT_16M) { | ||
174 | DBG("%s:%d: bad max_page_size %lxh\n", __func__, __LINE__, | ||
175 | max_page_size); | ||
176 | goto fail; | ||
177 | } | ||
178 | |||
179 | BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE > HTAB_SIZE_MAX); | ||
180 | BUILD_BUG_ON(CONFIG_PS3_HTAB_SIZE < HTAB_SIZE_MIN); | ||
181 | |||
182 | result = lv1_construct_virtual_address_space(CONFIG_PS3_HTAB_SIZE, | ||
183 | 2, make_page_sizes(PAGE_SHIFT_16M, PAGE_SHIFT_64K), | ||
184 | &map.vas_id, &map.htab_size); | ||
185 | |||
186 | if (result) { | ||
187 | DBG("%s:%d: lv1_construct_virtual_address_space failed: %s\n", | ||
188 | __func__, __LINE__, ps3_result(result)); | ||
189 | goto fail; | ||
190 | } | ||
191 | |||
192 | result = lv1_select_virtual_address_space(map.vas_id); | ||
193 | |||
194 | if (result) { | ||
195 | DBG("%s:%d: lv1_select_virtual_address_space failed: %s\n", | ||
196 | __func__, __LINE__, ps3_result(result)); | ||
197 | goto fail; | ||
198 | } | ||
199 | |||
200 | *htab_size = map.htab_size; | ||
201 | |||
202 | debug_dump_map(&map); | ||
203 | |||
204 | return; | ||
205 | |||
206 | fail: | ||
207 | panic("ps3_mm_vas_create failed"); | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * ps3_mm_vas_destroy - | ||
212 | */ | ||
213 | |||
214 | void ps3_mm_vas_destroy(void) | ||
215 | { | ||
216 | if (map.vas_id) { | ||
217 | lv1_select_virtual_address_space(0); | ||
218 | lv1_destruct_virtual_address_space(map.vas_id); | ||
219 | map.vas_id = 0; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /*============================================================================*/ | ||
224 | /* memory hotplug routines */ | ||
225 | /*============================================================================*/ | ||
226 | |||
227 | /** | ||
228 | * ps3_mm_region_create - create a memory region in the vas | ||
229 | * @r: pointer to a struct mem_region to accept initialized values | ||
230 | * @size: requested region size | ||
231 | * | ||
232 | * This implementation creates the region with the vas large page size. | ||
233 | * @size is rounded down to a multiple of the vas large page size. | ||
234 | */ | ||
235 | |||
236 | int ps3_mm_region_create(struct mem_region *r, unsigned long size) | ||
237 | { | ||
238 | int result; | ||
239 | unsigned long muid; | ||
240 | |||
241 | r->size = _ALIGN_DOWN(size, 1 << PAGE_SHIFT_16M); | ||
242 | |||
243 | DBG("%s:%d requested %lxh\n", __func__, __LINE__, size); | ||
244 | DBG("%s:%d actual %lxh\n", __func__, __LINE__, r->size); | ||
245 | DBG("%s:%d difference %lxh (%luMB)\n", __func__, __LINE__, | ||
246 | (unsigned long)(size - r->size), | ||
247 | (size - r->size) / 1024 / 1024); | ||
248 | |||
249 | if (r->size == 0) { | ||
250 | DBG("%s:%d: size == 0\n", __func__, __LINE__); | ||
251 | result = -1; | ||
252 | goto zero_region; | ||
253 | } | ||
254 | |||
255 | result = lv1_allocate_memory(r->size, PAGE_SHIFT_16M, 0, | ||
256 | ALLOCATE_MEMORY_TRY_ALT_UNIT, &r->base, &muid); | ||
257 | |||
258 | if (result || r->base < map.rm.size) { | ||
259 | DBG("%s:%d: lv1_allocate_memory failed: %s\n", | ||
260 | __func__, __LINE__, ps3_result(result)); | ||
261 | goto zero_region; | ||
262 | } | ||
263 | |||
264 | r->offset = r->base - map.rm.size; | ||
265 | return result; | ||
266 | |||
267 | zero_region: | ||
268 | r->size = r->base = r->offset = 0; | ||
269 | return result; | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * ps3_mm_region_destroy - destroy a memory region | ||
274 | * @r: pointer to struct mem_region | ||
275 | */ | ||
276 | |||
277 | void ps3_mm_region_destroy(struct mem_region *r) | ||
278 | { | ||
279 | if (r->base) { | ||
280 | lv1_release_memory(r->base); | ||
281 | r->size = r->base = r->offset = 0; | ||
282 | map.total = map.rm.size; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * ps3_mm_add_memory - hot add memory | ||
288 | */ | ||
289 | |||
290 | static int __init ps3_mm_add_memory(void) | ||
291 | { | ||
292 | int result; | ||
293 | unsigned long start_addr; | ||
294 | unsigned long start_pfn; | ||
295 | unsigned long nr_pages; | ||
296 | |||
297 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
298 | return 0; | ||
299 | |||
300 | BUG_ON(!mem_init_done); | ||
301 | |||
302 | start_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; | ||
303 | start_pfn = start_addr >> PAGE_SHIFT; | ||
304 | nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
305 | |||
306 | DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n", | ||
307 | __func__, __LINE__, start_addr, start_pfn, nr_pages); | ||
308 | |||
309 | result = add_memory(0, start_addr, map.r1.size); | ||
310 | |||
311 | if (result) { | ||
312 | DBG("%s:%d: add_memory failed: (%d)\n", | ||
313 | __func__, __LINE__, result); | ||
314 | return result; | ||
315 | } | ||
316 | |||
317 | result = online_pages(start_pfn, nr_pages); | ||
318 | |||
319 | if (result) | ||
320 | DBG("%s:%d: online_pages failed: (%d)\n", | ||
321 | __func__, __LINE__, result); | ||
322 | |||
323 | return result; | ||
324 | } | ||
325 | |||
326 | core_initcall(ps3_mm_add_memory); | ||
327 | |||
328 | /*============================================================================*/ | ||
329 | /* dma routines */ | ||
330 | /*============================================================================*/ | ||
331 | |||
332 | /** | ||
333 | * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address. | ||
334 | * @r: pointer to dma region structure | ||
335 | * @lpar_addr: HV lpar address | ||
336 | */ | ||
337 | |||
338 | static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r, | ||
339 | unsigned long lpar_addr) | ||
340 | { | ||
341 | BUG_ON(lpar_addr >= map.r1.base + map.r1.size); | ||
342 | return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr | ||
343 | : lpar_addr - map.r1.offset); | ||
344 | } | ||
345 | |||
346 | #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__) | ||
347 | static void _dma_dump_region(const struct ps3_dma_region *r, const char* func, | ||
348 | int line) | ||
349 | { | ||
350 | DBG("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, | ||
351 | r->did.dev_id); | ||
352 | DBG("%s:%d: page_size %u\n", func, line, r->page_size); | ||
353 | DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | ||
354 | DBG("%s:%d: len %lxh\n", func, line, r->len); | ||
355 | } | ||
356 | |||
357 | /** | ||
358 | * dma_chunk - A chunk of dma pages mapped by the io controller. | ||
359 | * @region - The dma region that owns this chunk. | ||
360 | * @lpar_addr: Starting lpar address of the area to map. | ||
361 | * @bus_addr: Starting ioc bus address of the area to map. | ||
362 | * @len: Length in bytes of the area to map. | ||
363 | * @link: A struct list_head used with struct ps3_dma_region.chunk_list, the | ||
364 | * list of all chuncks owned by the region. | ||
365 | * | ||
366 | * This implementation uses a very simple dma page manager | ||
367 | * based on the dma_chunk structure. This scheme assumes | ||
368 | * that all drivers use very well behaved dma ops. | ||
369 | */ | ||
370 | |||
371 | struct dma_chunk { | ||
372 | struct ps3_dma_region *region; | ||
373 | unsigned long lpar_addr; | ||
374 | unsigned long bus_addr; | ||
375 | unsigned long len; | ||
376 | struct list_head link; | ||
377 | unsigned int usage_count; | ||
378 | }; | ||
379 | |||
380 | #define dma_dump_chunk(_a) _dma_dump_chunk(_a, __func__, __LINE__) | ||
381 | static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, | ||
382 | int line) | ||
383 | { | ||
384 | DBG("%s:%d: r.dev %u:%u\n", func, line, | ||
385 | c->region->did.bus_id, c->region->did.dev_id); | ||
386 | DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); | ||
387 | DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); | ||
388 | DBG("%s:%d: r.len %lxh\n", func, line, c->region->len); | ||
389 | DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr); | ||
390 | DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr); | ||
391 | DBG("%s:%d: c.len %lxh\n", func, line, c->len); | ||
392 | } | ||
393 | |||
394 | static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r, | ||
395 | unsigned long bus_addr, unsigned long len) | ||
396 | { | ||
397 | struct dma_chunk *c; | ||
398 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); | ||
399 | unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); | ||
400 | |||
401 | list_for_each_entry(c, &r->chunk_list.head, link) { | ||
402 | /* intersection */ | ||
403 | if (aligned_bus >= c->bus_addr | ||
404 | && aligned_bus < c->bus_addr + c->len | ||
405 | && aligned_bus + aligned_len <= c->bus_addr + c->len) { | ||
406 | return c; | ||
407 | } | ||
408 | /* below */ | ||
409 | if (aligned_bus + aligned_len <= c->bus_addr) { | ||
410 | continue; | ||
411 | } | ||
412 | /* above */ | ||
413 | if (aligned_bus >= c->bus_addr + c->len) { | ||
414 | continue; | ||
415 | } | ||
416 | |||
417 | /* we don't handle the multi-chunk case for now */ | ||
418 | |||
419 | dma_dump_chunk(c); | ||
420 | BUG(); | ||
421 | } | ||
422 | return NULL; | ||
423 | } | ||
424 | |||
425 | static int dma_free_chunk(struct dma_chunk *c) | ||
426 | { | ||
427 | int result = 0; | ||
428 | |||
429 | if (c->bus_addr) { | ||
430 | result = lv1_unmap_device_dma_region(c->region->did.bus_id, | ||
431 | c->region->did.dev_id, c->bus_addr, c->len); | ||
432 | BUG_ON(result); | ||
433 | } | ||
434 | |||
435 | kfree(c); | ||
436 | return result; | ||
437 | } | ||
438 | |||
439 | /** | ||
440 | * dma_map_pages - Maps dma pages into the io controller bus address space. | ||
441 | * @r: Pointer to a struct ps3_dma_region. | ||
442 | * @phys_addr: Starting physical address of the area to map. | ||
443 | * @len: Length in bytes of the area to map. | ||
444 | * c_out: A pointer to receive an allocated struct dma_chunk for this area. | ||
445 | * | ||
446 | * This is the lowest level dma mapping routine, and is the one that will | ||
447 | * make the HV call to add the pages into the io controller address space. | ||
448 | */ | ||
449 | |||
450 | static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, | ||
451 | unsigned long len, struct dma_chunk **c_out) | ||
452 | { | ||
453 | int result; | ||
454 | struct dma_chunk *c; | ||
455 | |||
456 | c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC); | ||
457 | |||
458 | if (!c) { | ||
459 | result = -ENOMEM; | ||
460 | goto fail_alloc; | ||
461 | } | ||
462 | |||
463 | c->region = r; | ||
464 | c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | ||
465 | c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr); | ||
466 | c->len = len; | ||
467 | |||
468 | result = lv1_map_device_dma_region(c->region->did.bus_id, | ||
469 | c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len, | ||
470 | 0xf800000000000000UL); | ||
471 | |||
472 | if (result) { | ||
473 | DBG("%s:%d: lv1_map_device_dma_region failed: %s\n", | ||
474 | __func__, __LINE__, ps3_result(result)); | ||
475 | goto fail_map; | ||
476 | } | ||
477 | |||
478 | list_add(&c->link, &r->chunk_list.head); | ||
479 | |||
480 | *c_out = c; | ||
481 | return 0; | ||
482 | |||
483 | fail_map: | ||
484 | kfree(c); | ||
485 | fail_alloc: | ||
486 | *c_out = NULL; | ||
487 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
488 | return result; | ||
489 | } | ||
490 | |||
491 | /** | ||
492 | * dma_region_create - Create a device dma region. | ||
493 | * @r: Pointer to a struct ps3_dma_region. | ||
494 | * | ||
495 | * This is the lowest level dma region create routine, and is the one that | ||
496 | * will make the HV call to create the region. | ||
497 | */ | ||
498 | |||
499 | static int dma_region_create(struct ps3_dma_region* r) | ||
500 | { | ||
501 | int result; | ||
502 | |||
503 | r->len = _ALIGN_UP(map.total, 1 << r->page_size); | ||
504 | INIT_LIST_HEAD(&r->chunk_list.head); | ||
505 | spin_lock_init(&r->chunk_list.lock); | ||
506 | |||
507 | result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id, | ||
508 | r->len, r->page_size, r->region_type, &r->bus_addr); | ||
509 | |||
510 | dma_dump_region(r); | ||
511 | |||
512 | if (result) { | ||
513 | DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n", | ||
514 | __func__, __LINE__, ps3_result(result)); | ||
515 | r->len = r->bus_addr = 0; | ||
516 | } | ||
517 | |||
518 | return result; | ||
519 | } | ||
520 | |||
521 | /** | ||
522 | * dma_region_free - Free a device dma region. | ||
523 | * @r: Pointer to a struct ps3_dma_region. | ||
524 | * | ||
525 | * This is the lowest level dma region free routine, and is the one that | ||
526 | * will make the HV call to free the region. | ||
527 | */ | ||
528 | |||
529 | static int dma_region_free(struct ps3_dma_region* r) | ||
530 | { | ||
531 | int result; | ||
532 | struct dma_chunk *c; | ||
533 | struct dma_chunk *tmp; | ||
534 | |||
535 | list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) { | ||
536 | list_del(&c->link); | ||
537 | dma_free_chunk(c); | ||
538 | } | ||
539 | |||
540 | result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id, | ||
541 | r->bus_addr); | ||
542 | |||
543 | if (result) | ||
544 | DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", | ||
545 | __func__, __LINE__, ps3_result(result)); | ||
546 | |||
547 | r->len = r->bus_addr = 0; | ||
548 | |||
549 | return result; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * dma_map_area - Map an area of memory into a device dma region. | ||
554 | * @r: Pointer to a struct ps3_dma_region. | ||
555 | * @virt_addr: Starting virtual address of the area to map. | ||
556 | * @len: Length in bytes of the area to map. | ||
557 | * @bus_addr: A pointer to return the starting ioc bus address of the area to | ||
558 | * map. | ||
559 | * | ||
560 | * This is the common dma mapping routine. | ||
561 | */ | ||
562 | |||
563 | static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | ||
564 | unsigned long len, unsigned long *bus_addr) | ||
565 | { | ||
566 | int result; | ||
567 | unsigned long flags; | ||
568 | struct dma_chunk *c; | ||
569 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | ||
570 | : virt_addr; | ||
571 | |||
572 | *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | ||
573 | |||
574 | if (!USE_DYNAMIC_DMA) { | ||
575 | unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | ||
576 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
577 | DBG("%s:%d virt_addr %lxh\n", __func__, __LINE__, | ||
578 | virt_addr); | ||
579 | DBG("%s:%d phys_addr %lxh\n", __func__, __LINE__, | ||
580 | phys_addr); | ||
581 | DBG("%s:%d lpar_addr %lxh\n", __func__, __LINE__, | ||
582 | lpar_addr); | ||
583 | DBG("%s:%d len %lxh\n", __func__, __LINE__, len); | ||
584 | DBG("%s:%d bus_addr %lxh (%lxh)\n", __func__, __LINE__, | ||
585 | *bus_addr, len); | ||
586 | } | ||
587 | |||
588 | spin_lock_irqsave(&r->chunk_list.lock, flags); | ||
589 | c = dma_find_chunk(r, *bus_addr, len); | ||
590 | |||
591 | if (c) { | ||
592 | c->usage_count++; | ||
593 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size), | ||
598 | _ALIGN_UP(len, 1 << r->page_size), &c); | ||
599 | |||
600 | if (result) { | ||
601 | *bus_addr = 0; | ||
602 | DBG("%s:%d: dma_map_pages failed (%d)\n", | ||
603 | __func__, __LINE__, result); | ||
604 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
605 | return result; | ||
606 | } | ||
607 | |||
608 | c->usage_count = 1; | ||
609 | |||
610 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
611 | return result; | ||
612 | } | ||
613 | |||
614 | /** | ||
615 | * dma_unmap_area - Unmap an area of memory from a device dma region. | ||
616 | * @r: Pointer to a struct ps3_dma_region. | ||
617 | * @bus_addr: The starting ioc bus address of the area to unmap. | ||
618 | * @len: Length in bytes of the area to unmap. | ||
619 | * | ||
620 | * This is the common dma unmap routine. | ||
621 | */ | ||
622 | |||
623 | int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, | ||
624 | unsigned long len) | ||
625 | { | ||
626 | unsigned long flags; | ||
627 | struct dma_chunk *c; | ||
628 | |||
629 | spin_lock_irqsave(&r->chunk_list.lock, flags); | ||
630 | c = dma_find_chunk(r, bus_addr, len); | ||
631 | |||
632 | if (!c) { | ||
633 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, | ||
634 | 1 << r->page_size); | ||
635 | unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); | ||
636 | DBG("%s:%d: not found: bus_addr %lxh\n", | ||
637 | __func__, __LINE__, bus_addr); | ||
638 | DBG("%s:%d: not found: len %lxh\n", | ||
639 | __func__, __LINE__, len); | ||
640 | DBG("%s:%d: not found: aligned_bus %lxh\n", | ||
641 | __func__, __LINE__, aligned_bus); | ||
642 | DBG("%s:%d: not found: aligned_len %lxh\n", | ||
643 | __func__, __LINE__, aligned_len); | ||
644 | BUG(); | ||
645 | } | ||
646 | |||
647 | c->usage_count--; | ||
648 | |||
649 | if (!c->usage_count) { | ||
650 | list_del(&c->link); | ||
651 | dma_free_chunk(c); | ||
652 | } | ||
653 | |||
654 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | /** | ||
659 | * dma_region_create_linear - Setup a linear dma maping for a device. | ||
660 | * @r: Pointer to a struct ps3_dma_region. | ||
661 | * | ||
662 | * This routine creates an HV dma region for the device and maps all available | ||
663 | * ram into the io controller bus address space. | ||
664 | */ | ||
665 | |||
666 | static int dma_region_create_linear(struct ps3_dma_region *r) | ||
667 | { | ||
668 | int result; | ||
669 | unsigned long tmp; | ||
670 | |||
671 | /* force 16M dma pages for linear mapping */ | ||
672 | |||
673 | if (r->page_size != PS3_DMA_16M) { | ||
674 | pr_info("%s:%d: forcing 16M pages for linear map\n", | ||
675 | __func__, __LINE__); | ||
676 | r->page_size = PS3_DMA_16M; | ||
677 | } | ||
678 | |||
679 | result = dma_region_create(r); | ||
680 | BUG_ON(result); | ||
681 | |||
682 | result = dma_map_area(r, map.rm.base, map.rm.size, &tmp); | ||
683 | BUG_ON(result); | ||
684 | |||
685 | if (USE_LPAR_ADDR) | ||
686 | result = dma_map_area(r, map.r1.base, map.r1.size, | ||
687 | &tmp); | ||
688 | else | ||
689 | result = dma_map_area(r, map.rm.size, map.r1.size, | ||
690 | &tmp); | ||
691 | |||
692 | BUG_ON(result); | ||
693 | |||
694 | return result; | ||
695 | } | ||
696 | |||
697 | /** | ||
698 | * dma_region_free_linear - Free a linear dma mapping for a device. | ||
699 | * @r: Pointer to a struct ps3_dma_region. | ||
700 | * | ||
701 | * This routine will unmap all mapped areas and free the HV dma region. | ||
702 | */ | ||
703 | |||
704 | static int dma_region_free_linear(struct ps3_dma_region *r) | ||
705 | { | ||
706 | int result; | ||
707 | |||
708 | result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size); | ||
709 | BUG_ON(result); | ||
710 | |||
711 | result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base), | ||
712 | map.r1.size); | ||
713 | BUG_ON(result); | ||
714 | |||
715 | result = dma_region_free(r); | ||
716 | BUG_ON(result); | ||
717 | |||
718 | return result; | ||
719 | } | ||
720 | |||
721 | /** | ||
722 | * dma_map_area_linear - Map an area of memory into a device dma region. | ||
723 | * @r: Pointer to a struct ps3_dma_region. | ||
724 | * @virt_addr: Starting virtual address of the area to map. | ||
725 | * @len: Length in bytes of the area to map. | ||
726 | * @bus_addr: A pointer to return the starting ioc bus address of the area to | ||
727 | * map. | ||
728 | * | ||
729 | * This routine just returns the coresponding bus address. Actual mapping | ||
730 | * occurs in dma_region_create_linear(). | ||
731 | */ | ||
732 | |||
733 | static int dma_map_area_linear(struct ps3_dma_region *r, | ||
734 | unsigned long virt_addr, unsigned long len, unsigned long *bus_addr) | ||
735 | { | ||
736 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | ||
737 | : virt_addr; | ||
738 | *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | ||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | /** | ||
743 | * dma_unmap_area_linear - Unmap an area of memory from a device dma region. | ||
744 | * @r: Pointer to a struct ps3_dma_region. | ||
745 | * @bus_addr: The starting ioc bus address of the area to unmap. | ||
746 | * @len: Length in bytes of the area to unmap. | ||
747 | * | ||
748 | * This routine does nothing. Unmapping occurs in dma_region_free_linear(). | ||
749 | */ | ||
750 | |||
751 | static int dma_unmap_area_linear(struct ps3_dma_region *r, | ||
752 | unsigned long bus_addr, unsigned long len) | ||
753 | { | ||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | int ps3_dma_region_create(struct ps3_dma_region *r) | ||
758 | { | ||
759 | return (USE_DYNAMIC_DMA) | ||
760 | ? dma_region_create(r) | ||
761 | : dma_region_create_linear(r); | ||
762 | } | ||
763 | |||
764 | int ps3_dma_region_free(struct ps3_dma_region *r) | ||
765 | { | ||
766 | return (USE_DYNAMIC_DMA) | ||
767 | ? dma_region_free(r) | ||
768 | : dma_region_free_linear(r); | ||
769 | } | ||
770 | |||
771 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, | ||
772 | unsigned long len, unsigned long *bus_addr) | ||
773 | { | ||
774 | return (USE_DYNAMIC_DMA) | ||
775 | ? dma_map_area(r, virt_addr, len, bus_addr) | ||
776 | : dma_map_area_linear(r, virt_addr, len, bus_addr); | ||
777 | } | ||
778 | |||
779 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, | ||
780 | unsigned long len) | ||
781 | { | ||
782 | return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len) | ||
783 | : dma_unmap_area_linear(r, bus_addr, len); | ||
784 | } | ||
785 | |||
786 | /*============================================================================*/ | ||
787 | /* system startup routines */ | ||
788 | /*============================================================================*/ | ||
789 | |||
790 | /** | ||
791 | * ps3_mm_init - initialize the address space state variables | ||
792 | */ | ||
793 | |||
794 | void __init ps3_mm_init(void) | ||
795 | { | ||
796 | int result; | ||
797 | |||
798 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
799 | |||
800 | result = ps3_repository_read_mm_info(&map.rm.base, &map.rm.size, | ||
801 | &map.total); | ||
802 | |||
803 | if (result) | ||
804 | panic("ps3_repository_read_mm_info() failed"); | ||
805 | |||
806 | map.rm.offset = map.rm.base; | ||
807 | map.vas_id = map.htab_size = 0; | ||
808 | |||
809 | /* this implementation assumes map.rm.base is zero */ | ||
810 | |||
811 | BUG_ON(map.rm.base); | ||
812 | BUG_ON(!map.rm.size); | ||
813 | |||
814 | lmb_add(map.rm.base, map.rm.size); | ||
815 | lmb_analyze(); | ||
816 | |||
817 | /* arrange to do this in ps3_mm_add_memory */ | ||
818 | ps3_mm_region_create(&map.r1, map.total - map.rm.size); | ||
819 | |||
820 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * ps3_mm_shutdown - final cleanup of address space | ||
825 | */ | ||
826 | |||
827 | void ps3_mm_shutdown(void) | ||
828 | { | ||
829 | ps3_mm_region_destroy(&map.r1); | ||
830 | map.total = map.rm.size; | ||
831 | } | ||
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c new file mode 100644 index 00000000000..58358305dc1 --- /dev/null +++ b/arch/powerpc/platforms/ps3/os-area.c | |||
@@ -0,0 +1,259 @@ | |||
1 | /* | ||
2 | * PS3 'Other OS' area data. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include <asm/lmb.h> | ||
25 | #include <asm/ps3.h> | ||
26 | |||
27 | #include "platform.h" | ||
28 | |||
29 | enum { | ||
30 | OS_AREA_SEGMENT_SIZE = 0X200, | ||
31 | }; | ||
32 | |||
33 | enum { | ||
34 | HEADER_LDR_FORMAT_RAW = 0, | ||
35 | HEADER_LDR_FORMAT_GZIP = 1, | ||
36 | }; | ||
37 | |||
38 | /** | ||
39 | * struct os_area_header - os area header segment. | ||
40 | * @magic_num: Always 'cell_ext_os_area'. | ||
41 | * @hdr_version: Header format version number. | ||
42 | * @os_area_offset: Starting segment number of os image area. | ||
43 | * @ldr_area_offset: Starting segment number of bootloader image area. | ||
44 | * @ldr_format: HEADER_LDR_FORMAT flag. | ||
45 | * @ldr_size: Size of bootloader image in bytes. | ||
46 | * | ||
47 | * Note that the docs refer to area offsets. These are offsets in units of | ||
48 | * segments from the start of the os area (top of the header). These are | ||
49 | * better thought of as segment numbers. The os area of the os area is | ||
50 | * reserved for the os image. | ||
51 | */ | ||
52 | |||
53 | struct os_area_header { | ||
54 | s8 magic_num[16]; | ||
55 | u32 hdr_version; | ||
56 | u32 os_area_offset; | ||
57 | u32 ldr_area_offset; | ||
58 | u32 _reserved_1; | ||
59 | u32 ldr_format; | ||
60 | u32 ldr_size; | ||
61 | u32 _reserved_2[6]; | ||
62 | } __attribute__ ((packed)); | ||
63 | |||
64 | enum { | ||
65 | PARAM_BOOT_FLAG_GAME_OS = 0, | ||
66 | PARAM_BOOT_FLAG_OTHER_OS = 1, | ||
67 | }; | ||
68 | |||
69 | enum { | ||
70 | PARAM_AV_MULTI_OUT_NTSC = 0, | ||
71 | PARAM_AV_MULTI_OUT_PAL_RGB = 1, | ||
72 | PARAM_AV_MULTI_OUT_PAL_YCBCR = 2, | ||
73 | PARAM_AV_MULTI_OUT_SECAM = 3, | ||
74 | }; | ||
75 | |||
76 | enum { | ||
77 | PARAM_CTRL_BUTTON_O_IS_YES = 0, | ||
78 | PARAM_CTRL_BUTTON_X_IS_YES = 1, | ||
79 | }; | ||
80 | |||
81 | /** | ||
82 | * struct os_area_params - os area params segment. | ||
83 | * @boot_flag: User preference of operating system, PARAM_BOOT_FLAG flag. | ||
84 | * @num_params: Number of params in this (params) segment. | ||
85 | * @rtc_diff: Difference in seconds between 1970 and the ps3 rtc value. | ||
86 | * @av_multi_out: User preference of AV output, PARAM_AV_MULTI_OUT flag. | ||
87 | * @ctrl_button: User preference of controller button config, PARAM_CTRL_BUTTON | ||
88 | * flag. | ||
89 | * @static_ip_addr: User preference of static IP address. | ||
90 | * @network_mask: User preference of static network mask. | ||
91 | * @default_gateway: User preference of static default gateway. | ||
92 | * @dns_primary: User preference of static primary dns server. | ||
93 | * @dns_secondary: User preference of static secondary dns server. | ||
94 | * | ||
95 | * User preference of zero for static_ip_addr means use dhcp. | ||
96 | */ | ||
97 | |||
98 | struct os_area_params { | ||
99 | u32 boot_flag; | ||
100 | u32 _reserved_1[3]; | ||
101 | u32 num_params; | ||
102 | u32 _reserved_2[3]; | ||
103 | /* param 0 */ | ||
104 | s64 rtc_diff; | ||
105 | u8 av_multi_out; | ||
106 | u8 ctrl_button; | ||
107 | u8 _reserved_3[6]; | ||
108 | /* param 1 */ | ||
109 | u8 static_ip_addr[4]; | ||
110 | u8 network_mask[4]; | ||
111 | u8 default_gateway[4]; | ||
112 | u8 _reserved_4[4]; | ||
113 | /* param 2 */ | ||
114 | u8 dns_primary[4]; | ||
115 | u8 dns_secondary[4]; | ||
116 | u8 _reserved_5[8]; | ||
117 | } __attribute__ ((packed)); | ||
118 | |||
119 | /** | ||
120 | * struct saved_params - Static working copies of data from the 'Other OS' area. | ||
121 | * | ||
122 | * For the convinience of the guest, the HV makes a copy of the 'Other OS' area | ||
123 | * in flash to a high address in the boot memory region and then puts that RAM | ||
124 | * address and the byte count into the repository for retreval by the guest. | ||
125 | * We copy the data we want into a static variable and allow the memory setup | ||
126 | * by the HV to be claimed by the lmb manager. | ||
127 | */ | ||
128 | |||
129 | struct saved_params { | ||
130 | /* param 0 */ | ||
131 | s64 rtc_diff; | ||
132 | unsigned int av_multi_out; | ||
133 | unsigned int ctrl_button; | ||
134 | /* param 1 */ | ||
135 | u8 static_ip_addr[4]; | ||
136 | u8 network_mask[4]; | ||
137 | u8 default_gateway[4]; | ||
138 | /* param 2 */ | ||
139 | u8 dns_primary[4]; | ||
140 | u8 dns_secondary[4]; | ||
141 | } static saved_params; | ||
142 | |||
143 | #define dump_header(_a) _dump_header(_a, __func__, __LINE__) | ||
144 | static void _dump_header(const struct os_area_header __iomem *h, const char* func, | ||
145 | int line) | ||
146 | { | ||
147 | pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, | ||
148 | h->magic_num); | ||
149 | pr_debug("%s:%d: h.hdr_version: %u\n", func, line, | ||
150 | h->hdr_version); | ||
151 | pr_debug("%s:%d: h.os_area_offset: %u\n", func, line, | ||
152 | h->os_area_offset); | ||
153 | pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line, | ||
154 | h->ldr_area_offset); | ||
155 | pr_debug("%s:%d: h.ldr_format: %u\n", func, line, | ||
156 | h->ldr_format); | ||
157 | pr_debug("%s:%d: h.ldr_size: %xh\n", func, line, | ||
158 | h->ldr_size); | ||
159 | } | ||
160 | |||
161 | #define dump_params(_a) _dump_params(_a, __func__, __LINE__) | ||
162 | static void _dump_params(const struct os_area_params __iomem *p, const char* func, | ||
163 | int line) | ||
164 | { | ||
165 | pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag); | ||
166 | pr_debug("%s:%d: p.num_params: %u\n", func, line, p->num_params); | ||
167 | pr_debug("%s:%d: p.rtc_diff %ld\n", func, line, p->rtc_diff); | ||
168 | pr_debug("%s:%d: p.av_multi_out %u\n", func, line, p->av_multi_out); | ||
169 | pr_debug("%s:%d: p.ctrl_button: %u\n", func, line, p->ctrl_button); | ||
170 | pr_debug("%s:%d: p.static_ip_addr: %u.%u.%u.%u\n", func, line, | ||
171 | p->static_ip_addr[0], p->static_ip_addr[1], | ||
172 | p->static_ip_addr[2], p->static_ip_addr[3]); | ||
173 | pr_debug("%s:%d: p.network_mask: %u.%u.%u.%u\n", func, line, | ||
174 | p->network_mask[0], p->network_mask[1], | ||
175 | p->network_mask[2], p->network_mask[3]); | ||
176 | pr_debug("%s:%d: p.default_gateway: %u.%u.%u.%u\n", func, line, | ||
177 | p->default_gateway[0], p->default_gateway[1], | ||
178 | p->default_gateway[2], p->default_gateway[3]); | ||
179 | pr_debug("%s:%d: p.dns_primary: %u.%u.%u.%u\n", func, line, | ||
180 | p->dns_primary[0], p->dns_primary[1], | ||
181 | p->dns_primary[2], p->dns_primary[3]); | ||
182 | pr_debug("%s:%d: p.dns_secondary: %u.%u.%u.%u\n", func, line, | ||
183 | p->dns_secondary[0], p->dns_secondary[1], | ||
184 | p->dns_secondary[2], p->dns_secondary[3]); | ||
185 | } | ||
186 | |||
187 | static int __init verify_header(const struct os_area_header *header) | ||
188 | { | ||
189 | if (memcmp(header->magic_num, "cell_ext_os_area", 16)) { | ||
190 | pr_debug("%s:%d magic_num failed\n", __func__, __LINE__); | ||
191 | return -1; | ||
192 | } | ||
193 | |||
194 | if (header->hdr_version < 1) { | ||
195 | pr_debug("%s:%d hdr_version failed\n", __func__, __LINE__); | ||
196 | return -1; | ||
197 | } | ||
198 | |||
199 | if (header->os_area_offset > header->ldr_area_offset) { | ||
200 | pr_debug("%s:%d offsets failed\n", __func__, __LINE__); | ||
201 | return -1; | ||
202 | } | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | int __init ps3_os_area_init(void) | ||
208 | { | ||
209 | int result; | ||
210 | u64 lpar_addr; | ||
211 | unsigned int size; | ||
212 | struct os_area_header *header; | ||
213 | struct os_area_params *params; | ||
214 | |||
215 | result = ps3_repository_read_boot_dat_info(&lpar_addr, &size); | ||
216 | |||
217 | if (result) { | ||
218 | pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n", | ||
219 | __func__, __LINE__); | ||
220 | return result; | ||
221 | } | ||
222 | |||
223 | header = (struct os_area_header *)__va(lpar_addr); | ||
224 | params = (struct os_area_params *)__va(lpar_addr + OS_AREA_SEGMENT_SIZE); | ||
225 | |||
226 | result = verify_header(header); | ||
227 | |||
228 | if (result) { | ||
229 | pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); | ||
230 | dump_header(header); | ||
231 | return -EIO; | ||
232 | } | ||
233 | |||
234 | dump_header(header); | ||
235 | dump_params(params); | ||
236 | |||
237 | saved_params.rtc_diff = params->rtc_diff; | ||
238 | saved_params.av_multi_out = params->av_multi_out; | ||
239 | saved_params.ctrl_button = params->ctrl_button; | ||
240 | memcpy(saved_params.static_ip_addr, params->static_ip_addr, 4); | ||
241 | memcpy(saved_params.network_mask, params->network_mask, 4); | ||
242 | memcpy(saved_params.default_gateway, params->default_gateway, 4); | ||
243 | memcpy(saved_params.dns_secondary, params->dns_secondary, 4); | ||
244 | |||
245 | return result; | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * ps3_os_area_rtc_diff - Returns the ps3 rtc diff value. | ||
250 | * | ||
251 | * The ps3 rtc maintains a value that approximates seconds since | ||
252 | * 2000-01-01 00:00:00 UTC. Returns the exact number of seconds from 1970 to | ||
253 | * 2000 when saved_params.rtc_diff has not been properly set up. | ||
254 | */ | ||
255 | |||
256 | u64 ps3_os_area_rtc_diff(void) | ||
257 | { | ||
258 | return saved_params.rtc_diff ? saved_params.rtc_diff : 946684800UL; | ||
259 | } | ||
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h new file mode 100644 index 00000000000..23b111bea9d --- /dev/null +++ b/arch/powerpc/platforms/ps3/platform.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * PS3 platform declarations. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #if !defined(_PS3_PLATFORM_H) | ||
22 | #define _PS3_PLATFORM_H | ||
23 | |||
24 | #include <linux/rtc.h> | ||
25 | |||
26 | /* htab */ | ||
27 | |||
28 | void __init ps3_hpte_init(unsigned long htab_size); | ||
29 | void __init ps3_map_htab(void); | ||
30 | |||
31 | /* mm */ | ||
32 | |||
33 | void __init ps3_mm_init(void); | ||
34 | void __init ps3_mm_vas_create(unsigned long* htab_size); | ||
35 | void ps3_mm_vas_destroy(void); | ||
36 | void ps3_mm_shutdown(void); | ||
37 | |||
38 | /* irq */ | ||
39 | |||
40 | void ps3_init_IRQ(void); | ||
41 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); | ||
42 | |||
43 | /* smp */ | ||
44 | |||
45 | void smp_init_ps3(void); | ||
46 | void ps3_smp_cleanup_cpu(int cpu); | ||
47 | |||
48 | /* time */ | ||
49 | |||
50 | void __init ps3_calibrate_decr(void); | ||
51 | unsigned long __init ps3_get_boot_time(void); | ||
52 | void ps3_get_rtc_time(struct rtc_time *time); | ||
53 | int ps3_set_rtc_time(struct rtc_time *time); | ||
54 | |||
55 | /* os area */ | ||
56 | |||
57 | int __init ps3_os_area_init(void); | ||
58 | u64 ps3_os_area_rtc_diff(void); | ||
59 | |||
60 | /* spu */ | ||
61 | |||
62 | #if defined(CONFIG_SPU_BASE) | ||
63 | void ps3_spu_set_platform (void); | ||
64 | #else | ||
65 | static inline void ps3_spu_set_platform (void) {} | ||
66 | #endif | ||
67 | |||
68 | #endif | ||
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c new file mode 100644 index 00000000000..273a0d621bd --- /dev/null +++ b/arch/powerpc/platforms/ps3/repository.c | |||
@@ -0,0 +1,840 @@ | |||
1 | /* | ||
2 | * PS3 repository routines. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <asm/ps3.h> | ||
22 | #include <asm/lv1call.h> | ||
23 | |||
24 | enum ps3_vendor_id { | ||
25 | PS3_VENDOR_ID_NONE = 0, | ||
26 | PS3_VENDOR_ID_SONY = 0x8000000000000000UL, | ||
27 | }; | ||
28 | |||
29 | enum ps3_lpar_id { | ||
30 | PS3_LPAR_ID_CURRENT = 0, | ||
31 | PS3_LPAR_ID_PME = 1, | ||
32 | }; | ||
33 | |||
34 | #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__) | ||
35 | static void _dump_field(const char *hdr, u64 n, const char* func, int line) | ||
36 | { | ||
37 | #if defined(DEBUG) | ||
38 | char s[16]; | ||
39 | const char *const in = (const char *)&n; | ||
40 | unsigned int i; | ||
41 | |||
42 | for (i = 0; i < 8; i++) | ||
43 | s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.'; | ||
44 | s[i] = 0; | ||
45 | |||
46 | pr_debug("%s:%d: %s%016lx : %s\n", func, line, hdr, n, s); | ||
47 | #endif | ||
48 | } | ||
49 | |||
50 | #define dump_node_name(_a, _b, _c, _d, _e) \ | ||
51 | _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__) | ||
52 | static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3, | ||
53 | u64 n4, const char* func, int line) | ||
54 | { | ||
55 | pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); | ||
56 | _dump_field("n1: ", n1, func, line); | ||
57 | _dump_field("n2: ", n2, func, line); | ||
58 | _dump_field("n3: ", n3, func, line); | ||
59 | _dump_field("n4: ", n4, func, line); | ||
60 | } | ||
61 | |||
62 | #define dump_node(_a, _b, _c, _d, _e, _f, _g) \ | ||
63 | _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) | ||
64 | static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, | ||
65 | u64 v1, u64 v2, const char* func, int line) | ||
66 | { | ||
67 | pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); | ||
68 | _dump_field("n1: ", n1, func, line); | ||
69 | _dump_field("n2: ", n2, func, line); | ||
70 | _dump_field("n3: ", n3, func, line); | ||
71 | _dump_field("n4: ", n4, func, line); | ||
72 | pr_debug("%s:%d: v1: %016lx\n", func, line, v1); | ||
73 | pr_debug("%s:%d: v2: %016lx\n", func, line, v2); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * make_first_field - Make the first field of a repository node name. | ||
78 | * @text: Text portion of the field. | ||
79 | * @index: Numeric index portion of the field. Use zero for 'don't care'. | ||
80 | * | ||
81 | * This routine sets the vendor id to zero (non-vendor specific). | ||
82 | * Returns field value. | ||
83 | */ | ||
84 | |||
85 | static u64 make_first_field(const char *text, u64 index) | ||
86 | { | ||
87 | u64 n; | ||
88 | |||
89 | strncpy((char *)&n, text, 8); | ||
90 | return PS3_VENDOR_ID_NONE + (n >> 32) + index; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * make_field - Make subsequent fields of a repository node name. | ||
95 | * @text: Text portion of the field. Use "" for 'don't care'. | ||
96 | * @index: Numeric index portion of the field. Use zero for 'don't care'. | ||
97 | * | ||
98 | * Returns field value. | ||
99 | */ | ||
100 | |||
101 | static u64 make_field(const char *text, u64 index) | ||
102 | { | ||
103 | u64 n; | ||
104 | |||
105 | strncpy((char *)&n, text, 8); | ||
106 | return n + index; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * read_node - Read a repository node from raw fields. | ||
111 | * @n1: First field of node name. | ||
112 | * @n2: Second field of node name. Use zero for 'don't care'. | ||
113 | * @n3: Third field of node name. Use zero for 'don't care'. | ||
114 | * @n4: Fourth field of node name. Use zero for 'don't care'. | ||
115 | * @v1: First repository value (high word). | ||
116 | * @v2: Second repository value (low word). Optional parameter, use zero | ||
117 | * for 'don't care'. | ||
118 | */ | ||
119 | |||
120 | static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, | ||
121 | u64 *_v1, u64 *_v2) | ||
122 | { | ||
123 | int result; | ||
124 | u64 v1; | ||
125 | u64 v2; | ||
126 | |||
127 | if (lpar_id == PS3_LPAR_ID_CURRENT) { | ||
128 | u64 id; | ||
129 | lv1_get_logical_partition_id(&id); | ||
130 | lpar_id = id; | ||
131 | } | ||
132 | |||
133 | result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1, | ||
134 | &v2); | ||
135 | |||
136 | if (result) { | ||
137 | pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", | ||
138 | __func__, __LINE__, ps3_result(result)); | ||
139 | dump_node_name(lpar_id, n1, n2, n3, n4); | ||
140 | return result; | ||
141 | } | ||
142 | |||
143 | dump_node(lpar_id, n1, n2, n3, n4, v1, v2); | ||
144 | |||
145 | if (_v1) | ||
146 | *_v1 = v1; | ||
147 | if (_v2) | ||
148 | *_v2 = v2; | ||
149 | |||
150 | if (v1 && !_v1) | ||
151 | pr_debug("%s:%d: warning: discarding non-zero v1: %016lx\n", | ||
152 | __func__, __LINE__, v1); | ||
153 | if (v2 && !_v2) | ||
154 | pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n", | ||
155 | __func__, __LINE__, v2); | ||
156 | |||
157 | return result; | ||
158 | } | ||
159 | |||
160 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | ||
161 | u64 *value) | ||
162 | { | ||
163 | return read_node(PS3_LPAR_ID_PME, | ||
164 | make_first_field("bus", bus_index), | ||
165 | make_field(bus_str, 0), | ||
166 | 0, 0, | ||
167 | value, 0); | ||
168 | } | ||
169 | |||
170 | int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id) | ||
171 | { | ||
172 | int result; | ||
173 | u64 v1; | ||
174 | u64 v2; /* unused */ | ||
175 | |||
176 | result = read_node(PS3_LPAR_ID_PME, | ||
177 | make_first_field("bus", bus_index), | ||
178 | make_field("id", 0), | ||
179 | 0, 0, | ||
180 | &v1, &v2); | ||
181 | *bus_id = v1; | ||
182 | return result; | ||
183 | } | ||
184 | |||
185 | int ps3_repository_read_bus_type(unsigned int bus_index, | ||
186 | enum ps3_bus_type *bus_type) | ||
187 | { | ||
188 | int result; | ||
189 | u64 v1; | ||
190 | |||
191 | result = read_node(PS3_LPAR_ID_PME, | ||
192 | make_first_field("bus", bus_index), | ||
193 | make_field("type", 0), | ||
194 | 0, 0, | ||
195 | &v1, 0); | ||
196 | *bus_type = v1; | ||
197 | return result; | ||
198 | } | ||
199 | |||
200 | int ps3_repository_read_bus_num_dev(unsigned int bus_index, | ||
201 | unsigned int *num_dev) | ||
202 | { | ||
203 | int result; | ||
204 | u64 v1; | ||
205 | |||
206 | result = read_node(PS3_LPAR_ID_PME, | ||
207 | make_first_field("bus", bus_index), | ||
208 | make_field("num_dev", 0), | ||
209 | 0, 0, | ||
210 | &v1, 0); | ||
211 | *num_dev = v1; | ||
212 | return result; | ||
213 | } | ||
214 | |||
215 | int ps3_repository_read_dev_str(unsigned int bus_index, | ||
216 | unsigned int dev_index, const char *dev_str, u64 *value) | ||
217 | { | ||
218 | return read_node(PS3_LPAR_ID_PME, | ||
219 | make_first_field("bus", bus_index), | ||
220 | make_field("dev", dev_index), | ||
221 | make_field(dev_str, 0), | ||
222 | 0, | ||
223 | value, 0); | ||
224 | } | ||
225 | |||
226 | int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, | ||
227 | unsigned int *dev_id) | ||
228 | { | ||
229 | int result; | ||
230 | u64 v1; | ||
231 | |||
232 | result = read_node(PS3_LPAR_ID_PME, | ||
233 | make_first_field("bus", bus_index), | ||
234 | make_field("dev", dev_index), | ||
235 | make_field("id", 0), | ||
236 | 0, | ||
237 | &v1, 0); | ||
238 | *dev_id = v1; | ||
239 | return result; | ||
240 | } | ||
241 | |||
242 | int ps3_repository_read_dev_type(unsigned int bus_index, | ||
243 | unsigned int dev_index, enum ps3_dev_type *dev_type) | ||
244 | { | ||
245 | int result; | ||
246 | u64 v1; | ||
247 | |||
248 | result = read_node(PS3_LPAR_ID_PME, | ||
249 | make_first_field("bus", bus_index), | ||
250 | make_field("dev", dev_index), | ||
251 | make_field("type", 0), | ||
252 | 0, | ||
253 | &v1, 0); | ||
254 | *dev_type = v1; | ||
255 | return result; | ||
256 | } | ||
257 | |||
258 | int ps3_repository_read_dev_intr(unsigned int bus_index, | ||
259 | unsigned int dev_index, unsigned int intr_index, | ||
260 | unsigned int *intr_type, unsigned int* interrupt_id) | ||
261 | { | ||
262 | int result; | ||
263 | u64 v1; | ||
264 | u64 v2; | ||
265 | |||
266 | result = read_node(PS3_LPAR_ID_PME, | ||
267 | make_first_field("bus", bus_index), | ||
268 | make_field("dev", dev_index), | ||
269 | make_field("intr", intr_index), | ||
270 | 0, | ||
271 | &v1, &v2); | ||
272 | *intr_type = v1; | ||
273 | *interrupt_id = v2; | ||
274 | return result; | ||
275 | } | ||
276 | |||
277 | int ps3_repository_read_dev_reg_type(unsigned int bus_index, | ||
278 | unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type) | ||
279 | { | ||
280 | int result; | ||
281 | u64 v1; | ||
282 | |||
283 | result = read_node(PS3_LPAR_ID_PME, | ||
284 | make_first_field("bus", bus_index), | ||
285 | make_field("dev", dev_index), | ||
286 | make_field("reg", reg_index), | ||
287 | make_field("type", 0), | ||
288 | &v1, 0); | ||
289 | *reg_type = v1; | ||
290 | return result; | ||
291 | } | ||
292 | |||
293 | int ps3_repository_read_dev_reg_addr(unsigned int bus_index, | ||
294 | unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len) | ||
295 | { | ||
296 | return read_node(PS3_LPAR_ID_PME, | ||
297 | make_first_field("bus", bus_index), | ||
298 | make_field("dev", dev_index), | ||
299 | make_field("reg", reg_index), | ||
300 | make_field("data", 0), | ||
301 | bus_addr, len); | ||
302 | } | ||
303 | |||
304 | int ps3_repository_read_dev_reg(unsigned int bus_index, | ||
305 | unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type, | ||
306 | u64 *bus_addr, u64 *len) | ||
307 | { | ||
308 | int result = ps3_repository_read_dev_reg_type(bus_index, dev_index, | ||
309 | reg_index, reg_type); | ||
310 | return result ? result | ||
311 | : ps3_repository_read_dev_reg_addr(bus_index, dev_index, | ||
312 | reg_index, bus_addr, len); | ||
313 | } | ||
314 | |||
315 | #if defined(DEBUG) | ||
316 | int ps3_repository_dump_resource_info(unsigned int bus_index, | ||
317 | unsigned int dev_index) | ||
318 | { | ||
319 | int result = 0; | ||
320 | unsigned int res_index; | ||
321 | |||
322 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
323 | bus_index, dev_index); | ||
324 | |||
325 | for (res_index = 0; res_index < 10; res_index++) { | ||
326 | enum ps3_interrupt_type intr_type; | ||
327 | unsigned int interrupt_id; | ||
328 | |||
329 | result = ps3_repository_read_dev_intr(bus_index, dev_index, | ||
330 | res_index, &intr_type, &interrupt_id); | ||
331 | |||
332 | if (result) { | ||
333 | if (result != LV1_NO_ENTRY) | ||
334 | pr_debug("%s:%d ps3_repository_read_dev_intr" | ||
335 | " (%u:%u) failed\n", __func__, __LINE__, | ||
336 | bus_index, dev_index); | ||
337 | break; | ||
338 | } | ||
339 | |||
340 | pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", | ||
341 | __func__, __LINE__, bus_index, dev_index, intr_type, | ||
342 | interrupt_id); | ||
343 | } | ||
344 | |||
345 | for (res_index = 0; res_index < 10; res_index++) { | ||
346 | enum ps3_region_type reg_type; | ||
347 | u64 bus_addr; | ||
348 | u64 len; | ||
349 | |||
350 | result = ps3_repository_read_dev_reg(bus_index, dev_index, | ||
351 | res_index, ®_type, &bus_addr, &len); | ||
352 | |||
353 | if (result) { | ||
354 | if (result != LV1_NO_ENTRY) | ||
355 | pr_debug("%s:%d ps3_repository_read_dev_reg" | ||
356 | " (%u:%u) failed\n", __func__, __LINE__, | ||
357 | bus_index, dev_index); | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", | ||
362 | __func__, __LINE__, bus_index, dev_index, reg_type, | ||
363 | bus_addr, len); | ||
364 | } | ||
365 | |||
366 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
367 | return result; | ||
368 | } | ||
369 | |||
370 | static int dump_device_info(unsigned int bus_index, unsigned int num_dev) | ||
371 | { | ||
372 | int result = 0; | ||
373 | unsigned int dev_index; | ||
374 | |||
375 | pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index); | ||
376 | |||
377 | for (dev_index = 0; dev_index < num_dev; dev_index++) { | ||
378 | enum ps3_dev_type dev_type; | ||
379 | unsigned int dev_id; | ||
380 | |||
381 | result = ps3_repository_read_dev_type(bus_index, dev_index, | ||
382 | &dev_type); | ||
383 | |||
384 | if (result) { | ||
385 | pr_debug("%s:%d ps3_repository_read_dev_type" | ||
386 | " (%u:%u) failed\n", __func__, __LINE__, | ||
387 | bus_index, dev_index); | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | result = ps3_repository_read_dev_id(bus_index, dev_index, | ||
392 | &dev_id); | ||
393 | |||
394 | if (result) { | ||
395 | pr_debug("%s:%d ps3_repository_read_dev_id" | ||
396 | " (%u:%u) failed\n", __func__, __LINE__, | ||
397 | bus_index, dev_index); | ||
398 | continue; | ||
399 | } | ||
400 | |||
401 | pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, | ||
402 | __LINE__, bus_index, dev_index, dev_type, dev_id); | ||
403 | |||
404 | ps3_repository_dump_resource_info(bus_index, dev_index); | ||
405 | } | ||
406 | |||
407 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
408 | return result; | ||
409 | } | ||
410 | |||
411 | int ps3_repository_dump_bus_info(void) | ||
412 | { | ||
413 | int result = 0; | ||
414 | unsigned int bus_index; | ||
415 | |||
416 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
417 | |||
418 | for (bus_index = 0; bus_index < 10; bus_index++) { | ||
419 | enum ps3_bus_type bus_type; | ||
420 | unsigned int bus_id; | ||
421 | unsigned int num_dev; | ||
422 | |||
423 | result = ps3_repository_read_bus_type(bus_index, &bus_type); | ||
424 | |||
425 | if (result) { | ||
426 | pr_debug("%s:%d read_bus_type(%u) failed\n", | ||
427 | __func__, __LINE__, bus_index); | ||
428 | break; | ||
429 | } | ||
430 | |||
431 | result = ps3_repository_read_bus_id(bus_index, &bus_id); | ||
432 | |||
433 | if (result) { | ||
434 | pr_debug("%s:%d read_bus_id(%u) failed\n", | ||
435 | __func__, __LINE__, bus_index); | ||
436 | continue; | ||
437 | } | ||
438 | |||
439 | if (bus_index != bus_id) | ||
440 | pr_debug("%s:%d bus_index != bus_id\n", | ||
441 | __func__, __LINE__); | ||
442 | |||
443 | result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); | ||
444 | |||
445 | if (result) { | ||
446 | pr_debug("%s:%d read_bus_num_dev(%u) failed\n", | ||
447 | __func__, __LINE__, bus_index); | ||
448 | continue; | ||
449 | } | ||
450 | |||
451 | pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", | ||
452 | __func__, __LINE__, bus_index, bus_type, bus_id, | ||
453 | num_dev); | ||
454 | |||
455 | dump_device_info(bus_index, num_dev); | ||
456 | } | ||
457 | |||
458 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
459 | return result; | ||
460 | } | ||
461 | #endif /* defined(DEBUG) */ | ||
462 | |||
463 | static int find_device(unsigned int bus_index, unsigned int num_dev, | ||
464 | unsigned int start_dev_index, enum ps3_dev_type dev_type, | ||
465 | struct ps3_repository_device *dev) | ||
466 | { | ||
467 | int result = 0; | ||
468 | unsigned int dev_index; | ||
469 | |||
470 | pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type); | ||
471 | |||
472 | dev->dev_index = UINT_MAX; | ||
473 | |||
474 | for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) { | ||
475 | enum ps3_dev_type x; | ||
476 | |||
477 | result = ps3_repository_read_dev_type(bus_index, dev_index, | ||
478 | &x); | ||
479 | |||
480 | if (result) { | ||
481 | pr_debug("%s:%d read_dev_type failed\n", | ||
482 | __func__, __LINE__); | ||
483 | return result; | ||
484 | } | ||
485 | |||
486 | if (x == dev_type) | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | BUG_ON(dev_index == num_dev); | ||
491 | |||
492 | pr_debug("%s:%d: found dev_type %u at dev_index %u\n", | ||
493 | __func__, __LINE__, dev_type, dev_index); | ||
494 | |||
495 | result = ps3_repository_read_dev_id(bus_index, dev_index, | ||
496 | &dev->did.dev_id); | ||
497 | |||
498 | if (result) { | ||
499 | pr_debug("%s:%d read_dev_id failed\n", | ||
500 | __func__, __LINE__); | ||
501 | return result; | ||
502 | } | ||
503 | |||
504 | dev->dev_index = dev_index; | ||
505 | |||
506 | pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__, | ||
507 | dev->did.dev_id); | ||
508 | |||
509 | return result; | ||
510 | } | ||
511 | |||
512 | int ps3_repository_find_device (enum ps3_bus_type bus_type, | ||
513 | enum ps3_dev_type dev_type, | ||
514 | const struct ps3_repository_device *start_dev, | ||
515 | struct ps3_repository_device *dev) | ||
516 | { | ||
517 | int result = 0; | ||
518 | unsigned int bus_index; | ||
519 | unsigned int num_dev; | ||
520 | |||
521 | pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__, | ||
522 | bus_type, dev_type); | ||
523 | |||
524 | dev->bus_index = UINT_MAX; | ||
525 | |||
526 | for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10; | ||
527 | bus_index++) { | ||
528 | enum ps3_bus_type x; | ||
529 | |||
530 | result = ps3_repository_read_bus_type(bus_index, &x); | ||
531 | |||
532 | if (result) { | ||
533 | pr_debug("%s:%d read_bus_type failed\n", | ||
534 | __func__, __LINE__); | ||
535 | return result; | ||
536 | } | ||
537 | if (x == bus_type) | ||
538 | break; | ||
539 | } | ||
540 | |||
541 | BUG_ON(bus_index == 10); | ||
542 | |||
543 | pr_debug("%s:%d: found bus_type %u at bus_index %u\n", | ||
544 | __func__, __LINE__, bus_type, bus_index); | ||
545 | |||
546 | result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); | ||
547 | |||
548 | if (result) { | ||
549 | pr_debug("%s:%d read_bus_num_dev failed\n", | ||
550 | __func__, __LINE__); | ||
551 | return result; | ||
552 | } | ||
553 | |||
554 | result = find_device(bus_index, num_dev, start_dev | ||
555 | ? start_dev->dev_index + 1 : 0, dev_type, dev); | ||
556 | |||
557 | if (result) { | ||
558 | pr_debug("%s:%d get_did failed\n", __func__, __LINE__); | ||
559 | return result; | ||
560 | } | ||
561 | |||
562 | result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id); | ||
563 | |||
564 | if (result) { | ||
565 | pr_debug("%s:%d read_bus_id failed\n", | ||
566 | __func__, __LINE__); | ||
567 | return result; | ||
568 | } | ||
569 | |||
570 | dev->bus_index = bus_index; | ||
571 | |||
572 | pr_debug("%s:%d found: bus_id %u, dev_id %u\n", | ||
573 | __func__, __LINE__, dev->did.bus_id, dev->did.dev_id); | ||
574 | |||
575 | return result; | ||
576 | } | ||
577 | |||
578 | int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | ||
579 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) | ||
580 | { | ||
581 | int result = 0; | ||
582 | unsigned int res_index; | ||
583 | |||
584 | pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type); | ||
585 | |||
586 | *interrupt_id = UINT_MAX; | ||
587 | |||
588 | for (res_index = 0; res_index < 10; res_index++) { | ||
589 | enum ps3_interrupt_type t; | ||
590 | unsigned int id; | ||
591 | |||
592 | result = ps3_repository_read_dev_intr(dev->bus_index, | ||
593 | dev->dev_index, res_index, &t, &id); | ||
594 | |||
595 | if (result) { | ||
596 | pr_debug("%s:%d read_dev_intr failed\n", | ||
597 | __func__, __LINE__); | ||
598 | return result; | ||
599 | } | ||
600 | |||
601 | if (t == intr_type) { | ||
602 | *interrupt_id = id; | ||
603 | break; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | BUG_ON(res_index == 10); | ||
608 | |||
609 | pr_debug("%s:%d: found intr_type %u at res_index %u\n", | ||
610 | __func__, __LINE__, intr_type, res_index); | ||
611 | |||
612 | return result; | ||
613 | } | ||
614 | |||
615 | int ps3_repository_find_region(const struct ps3_repository_device *dev, | ||
616 | enum ps3_region_type reg_type, u64 *bus_addr, u64 *len) | ||
617 | { | ||
618 | int result = 0; | ||
619 | unsigned int res_index; | ||
620 | |||
621 | pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type); | ||
622 | |||
623 | *bus_addr = *len = 0; | ||
624 | |||
625 | for (res_index = 0; res_index < 10; res_index++) { | ||
626 | enum ps3_region_type t; | ||
627 | u64 a; | ||
628 | u64 l; | ||
629 | |||
630 | result = ps3_repository_read_dev_reg(dev->bus_index, | ||
631 | dev->dev_index, res_index, &t, &a, &l); | ||
632 | |||
633 | if (result) { | ||
634 | pr_debug("%s:%d read_dev_reg failed\n", | ||
635 | __func__, __LINE__); | ||
636 | return result; | ||
637 | } | ||
638 | |||
639 | if (t == reg_type) { | ||
640 | *bus_addr = a; | ||
641 | *len = l; | ||
642 | break; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | BUG_ON(res_index == 10); | ||
647 | |||
648 | pr_debug("%s:%d: found reg_type %u at res_index %u\n", | ||
649 | __func__, __LINE__, reg_type, res_index); | ||
650 | |||
651 | return result; | ||
652 | } | ||
653 | |||
654 | int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) | ||
655 | { | ||
656 | return read_node(PS3_LPAR_ID_CURRENT, | ||
657 | make_first_field("bi", 0), | ||
658 | make_field("pu", 0), | ||
659 | ppe_id, | ||
660 | make_field("rm_size", 0), | ||
661 | rm_size, 0); | ||
662 | } | ||
663 | |||
664 | int ps3_repository_read_region_total(u64 *region_total) | ||
665 | { | ||
666 | return read_node(PS3_LPAR_ID_CURRENT, | ||
667 | make_first_field("bi", 0), | ||
668 | make_field("rgntotal", 0), | ||
669 | 0, 0, | ||
670 | region_total, 0); | ||
671 | } | ||
672 | |||
673 | /** | ||
674 | * ps3_repository_read_mm_info - Read mm info for single pu system. | ||
675 | * @rm_base: Real mode memory base address. | ||
676 | * @rm_size: Real mode memory size. | ||
677 | * @region_total: Maximum memory region size. | ||
678 | */ | ||
679 | |||
680 | int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) | ||
681 | { | ||
682 | int result; | ||
683 | u64 ppe_id; | ||
684 | |||
685 | lv1_get_logical_ppe_id(&ppe_id); | ||
686 | *rm_base = 0; | ||
687 | result = ps3_repository_read_rm_size(ppe_id, rm_size); | ||
688 | return result ? result | ||
689 | : ps3_repository_read_region_total(region_total); | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * ps3_repository_read_num_spu_reserved - Number of physical spus reserved. | ||
694 | * @num_spu: Number of physical spus. | ||
695 | */ | ||
696 | |||
697 | int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) | ||
698 | { | ||
699 | int result; | ||
700 | u64 v1; | ||
701 | |||
702 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
703 | make_first_field("bi", 0), | ||
704 | make_field("spun", 0), | ||
705 | 0, 0, | ||
706 | &v1, 0); | ||
707 | *num_spu_reserved = v1; | ||
708 | return result; | ||
709 | } | ||
710 | |||
711 | /** | ||
712 | * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations. | ||
713 | * @num_resource_id: Number of spu resource ids. | ||
714 | */ | ||
715 | |||
716 | int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) | ||
717 | { | ||
718 | int result; | ||
719 | u64 v1; | ||
720 | |||
721 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
722 | make_first_field("bi", 0), | ||
723 | make_field("spursvn", 0), | ||
724 | 0, 0, | ||
725 | &v1, 0); | ||
726 | *num_resource_id = v1; | ||
727 | return result; | ||
728 | } | ||
729 | |||
730 | /** | ||
731 | * ps3_repository_read_spu_resource_id - spu resource reservation id value. | ||
732 | * @res_index: Resource reservation index. | ||
733 | * @resource_type: Resource reservation type. | ||
734 | * @resource_id: Resource reservation id. | ||
735 | */ | ||
736 | |||
737 | int ps3_repository_read_spu_resource_id(unsigned int res_index, | ||
738 | enum ps3_spu_resource_type* resource_type, unsigned int *resource_id) | ||
739 | { | ||
740 | int result; | ||
741 | u64 v1; | ||
742 | u64 v2; | ||
743 | |||
744 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
745 | make_first_field("bi", 0), | ||
746 | make_field("spursv", 0), | ||
747 | res_index, | ||
748 | 0, | ||
749 | &v1, &v2); | ||
750 | *resource_type = v1; | ||
751 | *resource_id = v2; | ||
752 | return result; | ||
753 | } | ||
754 | |||
755 | int ps3_repository_read_boot_dat_address(u64 *address) | ||
756 | { | ||
757 | return read_node(PS3_LPAR_ID_CURRENT, | ||
758 | make_first_field("bi", 0), | ||
759 | make_field("boot_dat", 0), | ||
760 | make_field("address", 0), | ||
761 | 0, | ||
762 | address, 0); | ||
763 | } | ||
764 | |||
765 | int ps3_repository_read_boot_dat_size(unsigned int *size) | ||
766 | { | ||
767 | int result; | ||
768 | u64 v1; | ||
769 | |||
770 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
771 | make_first_field("bi", 0), | ||
772 | make_field("boot_dat", 0), | ||
773 | make_field("size", 0), | ||
774 | 0, | ||
775 | &v1, 0); | ||
776 | *size = v1; | ||
777 | return result; | ||
778 | } | ||
779 | |||
780 | /** | ||
781 | * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. | ||
782 | * address: lpar address of cell_ext_os_area | ||
783 | * @size: size of cell_ext_os_area | ||
784 | */ | ||
785 | |||
786 | int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) | ||
787 | { | ||
788 | int result; | ||
789 | |||
790 | *size = 0; | ||
791 | result = ps3_repository_read_boot_dat_address(lpar_addr); | ||
792 | return result ? result | ||
793 | : ps3_repository_read_boot_dat_size(size); | ||
794 | } | ||
795 | |||
796 | int ps3_repository_read_num_be(unsigned int *num_be) | ||
797 | { | ||
798 | int result; | ||
799 | u64 v1; | ||
800 | |||
801 | result = read_node(PS3_LPAR_ID_PME, | ||
802 | make_first_field("ben", 0), | ||
803 | 0, | ||
804 | 0, | ||
805 | 0, | ||
806 | &v1, 0); | ||
807 | *num_be = v1; | ||
808 | return result; | ||
809 | } | ||
810 | |||
811 | int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) | ||
812 | { | ||
813 | return read_node(PS3_LPAR_ID_PME, | ||
814 | make_first_field("be", be_index), | ||
815 | 0, | ||
816 | 0, | ||
817 | 0, | ||
818 | node_id, 0); | ||
819 | } | ||
820 | |||
821 | int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) | ||
822 | { | ||
823 | return read_node(PS3_LPAR_ID_PME, | ||
824 | make_first_field("be", 0), | ||
825 | node_id, | ||
826 | make_field("clock", 0), | ||
827 | 0, | ||
828 | tb_freq, 0); | ||
829 | } | ||
830 | |||
831 | int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) | ||
832 | { | ||
833 | int result; | ||
834 | u64 node_id; | ||
835 | |||
836 | *tb_freq = 0; | ||
837 | result = ps3_repository_read_be_node_id(0, &node_id); | ||
838 | return result ? result | ||
839 | : ps3_repository_read_tb_freq(node_id, tb_freq); | ||
840 | } | ||
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c new file mode 100644 index 00000000000..d8b5cadbe80 --- /dev/null +++ b/arch/powerpc/platforms/ps3/setup.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * PS3 platform setup routines. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/root_dev.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/kexec.h> | ||
27 | |||
28 | #include <asm/machdep.h> | ||
29 | #include <asm/firmware.h> | ||
30 | #include <asm/time.h> | ||
31 | #include <asm/iommu.h> | ||
32 | #include <asm/udbg.h> | ||
33 | #include <asm/prom.h> | ||
34 | #include <asm/lv1call.h> | ||
35 | |||
36 | #include "platform.h" | ||
37 | |||
38 | #if defined(DEBUG) | ||
39 | #define DBG(fmt...) udbg_printf(fmt) | ||
40 | #else | ||
41 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | ||
42 | #endif | ||
43 | |||
44 | static void ps3_show_cpuinfo(struct seq_file *m) | ||
45 | { | ||
46 | seq_printf(m, "machine\t\t: %s\n", ppc_md.name); | ||
47 | } | ||
48 | |||
49 | static void ps3_power_save(void) | ||
50 | { | ||
51 | /* | ||
52 | * lv1_pause() puts the PPE thread into inactive state until an | ||
53 | * irq on an unmasked plug exists. MSR[EE] has no effect. | ||
54 | * flags: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt. | ||
55 | */ | ||
56 | |||
57 | lv1_pause(0); | ||
58 | } | ||
59 | |||
60 | static void ps3_panic(char *str) | ||
61 | { | ||
62 | DBG("%s:%d %s\n", __func__, __LINE__, str); | ||
63 | |||
64 | #ifdef CONFIG_SMP | ||
65 | smp_send_stop(); | ||
66 | #endif | ||
67 | printk("\n"); | ||
68 | printk(" System does not reboot automatically.\n"); | ||
69 | printk(" Please press POWER button.\n"); | ||
70 | printk("\n"); | ||
71 | |||
72 | for (;;) ; | ||
73 | } | ||
74 | |||
75 | static void __init ps3_setup_arch(void) | ||
76 | { | ||
77 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
78 | |||
79 | ps3_spu_set_platform(); | ||
80 | ps3_map_htab(); | ||
81 | |||
82 | #ifdef CONFIG_SMP | ||
83 | smp_init_ps3(); | ||
84 | #endif | ||
85 | |||
86 | #ifdef CONFIG_DUMMY_CONSOLE | ||
87 | conswitchp = &dummy_con; | ||
88 | #endif | ||
89 | |||
90 | ppc_md.power_save = ps3_power_save; | ||
91 | |||
92 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
93 | } | ||
94 | |||
95 | static void __init ps3_progress(char *s, unsigned short hex) | ||
96 | { | ||
97 | printk("*** %04x : %s\n", hex, s ? s : ""); | ||
98 | } | ||
99 | |||
100 | static int __init ps3_probe(void) | ||
101 | { | ||
102 | unsigned long htab_size; | ||
103 | unsigned long dt_root; | ||
104 | |||
105 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
106 | |||
107 | dt_root = of_get_flat_dt_root(); | ||
108 | if (!of_flat_dt_is_compatible(dt_root, "PS3")) | ||
109 | return 0; | ||
110 | |||
111 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; | ||
112 | |||
113 | ps3_os_area_init(); | ||
114 | ps3_mm_init(); | ||
115 | ps3_mm_vas_create(&htab_size); | ||
116 | ps3_hpte_init(htab_size); | ||
117 | |||
118 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
119 | return 1; | ||
120 | } | ||
121 | |||
122 | #if defined(CONFIG_KEXEC) | ||
123 | static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) | ||
124 | { | ||
125 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
126 | |||
127 | if (secondary) { | ||
128 | int cpu; | ||
129 | for_each_online_cpu(cpu) | ||
130 | if (cpu) | ||
131 | ps3_smp_cleanup_cpu(cpu); | ||
132 | } else | ||
133 | ps3_smp_cleanup_cpu(0); | ||
134 | |||
135 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
136 | } | ||
137 | |||
138 | static void ps3_machine_kexec(struct kimage *image) | ||
139 | { | ||
140 | unsigned long ppe_id; | ||
141 | |||
142 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
143 | |||
144 | lv1_get_logical_ppe_id(&ppe_id); | ||
145 | lv1_configure_irq_state_bitmap(ppe_id, 0, 0); | ||
146 | ps3_mm_shutdown(); | ||
147 | ps3_mm_vas_destroy(); | ||
148 | |||
149 | default_machine_kexec(image); | ||
150 | |||
151 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
152 | } | ||
153 | #endif | ||
154 | |||
155 | define_machine(ps3) { | ||
156 | .name = "PS3", | ||
157 | .probe = ps3_probe, | ||
158 | .setup_arch = ps3_setup_arch, | ||
159 | .show_cpuinfo = ps3_show_cpuinfo, | ||
160 | .init_IRQ = ps3_init_IRQ, | ||
161 | .panic = ps3_panic, | ||
162 | .get_boot_time = ps3_get_boot_time, | ||
163 | .set_rtc_time = ps3_set_rtc_time, | ||
164 | .get_rtc_time = ps3_get_rtc_time, | ||
165 | .calibrate_decr = ps3_calibrate_decr, | ||
166 | .progress = ps3_progress, | ||
167 | #if defined(CONFIG_KEXEC) | ||
168 | .kexec_cpu_down = ps3_kexec_cpu_down, | ||
169 | .machine_kexec = ps3_machine_kexec, | ||
170 | .machine_kexec_prepare = default_machine_kexec_prepare, | ||
171 | .machine_crash_shutdown = default_machine_crash_shutdown, | ||
172 | #endif | ||
173 | }; | ||
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c new file mode 100644 index 00000000000..11d2080607e --- /dev/null +++ b/arch/powerpc/platforms/ps3/smp.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * PS3 SMP routines. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/smp.h> | ||
23 | |||
24 | #include <asm/machdep.h> | ||
25 | #include <asm/udbg.h> | ||
26 | #include <asm/ps3.h> | ||
27 | |||
28 | #include "platform.h" | ||
29 | |||
30 | #if defined(DEBUG) | ||
31 | #define DBG(fmt...) udbg_printf(fmt) | ||
32 | #else | ||
33 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | ||
34 | #endif | ||
35 | |||
36 | static irqreturn_t ipi_function_handler(int irq, void *msg) | ||
37 | { | ||
38 | smp_message_recv((int)(long)msg); | ||
39 | return IRQ_HANDLED; | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * virqs - a per cpu array of virqs for ipi use | ||
44 | */ | ||
45 | |||
46 | #define MSG_COUNT 4 | ||
47 | static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]); | ||
48 | |||
49 | static const char *names[MSG_COUNT] = { | ||
50 | "ipi call", | ||
51 | "ipi reschedule", | ||
52 | "ipi migrate", | ||
53 | "ipi debug brk" | ||
54 | }; | ||
55 | |||
56 | static void do_message_pass(int target, int msg) | ||
57 | { | ||
58 | int result; | ||
59 | unsigned int virq; | ||
60 | |||
61 | if (msg >= MSG_COUNT) { | ||
62 | DBG("%s:%d: bad msg: %d\n", __func__, __LINE__, msg); | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | virq = per_cpu(virqs, target)[msg]; | ||
67 | result = ps3_send_event_locally(virq); | ||
68 | |||
69 | if (result) | ||
70 | DBG("%s:%d: ps3_send_event_locally(%d, %d) failed" | ||
71 | " (%d)\n", __func__, __LINE__, target, msg, result); | ||
72 | } | ||
73 | |||
74 | static void ps3_smp_message_pass(int target, int msg) | ||
75 | { | ||
76 | int cpu; | ||
77 | |||
78 | if (target < NR_CPUS) | ||
79 | do_message_pass(target, msg); | ||
80 | else if (target == MSG_ALL_BUT_SELF) { | ||
81 | for_each_online_cpu(cpu) | ||
82 | if (cpu != smp_processor_id()) | ||
83 | do_message_pass(cpu, msg); | ||
84 | } else { | ||
85 | for_each_online_cpu(cpu) | ||
86 | do_message_pass(cpu, msg); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static int ps3_smp_probe(void) | ||
91 | { | ||
92 | return 2; | ||
93 | } | ||
94 | |||
95 | static void __init ps3_smp_setup_cpu(int cpu) | ||
96 | { | ||
97 | int result; | ||
98 | unsigned int *virqs = per_cpu(virqs, cpu); | ||
99 | int i; | ||
100 | |||
101 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); | ||
102 | |||
103 | /* | ||
104 | * Check assumptions on virqs[] indexing. If this | ||
105 | * check fails, then a different mapping of PPC_MSG_ | ||
106 | * to index needs to be setup. | ||
107 | */ | ||
108 | |||
109 | BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0); | ||
110 | BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1); | ||
111 | BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3); | ||
112 | |||
113 | for (i = 0; i < MSG_COUNT; i++) { | ||
114 | result = ps3_alloc_event_irq(&virqs[i]); | ||
115 | |||
116 | if (result) | ||
117 | continue; | ||
118 | |||
119 | DBG("%s:%d: (%d, %d) => virq %u\n", | ||
120 | __func__, __LINE__, cpu, i, virqs[i]); | ||
121 | |||
122 | |||
123 | request_irq(virqs[i], ipi_function_handler, IRQF_DISABLED, | ||
124 | names[i], (void*)(long)i); | ||
125 | } | ||
126 | |||
127 | ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]); | ||
128 | |||
129 | DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); | ||
130 | } | ||
131 | |||
132 | void ps3_smp_cleanup_cpu(int cpu) | ||
133 | { | ||
134 | unsigned int *virqs = per_cpu(virqs, cpu); | ||
135 | int i; | ||
136 | |||
137 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); | ||
138 | for (i = 0; i < MSG_COUNT; i++) { | ||
139 | ps3_free_event_irq(virqs[i]); | ||
140 | free_irq(virqs[i], (void*)(long)i); | ||
141 | virqs[i] = NO_IRQ; | ||
142 | } | ||
143 | DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); | ||
144 | } | ||
145 | |||
146 | static struct smp_ops_t ps3_smp_ops = { | ||
147 | .probe = ps3_smp_probe, | ||
148 | .message_pass = ps3_smp_message_pass, | ||
149 | .kick_cpu = smp_generic_kick_cpu, | ||
150 | .setup_cpu = ps3_smp_setup_cpu, | ||
151 | }; | ||
152 | |||
153 | void smp_init_ps3(void) | ||
154 | { | ||
155 | DBG(" -> %s\n", __func__); | ||
156 | smp_ops = &ps3_smp_ops; | ||
157 | DBG(" <- %s\n", __func__); | ||
158 | } | ||
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c new file mode 100644 index 00000000000..644532c3b7c --- /dev/null +++ b/arch/powerpc/platforms/ps3/spu.c | |||
@@ -0,0 +1,613 @@ | |||
1 | /* | ||
2 | * PS3 Platform spu routines. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/mmzone.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/mm.h> | ||
26 | |||
27 | #include <asm/spu.h> | ||
28 | #include <asm/spu_priv1.h> | ||
29 | #include <asm/ps3.h> | ||
30 | #include <asm/lv1call.h> | ||
31 | |||
32 | /* spu_management_ops */ | ||
33 | |||
34 | /** | ||
35 | * enum spe_type - Type of spe to create. | ||
36 | * @spe_type_logical: Standard logical spe. | ||
37 | * | ||
38 | * For use with lv1_construct_logical_spe(). The current HV does not support | ||
39 | * any types other than those listed. | ||
40 | */ | ||
41 | |||
42 | enum spe_type { | ||
43 | SPE_TYPE_LOGICAL = 0, | ||
44 | }; | ||
45 | |||
46 | /** | ||
47 | * struct spe_shadow - logical spe shadow register area. | ||
48 | * | ||
49 | * Read-only shadow of spe registers. | ||
50 | */ | ||
51 | |||
52 | struct spe_shadow { | ||
53 | u8 padding_0000[0x0140]; | ||
54 | u64 int_status_class0_RW; /* 0x0140 */ | ||
55 | u64 int_status_class1_RW; /* 0x0148 */ | ||
56 | u64 int_status_class2_RW; /* 0x0150 */ | ||
57 | u8 padding_0158[0x0610-0x0158]; | ||
58 | u64 mfc_dsisr_RW; /* 0x0610 */ | ||
59 | u8 padding_0618[0x0620-0x0618]; | ||
60 | u64 mfc_dar_RW; /* 0x0620 */ | ||
61 | u8 padding_0628[0x0800-0x0628]; | ||
62 | u64 mfc_dsipr_R; /* 0x0800 */ | ||
63 | u8 padding_0808[0x0810-0x0808]; | ||
64 | u64 mfc_lscrr_R; /* 0x0810 */ | ||
65 | u8 padding_0818[0x0c00-0x0818]; | ||
66 | u64 mfc_cer_R; /* 0x0c00 */ | ||
67 | u8 padding_0c08[0x0f00-0x0c08]; | ||
68 | u64 spe_execution_status; /* 0x0f00 */ | ||
69 | u8 padding_0f08[0x1000-0x0f08]; | ||
70 | } __attribute__ ((packed)); | ||
71 | |||
72 | |||
73 | /** | ||
74 | * enum spe_ex_state - Logical spe execution state. | ||
75 | * @spe_ex_state_unexecutable: Uninitialized. | ||
76 | * @spe_ex_state_executable: Enabled, not ready. | ||
77 | * @spe_ex_state_executed: Ready for use. | ||
78 | * | ||
79 | * The execution state (status) of the logical spe as reported in | ||
80 | * struct spe_shadow:spe_execution_status. | ||
81 | */ | ||
82 | |||
83 | enum spe_ex_state { | ||
84 | SPE_EX_STATE_UNEXECUTABLE = 0, | ||
85 | SPE_EX_STATE_EXECUTABLE = 2, | ||
86 | SPE_EX_STATE_EXECUTED = 3, | ||
87 | }; | ||
88 | |||
89 | /** | ||
90 | * struct priv1_cache - Cached values of priv1 registers. | ||
91 | * @masks[]: Array of cached spe interrupt masks, indexed by class. | ||
92 | * @sr1: Cached mfc_sr1 register. | ||
93 | * @tclass_id: Cached mfc_tclass_id register. | ||
94 | */ | ||
95 | |||
96 | struct priv1_cache { | ||
97 | u64 masks[3]; | ||
98 | u64 sr1; | ||
99 | u64 tclass_id; | ||
100 | }; | ||
101 | |||
102 | /** | ||
103 | * struct spu_pdata - Platform state variables. | ||
104 | * @spe_id: HV spe id returned by lv1_construct_logical_spe(). | ||
105 | * @resource_id: HV spe resource id returned by | ||
106 | * ps3_repository_read_spe_resource_id(). | ||
107 | * @priv2_addr: lpar address of spe priv2 area returned by | ||
108 | * lv1_construct_logical_spe(). | ||
109 | * @shadow_addr: lpar address of spe register shadow area returned by | ||
110 | * lv1_construct_logical_spe(). | ||
111 | * @shadow: Virtual (ioremap) address of spe register shadow area. | ||
112 | * @cache: Cached values of priv1 registers. | ||
113 | */ | ||
114 | |||
115 | struct spu_pdata { | ||
116 | u64 spe_id; | ||
117 | u64 resource_id; | ||
118 | u64 priv2_addr; | ||
119 | u64 shadow_addr; | ||
120 | struct spe_shadow __iomem *shadow; | ||
121 | struct priv1_cache cache; | ||
122 | }; | ||
123 | |||
124 | static struct spu_pdata *spu_pdata(struct spu *spu) | ||
125 | { | ||
126 | return spu->pdata; | ||
127 | } | ||
128 | |||
129 | #define dump_areas(_a, _b, _c, _d, _e) \ | ||
130 | _dump_areas(_a, _b, _c, _d, _e, __func__, __LINE__) | ||
131 | static void _dump_areas(unsigned int spe_id, unsigned long priv2, | ||
132 | unsigned long problem, unsigned long ls, unsigned long shadow, | ||
133 | const char* func, int line) | ||
134 | { | ||
135 | pr_debug("%s:%d: spe_id: %xh (%u)\n", func, line, spe_id, spe_id); | ||
136 | pr_debug("%s:%d: priv2: %lxh\n", func, line, priv2); | ||
137 | pr_debug("%s:%d: problem: %lxh\n", func, line, problem); | ||
138 | pr_debug("%s:%d: ls: %lxh\n", func, line, ls); | ||
139 | pr_debug("%s:%d: shadow: %lxh\n", func, line, shadow); | ||
140 | } | ||
141 | |||
142 | static unsigned long get_vas_id(void) | ||
143 | { | ||
144 | unsigned long id; | ||
145 | |||
146 | lv1_get_logical_ppe_id(&id); | ||
147 | lv1_get_virtual_address_space_id_of_ppe(id, &id); | ||
148 | |||
149 | return id; | ||
150 | } | ||
151 | |||
152 | static int __init construct_spu(struct spu *spu) | ||
153 | { | ||
154 | int result; | ||
155 | unsigned long unused; | ||
156 | |||
157 | result = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, | ||
158 | PAGE_SHIFT, PAGE_SHIFT, get_vas_id(), SPE_TYPE_LOGICAL, | ||
159 | &spu_pdata(spu)->priv2_addr, &spu->problem_phys, | ||
160 | &spu->local_store_phys, &unused, | ||
161 | &spu_pdata(spu)->shadow_addr, | ||
162 | &spu_pdata(spu)->spe_id); | ||
163 | |||
164 | if (result) { | ||
165 | pr_debug("%s:%d: lv1_construct_logical_spe failed: %s\n", | ||
166 | __func__, __LINE__, ps3_result(result)); | ||
167 | return result; | ||
168 | } | ||
169 | |||
170 | return result; | ||
171 | } | ||
172 | |||
173 | static int __init add_spu_pages(unsigned long start_addr, unsigned long size) | ||
174 | { | ||
175 | int result; | ||
176 | unsigned long start_pfn; | ||
177 | unsigned long nr_pages; | ||
178 | struct pglist_data *pgdata; | ||
179 | struct zone *zone; | ||
180 | |||
181 | BUG_ON(!mem_init_done); | ||
182 | |||
183 | start_pfn = start_addr >> PAGE_SHIFT; | ||
184 | nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
185 | |||
186 | pgdata = NODE_DATA(0); | ||
187 | zone = pgdata->node_zones; | ||
188 | |||
189 | result = __add_pages(zone, start_pfn, nr_pages); | ||
190 | |||
191 | if (result) | ||
192 | pr_debug("%s:%d: __add_pages failed: (%d)\n", | ||
193 | __func__, __LINE__, result); | ||
194 | |||
195 | return result; | ||
196 | } | ||
197 | |||
198 | static void spu_unmap(struct spu *spu) | ||
199 | { | ||
200 | iounmap(spu->priv2); | ||
201 | iounmap(spu->problem); | ||
202 | iounmap((__force u8 __iomem *)spu->local_store); | ||
203 | iounmap(spu_pdata(spu)->shadow); | ||
204 | } | ||
205 | |||
206 | static int __init setup_areas(struct spu *spu) | ||
207 | { | ||
208 | struct table {char* name; unsigned long addr; unsigned long size;}; | ||
209 | int result; | ||
210 | |||
211 | /* setup pages */ | ||
212 | |||
213 | result = add_spu_pages(spu->local_store_phys, LS_SIZE); | ||
214 | if (result) | ||
215 | goto fail_add; | ||
216 | |||
217 | result = add_spu_pages(spu->problem_phys, sizeof(struct spu_problem)); | ||
218 | if (result) | ||
219 | goto fail_add; | ||
220 | |||
221 | /* ioremap */ | ||
222 | |||
223 | spu_pdata(spu)->shadow = __ioremap( | ||
224 | spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow), | ||
225 | PAGE_READONLY | _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
226 | if (!spu_pdata(spu)->shadow) { | ||
227 | pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); | ||
228 | goto fail_ioremap; | ||
229 | } | ||
230 | |||
231 | spu->local_store = ioremap(spu->local_store_phys, LS_SIZE); | ||
232 | if (!spu->local_store) { | ||
233 | pr_debug("%s:%d: ioremap local_store failed\n", | ||
234 | __func__, __LINE__); | ||
235 | goto fail_ioremap; | ||
236 | } | ||
237 | |||
238 | spu->problem = ioremap(spu->problem_phys, | ||
239 | sizeof(struct spu_problem)); | ||
240 | if (!spu->problem) { | ||
241 | pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); | ||
242 | goto fail_ioremap; | ||
243 | } | ||
244 | |||
245 | spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, | ||
246 | sizeof(struct spu_priv2)); | ||
247 | if (!spu->priv2) { | ||
248 | pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); | ||
249 | goto fail_ioremap; | ||
250 | } | ||
251 | |||
252 | dump_areas(spu_pdata(spu)->spe_id, spu_pdata(spu)->priv2_addr, | ||
253 | spu->problem_phys, spu->local_store_phys, | ||
254 | spu_pdata(spu)->shadow_addr); | ||
255 | dump_areas(spu_pdata(spu)->spe_id, (unsigned long)spu->priv2, | ||
256 | (unsigned long)spu->problem, (unsigned long)spu->local_store, | ||
257 | (unsigned long)spu_pdata(spu)->shadow); | ||
258 | |||
259 | return 0; | ||
260 | |||
261 | fail_ioremap: | ||
262 | spu_unmap(spu); | ||
263 | fail_add: | ||
264 | return result; | ||
265 | } | ||
266 | |||
267 | static int __init setup_interrupts(struct spu *spu) | ||
268 | { | ||
269 | int result; | ||
270 | |||
271 | result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 0, | ||
272 | &spu->irqs[0]); | ||
273 | |||
274 | if (result) | ||
275 | goto fail_alloc_0; | ||
276 | |||
277 | result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 1, | ||
278 | &spu->irqs[1]); | ||
279 | |||
280 | if (result) | ||
281 | goto fail_alloc_1; | ||
282 | |||
283 | result = ps3_alloc_spe_irq(spu_pdata(spu)->spe_id, 2, | ||
284 | &spu->irqs[2]); | ||
285 | |||
286 | if (result) | ||
287 | goto fail_alloc_2; | ||
288 | |||
289 | return result; | ||
290 | |||
291 | fail_alloc_2: | ||
292 | ps3_free_spe_irq(spu->irqs[1]); | ||
293 | fail_alloc_1: | ||
294 | ps3_free_spe_irq(spu->irqs[0]); | ||
295 | fail_alloc_0: | ||
296 | spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; | ||
297 | return result; | ||
298 | } | ||
299 | |||
300 | static int __init enable_spu(struct spu *spu) | ||
301 | { | ||
302 | int result; | ||
303 | |||
304 | result = lv1_enable_logical_spe(spu_pdata(spu)->spe_id, | ||
305 | spu_pdata(spu)->resource_id); | ||
306 | |||
307 | if (result) { | ||
308 | pr_debug("%s:%d: lv1_enable_logical_spe failed: %s\n", | ||
309 | __func__, __LINE__, ps3_result(result)); | ||
310 | goto fail_enable; | ||
311 | } | ||
312 | |||
313 | result = setup_areas(spu); | ||
314 | |||
315 | if (result) | ||
316 | goto fail_areas; | ||
317 | |||
318 | result = setup_interrupts(spu); | ||
319 | |||
320 | if (result) | ||
321 | goto fail_interrupts; | ||
322 | |||
323 | return 0; | ||
324 | |||
325 | fail_interrupts: | ||
326 | spu_unmap(spu); | ||
327 | fail_areas: | ||
328 | lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); | ||
329 | fail_enable: | ||
330 | return result; | ||
331 | } | ||
332 | |||
333 | static int ps3_destroy_spu(struct spu *spu) | ||
334 | { | ||
335 | int result; | ||
336 | |||
337 | pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number); | ||
338 | |||
339 | result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0); | ||
340 | BUG_ON(result); | ||
341 | |||
342 | ps3_free_spe_irq(spu->irqs[2]); | ||
343 | ps3_free_spe_irq(spu->irqs[1]); | ||
344 | ps3_free_spe_irq(spu->irqs[0]); | ||
345 | |||
346 | spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = NO_IRQ; | ||
347 | |||
348 | spu_unmap(spu); | ||
349 | |||
350 | result = lv1_destruct_logical_spe(spu_pdata(spu)->spe_id); | ||
351 | BUG_ON(result); | ||
352 | |||
353 | kfree(spu->pdata); | ||
354 | spu->pdata = NULL; | ||
355 | |||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static int __init ps3_create_spu(struct spu *spu, void *data) | ||
360 | { | ||
361 | int result; | ||
362 | |||
363 | pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number); | ||
364 | |||
365 | spu->pdata = kzalloc(sizeof(struct spu_pdata), | ||
366 | GFP_KERNEL); | ||
367 | |||
368 | if (!spu->pdata) { | ||
369 | result = -ENOMEM; | ||
370 | goto fail_malloc; | ||
371 | } | ||
372 | |||
373 | spu_pdata(spu)->resource_id = (unsigned long)data; | ||
374 | |||
375 | /* Init cached reg values to HV defaults. */ | ||
376 | |||
377 | spu_pdata(spu)->cache.sr1 = 0x33; | ||
378 | |||
379 | result = construct_spu(spu); | ||
380 | |||
381 | if (result) | ||
382 | goto fail_construct; | ||
383 | |||
384 | /* For now, just go ahead and enable it. */ | ||
385 | |||
386 | result = enable_spu(spu); | ||
387 | |||
388 | if (result) | ||
389 | goto fail_enable; | ||
390 | |||
391 | /* Make sure the spu is in SPE_EX_STATE_EXECUTED. */ | ||
392 | |||
393 | /* need something better here!!! */ | ||
394 | while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status) | ||
395 | != SPE_EX_STATE_EXECUTED) | ||
396 | (void)0; | ||
397 | |||
398 | return result; | ||
399 | |||
400 | fail_enable: | ||
401 | fail_construct: | ||
402 | ps3_destroy_spu(spu); | ||
403 | fail_malloc: | ||
404 | return result; | ||
405 | } | ||
406 | |||
407 | static int __init ps3_enumerate_spus(int (*fn)(void *data)) | ||
408 | { | ||
409 | int result; | ||
410 | unsigned int num_resource_id; | ||
411 | unsigned int i; | ||
412 | |||
413 | result = ps3_repository_read_num_spu_resource_id(&num_resource_id); | ||
414 | |||
415 | pr_debug("%s:%d: num_resource_id %u\n", __func__, __LINE__, | ||
416 | num_resource_id); | ||
417 | |||
418 | /* | ||
419 | * For now, just create logical spus equal to the number | ||
420 | * of physical spus reserved for the partition. | ||
421 | */ | ||
422 | |||
423 | for (i = 0; i < num_resource_id; i++) { | ||
424 | enum ps3_spu_resource_type resource_type; | ||
425 | unsigned int resource_id; | ||
426 | |||
427 | result = ps3_repository_read_spu_resource_id(i, | ||
428 | &resource_type, &resource_id); | ||
429 | |||
430 | if (result) | ||
431 | break; | ||
432 | |||
433 | if (resource_type == PS3_SPU_RESOURCE_TYPE_EXCLUSIVE) { | ||
434 | result = fn((void*)(unsigned long)resource_id); | ||
435 | |||
436 | if (result) | ||
437 | break; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | if (result) | ||
442 | printk(KERN_WARNING "%s:%d: Error initializing spus\n", | ||
443 | __func__, __LINE__); | ||
444 | |||
445 | return result; | ||
446 | } | ||
447 | |||
448 | const struct spu_management_ops spu_management_ps3_ops = { | ||
449 | .enumerate_spus = ps3_enumerate_spus, | ||
450 | .create_spu = ps3_create_spu, | ||
451 | .destroy_spu = ps3_destroy_spu, | ||
452 | }; | ||
453 | |||
454 | /* spu_priv1_ops */ | ||
455 | |||
456 | static void int_mask_and(struct spu *spu, int class, u64 mask) | ||
457 | { | ||
458 | u64 old_mask; | ||
459 | |||
460 | /* are these serialized by caller??? */ | ||
461 | old_mask = spu_int_mask_get(spu, class); | ||
462 | spu_int_mask_set(spu, class, old_mask & mask); | ||
463 | } | ||
464 | |||
465 | static void int_mask_or(struct spu *spu, int class, u64 mask) | ||
466 | { | ||
467 | u64 old_mask; | ||
468 | |||
469 | old_mask = spu_int_mask_get(spu, class); | ||
470 | spu_int_mask_set(spu, class, old_mask | mask); | ||
471 | } | ||
472 | |||
473 | static void int_mask_set(struct spu *spu, int class, u64 mask) | ||
474 | { | ||
475 | spu_pdata(spu)->cache.masks[class] = mask; | ||
476 | lv1_set_spe_interrupt_mask(spu_pdata(spu)->spe_id, class, | ||
477 | spu_pdata(spu)->cache.masks[class]); | ||
478 | } | ||
479 | |||
480 | static u64 int_mask_get(struct spu *spu, int class) | ||
481 | { | ||
482 | return spu_pdata(spu)->cache.masks[class]; | ||
483 | } | ||
484 | |||
485 | static void int_stat_clear(struct spu *spu, int class, u64 stat) | ||
486 | { | ||
487 | /* Note that MFC_DSISR will be cleared when class1[MF] is set. */ | ||
488 | |||
489 | lv1_clear_spe_interrupt_status(spu_pdata(spu)->spe_id, class, | ||
490 | stat, 0); | ||
491 | } | ||
492 | |||
493 | static u64 int_stat_get(struct spu *spu, int class) | ||
494 | { | ||
495 | u64 stat; | ||
496 | |||
497 | lv1_get_spe_interrupt_status(spu_pdata(spu)->spe_id, class, &stat); | ||
498 | return stat; | ||
499 | } | ||
500 | |||
501 | static void cpu_affinity_set(struct spu *spu, int cpu) | ||
502 | { | ||
503 | /* No support. */ | ||
504 | } | ||
505 | |||
506 | static u64 mfc_dar_get(struct spu *spu) | ||
507 | { | ||
508 | return in_be64(&spu_pdata(spu)->shadow->mfc_dar_RW); | ||
509 | } | ||
510 | |||
511 | static void mfc_dsisr_set(struct spu *spu, u64 dsisr) | ||
512 | { | ||
513 | /* Nothing to do, cleared in int_stat_clear(). */ | ||
514 | } | ||
515 | |||
516 | static u64 mfc_dsisr_get(struct spu *spu) | ||
517 | { | ||
518 | return in_be64(&spu_pdata(spu)->shadow->mfc_dsisr_RW); | ||
519 | } | ||
520 | |||
521 | static void mfc_sdr_setup(struct spu *spu) | ||
522 | { | ||
523 | /* Nothing to do. */ | ||
524 | } | ||
525 | |||
526 | static void mfc_sr1_set(struct spu *spu, u64 sr1) | ||
527 | { | ||
528 | /* Check bits allowed by HV. */ | ||
529 | |||
530 | static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK | ||
531 | | MFC_STATE1_PROBLEM_STATE_MASK); | ||
532 | |||
533 | BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed)); | ||
534 | |||
535 | spu_pdata(spu)->cache.sr1 = sr1; | ||
536 | lv1_set_spe_privilege_state_area_1_register( | ||
537 | spu_pdata(spu)->spe_id, | ||
538 | offsetof(struct spu_priv1, mfc_sr1_RW), | ||
539 | spu_pdata(spu)->cache.sr1); | ||
540 | } | ||
541 | |||
542 | static u64 mfc_sr1_get(struct spu *spu) | ||
543 | { | ||
544 | return spu_pdata(spu)->cache.sr1; | ||
545 | } | ||
546 | |||
547 | static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) | ||
548 | { | ||
549 | spu_pdata(spu)->cache.tclass_id = tclass_id; | ||
550 | lv1_set_spe_privilege_state_area_1_register( | ||
551 | spu_pdata(spu)->spe_id, | ||
552 | offsetof(struct spu_priv1, mfc_tclass_id_RW), | ||
553 | spu_pdata(spu)->cache.tclass_id); | ||
554 | } | ||
555 | |||
556 | static u64 mfc_tclass_id_get(struct spu *spu) | ||
557 | { | ||
558 | return spu_pdata(spu)->cache.tclass_id; | ||
559 | } | ||
560 | |||
561 | static void tlb_invalidate(struct spu *spu) | ||
562 | { | ||
563 | /* Nothing to do. */ | ||
564 | } | ||
565 | |||
566 | static void resource_allocation_groupID_set(struct spu *spu, u64 id) | ||
567 | { | ||
568 | /* No support. */ | ||
569 | } | ||
570 | |||
571 | static u64 resource_allocation_groupID_get(struct spu *spu) | ||
572 | { | ||
573 | return 0; /* No support. */ | ||
574 | } | ||
575 | |||
576 | static void resource_allocation_enable_set(struct spu *spu, u64 enable) | ||
577 | { | ||
578 | /* No support. */ | ||
579 | } | ||
580 | |||
581 | static u64 resource_allocation_enable_get(struct spu *spu) | ||
582 | { | ||
583 | return 0; /* No support. */ | ||
584 | } | ||
585 | |||
586 | const struct spu_priv1_ops spu_priv1_ps3_ops = { | ||
587 | .int_mask_and = int_mask_and, | ||
588 | .int_mask_or = int_mask_or, | ||
589 | .int_mask_set = int_mask_set, | ||
590 | .int_mask_get = int_mask_get, | ||
591 | .int_stat_clear = int_stat_clear, | ||
592 | .int_stat_get = int_stat_get, | ||
593 | .cpu_affinity_set = cpu_affinity_set, | ||
594 | .mfc_dar_get = mfc_dar_get, | ||
595 | .mfc_dsisr_set = mfc_dsisr_set, | ||
596 | .mfc_dsisr_get = mfc_dsisr_get, | ||
597 | .mfc_sdr_setup = mfc_sdr_setup, | ||
598 | .mfc_sr1_set = mfc_sr1_set, | ||
599 | .mfc_sr1_get = mfc_sr1_get, | ||
600 | .mfc_tclass_id_set = mfc_tclass_id_set, | ||
601 | .mfc_tclass_id_get = mfc_tclass_id_get, | ||
602 | .tlb_invalidate = tlb_invalidate, | ||
603 | .resource_allocation_groupID_set = resource_allocation_groupID_set, | ||
604 | .resource_allocation_groupID_get = resource_allocation_groupID_get, | ||
605 | .resource_allocation_enable_set = resource_allocation_enable_set, | ||
606 | .resource_allocation_enable_get = resource_allocation_enable_get, | ||
607 | }; | ||
608 | |||
609 | void ps3_spu_set_platform(void) | ||
610 | { | ||
611 | spu_priv1_ops = &spu_priv1_ps3_ops; | ||
612 | spu_management_ops = &spu_management_ps3_ops; | ||
613 | } | ||
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c new file mode 100644 index 00000000000..1bae8b19b36 --- /dev/null +++ b/arch/powerpc/platforms/ps3/time.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * PS3 time and rtc routines. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | |||
23 | #include <asm/rtc.h> | ||
24 | #include <asm/lv1call.h> | ||
25 | #include <asm/ps3.h> | ||
26 | |||
27 | #include "platform.h" | ||
28 | |||
29 | #define dump_tm(_a) _dump_tm(_a, __func__, __LINE__) | ||
30 | static void _dump_tm(const struct rtc_time *tm, const char* func, int line) | ||
31 | { | ||
32 | pr_debug("%s:%d tm_sec %d\n", func, line, tm->tm_sec); | ||
33 | pr_debug("%s:%d tm_min %d\n", func, line, tm->tm_min); | ||
34 | pr_debug("%s:%d tm_hour %d\n", func, line, tm->tm_hour); | ||
35 | pr_debug("%s:%d tm_mday %d\n", func, line, tm->tm_mday); | ||
36 | pr_debug("%s:%d tm_mon %d\n", func, line, tm->tm_mon); | ||
37 | pr_debug("%s:%d tm_year %d\n", func, line, tm->tm_year); | ||
38 | pr_debug("%s:%d tm_wday %d\n", func, line, tm->tm_wday); | ||
39 | } | ||
40 | |||
41 | #define dump_time(_a) _dump_time(_a, __func__, __LINE__) | ||
42 | static void __attribute__ ((unused)) _dump_time(int time, const char* func, | ||
43 | int line) | ||
44 | { | ||
45 | struct rtc_time tm; | ||
46 | |||
47 | to_tm(time, &tm); | ||
48 | |||
49 | pr_debug("%s:%d time %d\n", func, line, time); | ||
50 | _dump_tm(&tm, func, line); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value. | ||
55 | */ | ||
56 | |||
57 | static s64 rtc_shift; | ||
58 | |||
59 | void __init ps3_calibrate_decr(void) | ||
60 | { | ||
61 | int result; | ||
62 | u64 tmp; | ||
63 | |||
64 | result = ps3_repository_read_be_tb_freq(0, &tmp); | ||
65 | BUG_ON(result); | ||
66 | |||
67 | ppc_tb_freq = tmp; | ||
68 | ppc_proc_freq = ppc_tb_freq * 40; | ||
69 | |||
70 | rtc_shift = ps3_os_area_rtc_diff(); | ||
71 | } | ||
72 | |||
73 | static u64 read_rtc(void) | ||
74 | { | ||
75 | int result; | ||
76 | u64 rtc_val; | ||
77 | u64 tb_val; | ||
78 | |||
79 | result = lv1_get_rtc(&rtc_val, &tb_val); | ||
80 | BUG_ON(result); | ||
81 | |||
82 | return rtc_val; | ||
83 | } | ||
84 | |||
85 | int ps3_set_rtc_time(struct rtc_time *tm) | ||
86 | { | ||
87 | u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | ||
88 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
89 | |||
90 | rtc_shift = now - read_rtc(); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | void ps3_get_rtc_time(struct rtc_time *tm) | ||
95 | { | ||
96 | to_tm(read_rtc() + rtc_shift, tm); | ||
97 | tm->tm_year -= 1900; | ||
98 | tm->tm_mon -= 1; | ||
99 | } | ||
100 | |||
101 | unsigned long __init ps3_get_boot_time(void) | ||
102 | { | ||
103 | return read_rtc() + rtc_shift; | ||
104 | } | ||
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 556c279a789..3c95392f4f4 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -309,7 +309,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; | 309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; |
310 | } | 310 | } |
311 | 311 | ||
312 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 312 | static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) |
313 | { | 313 | { |
314 | struct device_node *dn; | 314 | struct device_node *dn; |
315 | struct iommu_table *tbl; | 315 | struct iommu_table *tbl; |
@@ -318,10 +318,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
318 | struct pci_dn *pci; | 318 | struct pci_dn *pci; |
319 | int children; | 319 | int children; |
320 | 320 | ||
321 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | ||
322 | |||
323 | dn = pci_bus_to_OF_node(bus); | 321 | dn = pci_bus_to_OF_node(bus); |
324 | pci = PCI_DN(dn); | 322 | |
323 | DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name); | ||
325 | 324 | ||
326 | if (bus->self) { | 325 | if (bus->self) { |
327 | /* This is not a root bus, any setup will be done for the | 326 | /* This is not a root bus, any setup will be done for the |
@@ -329,6 +328,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
329 | */ | 328 | */ |
330 | return; | 329 | return; |
331 | } | 330 | } |
331 | pci = PCI_DN(dn); | ||
332 | 332 | ||
333 | /* Check if the ISA bus on the system is under | 333 | /* Check if the ISA bus on the system is under |
334 | * this PHB. | 334 | * this PHB. |
@@ -390,17 +390,17 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
390 | } | 390 | } |
391 | 391 | ||
392 | 392 | ||
393 | static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | 393 | static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) |
394 | { | 394 | { |
395 | struct iommu_table *tbl; | 395 | struct iommu_table *tbl; |
396 | struct device_node *dn, *pdn; | 396 | struct device_node *dn, *pdn; |
397 | struct pci_dn *ppci; | 397 | struct pci_dn *ppci; |
398 | const void *dma_window = NULL; | 398 | const void *dma_window = NULL; |
399 | 399 | ||
400 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); | ||
401 | |||
402 | dn = pci_bus_to_OF_node(bus); | 400 | dn = pci_bus_to_OF_node(bus); |
403 | 401 | ||
402 | DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name); | ||
403 | |||
404 | /* Find nearest ibm,dma-window, walking up the device tree */ | 404 | /* Find nearest ibm,dma-window, walking up the device tree */ |
405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { | 405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { |
406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); | 406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); |
@@ -409,11 +409,15 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
409 | } | 409 | } |
410 | 410 | ||
411 | if (dma_window == NULL) { | 411 | if (dma_window == NULL) { |
412 | DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name); | 412 | DBG(" no ibm,dma-window property !\n"); |
413 | return; | 413 | return; |
414 | } | 414 | } |
415 | 415 | ||
416 | ppci = PCI_DN(pdn); | 416 | ppci = PCI_DN(pdn); |
417 | |||
418 | DBG(" parent is %s, iommu_table: 0x%p\n", | ||
419 | pdn->full_name, ppci->iommu_table); | ||
420 | |||
417 | if (!ppci->iommu_table) { | 421 | if (!ppci->iommu_table) { |
418 | /* Bussubno hasn't been copied yet. | 422 | /* Bussubno hasn't been copied yet. |
419 | * Do it now because iommu_table_setparms_lpar needs it. | 423 | * Do it now because iommu_table_setparms_lpar needs it. |
@@ -427,6 +431,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
427 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); | 431 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); |
428 | 432 | ||
429 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); | 433 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); |
434 | DBG(" created table: %p\n", ppci->iommu_table); | ||
430 | } | 435 | } |
431 | 436 | ||
432 | if (pdn != dn) | 437 | if (pdn != dn) |
@@ -434,27 +439,27 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
434 | } | 439 | } |
435 | 440 | ||
436 | 441 | ||
437 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) | 442 | static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) |
438 | { | 443 | { |
439 | struct device_node *dn, *mydn; | 444 | struct device_node *dn; |
440 | struct iommu_table *tbl; | 445 | struct iommu_table *tbl; |
441 | 446 | ||
442 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); | 447 | DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev)); |
443 | 448 | ||
444 | mydn = dn = pci_device_to_OF_node(dev); | 449 | dn = dev->dev.archdata.of_node; |
445 | 450 | ||
446 | /* If we're the direct child of a root bus, then we need to allocate | 451 | /* If we're the direct child of a root bus, then we need to allocate |
447 | * an iommu table ourselves. The bus setup code should have setup | 452 | * an iommu table ourselves. The bus setup code should have setup |
448 | * the window sizes already. | 453 | * the window sizes already. |
449 | */ | 454 | */ |
450 | if (!dev->bus->self) { | 455 | if (!dev->bus->self) { |
456 | struct pci_controller *phb = PCI_DN(dn)->phb; | ||
457 | |||
451 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | 458 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); |
452 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 459 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
453 | PCI_DN(dn)->phb->node); | 460 | phb->node); |
454 | iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); | 461 | iommu_table_setparms(phb, dn, tbl); |
455 | PCI_DN(dn)->iommu_table = iommu_init_table(tbl, | 462 | dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node); |
456 | PCI_DN(dn)->phb->node); | ||
457 | |||
458 | return; | 463 | return; |
459 | } | 464 | } |
460 | 465 | ||
@@ -465,11 +470,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) | |||
465 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) | 470 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) |
466 | dn = dn->parent; | 471 | dn = dn->parent; |
467 | 472 | ||
468 | if (dn && PCI_DN(dn)) { | 473 | if (dn && PCI_DN(dn)) |
469 | PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; | 474 | dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table; |
470 | } else { | 475 | else |
471 | DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); | 476 | printk(KERN_WARNING "iommu: Device %s has no iommu table\n", |
472 | } | 477 | pci_name(dev)); |
473 | } | 478 | } |
474 | 479 | ||
475 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | 480 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) |
@@ -495,13 +500,15 @@ static struct notifier_block iommu_reconfig_nb = { | |||
495 | .notifier_call = iommu_reconfig_notifier, | 500 | .notifier_call = iommu_reconfig_notifier, |
496 | }; | 501 | }; |
497 | 502 | ||
498 | static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | 503 | static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) |
499 | { | 504 | { |
500 | struct device_node *pdn, *dn; | 505 | struct device_node *pdn, *dn; |
501 | struct iommu_table *tbl; | 506 | struct iommu_table *tbl; |
502 | const void *dma_window = NULL; | 507 | const void *dma_window = NULL; |
503 | struct pci_dn *pci; | 508 | struct pci_dn *pci; |
504 | 509 | ||
510 | DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); | ||
511 | |||
505 | /* dev setup for LPAR is a little tricky, since the device tree might | 512 | /* dev setup for LPAR is a little tricky, since the device tree might |
506 | * contain the dma-window properties per-device and not neccesarily | 513 | * contain the dma-window properties per-device and not neccesarily |
507 | * for the bus. So we need to search upwards in the tree until we | 514 | * for the bus. So we need to search upwards in the tree until we |
@@ -509,9 +516,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
509 | * already allocated. | 516 | * already allocated. |
510 | */ | 517 | */ |
511 | dn = pci_device_to_OF_node(dev); | 518 | dn = pci_device_to_OF_node(dev); |
512 | 519 | DBG(" node is %s\n", dn->full_name); | |
513 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n", | ||
514 | dev, pci_name(dev), dn->full_name); | ||
515 | 520 | ||
516 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; | 521 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; |
517 | pdn = pdn->parent) { | 522 | pdn = pdn->parent) { |
@@ -520,16 +525,17 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
520 | break; | 525 | break; |
521 | } | 526 | } |
522 | 527 | ||
528 | DBG(" parent is %s\n", pdn->full_name); | ||
529 | |||
523 | /* Check for parent == NULL so we don't try to setup the empty EADS | 530 | /* Check for parent == NULL so we don't try to setup the empty EADS |
524 | * slots on POWER4 machines. | 531 | * slots on POWER4 machines. |
525 | */ | 532 | */ |
526 | if (dma_window == NULL || pdn->parent == NULL) { | 533 | if (dma_window == NULL || pdn->parent == NULL) { |
527 | DBG("No dma window for device, linking to parent\n"); | 534 | DBG(" no dma window for device, linking to parent\n"); |
528 | PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; | 535 | dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; |
529 | return; | 536 | return; |
530 | } else { | ||
531 | DBG("Found DMA window, allocating table\n"); | ||
532 | } | 537 | } |
538 | DBG(" found DMA window, table: %p\n", pci->iommu_table); | ||
533 | 539 | ||
534 | pci = PCI_DN(pdn); | 540 | pci = PCI_DN(pdn); |
535 | if (!pci->iommu_table) { | 541 | if (!pci->iommu_table) { |
@@ -542,24 +548,20 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
542 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); | 548 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); |
543 | 549 | ||
544 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); | 550 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); |
551 | DBG(" created table: %p\n", pci->iommu_table); | ||
545 | } | 552 | } |
546 | 553 | ||
547 | if (pdn != dn) | 554 | dev->dev.archdata.dma_data = pci->iommu_table; |
548 | PCI_DN(dn)->iommu_table = pci->iommu_table; | ||
549 | } | 555 | } |
550 | 556 | ||
551 | static void iommu_bus_setup_null(struct pci_bus *b) { } | ||
552 | static void iommu_dev_setup_null(struct pci_dev *d) { } | ||
553 | |||
554 | /* These are called very early. */ | 557 | /* These are called very early. */ |
555 | void iommu_init_early_pSeries(void) | 558 | void iommu_init_early_pSeries(void) |
556 | { | 559 | { |
557 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { | 560 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { |
558 | /* Direct I/O, IOMMU off */ | 561 | /* Direct I/O, IOMMU off */ |
559 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | 562 | ppc_md.pci_dma_dev_setup = NULL; |
560 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | 563 | ppc_md.pci_dma_bus_setup = NULL; |
561 | pci_direct_iommu_init(); | 564 | pci_dma_ops = &dma_direct_ops; |
562 | |||
563 | return; | 565 | return; |
564 | } | 566 | } |
565 | 567 | ||
@@ -572,19 +574,19 @@ void iommu_init_early_pSeries(void) | |||
572 | ppc_md.tce_free = tce_free_pSeriesLP; | 574 | ppc_md.tce_free = tce_free_pSeriesLP; |
573 | } | 575 | } |
574 | ppc_md.tce_get = tce_get_pSeriesLP; | 576 | ppc_md.tce_get = tce_get_pSeriesLP; |
575 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; | 577 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP; |
576 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; | 578 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP; |
577 | } else { | 579 | } else { |
578 | ppc_md.tce_build = tce_build_pSeries; | 580 | ppc_md.tce_build = tce_build_pSeries; |
579 | ppc_md.tce_free = tce_free_pSeries; | 581 | ppc_md.tce_free = tce_free_pSeries; |
580 | ppc_md.tce_get = tce_get_pseries; | 582 | ppc_md.tce_get = tce_get_pseries; |
581 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; | 583 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries; |
582 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; | 584 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries; |
583 | } | 585 | } |
584 | 586 | ||
585 | 587 | ||
586 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); | 588 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); |
587 | 589 | ||
588 | pci_iommu_init(); | 590 | pci_dma_ops = &dma_iommu_ops; |
589 | } | 591 | } |
590 | 592 | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1820a0b0a8c..721436db3ef 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -282,7 +282,7 @@ void vpa_init(int cpu) | |||
282 | } | 282 | } |
283 | } | 283 | } |
284 | 284 | ||
285 | long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 285 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
286 | unsigned long va, unsigned long pa, | 286 | unsigned long va, unsigned long pa, |
287 | unsigned long rflags, unsigned long vflags, | 287 | unsigned long rflags, unsigned long vflags, |
288 | int psize) | 288 | int psize) |
@@ -506,7 +506,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
506 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie | 506 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie |
507 | * lock. | 507 | * lock. |
508 | */ | 508 | */ |
509 | void pSeries_lpar_flush_hash_range(unsigned long number, int local) | 509 | static void pSeries_lpar_flush_hash_range(unsigned long number, int local) |
510 | { | 510 | { |
511 | int i; | 511 | int i; |
512 | unsigned long flags = 0; | 512 | unsigned long flags = 0; |
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 410a6bcc4ca..715db5c8990 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -29,8 +29,6 @@ | |||
29 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
30 | #include <asm/ppc-pci.h> | 30 | #include <asm/ppc-pci.h> |
31 | 31 | ||
32 | static int __devinitdata s7a_workaround = -1; | ||
33 | |||
34 | #if 0 | 32 | #if 0 |
35 | void pcibios_name_device(struct pci_dev *dev) | 33 | void pcibios_name_device(struct pci_dev *dev) |
36 | { | 34 | { |
@@ -57,39 +55,6 @@ void pcibios_name_device(struct pci_dev *dev) | |||
57 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); | 55 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); |
58 | #endif | 56 | #endif |
59 | 57 | ||
60 | static void __devinit check_s7a(void) | ||
61 | { | ||
62 | struct device_node *root; | ||
63 | const char *model; | ||
64 | |||
65 | s7a_workaround = 0; | ||
66 | root = of_find_node_by_path("/"); | ||
67 | if (root) { | ||
68 | model = get_property(root, "model", NULL); | ||
69 | if (model && !strcmp(model, "IBM,7013-S7A")) | ||
70 | s7a_workaround = 1; | ||
71 | of_node_put(root); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | void __devinit pSeries_irq_bus_setup(struct pci_bus *bus) | ||
76 | { | ||
77 | struct pci_dev *dev; | ||
78 | |||
79 | if (s7a_workaround < 0) | ||
80 | check_s7a(); | ||
81 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
82 | pci_read_irq_line(dev); | ||
83 | if (s7a_workaround) { | ||
84 | if (dev->irq > 16) { | ||
85 | dev->irq -= 3; | ||
86 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, | ||
87 | dev->irq); | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static void __init pSeries_request_regions(void) | 58 | static void __init pSeries_request_regions(void) |
94 | { | 59 | { |
95 | if (!isa_io_base) | 60 | if (!isa_io_base) |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 6bfacc21708..ac56b868913 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -93,8 +93,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
93 | if (list_empty(&dev->global_list)) { | 93 | if (list_empty(&dev->global_list)) { |
94 | int i; | 94 | int i; |
95 | 95 | ||
96 | /* Need to setup IOMMU tables */ | 96 | /* Fill device archdata and setup iommu table */ |
97 | ppc_md.iommu_dev_setup(dev); | 97 | pcibios_setup_new_device(dev); |
98 | 98 | ||
99 | if(fix_bus) | 99 | if(fix_bus) |
100 | pcibios_fixup_device_resources(dev, bus); | 100 | pcibios_fixup_device_resources(dev, bus); |
@@ -195,7 +195,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
195 | phb = pcibios_alloc_controller(dn); | 195 | phb = pcibios_alloc_controller(dn); |
196 | if (!phb) | 196 | if (!phb) |
197 | return NULL; | 197 | return NULL; |
198 | setup_phb(dn, phb); | 198 | rtas_setup_phb(phb); |
199 | pci_process_bridge_OF_ranges(phb, dn, 0); | 199 | pci_process_bridge_OF_ranges(phb, dn, 0); |
200 | 200 | ||
201 | pci_setup_phb_io_dynamic(phb, primary); | 201 | pci_setup_phb_io_dynamic(phb, primary); |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 1773103354b..4ad33e41b00 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -268,11 +268,10 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length | |||
268 | static struct property *new_property(const char *name, const int length, | 268 | static struct property *new_property(const char *name, const int length, |
269 | const unsigned char *value, struct property *last) | 269 | const unsigned char *value, struct property *last) |
270 | { | 270 | { |
271 | struct property *new = kmalloc(sizeof(*new), GFP_KERNEL); | 271 | struct property *new = kzalloc(sizeof(*new), GFP_KERNEL); |
272 | 272 | ||
273 | if (!new) | 273 | if (!new) |
274 | return NULL; | 274 | return NULL; |
275 | memset(new, 0, sizeof(*new)); | ||
276 | 275 | ||
277 | if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) | 276 | if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) |
278 | goto cleanup; | 277 | goto cleanup; |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 89a8119f988..0dc2548ca9b 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -347,6 +347,7 @@ static int __init pSeries_init_panel(void) | |||
347 | } | 347 | } |
348 | arch_initcall(pSeries_init_panel); | 348 | arch_initcall(pSeries_init_panel); |
349 | 349 | ||
350 | #ifdef CONFIG_HOTPLUG_CPU | ||
350 | static void pSeries_mach_cpu_die(void) | 351 | static void pSeries_mach_cpu_die(void) |
351 | { | 352 | { |
352 | local_irq_disable(); | 353 | local_irq_disable(); |
@@ -357,6 +358,9 @@ static void pSeries_mach_cpu_die(void) | |||
357 | BUG(); | 358 | BUG(); |
358 | for(;;); | 359 | for(;;); |
359 | } | 360 | } |
361 | #else | ||
362 | #define pSeries_mach_cpu_die NULL | ||
363 | #endif | ||
360 | 364 | ||
361 | static int pseries_set_dabr(unsigned long dabr) | 365 | static int pseries_set_dabr(unsigned long dabr) |
362 | { | 366 | { |
@@ -553,7 +557,6 @@ define_machine(pseries) { | |||
553 | .log_error = pSeries_log_error, | 557 | .log_error = pSeries_log_error, |
554 | .pcibios_fixup = pSeries_final_fixup, | 558 | .pcibios_fixup = pSeries_final_fixup, |
555 | .pci_probe_mode = pSeries_pci_probe_mode, | 559 | .pci_probe_mode = pSeries_pci_probe_mode, |
556 | .irq_bus_setup = pSeries_irq_bus_setup, | ||
557 | .restart = rtas_restart, | 560 | .restart = rtas_restart, |
558 | .power_off = rtas_power_off, | 561 | .power_off = rtas_power_off, |
559 | .halt = rtas_halt, | 562 | .halt = rtas_halt, |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index d071abe78ab..b5b2b1103de 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -656,13 +656,38 @@ static void __init xics_setup_8259_cascade(void) | |||
656 | set_irq_chained_handler(cascade, pseries_8259_cascade); | 656 | set_irq_chained_handler(cascade, pseries_8259_cascade); |
657 | } | 657 | } |
658 | 658 | ||
659 | static struct device_node *cpuid_to_of_node(int cpu) | ||
660 | { | ||
661 | struct device_node *np; | ||
662 | u32 hcpuid = get_hard_smp_processor_id(cpu); | ||
663 | |||
664 | for_each_node_by_type(np, "cpu") { | ||
665 | int i, len; | ||
666 | const u32 *intserv; | ||
667 | |||
668 | intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); | ||
669 | |||
670 | if (!intserv) | ||
671 | intserv = get_property(np, "reg", &len); | ||
672 | |||
673 | i = len / sizeof(u32); | ||
674 | |||
675 | while (i--) | ||
676 | if (intserv[i] == hcpuid) | ||
677 | return np; | ||
678 | } | ||
679 | |||
680 | return NULL; | ||
681 | } | ||
682 | |||
659 | void __init xics_init_IRQ(void) | 683 | void __init xics_init_IRQ(void) |
660 | { | 684 | { |
661 | int i; | 685 | int i, j; |
662 | struct device_node *np; | 686 | struct device_node *np; |
663 | u32 ilen, indx = 0; | 687 | u32 ilen, indx = 0; |
664 | const u32 *ireg; | 688 | const u32 *ireg, *isize; |
665 | int found = 0; | 689 | int found = 0; |
690 | u32 hcpuid; | ||
666 | 691 | ||
667 | ppc64_boot_msg(0x20, "XICS Init"); | 692 | ppc64_boot_msg(0x20, "XICS Init"); |
668 | 693 | ||
@@ -683,26 +708,31 @@ void __init xics_init_IRQ(void) | |||
683 | xics_init_host(); | 708 | xics_init_host(); |
684 | 709 | ||
685 | /* Find the server numbers for the boot cpu. */ | 710 | /* Find the server numbers for the boot cpu. */ |
686 | for (np = of_find_node_by_type(NULL, "cpu"); | 711 | np = cpuid_to_of_node(boot_cpuid); |
687 | np; | 712 | BUG_ON(!np); |
688 | np = of_find_node_by_type(np, "cpu")) { | 713 | ireg = get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); |
689 | ireg = get_property(np, "reg", &ilen); | 714 | if (!ireg) |
690 | if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { | 715 | goto skip_gserver_check; |
691 | ireg = get_property(np, | 716 | i = ilen / sizeof(int); |
692 | "ibm,ppc-interrupt-gserver#s", &ilen); | 717 | hcpuid = get_hard_smp_processor_id(boot_cpuid); |
693 | i = ilen / sizeof(int); | 718 | |
694 | if (ireg && i > 0) { | 719 | /* Global interrupt distribution server is specified in the last |
695 | default_server = ireg[0]; | 720 | * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last |
696 | /* take last element */ | 721 | * entry fom this property for current boot cpu id and use it as |
697 | default_distrib_server = ireg[i-1]; | 722 | * default distribution server |
698 | } | 723 | */ |
699 | ireg = get_property(np, | 724 | for (j = 0; j < i; j += 2) { |
725 | if (ireg[j] == hcpuid) { | ||
726 | default_server = hcpuid; | ||
727 | default_distrib_server = ireg[j+1]; | ||
728 | |||
729 | isize = get_property(np, | ||
700 | "ibm,interrupt-server#-size", NULL); | 730 | "ibm,interrupt-server#-size", NULL); |
701 | if (ireg) | 731 | if (isize) |
702 | interrupt_server_size = *ireg; | 732 | interrupt_server_size = *isize; |
703 | break; | ||
704 | } | 733 | } |
705 | } | 734 | } |
735 | skip_gserver_check: | ||
706 | of_node_put(np); | 736 | of_node_put(np); |
707 | 737 | ||
708 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 738 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 91f052d8cce..6cc34597a62 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -5,14 +5,13 @@ endif | |||
5 | obj-$(CONFIG_MPIC) += mpic.o | 5 | obj-$(CONFIG_MPIC) += mpic.o |
6 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | 6 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o |
7 | obj-$(CONFIG_PPC_MPC106) += grackle.o | 7 | obj-$(CONFIG_PPC_MPC106) += grackle.o |
8 | obj-$(CONFIG_BOOKE) += dcr.o | 8 | obj-$(CONFIG_PPC_DCR) += dcr.o dcr-low.o |
9 | obj-$(CONFIG_40x) += dcr.o | ||
10 | obj-$(CONFIG_U3_DART) += dart_iommu.o | 9 | obj-$(CONFIG_U3_DART) += dart_iommu.o |
11 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 10 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
12 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o | 11 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o |
13 | obj-$(CONFIG_PPC_TODC) += todc.o | ||
14 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 12 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
15 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ | 13 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ |
14 | obj-$(CONFIG_MTD) += rom.o | ||
16 | 15 | ||
17 | ifeq ($(CONFIG_PPC_MERGE),y) | 16 | ifeq ($(CONFIG_PPC_MERGE),y) |
18 | obj-$(CONFIG_PPC_I8259) += i8259.o | 17 | obj-$(CONFIG_PPC_I8259) += i8259.o |
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 572b7846cc7..1488535b0e1 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
@@ -48,9 +48,6 @@ | |||
48 | 48 | ||
49 | #include "dart.h" | 49 | #include "dart.h" |
50 | 50 | ||
51 | extern int iommu_is_off; | ||
52 | extern int iommu_force_on; | ||
53 | |||
54 | /* Physical base address and size of the DART table */ | 51 | /* Physical base address and size of the DART table */ |
55 | unsigned long dart_tablebase; /* exported to htab_initialize */ | 52 | unsigned long dart_tablebase; /* exported to htab_initialize */ |
56 | static unsigned long dart_tablesize; | 53 | static unsigned long dart_tablesize; |
@@ -289,24 +286,15 @@ static void iommu_table_dart_setup(void) | |||
289 | set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); | 286 | set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); |
290 | } | 287 | } |
291 | 288 | ||
292 | static void iommu_dev_setup_dart(struct pci_dev *dev) | 289 | static void pci_dma_dev_setup_dart(struct pci_dev *dev) |
293 | { | 290 | { |
294 | struct device_node *dn; | ||
295 | |||
296 | /* We only have one iommu table on the mac for now, which makes | 291 | /* We only have one iommu table on the mac for now, which makes |
297 | * things simple. Setup all PCI devices to point to this table | 292 | * things simple. Setup all PCI devices to point to this table |
298 | * | ||
299 | * We must use pci_device_to_OF_node() to make sure that | ||
300 | * we get the real "final" pointer to the device in the | ||
301 | * pci_dev sysdata and not the temporary PHB one | ||
302 | */ | 293 | */ |
303 | dn = pci_device_to_OF_node(dev); | 294 | dev->dev.archdata.dma_data = &iommu_table_dart; |
304 | |||
305 | if (dn) | ||
306 | PCI_DN(dn)->iommu_table = &iommu_table_dart; | ||
307 | } | 295 | } |
308 | 296 | ||
309 | static void iommu_bus_setup_dart(struct pci_bus *bus) | 297 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) |
310 | { | 298 | { |
311 | struct device_node *dn; | 299 | struct device_node *dn; |
312 | 300 | ||
@@ -321,9 +309,6 @@ static void iommu_bus_setup_dart(struct pci_bus *bus) | |||
321 | PCI_DN(dn)->iommu_table = &iommu_table_dart; | 309 | PCI_DN(dn)->iommu_table = &iommu_table_dart; |
322 | } | 310 | } |
323 | 311 | ||
324 | static void iommu_dev_setup_null(struct pci_dev *dev) { } | ||
325 | static void iommu_bus_setup_null(struct pci_bus *bus) { } | ||
326 | |||
327 | void iommu_init_early_dart(void) | 312 | void iommu_init_early_dart(void) |
328 | { | 313 | { |
329 | struct device_node *dn; | 314 | struct device_node *dn; |
@@ -344,22 +329,21 @@ void iommu_init_early_dart(void) | |||
344 | 329 | ||
345 | /* Initialize the DART HW */ | 330 | /* Initialize the DART HW */ |
346 | if (dart_init(dn) == 0) { | 331 | if (dart_init(dn) == 0) { |
347 | ppc_md.iommu_dev_setup = iommu_dev_setup_dart; | 332 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; |
348 | ppc_md.iommu_bus_setup = iommu_bus_setup_dart; | 333 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; |
349 | 334 | ||
350 | /* Setup pci_dma ops */ | 335 | /* Setup pci_dma ops */ |
351 | pci_iommu_init(); | 336 | pci_dma_ops = &dma_iommu_ops; |
352 | |||
353 | return; | 337 | return; |
354 | } | 338 | } |
355 | 339 | ||
356 | bail: | 340 | bail: |
357 | /* If init failed, use direct iommu and null setup functions */ | 341 | /* If init failed, use direct iommu and null setup functions */ |
358 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | 342 | ppc_md.pci_dma_dev_setup = NULL; |
359 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | 343 | ppc_md.pci_dma_bus_setup = NULL; |
360 | 344 | ||
361 | /* Setup pci_dma ops */ | 345 | /* Setup pci_dma ops */ |
362 | pci_direct_iommu_init(); | 346 | pci_dma_ops = &dma_direct_ops; |
363 | } | 347 | } |
364 | 348 | ||
365 | 349 | ||
diff --git a/arch/powerpc/sysdev/dcr-low.S b/arch/powerpc/sysdev/dcr-low.S new file mode 100644 index 00000000000..2078f39e2f1 --- /dev/null +++ b/arch/powerpc/sysdev/dcr-low.S | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * "Indirect" DCR access | ||
3 | * | ||
4 | * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.net> | ||
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 | #include <asm/ppc_asm.h> | ||
13 | #include <asm/processor.h> | ||
14 | |||
15 | #define DCR_ACCESS_PROLOG(table) \ | ||
16 | rlwinm r3,r3,4,18,27; \ | ||
17 | lis r5,table@h; \ | ||
18 | ori r5,r5,table@l; \ | ||
19 | add r3,r3,r5; \ | ||
20 | mtctr r3; \ | ||
21 | bctr | ||
22 | |||
23 | _GLOBAL(__mfdcr) | ||
24 | DCR_ACCESS_PROLOG(__mfdcr_table) | ||
25 | |||
26 | _GLOBAL(__mtdcr) | ||
27 | DCR_ACCESS_PROLOG(__mtdcr_table) | ||
28 | |||
29 | __mfdcr_table: | ||
30 | mfdcr r3,0; blr | ||
31 | __mtdcr_table: | ||
32 | mtdcr 0,r4; blr | ||
33 | |||
34 | dcr = 1 | ||
35 | .rept 1023 | ||
36 | mfdcr r3,dcr; blr | ||
37 | mtdcr dcr,r4; blr | ||
38 | dcr = dcr + 1 | ||
39 | .endr | ||
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c new file mode 100644 index 00000000000..dffeeaeca1d --- /dev/null +++ b/arch/powerpc/sysdev/dcr.c | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. | ||
3 | * <benh@kernel.crashing.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
13 | * the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #undef DEBUG | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/dcr.h> | ||
25 | |||
26 | unsigned int dcr_resource_start(struct device_node *np, unsigned int index) | ||
27 | { | ||
28 | unsigned int ds; | ||
29 | const u32 *dr = get_property(np, "dcr-reg", &ds); | ||
30 | |||
31 | if (dr == NULL || ds & 1 || index >= (ds / 8)) | ||
32 | return 0; | ||
33 | |||
34 | return dr[index * 2]; | ||
35 | } | ||
36 | |||
37 | unsigned int dcr_resource_len(struct device_node *np, unsigned int index) | ||
38 | { | ||
39 | unsigned int ds; | ||
40 | const u32 *dr = get_property(np, "dcr-reg", &ds); | ||
41 | |||
42 | if (dr == NULL || ds & 1 || index >= (ds / 8)) | ||
43 | return 0; | ||
44 | |||
45 | return dr[index * 2 + 1]; | ||
46 | } | ||
47 | |||
48 | #ifndef CONFIG_PPC_DCR_NATIVE | ||
49 | |||
50 | static struct device_node * find_dcr_parent(struct device_node * node) | ||
51 | { | ||
52 | struct device_node *par, *tmp; | ||
53 | const u32 *p; | ||
54 | |||
55 | for (par = of_node_get(node); par;) { | ||
56 | if (get_property(par, "dcr-controller", NULL)) | ||
57 | break; | ||
58 | p = get_property(par, "dcr-parent", NULL); | ||
59 | tmp = par; | ||
60 | if (p == NULL) | ||
61 | par = of_get_parent(par); | ||
62 | else | ||
63 | par = of_find_node_by_phandle(*p); | ||
64 | of_node_put(tmp); | ||
65 | } | ||
66 | return par; | ||
67 | } | ||
68 | |||
69 | u64 of_translate_dcr_address(struct device_node *dev, | ||
70 | unsigned int dcr_n, | ||
71 | unsigned int *out_stride) | ||
72 | { | ||
73 | struct device_node *dp; | ||
74 | const u32 *p; | ||
75 | unsigned int stride; | ||
76 | u64 ret; | ||
77 | |||
78 | dp = find_dcr_parent(dev); | ||
79 | if (dp == NULL) | ||
80 | return OF_BAD_ADDR; | ||
81 | |||
82 | /* Stride is not properly defined yet, default to 0x10 for Axon */ | ||
83 | p = get_property(dp, "dcr-mmio-stride", NULL); | ||
84 | stride = (p == NULL) ? 0x10 : *p; | ||
85 | |||
86 | /* XXX FIXME: Which property name is to use of the 2 following ? */ | ||
87 | p = get_property(dp, "dcr-mmio-range", NULL); | ||
88 | if (p == NULL) | ||
89 | p = get_property(dp, "dcr-mmio-space", NULL); | ||
90 | if (p == NULL) | ||
91 | return OF_BAD_ADDR; | ||
92 | |||
93 | /* Maybe could do some better range checking here */ | ||
94 | ret = of_translate_address(dp, p); | ||
95 | if (ret != OF_BAD_ADDR) | ||
96 | ret += (u64)(stride) * (u64)dcr_n; | ||
97 | if (out_stride) | ||
98 | *out_stride = stride; | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | ||
103 | unsigned int dcr_c) | ||
104 | { | ||
105 | dcr_host_t ret = { .token = NULL, .stride = 0 }; | ||
106 | u64 addr; | ||
107 | |||
108 | pr_debug("dcr_map(%s, 0x%x, 0x%x)\n", | ||
109 | dev->full_name, dcr_n, dcr_c); | ||
110 | |||
111 | addr = of_translate_dcr_address(dev, dcr_n, &ret.stride); | ||
112 | pr_debug("translates to addr: 0x%lx, stride: 0x%x\n", | ||
113 | addr, ret.stride); | ||
114 | if (addr == OF_BAD_ADDR) | ||
115 | return ret; | ||
116 | pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride); | ||
117 | ret.token = ioremap(addr, dcr_c * ret.stride); | ||
118 | if (ret.token == NULL) | ||
119 | return ret; | ||
120 | pr_debug("mapped at 0x%p -> base is 0x%p\n", | ||
121 | ret.token, ret.token - dcr_n * ret.stride); | ||
122 | ret.token -= dcr_n * ret.stride; | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c) | ||
127 | { | ||
128 | dcr_host_t h = host; | ||
129 | |||
130 | if (h.token == NULL) | ||
131 | return; | ||
132 | h.token -= dcr_n * h.stride; | ||
133 | iounmap(h.token); | ||
134 | h.token = NULL; | ||
135 | } | ||
136 | |||
137 | #endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index dbe92ae2033..ad31e56e892 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/phy.h> | ||
25 | #include <linux/fsl_devices.h> | 26 | #include <linux/fsl_devices.h> |
26 | #include <linux/fs_enet_pd.h> | 27 | #include <linux/fs_enet_pd.h> |
27 | #include <linux/fs_uart_pd.h> | 28 | #include <linux/fs_uart_pd.h> |
@@ -146,7 +147,7 @@ static int __init gfar_mdio_of_init(void) | |||
146 | } | 147 | } |
147 | 148 | ||
148 | for (k = 0; k < 32; k++) | 149 | for (k = 0; k < 32; k++) |
149 | mdio_data.irq[k] = -1; | 150 | mdio_data.irq[k] = PHY_POLL; |
150 | 151 | ||
151 | while ((child = of_get_next_child(np, child)) != NULL) { | 152 | while ((child = of_get_next_child(np, child)) != NULL) { |
152 | int irq = irq_of_parse_and_map(child, 0); | 153 | int irq = irq_of_parse_and_map(child, 0); |
@@ -177,6 +178,7 @@ static const char *gfar_tx_intr = "tx"; | |||
177 | static const char *gfar_rx_intr = "rx"; | 178 | static const char *gfar_rx_intr = "rx"; |
178 | static const char *gfar_err_intr = "error"; | 179 | static const char *gfar_err_intr = "error"; |
179 | 180 | ||
181 | |||
180 | static int __init gfar_of_init(void) | 182 | static int __init gfar_of_init(void) |
181 | { | 183 | { |
182 | struct device_node *np; | 184 | struct device_node *np; |
@@ -204,8 +206,7 @@ static int __init gfar_of_init(void) | |||
204 | if (ret) | 206 | if (ret) |
205 | goto err; | 207 | goto err; |
206 | 208 | ||
207 | r[1].start = r[1].end = irq_of_parse_and_map(np, 0); | 209 | of_irq_to_resource(np, 0, &r[1]); |
208 | r[1].flags = IORESOURCE_IRQ; | ||
209 | 210 | ||
210 | model = get_property(np, "model", NULL); | 211 | model = get_property(np, "model", NULL); |
211 | 212 | ||
@@ -214,12 +215,10 @@ static int __init gfar_of_init(void) | |||
214 | r[1].name = gfar_tx_intr; | 215 | r[1].name = gfar_tx_intr; |
215 | 216 | ||
216 | r[2].name = gfar_rx_intr; | 217 | r[2].name = gfar_rx_intr; |
217 | r[2].start = r[2].end = irq_of_parse_and_map(np, 1); | 218 | of_irq_to_resource(np, 1, &r[2]); |
218 | r[2].flags = IORESOURCE_IRQ; | ||
219 | 219 | ||
220 | r[3].name = gfar_err_intr; | 220 | r[3].name = gfar_err_intr; |
221 | r[3].start = r[3].end = irq_of_parse_and_map(np, 2); | 221 | of_irq_to_resource(np, 2, &r[3]); |
222 | r[3].flags = IORESOURCE_IRQ; | ||
223 | 222 | ||
224 | n_res += 2; | 223 | n_res += 2; |
225 | } | 224 | } |
@@ -323,8 +322,7 @@ static int __init fsl_i2c_of_init(void) | |||
323 | if (ret) | 322 | if (ret) |
324 | goto err; | 323 | goto err; |
325 | 324 | ||
326 | r[1].start = r[1].end = irq_of_parse_and_map(np, 0); | 325 | of_irq_to_resource(np, 0, &r[1]); |
327 | r[1].flags = IORESOURCE_IRQ; | ||
328 | 326 | ||
329 | i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); | 327 | i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); |
330 | if (IS_ERR(i2c_dev)) { | 328 | if (IS_ERR(i2c_dev)) { |
@@ -459,8 +457,7 @@ static int __init fsl_usb_of_init(void) | |||
459 | if (ret) | 457 | if (ret) |
460 | goto err; | 458 | goto err; |
461 | 459 | ||
462 | r[1].start = r[1].end = irq_of_parse_and_map(np, 0); | 460 | of_irq_to_resource(np, 0, &r[1]); |
463 | r[1].flags = IORESOURCE_IRQ; | ||
464 | 461 | ||
465 | usb_dev_mph = | 462 | usb_dev_mph = |
466 | platform_device_register_simple("fsl-ehci", i, r, 2); | 463 | platform_device_register_simple("fsl-ehci", i, r, 2); |
@@ -507,8 +504,7 @@ static int __init fsl_usb_of_init(void) | |||
507 | if (ret) | 504 | if (ret) |
508 | goto unreg_mph; | 505 | goto unreg_mph; |
509 | 506 | ||
510 | r[1].start = r[1].end = irq_of_parse_and_map(np, 0); | 507 | of_irq_to_resource(np, 0, &r[1]); |
511 | r[1].flags = IORESOURCE_IRQ; | ||
512 | 508 | ||
513 | usb_dev_dr = | 509 | usb_dev_dr = |
514 | platform_device_register_simple("fsl-ehci", i, r, 2); | 510 | platform_device_register_simple("fsl-ehci", i, r, 2); |
@@ -591,8 +587,7 @@ static int __init fs_enet_of_init(void) | |||
591 | r[2].name = fcc_regs_c; | 587 | r[2].name = fcc_regs_c; |
592 | fs_enet_data.fcc_regs_c = r[2].start; | 588 | fs_enet_data.fcc_regs_c = r[2].start; |
593 | 589 | ||
594 | r[3].start = r[3].end = irq_of_parse_and_map(np, 0); | 590 | of_irq_to_resource(np, 0, &r[3]); |
595 | r[3].flags = IORESOURCE_IRQ; | ||
596 | 591 | ||
597 | fs_enet_dev = | 592 | fs_enet_dev = |
598 | platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4); | 593 | platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4); |
@@ -754,8 +749,7 @@ static int __init cpm_uart_of_init(void) | |||
754 | goto err; | 749 | goto err; |
755 | r[1].name = scc_pram; | 750 | r[1].name = scc_pram; |
756 | 751 | ||
757 | r[2].start = r[2].end = irq_of_parse_and_map(np, 0); | 752 | of_irq_to_resource(np, 0, &r[2]); |
758 | r[2].flags = IORESOURCE_IRQ; | ||
759 | 753 | ||
760 | cpm_uart_dev = | 754 | cpm_uart_dev = |
761 | platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3); | 755 | platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3); |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index ba4833f57d4..411480d5c62 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -147,33 +147,51 @@ static u32 mpic_infos[][MPIC_IDX_END] = { | |||
147 | */ | 147 | */ |
148 | 148 | ||
149 | 149 | ||
150 | static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base, | 150 | static inline u32 _mpic_read(enum mpic_reg_type type, |
151 | unsigned int reg) | 151 | struct mpic_reg_bank *rb, |
152 | unsigned int reg) | ||
152 | { | 153 | { |
153 | if (be) | 154 | switch(type) { |
154 | return in_be32(base + (reg >> 2)); | 155 | #ifdef CONFIG_PPC_DCR |
155 | else | 156 | case mpic_access_dcr: |
156 | return in_le32(base + (reg >> 2)); | 157 | return dcr_read(rb->dhost, |
158 | rb->dbase + reg + rb->doff); | ||
159 | #endif | ||
160 | case mpic_access_mmio_be: | ||
161 | return in_be32(rb->base + (reg >> 2)); | ||
162 | case mpic_access_mmio_le: | ||
163 | default: | ||
164 | return in_le32(rb->base + (reg >> 2)); | ||
165 | } | ||
157 | } | 166 | } |
158 | 167 | ||
159 | static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, | 168 | static inline void _mpic_write(enum mpic_reg_type type, |
160 | unsigned int reg, u32 value) | 169 | struct mpic_reg_bank *rb, |
170 | unsigned int reg, u32 value) | ||
161 | { | 171 | { |
162 | if (be) | 172 | switch(type) { |
163 | out_be32(base + (reg >> 2), value); | 173 | #ifdef CONFIG_PPC_DCR |
164 | else | 174 | case mpic_access_dcr: |
165 | out_le32(base + (reg >> 2), value); | 175 | return dcr_write(rb->dhost, |
176 | rb->dbase + reg + rb->doff, value); | ||
177 | #endif | ||
178 | case mpic_access_mmio_be: | ||
179 | return out_be32(rb->base + (reg >> 2), value); | ||
180 | case mpic_access_mmio_le: | ||
181 | default: | ||
182 | return out_le32(rb->base + (reg >> 2), value); | ||
183 | } | ||
166 | } | 184 | } |
167 | 185 | ||
168 | static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) | 186 | static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) |
169 | { | 187 | { |
170 | unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; | 188 | enum mpic_reg_type type = mpic->reg_type; |
171 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + | 189 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + |
172 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); | 190 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); |
173 | 191 | ||
174 | if (mpic->flags & MPIC_BROKEN_IPI) | 192 | if ((mpic->flags & MPIC_BROKEN_IPI) && type == mpic_access_mmio_le) |
175 | be = !be; | 193 | type = mpic_access_mmio_be; |
176 | return _mpic_read(be, mpic->gregs, offset); | 194 | return _mpic_read(type, &mpic->gregs, offset); |
177 | } | 195 | } |
178 | 196 | ||
179 | static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) | 197 | static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) |
@@ -181,7 +199,7 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu | |||
181 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + | 199 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + |
182 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); | 200 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); |
183 | 201 | ||
184 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); | 202 | _mpic_write(mpic->reg_type, &mpic->gregs, offset, value); |
185 | } | 203 | } |
186 | 204 | ||
187 | static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) | 205 | static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) |
@@ -190,8 +208,7 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) | |||
190 | 208 | ||
191 | if (mpic->flags & MPIC_PRIMARY) | 209 | if (mpic->flags & MPIC_PRIMARY) |
192 | cpu = hard_smp_processor_id(); | 210 | cpu = hard_smp_processor_id(); |
193 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, | 211 | return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg); |
194 | mpic->cpuregs[cpu], reg); | ||
195 | } | 212 | } |
196 | 213 | ||
197 | static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) | 214 | static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) |
@@ -201,7 +218,7 @@ static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 valu | |||
201 | if (mpic->flags & MPIC_PRIMARY) | 218 | if (mpic->flags & MPIC_PRIMARY) |
202 | cpu = hard_smp_processor_id(); | 219 | cpu = hard_smp_processor_id(); |
203 | 220 | ||
204 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value); | 221 | _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value); |
205 | } | 222 | } |
206 | 223 | ||
207 | static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) | 224 | static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg) |
@@ -209,7 +226,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne | |||
209 | unsigned int isu = src_no >> mpic->isu_shift; | 226 | unsigned int isu = src_no >> mpic->isu_shift; |
210 | unsigned int idx = src_no & mpic->isu_mask; | 227 | unsigned int idx = src_no & mpic->isu_mask; |
211 | 228 | ||
212 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], | 229 | return _mpic_read(mpic->reg_type, &mpic->isus[isu], |
213 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); | 230 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); |
214 | } | 231 | } |
215 | 232 | ||
@@ -219,12 +236,12 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
219 | unsigned int isu = src_no >> mpic->isu_shift; | 236 | unsigned int isu = src_no >> mpic->isu_shift; |
220 | unsigned int idx = src_no & mpic->isu_mask; | 237 | unsigned int idx = src_no & mpic->isu_mask; |
221 | 238 | ||
222 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], | 239 | _mpic_write(mpic->reg_type, &mpic->isus[isu], |
223 | reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); | 240 | reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); |
224 | } | 241 | } |
225 | 242 | ||
226 | #define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) | 243 | #define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r)) |
227 | #define mpic_write(b,r,v) _mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v)) | 244 | #define mpic_write(b,r,v) _mpic_write(mpic->reg_type,&(b),(r),(v)) |
228 | #define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) | 245 | #define mpic_ipi_read(i) _mpic_ipi_read(mpic,(i)) |
229 | #define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) | 246 | #define mpic_ipi_write(i,v) _mpic_ipi_write(mpic,(i),(v)) |
230 | #define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) | 247 | #define mpic_cpu_read(i) _mpic_cpu_read(mpic,(i)) |
@@ -238,6 +255,38 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
238 | */ | 255 | */ |
239 | 256 | ||
240 | 257 | ||
258 | static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr, | ||
259 | struct mpic_reg_bank *rb, unsigned int offset, | ||
260 | unsigned int size) | ||
261 | { | ||
262 | rb->base = ioremap(phys_addr + offset, size); | ||
263 | BUG_ON(rb->base == NULL); | ||
264 | } | ||
265 | |||
266 | #ifdef CONFIG_PPC_DCR | ||
267 | static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, | ||
268 | unsigned int offset, unsigned int size) | ||
269 | { | ||
270 | rb->dbase = mpic->dcr_base; | ||
271 | rb->doff = offset; | ||
272 | rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size); | ||
273 | BUG_ON(!DCR_MAP_OK(rb->dhost)); | ||
274 | } | ||
275 | |||
276 | static inline void mpic_map(struct mpic *mpic, unsigned long phys_addr, | ||
277 | struct mpic_reg_bank *rb, unsigned int offset, | ||
278 | unsigned int size) | ||
279 | { | ||
280 | if (mpic->flags & MPIC_USES_DCR) | ||
281 | _mpic_map_dcr(mpic, rb, offset, size); | ||
282 | else | ||
283 | _mpic_map_mmio(mpic, phys_addr, rb, offset, size); | ||
284 | } | ||
285 | #else /* CONFIG_PPC_DCR */ | ||
286 | #define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) | ||
287 | #endif /* !CONFIG_PPC_DCR */ | ||
288 | |||
289 | |||
241 | 290 | ||
242 | /* Check if we have one of those nice broken MPICs with a flipped endian on | 291 | /* Check if we have one of those nice broken MPICs with a flipped endian on |
243 | * reads from IPI registers | 292 | * reads from IPI registers |
@@ -845,7 +894,7 @@ static struct irq_host_ops mpic_host_ops = { | |||
845 | */ | 894 | */ |
846 | 895 | ||
847 | struct mpic * __init mpic_alloc(struct device_node *node, | 896 | struct mpic * __init mpic_alloc(struct device_node *node, |
848 | unsigned long phys_addr, | 897 | phys_addr_t phys_addr, |
849 | unsigned int flags, | 898 | unsigned int flags, |
850 | unsigned int isu_size, | 899 | unsigned int isu_size, |
851 | unsigned int irq_count, | 900 | unsigned int irq_count, |
@@ -855,6 +904,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
855 | u32 reg; | 904 | u32 reg; |
856 | const char *vers; | 905 | const char *vers; |
857 | int i; | 906 | int i; |
907 | u64 paddr = phys_addr; | ||
858 | 908 | ||
859 | mpic = alloc_bootmem(sizeof(struct mpic)); | 909 | mpic = alloc_bootmem(sizeof(struct mpic)); |
860 | if (mpic == NULL) | 910 | if (mpic == NULL) |
@@ -883,6 +933,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
883 | if (flags & MPIC_PRIMARY) | 933 | if (flags & MPIC_PRIMARY) |
884 | mpic->hc_ht_irq.set_affinity = mpic_set_affinity; | 934 | mpic->hc_ht_irq.set_affinity = mpic_set_affinity; |
885 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | 935 | #endif /* CONFIG_MPIC_BROKEN_U3 */ |
936 | |||
886 | #ifdef CONFIG_SMP | 937 | #ifdef CONFIG_SMP |
887 | mpic->hc_ipi = mpic_ipi_chip; | 938 | mpic->hc_ipi = mpic_ipi_chip; |
888 | mpic->hc_ipi.typename = name; | 939 | mpic->hc_ipi.typename = name; |
@@ -893,15 +944,52 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
893 | mpic->irq_count = irq_count; | 944 | mpic->irq_count = irq_count; |
894 | mpic->num_sources = 0; /* so far */ | 945 | mpic->num_sources = 0; /* so far */ |
895 | 946 | ||
947 | /* Check for "big-endian" in device-tree */ | ||
948 | if (node && get_property(node, "big-endian", NULL) != NULL) | ||
949 | mpic->flags |= MPIC_BIG_ENDIAN; | ||
950 | |||
951 | |||
896 | #ifdef CONFIG_MPIC_WEIRD | 952 | #ifdef CONFIG_MPIC_WEIRD |
897 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; | 953 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; |
898 | #endif | 954 | #endif |
899 | 955 | ||
956 | /* default register type */ | ||
957 | mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ? | ||
958 | mpic_access_mmio_be : mpic_access_mmio_le; | ||
959 | |||
960 | /* If no physical address is passed in, a device-node is mandatory */ | ||
961 | BUG_ON(paddr == 0 && node == NULL); | ||
962 | |||
963 | /* If no physical address passed in, check if it's dcr based */ | ||
964 | if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL) | ||
965 | mpic->flags |= MPIC_USES_DCR; | ||
966 | |||
967 | #ifdef CONFIG_PPC_DCR | ||
968 | if (mpic->flags & MPIC_USES_DCR) { | ||
969 | const u32 *dbasep; | ||
970 | dbasep = get_property(node, "dcr-reg", NULL); | ||
971 | BUG_ON(dbasep == NULL); | ||
972 | mpic->dcr_base = *dbasep; | ||
973 | mpic->reg_type = mpic_access_dcr; | ||
974 | } | ||
975 | #else | ||
976 | BUG_ON (mpic->flags & MPIC_USES_DCR); | ||
977 | #endif /* CONFIG_PPC_DCR */ | ||
978 | |||
979 | /* If the MPIC is not DCR based, and no physical address was passed | ||
980 | * in, try to obtain one | ||
981 | */ | ||
982 | if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) { | ||
983 | const u32 *reg; | ||
984 | reg = get_property(node, "reg", NULL); | ||
985 | BUG_ON(reg == NULL); | ||
986 | paddr = of_translate_address(node, reg); | ||
987 | BUG_ON(paddr == OF_BAD_ADDR); | ||
988 | } | ||
989 | |||
900 | /* Map the global registers */ | 990 | /* Map the global registers */ |
901 | mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); | 991 | mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); |
902 | mpic->tmregs = mpic->gregs + | 992 | mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); |
903 | ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2); | ||
904 | BUG_ON(mpic->gregs == NULL); | ||
905 | 993 | ||
906 | /* Reset */ | 994 | /* Reset */ |
907 | if (flags & MPIC_WANTS_RESET) { | 995 | if (flags & MPIC_WANTS_RESET) { |
@@ -926,17 +1014,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
926 | 1014 | ||
927 | /* Map the per-CPU registers */ | 1015 | /* Map the per-CPU registers */ |
928 | for (i = 0; i < mpic->num_cpus; i++) { | 1016 | for (i = 0; i < mpic->num_cpus; i++) { |
929 | mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + | 1017 | mpic_map(mpic, paddr, &mpic->cpuregs[i], |
930 | i * MPIC_INFO(CPU_STRIDE), 0x1000); | 1018 | MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), |
931 | BUG_ON(mpic->cpuregs[i] == NULL); | 1019 | 0x1000); |
932 | } | 1020 | } |
933 | 1021 | ||
934 | /* Initialize main ISU if none provided */ | 1022 | /* Initialize main ISU if none provided */ |
935 | if (mpic->isu_size == 0) { | 1023 | if (mpic->isu_size == 0) { |
936 | mpic->isu_size = mpic->num_sources; | 1024 | mpic->isu_size = mpic->num_sources; |
937 | mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), | 1025 | mpic_map(mpic, paddr, &mpic->isus[0], |
938 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1026 | MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
939 | BUG_ON(mpic->isus[0] == NULL); | ||
940 | } | 1027 | } |
941 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); | 1028 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); |
942 | mpic->isu_mask = (1 << mpic->isu_shift) - 1; | 1029 | mpic->isu_mask = (1 << mpic->isu_shift) - 1; |
@@ -956,10 +1043,11 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
956 | vers = "<unknown>"; | 1043 | vers = "<unknown>"; |
957 | break; | 1044 | break; |
958 | } | 1045 | } |
959 | printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n", | 1046 | printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx," |
960 | name, vers, phys_addr, mpic->num_cpus); | 1047 | " max %d CPUs\n", |
961 | printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size, | 1048 | name, vers, (unsigned long long)paddr, mpic->num_cpus); |
962 | mpic->isu_shift, mpic->isu_mask); | 1049 | printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", |
1050 | mpic->isu_size, mpic->isu_shift, mpic->isu_mask); | ||
963 | 1051 | ||
964 | mpic->next = mpics; | 1052 | mpic->next = mpics; |
965 | mpics = mpic; | 1053 | mpics = mpic; |
@@ -973,14 +1061,14 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
973 | } | 1061 | } |
974 | 1062 | ||
975 | void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | 1063 | void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, |
976 | unsigned long phys_addr) | 1064 | phys_addr_t paddr) |
977 | { | 1065 | { |
978 | unsigned int isu_first = isu_num * mpic->isu_size; | 1066 | unsigned int isu_first = isu_num * mpic->isu_size; |
979 | 1067 | ||
980 | BUG_ON(isu_num >= MPIC_MAX_ISU); | 1068 | BUG_ON(isu_num >= MPIC_MAX_ISU); |
981 | 1069 | ||
982 | mpic->isus[isu_num] = ioremap(phys_addr, | 1070 | mpic_map(mpic, paddr, &mpic->isus[isu_num], 0, |
983 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1071 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
984 | if ((isu_first + mpic->isu_size) > mpic->num_sources) | 1072 | if ((isu_first + mpic->isu_size) > mpic->num_sources) |
985 | mpic->num_sources = isu_first + mpic->isu_size; | 1073 | mpic->num_sources = isu_first + mpic->isu_size; |
986 | } | 1074 | } |
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index e4223226a7a..e3d71e083f3 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c | |||
@@ -174,8 +174,7 @@ void qe_setbrg(u32 brg, u32 rate) | |||
174 | u32 divisor, tempval; | 174 | u32 divisor, tempval; |
175 | int div16 = 0; | 175 | int div16 = 0; |
176 | 176 | ||
177 | bp = &qe_immr->brg.brgc1; | 177 | bp = &qe_immr->brg.brgc[brg]; |
178 | bp += brg; | ||
179 | 178 | ||
180 | divisor = (get_brg_clk() / rate); | 179 | divisor = (get_brg_clk() / rate); |
181 | if (divisor > QE_BRGC_DIVISOR_MAX + 1) { | 180 | if (divisor > QE_BRGC_DIVISOR_MAX + 1) { |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c index 75fa3104a43..e657559bea9 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c | |||
@@ -216,14 +216,12 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc | |||
216 | return -EINVAL; | 216 | return -EINVAL; |
217 | } | 217 | } |
218 | 218 | ||
219 | uccf = (struct ucc_fast_private *) | 219 | uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL); |
220 | kmalloc(sizeof(struct ucc_fast_private), GFP_KERNEL); | ||
221 | if (!uccf) { | 220 | if (!uccf) { |
222 | uccf_err | 221 | uccf_err |
223 | ("ucc_fast_init: No memory for UCC slow data structure!"); | 222 | ("ucc_fast_init: No memory for UCC slow data structure!"); |
224 | return -ENOMEM; | 223 | return -ENOMEM; |
225 | } | 224 | } |
226 | memset(uccf, 0, sizeof(struct ucc_fast_private)); | ||
227 | 225 | ||
228 | /* Fill fast UCC structure */ | 226 | /* Fill fast UCC structure */ |
229 | uccf->uf_info = uf_info; | 227 | uccf->uf_info = uf_info; |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c index a49da6b73ec..47b56203f47 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c | |||
@@ -168,14 +168,12 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc | |||
168 | return -EINVAL; | 168 | return -EINVAL; |
169 | } | 169 | } |
170 | 170 | ||
171 | uccs = (struct ucc_slow_private *) | 171 | uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL); |
172 | kmalloc(sizeof(struct ucc_slow_private), GFP_KERNEL); | ||
173 | if (!uccs) { | 172 | if (!uccs) { |
174 | uccs_err | 173 | uccs_err |
175 | ("ucc_slow_init: No memory for UCC slow data structure!"); | 174 | ("ucc_slow_init: No memory for UCC slow data structure!"); |
176 | return -ENOMEM; | 175 | return -ENOMEM; |
177 | } | 176 | } |
178 | memset(uccs, 0, sizeof(struct ucc_slow_private)); | ||
179 | 177 | ||
180 | /* Fill slow UCC structure */ | 178 | /* Fill slow UCC structure */ |
181 | uccs->us_info = us_info; | 179 | uccs->us_info = us_info; |
diff --git a/arch/powerpc/sysdev/rom.c b/arch/powerpc/sysdev/rom.c new file mode 100644 index 00000000000..bf5b3f10e6c --- /dev/null +++ b/arch/powerpc/sysdev/rom.c | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * ROM device registration | ||
3 | * | ||
4 | * (C) 2006 MontaVista Software, Inc. This file is licensed under | ||
5 | * the terms of the GNU General Public License version 2. This program | ||
6 | * is licensed "as is" without any warranty of any kind, whether express | ||
7 | * or implied. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <asm/of_device.h> | ||
12 | |||
13 | static int __init powerpc_flash_init(void) | ||
14 | { | ||
15 | struct device_node *node = NULL; | ||
16 | |||
17 | /* | ||
18 | * Register all the devices which type is "rom" | ||
19 | */ | ||
20 | while ((node = of_find_node_by_type(node, "rom")) != NULL) { | ||
21 | if (node->name == NULL) { | ||
22 | printk(KERN_WARNING "powerpc_flash_init: found 'rom' " | ||
23 | "device, but with no name, skipping...\n"); | ||
24 | continue; | ||
25 | } | ||
26 | of_platform_device_create(node, node->name, NULL); | ||
27 | } | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | arch_initcall(powerpc_flash_init); | ||
diff --git a/arch/powerpc/sysdev/todc.c b/arch/powerpc/sysdev/todc.c deleted file mode 100644 index 0a65980efb5..00000000000 --- a/arch/powerpc/sysdev/todc.c +++ /dev/null | |||
@@ -1,392 +0,0 @@ | |||
1 | /* | ||
2 | * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818 | ||
3 | * Real Time Clocks/Timekeepers. | ||
4 | * | ||
5 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
6 | * | ||
7 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
8 | * the terms of the GNU General Public License version 2. This program | ||
9 | * is licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | */ | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/time.h> | ||
16 | #include <linux/timex.h> | ||
17 | #include <linux/bcd.h> | ||
18 | #include <linux/mc146818rtc.h> | ||
19 | |||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/io.h> | ||
22 | #include <asm/time.h> | ||
23 | #include <asm/todc.h> | ||
24 | |||
25 | /* | ||
26 | * Depending on the hardware on your board and your board design, the | ||
27 | * RTC/NVRAM may be accessed either directly (like normal memory) or via | ||
28 | * address/data registers. If your board uses the direct method, set | ||
29 | * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and | ||
30 | * 'nvram_as1' NULL. If your board uses address/data regs to access nvram, | ||
31 | * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the | ||
32 | * address of the upper byte (leave NULL if using mc146818), and set | ||
33 | * 'nvram_data' to the address of the 8-bit data register. | ||
34 | * | ||
35 | * Note: Even though the documentation for the various RTC chips say that it | ||
36 | * take up to a second before it starts updating once the 'R' bit is | ||
37 | * cleared, they always seem to update even though we bang on it many | ||
38 | * times a second. This is true, except for the Dallas Semi 1746/1747 | ||
39 | * (possibly others). Those chips seem to have a real problem whenever | ||
40 | * we set the 'R' bit before reading them, they basically stop counting. | ||
41 | * --MAG | ||
42 | */ | ||
43 | |||
44 | /* | ||
45 | * 'todc_info' should be initialized in your *_setup.c file to | ||
46 | * point to a fully initialized 'todc_info_t' structure. | ||
47 | * This structure holds all the register offsets for your particular | ||
48 | * TODC/RTC chip. | ||
49 | * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you. | ||
50 | */ | ||
51 | |||
52 | #ifdef RTC_FREQ_SELECT | ||
53 | #undef RTC_FREQ_SELECT | ||
54 | #define RTC_FREQ_SELECT control_b /* Register A */ | ||
55 | #endif | ||
56 | |||
57 | #ifdef RTC_CONTROL | ||
58 | #undef RTC_CONTROL | ||
59 | #define RTC_CONTROL control_a /* Register B */ | ||
60 | #endif | ||
61 | |||
62 | #ifdef RTC_INTR_FLAGS | ||
63 | #undef RTC_INTR_FLAGS | ||
64 | #define RTC_INTR_FLAGS watchdog /* Register C */ | ||
65 | #endif | ||
66 | |||
67 | #ifdef RTC_VALID | ||
68 | #undef RTC_VALID | ||
69 | #define RTC_VALID interrupts /* Register D */ | ||
70 | #endif | ||
71 | |||
72 | /* Access routines when RTC accessed directly (like normal memory) */ | ||
73 | u_char | ||
74 | todc_direct_read_val(int addr) | ||
75 | { | ||
76 | return readb((void __iomem *)(todc_info->nvram_data + addr)); | ||
77 | } | ||
78 | |||
79 | void | ||
80 | todc_direct_write_val(int addr, unsigned char val) | ||
81 | { | ||
82 | writeb(val, (void __iomem *)(todc_info->nvram_data + addr)); | ||
83 | return; | ||
84 | } | ||
85 | |||
86 | /* Access routines for accessing m48txx type chips via addr/data regs */ | ||
87 | u_char | ||
88 | todc_m48txx_read_val(int addr) | ||
89 | { | ||
90 | outb(addr, todc_info->nvram_as0); | ||
91 | outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); | ||
92 | return inb(todc_info->nvram_data); | ||
93 | } | ||
94 | |||
95 | void | ||
96 | todc_m48txx_write_val(int addr, unsigned char val) | ||
97 | { | ||
98 | outb(addr, todc_info->nvram_as0); | ||
99 | outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); | ||
100 | outb(val, todc_info->nvram_data); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | /* Access routines for accessing mc146818 type chips via addr/data regs */ | ||
105 | u_char | ||
106 | todc_mc146818_read_val(int addr) | ||
107 | { | ||
108 | outb_p(addr, todc_info->nvram_as0); | ||
109 | return inb_p(todc_info->nvram_data); | ||
110 | } | ||
111 | |||
112 | void | ||
113 | todc_mc146818_write_val(int addr, unsigned char val) | ||
114 | { | ||
115 | outb_p(addr, todc_info->nvram_as0); | ||
116 | outb_p(val, todc_info->nvram_data); | ||
117 | } | ||
118 | |||
119 | |||
120 | /* | ||
121 | * Routines to make RTC chips with NVRAM buried behind an addr/data pair | ||
122 | * have the NVRAM and clock regs appear at the same level. | ||
123 | * The NVRAM will appear to start at addr 0 and the clock regs will appear | ||
124 | * to start immediately after the NVRAM (actually, start at offset | ||
125 | * todc_info->nvram_size). | ||
126 | */ | ||
127 | static inline u_char | ||
128 | todc_read_val(int addr) | ||
129 | { | ||
130 | u_char val; | ||
131 | |||
132 | if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { | ||
133 | if (addr < todc_info->nvram_size) { /* NVRAM */ | ||
134 | ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); | ||
135 | val = ppc_md.rtc_read_val(todc_info->nvram_data_reg); | ||
136 | } else { /* Clock Reg */ | ||
137 | addr -= todc_info->nvram_size; | ||
138 | val = ppc_md.rtc_read_val(addr); | ||
139 | } | ||
140 | } else | ||
141 | val = ppc_md.rtc_read_val(addr); | ||
142 | |||
143 | return val; | ||
144 | } | ||
145 | |||
146 | static inline void | ||
147 | todc_write_val(int addr, u_char val) | ||
148 | { | ||
149 | if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { | ||
150 | if (addr < todc_info->nvram_size) { /* NVRAM */ | ||
151 | ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); | ||
152 | ppc_md.rtc_write_val(todc_info->nvram_data_reg, val); | ||
153 | } else { /* Clock Reg */ | ||
154 | addr -= todc_info->nvram_size; | ||
155 | ppc_md.rtc_write_val(addr, val); | ||
156 | } | ||
157 | } else | ||
158 | ppc_md.rtc_write_val(addr, val); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * TODC routines | ||
163 | * | ||
164 | * There is some ugly stuff in that there are assumptions for the mc146818. | ||
165 | * | ||
166 | * Assumptions: | ||
167 | * - todc_info->control_a has the offset as mc146818 Register B reg | ||
168 | * - todc_info->control_b has the offset as mc146818 Register A reg | ||
169 | * - m48txx control reg's write enable or 'W' bit is same as | ||
170 | * mc146818 Register B 'SET' bit (i.e., 0x80) | ||
171 | * | ||
172 | * These assumptions were made to make the code simpler. | ||
173 | */ | ||
174 | long __init | ||
175 | todc_time_init(void) | ||
176 | { | ||
177 | u_char cntl_b; | ||
178 | |||
179 | if (!ppc_md.rtc_read_val) | ||
180 | ppc_md.rtc_read_val = ppc_md.nvram_read_val; | ||
181 | if (!ppc_md.rtc_write_val) | ||
182 | ppc_md.rtc_write_val = ppc_md.nvram_write_val; | ||
183 | |||
184 | cntl_b = todc_read_val(todc_info->control_b); | ||
185 | |||
186 | if (todc_info->rtc_type == TODC_TYPE_MC146818) { | ||
187 | if ((cntl_b & 0x70) != 0x20) { | ||
188 | printk(KERN_INFO "TODC real-time-clock was stopped." | ||
189 | " Now starting..."); | ||
190 | cntl_b &= ~0x70; | ||
191 | cntl_b |= 0x20; | ||
192 | } | ||
193 | |||
194 | todc_write_val(todc_info->control_b, cntl_b); | ||
195 | } else if (todc_info->rtc_type == TODC_TYPE_DS17285) { | ||
196 | u_char mode; | ||
197 | |||
198 | mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A); | ||
199 | /* Make sure countdown clear is not set */ | ||
200 | mode &= ~0x40; | ||
201 | /* Enable oscillator, extended register set */ | ||
202 | mode |= 0x30; | ||
203 | todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode); | ||
204 | |||
205 | } else if (todc_info->rtc_type == TODC_TYPE_DS1501) { | ||
206 | u_char month; | ||
207 | |||
208 | todc_info->enable_read = TODC_DS1501_CNTL_B_TE; | ||
209 | todc_info->enable_write = TODC_DS1501_CNTL_B_TE; | ||
210 | |||
211 | month = todc_read_val(todc_info->month); | ||
212 | |||
213 | if ((month & 0x80) == 0x80) { | ||
214 | printk(KERN_INFO "TODC %s %s\n", | ||
215 | "real-time-clock was stopped.", | ||
216 | "Now starting..."); | ||
217 | month &= ~0x80; | ||
218 | todc_write_val(todc_info->month, month); | ||
219 | } | ||
220 | |||
221 | cntl_b &= ~TODC_DS1501_CNTL_B_TE; | ||
222 | todc_write_val(todc_info->control_b, cntl_b); | ||
223 | } else { /* must be a m48txx type */ | ||
224 | u_char cntl_a; | ||
225 | |||
226 | todc_info->enable_read = TODC_MK48TXX_CNTL_A_R; | ||
227 | todc_info->enable_write = TODC_MK48TXX_CNTL_A_W; | ||
228 | |||
229 | cntl_a = todc_read_val(todc_info->control_a); | ||
230 | |||
231 | /* Check & clear STOP bit in control B register */ | ||
232 | if (cntl_b & TODC_MK48TXX_DAY_CB) { | ||
233 | printk(KERN_INFO "TODC %s %s\n", | ||
234 | "real-time-clock was stopped.", | ||
235 | "Now starting..."); | ||
236 | |||
237 | cntl_a |= todc_info->enable_write; | ||
238 | cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */ | ||
239 | |||
240 | todc_write_val(todc_info->control_a, cntl_a); | ||
241 | todc_write_val(todc_info->control_b, cntl_b); | ||
242 | } | ||
243 | |||
244 | /* Make sure READ & WRITE bits are cleared. */ | ||
245 | cntl_a &= ~(todc_info->enable_write | todc_info->enable_read); | ||
246 | todc_write_val(todc_info->control_a, cntl_a); | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * There is some ugly stuff in that there are assumptions that for a mc146818, | ||
254 | * the todc_info->control_a has the offset of the mc146818 Register B reg and | ||
255 | * that the register'ss 'SET' bit is the same as the m48txx's write enable | ||
256 | * bit in the control register of the m48txx (i.e., 0x80). | ||
257 | * | ||
258 | * It was done to make the code look simpler. | ||
259 | */ | ||
260 | void | ||
261 | todc_get_rtc_time(struct rtc_time *tm) | ||
262 | { | ||
263 | uint year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0; | ||
264 | uint limit, i; | ||
265 | u_char save_control, uip = 0; | ||
266 | extern void GregorianDay(struct rtc_time *); | ||
267 | |||
268 | spin_lock(&rtc_lock); | ||
269 | save_control = todc_read_val(todc_info->control_a); | ||
270 | |||
271 | if (todc_info->rtc_type != TODC_TYPE_MC146818) { | ||
272 | limit = 1; | ||
273 | |||
274 | switch (todc_info->rtc_type) { | ||
275 | case TODC_TYPE_DS1553: | ||
276 | case TODC_TYPE_DS1557: | ||
277 | case TODC_TYPE_DS1743: | ||
278 | case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ | ||
279 | case TODC_TYPE_DS1747: | ||
280 | case TODC_TYPE_DS17285: | ||
281 | break; | ||
282 | default: | ||
283 | todc_write_val(todc_info->control_a, | ||
284 | (save_control | todc_info->enable_read)); | ||
285 | } | ||
286 | } else | ||
287 | limit = 100000000; | ||
288 | |||
289 | for (i=0; i<limit; i++) { | ||
290 | if (todc_info->rtc_type == TODC_TYPE_MC146818) | ||
291 | uip = todc_read_val(todc_info->RTC_FREQ_SELECT); | ||
292 | |||
293 | sec = todc_read_val(todc_info->seconds) & 0x7f; | ||
294 | min = todc_read_val(todc_info->minutes) & 0x7f; | ||
295 | hour = todc_read_val(todc_info->hours) & 0x3f; | ||
296 | mday = todc_read_val(todc_info->day_of_month) & 0x3f; | ||
297 | mon = todc_read_val(todc_info->month) & 0x1f; | ||
298 | year = todc_read_val(todc_info->year) & 0xff; | ||
299 | |||
300 | if (todc_info->rtc_type == TODC_TYPE_MC146818) { | ||
301 | uip |= todc_read_val(todc_info->RTC_FREQ_SELECT); | ||
302 | if ((uip & RTC_UIP) == 0) | ||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | if (todc_info->rtc_type != TODC_TYPE_MC146818) { | ||
308 | switch (todc_info->rtc_type) { | ||
309 | case TODC_TYPE_DS1553: | ||
310 | case TODC_TYPE_DS1557: | ||
311 | case TODC_TYPE_DS1743: | ||
312 | case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ | ||
313 | case TODC_TYPE_DS1747: | ||
314 | case TODC_TYPE_DS17285: | ||
315 | break; | ||
316 | default: | ||
317 | save_control &= ~(todc_info->enable_read); | ||
318 | todc_write_val(todc_info->control_a, save_control); | ||
319 | } | ||
320 | } | ||
321 | spin_unlock(&rtc_lock); | ||
322 | |||
323 | if ((todc_info->rtc_type != TODC_TYPE_MC146818) | ||
324 | || ((save_control & RTC_DM_BINARY) == 0) | ||
325 | || RTC_ALWAYS_BCD) { | ||
326 | BCD_TO_BIN(sec); | ||
327 | BCD_TO_BIN(min); | ||
328 | BCD_TO_BIN(hour); | ||
329 | BCD_TO_BIN(mday); | ||
330 | BCD_TO_BIN(mon); | ||
331 | BCD_TO_BIN(year); | ||
332 | } | ||
333 | |||
334 | if ((year + 1900) < 1970) { | ||
335 | year += 100; | ||
336 | } | ||
337 | |||
338 | tm->tm_sec = sec; | ||
339 | tm->tm_min = min; | ||
340 | tm->tm_hour = hour; | ||
341 | tm->tm_mday = mday; | ||
342 | tm->tm_mon = mon; | ||
343 | tm->tm_year = year; | ||
344 | |||
345 | GregorianDay(tm); | ||
346 | } | ||
347 | |||
348 | int | ||
349 | todc_set_rtc_time(struct rtc_time *tm) | ||
350 | { | ||
351 | u_char save_control, save_freq_select = 0; | ||
352 | |||
353 | spin_lock(&rtc_lock); | ||
354 | save_control = todc_read_val(todc_info->control_a); | ||
355 | |||
356 | /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */ | ||
357 | todc_write_val(todc_info->control_a, | ||
358 | (save_control | todc_info->enable_write)); | ||
359 | save_control &= ~(todc_info->enable_write); /* in case it was set */ | ||
360 | |||
361 | if (todc_info->rtc_type == TODC_TYPE_MC146818) { | ||
362 | save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT); | ||
363 | todc_write_val(todc_info->RTC_FREQ_SELECT, | ||
364 | save_freq_select | RTC_DIV_RESET2); | ||
365 | } | ||
366 | |||
367 | if ((todc_info->rtc_type != TODC_TYPE_MC146818) | ||
368 | || ((save_control & RTC_DM_BINARY) == 0) | ||
369 | || RTC_ALWAYS_BCD) { | ||
370 | BIN_TO_BCD(tm->tm_sec); | ||
371 | BIN_TO_BCD(tm->tm_min); | ||
372 | BIN_TO_BCD(tm->tm_hour); | ||
373 | BIN_TO_BCD(tm->tm_mon); | ||
374 | BIN_TO_BCD(tm->tm_mday); | ||
375 | BIN_TO_BCD(tm->tm_year); | ||
376 | } | ||
377 | |||
378 | todc_write_val(todc_info->seconds, tm->tm_sec); | ||
379 | todc_write_val(todc_info->minutes, tm->tm_min); | ||
380 | todc_write_val(todc_info->hours, tm->tm_hour); | ||
381 | todc_write_val(todc_info->month, tm->tm_mon); | ||
382 | todc_write_val(todc_info->day_of_month, tm->tm_mday); | ||
383 | todc_write_val(todc_info->year, tm->tm_year); | ||
384 | |||
385 | todc_write_val(todc_info->control_a, save_control); | ||
386 | |||
387 | if (todc_info->rtc_type == TODC_TYPE_MC146818) | ||
388 | todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select); | ||
389 | |||
390 | spin_unlock(&rtc_lock); | ||
391 | return 0; | ||
392 | } | ||
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 322f86e93de..ae249c6bbbc 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * 2004-2005 (c) Tundra Semiconductor Corp. | 4 | * 2004-2005 (c) Tundra Semiconductor Corp. |
5 | * Author: Alex Bounine (alexandreb@tundra.com) | 5 | * Author: Alex Bounine (alexandreb@tundra.com) |
6 | * Author: Roy Zang (tie-fei.zang@freescale.com) | ||
7 | * Add pci interrupt router host | ||
6 | * | 8 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 9 | * 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 Free | 10 | * under the terms of the GNU General Public License as published by the Free |
@@ -48,6 +50,8 @@ | |||
48 | 50 | ||
49 | u32 tsi108_pci_cfg_base; | 51 | u32 tsi108_pci_cfg_base; |
50 | u32 tsi108_csr_vir_base; | 52 | u32 tsi108_csr_vir_base; |
53 | static struct device_node *pci_irq_node; | ||
54 | static struct irq_host *pci_irq_host; | ||
51 | 55 | ||
52 | extern u32 get_vir_csrbase(void); | 56 | extern u32 get_vir_csrbase(void); |
53 | extern u32 tsi108_read_reg(u32 reg_offset); | 57 | extern u32 tsi108_read_reg(u32 reg_offset); |
@@ -378,6 +382,38 @@ static struct irq_chip tsi108_pci_irq = { | |||
378 | .unmask = tsi108_pci_irq_enable, | 382 | .unmask = tsi108_pci_irq_enable, |
379 | }; | 383 | }; |
380 | 384 | ||
385 | static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct, | ||
386 | u32 *intspec, unsigned int intsize, | ||
387 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | ||
388 | { | ||
389 | *out_hwirq = intspec[0]; | ||
390 | *out_flags = IRQ_TYPE_LEVEL_HIGH; | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int pci_irq_host_map(struct irq_host *h, unsigned int virq, | ||
395 | irq_hw_number_t hw) | ||
396 | { unsigned int irq; | ||
397 | DBG("%s(%d, 0x%lx)\n", __FUNCTION__, virq, hw); | ||
398 | if ((virq >= 1) && (virq <= 4)){ | ||
399 | irq = virq + IRQ_PCI_INTAD_BASE - 1; | ||
400 | get_irq_desc(irq)->status |= IRQ_LEVEL; | ||
401 | set_irq_chip(irq, &tsi108_pci_irq); | ||
402 | } | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int pci_irq_host_match(struct irq_host *h, struct device_node *node) | ||
407 | { | ||
408 | return pci_irq_node == node; | ||
409 | } | ||
410 | |||
411 | static struct irq_host_ops pci_irq_host_ops = { | ||
412 | .match = pci_irq_host_match, | ||
413 | .map = pci_irq_host_map, | ||
414 | .xlate = pci_irq_host_xlate, | ||
415 | }; | ||
416 | |||
381 | /* | 417 | /* |
382 | * Exported functions | 418 | * Exported functions |
383 | */ | 419 | */ |
@@ -391,15 +427,15 @@ static struct irq_chip tsi108_pci_irq = { | |||
391 | * to the MPIC. | 427 | * to the MPIC. |
392 | */ | 428 | */ |
393 | 429 | ||
394 | void __init tsi108_pci_int_init(void) | 430 | void __init tsi108_pci_int_init(struct device_node *node) |
395 | { | 431 | { |
396 | u_int i; | ||
397 | |||
398 | DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); | 432 | DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); |
399 | 433 | ||
400 | for (i = 0; i < NUM_PCI_IRQS; i++) { | 434 | pci_irq_node = of_node_get(node); |
401 | irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq; | 435 | pci_irq_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &pci_irq_host_ops, 0); |
402 | irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL; | 436 | if (pci_irq_host == NULL) { |
437 | printk(KERN_ERR "pci_irq_host: failed to allocate irq host !\n"); | ||
438 | return; | ||
403 | } | 439 | } |
404 | 440 | ||
405 | init_pci_source(); | 441 | init_pci_source(); |
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 109d874ecfb..51d97588e76 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile | |||
@@ -3,5 +3,10 @@ | |||
3 | ifdef CONFIG_PPC64 | 3 | ifdef CONFIG_PPC64 |
4 | EXTRA_CFLAGS += -mno-minimal-toc | 4 | EXTRA_CFLAGS += -mno-minimal-toc |
5 | endif | 5 | endif |
6 | obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o start.o \ | 6 | |
7 | nonstdio.o | 7 | obj-y += xmon.o setjmp.o start.o nonstdio.o |
8 | |||
9 | ifdef CONFIG_XMON_DISASSEMBLY | ||
10 | obj-y += ppc-dis.o ppc-opc.o | ||
11 | obj-$(CONFIG_SPU_BASE) += spu-dis.o spu-opc.o | ||
12 | endif | ||
diff --git a/arch/powerpc/xmon/dis-asm.h b/arch/powerpc/xmon/dis-asm.h new file mode 100644 index 00000000000..be3533b93f3 --- /dev/null +++ b/arch/powerpc/xmon/dis-asm.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #ifndef _POWERPC_XMON_DIS_ASM_H | ||
2 | #define _POWERPC_XMON_DIS_ASM_H | ||
3 | /* | ||
4 | * Copyright (C) 2006 Michael Ellerman, IBM Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | extern void print_address (unsigned long memaddr); | ||
13 | |||
14 | #ifdef CONFIG_XMON_DISASSEMBLY | ||
15 | extern int print_insn_powerpc(unsigned long insn, unsigned long memaddr); | ||
16 | extern int print_insn_spu(unsigned long insn, unsigned long memaddr); | ||
17 | #else | ||
18 | static inline int print_insn_powerpc(unsigned long insn, unsigned long memaddr) | ||
19 | { | ||
20 | printf("%.8x", insn); | ||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | static inline int print_insn_spu(unsigned long insn, unsigned long memaddr) | ||
25 | { | ||
26 | printf("%.8x", insn); | ||
27 | return 0; | ||
28 | } | ||
29 | #endif | ||
30 | |||
31 | #endif /* _POWERPC_XMON_DIS_ASM_H */ | ||
diff --git a/arch/powerpc/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c index ac0a9d2427e..89098f320ad 100644 --- a/arch/powerpc/xmon/ppc-dis.c +++ b/arch/powerpc/xmon/ppc-dis.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* ppc-dis.c -- Disassemble PowerPC instructions | 1 | /* ppc-dis.c -- Disassemble PowerPC instructions |
2 | Copyright 1994 Free Software Foundation, Inc. | 2 | Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006 |
3 | Free Software Foundation, Inc. | ||
3 | Written by Ian Lance Taylor, Cygnus Support | 4 | Written by Ian Lance Taylor, Cygnus Support |
4 | 5 | ||
5 | This file is part of GDB, GAS, and the GNU binutils. | 6 | This file is part of GDB, GAS, and the GNU binutils. |
@@ -16,27 +17,36 @@ the GNU General Public License for more details. | |||
16 | 17 | ||
17 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License |
18 | along with this file; see the file COPYING. If not, write to the Free | 19 | along with this file; see the file COPYING. If not, write to the Free |
19 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 20 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ |
20 | 21 | ||
22 | #include <asm/cputable.h> | ||
21 | #include "nonstdio.h" | 23 | #include "nonstdio.h" |
22 | #include "ansidecl.h" | 24 | #include "ansidecl.h" |
23 | #include "ppc.h" | 25 | #include "ppc.h" |
24 | 26 | #include "dis-asm.h" | |
25 | extern void print_address (unsigned long memaddr); | ||
26 | 27 | ||
27 | /* Print a PowerPC or POWER instruction. */ | 28 | /* Print a PowerPC or POWER instruction. */ |
28 | 29 | ||
29 | int | 30 | int |
30 | print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect) | 31 | print_insn_powerpc (unsigned long insn, unsigned long memaddr) |
31 | { | 32 | { |
32 | const struct powerpc_opcode *opcode; | 33 | const struct powerpc_opcode *opcode; |
33 | const struct powerpc_opcode *opcode_end; | 34 | const struct powerpc_opcode *opcode_end; |
34 | unsigned long op; | 35 | unsigned long op; |
36 | int dialect; | ||
35 | 37 | ||
36 | if (dialect == 0) | 38 | dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON |
37 | dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON | ||
38 | | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC; | 39 | | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC; |
39 | 40 | ||
41 | if (cpu_has_feature(CPU_FTRS_POWER5)) | ||
42 | dialect |= PPC_OPCODE_POWER5; | ||
43 | |||
44 | if (cpu_has_feature(CPU_FTRS_CELL)) | ||
45 | dialect |= PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC; | ||
46 | |||
47 | if (cpu_has_feature(CPU_FTRS_POWER6)) | ||
48 | dialect |= PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC; | ||
49 | |||
40 | /* Get the major opcode of the instruction. */ | 50 | /* Get the major opcode of the instruction. */ |
41 | op = PPC_OP (insn); | 51 | op = PPC_OP (insn); |
42 | 52 | ||
@@ -121,7 +131,8 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect) | |||
121 | } | 131 | } |
122 | 132 | ||
123 | /* Print the operand as directed by the flags. */ | 133 | /* Print the operand as directed by the flags. */ |
124 | if ((operand->flags & PPC_OPERAND_GPR) != 0) | 134 | if ((operand->flags & PPC_OPERAND_GPR) != 0 |
135 | || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) | ||
125 | printf("r%ld", value); | 136 | printf("r%ld", value); |
126 | else if ((operand->flags & PPC_OPERAND_FPR) != 0) | 137 | else if ((operand->flags & PPC_OPERAND_FPR) != 0) |
127 | printf("f%ld", value); | 138 | printf("f%ld", value); |
@@ -137,7 +148,7 @@ print_insn_powerpc (unsigned long insn, unsigned long memaddr, int dialect) | |||
137 | else | 148 | else |
138 | { | 149 | { |
139 | if (operand->bits == 3) | 150 | if (operand->bits == 3) |
140 | printf("cr%d", value); | 151 | printf("cr%ld", value); |
141 | else | 152 | else |
142 | { | 153 | { |
143 | static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; | 154 | static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; |
diff --git a/arch/powerpc/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c index 5ee8fc32f82..5d841f4b353 100644 --- a/arch/powerpc/xmon/ppc-opc.c +++ b/arch/powerpc/xmon/ppc-opc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* ppc-opc.c -- PowerPC opcode list | 1 | /* ppc-opc.c -- PowerPC opcode list |
2 | Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003 | 2 | Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, |
3 | Free Software Foundation, Inc. | 3 | 2005 Free Software Foundation, Inc. |
4 | Written by Ian Lance Taylor, Cygnus Support | 4 | Written by Ian Lance Taylor, Cygnus Support |
5 | 5 | ||
6 | This file is part of GDB, GAS, and the GNU binutils. | 6 | This file is part of GDB, GAS, and the GNU binutils. |
@@ -17,8 +17,8 @@ | |||
17 | 17 | ||
18 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License |
19 | along with this file; see the file COPYING. If not, write to the Free | 19 | along with this file; see the file COPYING. If not, write to the Free |
20 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | 20 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
21 | 02111-1307, USA. */ | 21 | 02110-1301, USA. */ |
22 | 22 | ||
23 | #include <linux/stddef.h> | 23 | #include <linux/stddef.h> |
24 | #include "nonstdio.h" | 24 | #include "nonstdio.h" |
@@ -86,6 +86,8 @@ static unsigned long insert_sh6 (unsigned long, long, int, const char **); | |||
86 | static long extract_sh6 (unsigned long, int, int *); | 86 | static long extract_sh6 (unsigned long, int, int *); |
87 | static unsigned long insert_spr (unsigned long, long, int, const char **); | 87 | static unsigned long insert_spr (unsigned long, long, int, const char **); |
88 | static long extract_spr (unsigned long, int, int *); | 88 | static long extract_spr (unsigned long, int, int *); |
89 | static unsigned long insert_sprg (unsigned long, long, int, const char **); | ||
90 | static long extract_sprg (unsigned long, int, int *); | ||
89 | static unsigned long insert_tbr (unsigned long, long, int, const char **); | 91 | static unsigned long insert_tbr (unsigned long, long, int, const char **); |
90 | static long extract_tbr (unsigned long, int, int *); | 92 | static long extract_tbr (unsigned long, int, int *); |
91 | static unsigned long insert_ev2 (unsigned long, long, int, const char **); | 93 | static unsigned long insert_ev2 (unsigned long, long, int, const char **); |
@@ -196,8 +198,11 @@ const struct powerpc_operand powerpc_operands[] = | |||
196 | #define BOE BO + 1 | 198 | #define BOE BO + 1 |
197 | { 5, 21, insert_boe, extract_boe, 0 }, | 199 | { 5, 21, insert_boe, extract_boe, 0 }, |
198 | 200 | ||
201 | #define BH BOE + 1 | ||
202 | { 2, 11, NULL, NULL, PPC_OPERAND_OPTIONAL }, | ||
203 | |||
199 | /* The BT field in an X or XL form instruction. */ | 204 | /* The BT field in an X or XL form instruction. */ |
200 | #define BT BOE + 1 | 205 | #define BT BH + 1 |
201 | { 5, 21, NULL, NULL, PPC_OPERAND_CR }, | 206 | { 5, 21, NULL, NULL, PPC_OPERAND_CR }, |
202 | 207 | ||
203 | /* The condition register number portion of the BI field in a B form | 208 | /* The condition register number portion of the BI field in a B form |
@@ -301,10 +306,14 @@ const struct powerpc_operand powerpc_operands[] = | |||
301 | #define L FXM4 + 1 | 306 | #define L FXM4 + 1 |
302 | { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, | 307 | { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, |
303 | 308 | ||
304 | /* The LEV field in a POWER SC form instruction. */ | 309 | /* The LEV field in a POWER SVC form instruction. */ |
305 | #define LEV L + 1 | 310 | #define SVC_LEV L + 1 |
306 | { 7, 5, NULL, NULL, 0 }, | 311 | { 7, 5, NULL, NULL, 0 }, |
307 | 312 | ||
313 | /* The LEV field in an SC form instruction. */ | ||
314 | #define LEV SVC_LEV + 1 | ||
315 | { 7, 5, NULL, NULL, PPC_OPERAND_OPTIONAL }, | ||
316 | |||
308 | /* The LI field in an I form instruction. The lower two bits are | 317 | /* The LI field in an I form instruction. The lower two bits are |
309 | forced to zero. */ | 318 | forced to zero. */ |
310 | #define LI LEV + 1 | 319 | #define LI LEV + 1 |
@@ -346,7 +355,7 @@ const struct powerpc_operand powerpc_operands[] = | |||
346 | 355 | ||
347 | /* The MO field in an mbar instruction. */ | 356 | /* The MO field in an mbar instruction. */ |
348 | #define MO MB6 + 1 | 357 | #define MO MB6 + 1 |
349 | { 5, 21, NULL, NULL, 0 }, | 358 | { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, |
350 | 359 | ||
351 | /* The NB field in an X form instruction. The value 32 is stored as | 360 | /* The NB field in an X form instruction. The value 32 is stored as |
352 | 0. */ | 361 | 0. */ |
@@ -364,30 +373,38 @@ const struct powerpc_operand powerpc_operands[] = | |||
364 | #define RA_MASK (0x1f << 16) | 373 | #define RA_MASK (0x1f << 16) |
365 | { 5, 16, NULL, NULL, PPC_OPERAND_GPR }, | 374 | { 5, 16, NULL, NULL, PPC_OPERAND_GPR }, |
366 | 375 | ||
376 | /* As above, but 0 in the RA field means zero, not r0. */ | ||
377 | #define RA0 RA + 1 | ||
378 | { 5, 16, NULL, NULL, PPC_OPERAND_GPR_0 }, | ||
379 | |||
367 | /* The RA field in the DQ form lq instruction, which has special | 380 | /* The RA field in the DQ form lq instruction, which has special |
368 | value restrictions. */ | 381 | value restrictions. */ |
369 | #define RAQ RA + 1 | 382 | #define RAQ RA0 + 1 |
370 | { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR }, | 383 | { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR_0 }, |
371 | 384 | ||
372 | /* The RA field in a D or X form instruction which is an updating | 385 | /* The RA field in a D or X form instruction which is an updating |
373 | load, which means that the RA field may not be zero and may not | 386 | load, which means that the RA field may not be zero and may not |
374 | equal the RT field. */ | 387 | equal the RT field. */ |
375 | #define RAL RAQ + 1 | 388 | #define RAL RAQ + 1 |
376 | { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR }, | 389 | { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR_0 }, |
377 | 390 | ||
378 | /* The RA field in an lmw instruction, which has special value | 391 | /* The RA field in an lmw instruction, which has special value |
379 | restrictions. */ | 392 | restrictions. */ |
380 | #define RAM RAL + 1 | 393 | #define RAM RAL + 1 |
381 | { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR }, | 394 | { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR_0 }, |
382 | 395 | ||
383 | /* The RA field in a D or X form instruction which is an updating | 396 | /* The RA field in a D or X form instruction which is an updating |
384 | store or an updating floating point load, which means that the RA | 397 | store or an updating floating point load, which means that the RA |
385 | field may not be zero. */ | 398 | field may not be zero. */ |
386 | #define RAS RAM + 1 | 399 | #define RAS RAM + 1 |
387 | { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR }, | 400 | { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR_0 }, |
401 | |||
402 | /* The RA field of the tlbwe instruction, which is optional. */ | ||
403 | #define RAOPT RAS + 1 | ||
404 | { 5, 16, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL }, | ||
388 | 405 | ||
389 | /* The RB field in an X, XO, M, or MDS form instruction. */ | 406 | /* The RB field in an X, XO, M, or MDS form instruction. */ |
390 | #define RB RAS + 1 | 407 | #define RB RAOPT + 1 |
391 | #define RB_MASK (0x1f << 11) | 408 | #define RB_MASK (0x1f << 11) |
392 | { 5, 11, NULL, NULL, PPC_OPERAND_GPR }, | 409 | { 5, 11, NULL, NULL, PPC_OPERAND_GPR }, |
393 | 410 | ||
@@ -408,15 +425,20 @@ const struct powerpc_operand powerpc_operands[] = | |||
408 | /* The RS field of the DS form stq instruction, which has special | 425 | /* The RS field of the DS form stq instruction, which has special |
409 | value restrictions. */ | 426 | value restrictions. */ |
410 | #define RSQ RS + 1 | 427 | #define RSQ RS + 1 |
411 | { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR }, | 428 | { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR_0 }, |
412 | 429 | ||
413 | /* The RT field of the DQ form lq instruction, which has special | 430 | /* The RT field of the DQ form lq instruction, which has special |
414 | value restrictions. */ | 431 | value restrictions. */ |
415 | #define RTQ RSQ + 1 | 432 | #define RTQ RSQ + 1 |
416 | { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR }, | 433 | { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR_0 }, |
434 | |||
435 | /* The RS field of the tlbwe instruction, which is optional. */ | ||
436 | #define RSO RTQ + 1 | ||
437 | #define RTO RSO | ||
438 | { 5, 21, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL }, | ||
417 | 439 | ||
418 | /* The SH field in an X or M form instruction. */ | 440 | /* The SH field in an X or M form instruction. */ |
419 | #define SH RTQ + 1 | 441 | #define SH RSO + 1 |
420 | #define SH_MASK (0x1f << 11) | 442 | #define SH_MASK (0x1f << 11) |
421 | { 5, 11, NULL, NULL, 0 }, | 443 | { 5, 11, NULL, NULL, 0 }, |
422 | 444 | ||
@@ -425,8 +447,12 @@ const struct powerpc_operand powerpc_operands[] = | |||
425 | #define SH6_MASK ((0x1f << 11) | (1 << 1)) | 447 | #define SH6_MASK ((0x1f << 11) | (1 << 1)) |
426 | { 6, 1, insert_sh6, extract_sh6, 0 }, | 448 | { 6, 1, insert_sh6, extract_sh6, 0 }, |
427 | 449 | ||
450 | /* The SH field of the tlbwe instruction, which is optional. */ | ||
451 | #define SHO SH6 + 1 | ||
452 | { 5, 11,NULL, NULL, PPC_OPERAND_OPTIONAL }, | ||
453 | |||
428 | /* The SI field in a D form instruction. */ | 454 | /* The SI field in a D form instruction. */ |
429 | #define SI SH6 + 1 | 455 | #define SI SHO + 1 |
430 | { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED }, | 456 | { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED }, |
431 | 457 | ||
432 | /* The SI field in a D form instruction when we accept a wide range | 458 | /* The SI field in a D form instruction when we accept a wide range |
@@ -448,8 +474,7 @@ const struct powerpc_operand powerpc_operands[] = | |||
448 | 474 | ||
449 | /* The SPRG register number in an XFX form m[ft]sprg instruction. */ | 475 | /* The SPRG register number in an XFX form m[ft]sprg instruction. */ |
450 | #define SPRG SPRBAT + 1 | 476 | #define SPRG SPRBAT + 1 |
451 | #define SPRG_MASK (0x3 << 16) | 477 | { 5, 16, insert_sprg, extract_sprg, 0 }, |
452 | { 2, 16, NULL, NULL, 0 }, | ||
453 | 478 | ||
454 | /* The SR field in an X form instruction. */ | 479 | /* The SR field in an X form instruction. */ |
455 | #define SR SPRG + 1 | 480 | #define SR SPRG + 1 |
@@ -536,10 +561,45 @@ const struct powerpc_operand powerpc_operands[] = | |||
536 | #define WS_MASK (0x7 << 11) | 561 | #define WS_MASK (0x7 << 11) |
537 | { 3, 11, NULL, NULL, 0 }, | 562 | { 3, 11, NULL, NULL, 0 }, |
538 | 563 | ||
539 | /* The L field in an mtmsrd instruction */ | 564 | /* The L field in an mtmsrd or A form instruction. */ |
540 | #define MTMSRD_L WS + 1 | 565 | #define MTMSRD_L WS + 1 |
566 | #define A_L MTMSRD_L | ||
541 | { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL }, | 567 | { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL }, |
542 | 568 | ||
569 | /* The DCM field in a Z form instruction. */ | ||
570 | #define DCM MTMSRD_L + 1 | ||
571 | { 6, 16, NULL, NULL, 0 }, | ||
572 | |||
573 | /* Likewise, the DGM field in a Z form instruction. */ | ||
574 | #define DGM DCM + 1 | ||
575 | { 6, 16, NULL, NULL, 0 }, | ||
576 | |||
577 | #define TE DGM + 1 | ||
578 | { 5, 11, NULL, NULL, 0 }, | ||
579 | |||
580 | #define RMC TE + 1 | ||
581 | { 2, 21, NULL, NULL, 0 }, | ||
582 | |||
583 | #define R RMC + 1 | ||
584 | { 1, 15, NULL, NULL, 0 }, | ||
585 | |||
586 | #define SP R + 1 | ||
587 | { 2, 11, NULL, NULL, 0 }, | ||
588 | |||
589 | #define S SP + 1 | ||
590 | { 1, 11, NULL, NULL, 0 }, | ||
591 | |||
592 | /* SH field starting at bit position 16. */ | ||
593 | #define SH16 S + 1 | ||
594 | { 6, 10, NULL, NULL, 0 }, | ||
595 | |||
596 | /* The L field in an X form with the RT field fixed instruction. */ | ||
597 | #define XRT_L SH16 + 1 | ||
598 | { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, | ||
599 | |||
600 | /* The EH field in larx instruction. */ | ||
601 | #define EH XRT_L + 1 | ||
602 | { 1, 0, NULL, NULL, PPC_OPERAND_OPTIONAL }, | ||
543 | }; | 603 | }; |
544 | 604 | ||
545 | /* The functions used to insert and extract complicated operands. */ | 605 | /* The functions used to insert and extract complicated operands. */ |
@@ -550,7 +610,6 @@ const struct powerpc_operand powerpc_operands[] = | |||
550 | and the extraction function just checks that the fields are the | 610 | and the extraction function just checks that the fields are the |
551 | same. */ | 611 | same. */ |
552 | 612 | ||
553 | /*ARGSUSED*/ | ||
554 | static unsigned long | 613 | static unsigned long |
555 | insert_bat (unsigned long insn, | 614 | insert_bat (unsigned long insn, |
556 | long value ATTRIBUTE_UNUSED, | 615 | long value ATTRIBUTE_UNUSED, |
@@ -576,7 +635,6 @@ extract_bat (unsigned long insn, | |||
576 | and the extraction function just checks that the fields are the | 635 | and the extraction function just checks that the fields are the |
577 | same. */ | 636 | same. */ |
578 | 637 | ||
579 | /*ARGSUSED*/ | ||
580 | static unsigned long | 638 | static unsigned long |
581 | insert_bba (unsigned long insn, | 639 | insert_bba (unsigned long insn, |
582 | long value ATTRIBUTE_UNUSED, | 640 | long value ATTRIBUTE_UNUSED, |
@@ -599,7 +657,6 @@ extract_bba (unsigned long insn, | |||
599 | /* The BD field in a B form instruction. The lower two bits are | 657 | /* The BD field in a B form instruction. The lower two bits are |
600 | forced to zero. */ | 658 | forced to zero. */ |
601 | 659 | ||
602 | /*ARGSUSED*/ | ||
603 | static unsigned long | 660 | static unsigned long |
604 | insert_bd (unsigned long insn, | 661 | insert_bd (unsigned long insn, |
605 | long value, | 662 | long value, |
@@ -609,7 +666,6 @@ insert_bd (unsigned long insn, | |||
609 | return insn | (value & 0xfffc); | 666 | return insn | (value & 0xfffc); |
610 | } | 667 | } |
611 | 668 | ||
612 | /*ARGSUSED*/ | ||
613 | static long | 669 | static long |
614 | extract_bd (unsigned long insn, | 670 | extract_bd (unsigned long insn, |
615 | int dialect ATTRIBUTE_UNUSED, | 671 | int dialect ATTRIBUTE_UNUSED, |
@@ -631,7 +687,6 @@ extract_bd (unsigned long insn, | |||
631 | in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000 | 687 | in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000 |
632 | for branch on CTR. We only handle the taken/not-taken hint here. */ | 688 | for branch on CTR. We only handle the taken/not-taken hint here. */ |
633 | 689 | ||
634 | /*ARGSUSED*/ | ||
635 | static unsigned long | 690 | static unsigned long |
636 | insert_bdm (unsigned long insn, | 691 | insert_bdm (unsigned long insn, |
637 | long value, | 692 | long value, |
@@ -677,7 +732,6 @@ extract_bdm (unsigned long insn, | |||
677 | This is like BDM, above, except that the branch is expected to be | 732 | This is like BDM, above, except that the branch is expected to be |
678 | taken. */ | 733 | taken. */ |
679 | 734 | ||
680 | /*ARGSUSED*/ | ||
681 | static unsigned long | 735 | static unsigned long |
682 | insert_bdp (unsigned long insn, | 736 | insert_bdp (unsigned long insn, |
683 | long value, | 737 | long value, |
@@ -831,7 +885,6 @@ extract_boe (unsigned long insn, | |||
831 | /* The DQ field in a DQ form instruction. This is like D, but the | 885 | /* The DQ field in a DQ form instruction. This is like D, but the |
832 | lower four bits are forced to zero. */ | 886 | lower four bits are forced to zero. */ |
833 | 887 | ||
834 | /*ARGSUSED*/ | ||
835 | static unsigned long | 888 | static unsigned long |
836 | insert_dq (unsigned long insn, | 889 | insert_dq (unsigned long insn, |
837 | long value, | 890 | long value, |
@@ -843,7 +896,6 @@ insert_dq (unsigned long insn, | |||
843 | return insn | (value & 0xfff0); | 896 | return insn | (value & 0xfff0); |
844 | } | 897 | } |
845 | 898 | ||
846 | /*ARGSUSED*/ | ||
847 | static long | 899 | static long |
848 | extract_dq (unsigned long insn, | 900 | extract_dq (unsigned long insn, |
849 | int dialect ATTRIBUTE_UNUSED, | 901 | int dialect ATTRIBUTE_UNUSED, |
@@ -918,7 +970,6 @@ extract_ev8 (unsigned long insn, | |||
918 | /* The DS field in a DS form instruction. This is like D, but the | 970 | /* The DS field in a DS form instruction. This is like D, but the |
919 | lower two bits are forced to zero. */ | 971 | lower two bits are forced to zero. */ |
920 | 972 | ||
921 | /*ARGSUSED*/ | ||
922 | static unsigned long | 973 | static unsigned long |
923 | insert_ds (unsigned long insn, | 974 | insert_ds (unsigned long insn, |
924 | long value, | 975 | long value, |
@@ -930,7 +981,6 @@ insert_ds (unsigned long insn, | |||
930 | return insn | (value & 0xfffc); | 981 | return insn | (value & 0xfffc); |
931 | } | 982 | } |
932 | 983 | ||
933 | /*ARGSUSED*/ | ||
934 | static long | 984 | static long |
935 | extract_ds (unsigned long insn, | 985 | extract_ds (unsigned long insn, |
936 | int dialect ATTRIBUTE_UNUSED, | 986 | int dialect ATTRIBUTE_UNUSED, |
@@ -941,7 +991,6 @@ extract_ds (unsigned long insn, | |||
941 | 991 | ||
942 | /* The DE field in a DE form instruction. */ | 992 | /* The DE field in a DE form instruction. */ |
943 | 993 | ||
944 | /*ARGSUSED*/ | ||
945 | static unsigned long | 994 | static unsigned long |
946 | insert_de (unsigned long insn, | 995 | insert_de (unsigned long insn, |
947 | long value, | 996 | long value, |
@@ -953,7 +1002,6 @@ insert_de (unsigned long insn, | |||
953 | return insn | ((value << 4) & 0xfff0); | 1002 | return insn | ((value << 4) & 0xfff0); |
954 | } | 1003 | } |
955 | 1004 | ||
956 | /*ARGSUSED*/ | ||
957 | static long | 1005 | static long |
958 | extract_de (unsigned long insn, | 1006 | extract_de (unsigned long insn, |
959 | int dialect ATTRIBUTE_UNUSED, | 1007 | int dialect ATTRIBUTE_UNUSED, |
@@ -964,7 +1012,6 @@ extract_de (unsigned long insn, | |||
964 | 1012 | ||
965 | /* The DES field in a DES form instruction. */ | 1013 | /* The DES field in a DES form instruction. */ |
966 | 1014 | ||
967 | /*ARGSUSED*/ | ||
968 | static unsigned long | 1015 | static unsigned long |
969 | insert_des (unsigned long insn, | 1016 | insert_des (unsigned long insn, |
970 | long value, | 1017 | long value, |
@@ -978,7 +1025,6 @@ insert_des (unsigned long insn, | |||
978 | return insn | ((value << 2) & 0xfff0); | 1025 | return insn | ((value << 2) & 0xfff0); |
979 | } | 1026 | } |
980 | 1027 | ||
981 | /*ARGSUSED*/ | ||
982 | static long | 1028 | static long |
983 | extract_des (unsigned long insn, | 1029 | extract_des (unsigned long insn, |
984 | int dialect ATTRIBUTE_UNUSED, | 1030 | int dialect ATTRIBUTE_UNUSED, |
@@ -995,17 +1041,33 @@ insert_fxm (unsigned long insn, | |||
995 | int dialect, | 1041 | int dialect, |
996 | const char **errmsg) | 1042 | const char **errmsg) |
997 | { | 1043 | { |
1044 | /* If we're handling the mfocrf and mtocrf insns ensure that exactly | ||
1045 | one bit of the mask field is set. */ | ||
1046 | if ((insn & (1 << 20)) != 0) | ||
1047 | { | ||
1048 | if (value == 0 || (value & -value) != value) | ||
1049 | { | ||
1050 | *errmsg = _("invalid mask field"); | ||
1051 | value = 0; | ||
1052 | } | ||
1053 | } | ||
1054 | |||
998 | /* If the optional field on mfcr is missing that means we want to use | 1055 | /* If the optional field on mfcr is missing that means we want to use |
999 | the old form of the instruction that moves the whole cr. In that | 1056 | the old form of the instruction that moves the whole cr. In that |
1000 | case we'll have VALUE zero. There doesn't seem to be a way to | 1057 | case we'll have VALUE zero. There doesn't seem to be a way to |
1001 | distinguish this from the case where someone writes mfcr %r3,0. */ | 1058 | distinguish this from the case where someone writes mfcr %r3,0. */ |
1002 | if (value == 0) | 1059 | else if (value == 0) |
1003 | ; | 1060 | ; |
1004 | 1061 | ||
1005 | /* If only one bit of the FXM field is set, we can use the new form | 1062 | /* If only one bit of the FXM field is set, we can use the new form |
1006 | of the instruction, which is faster. Unlike the Power4 branch hint | 1063 | of the instruction, which is faster. Unlike the Power4 branch hint |
1007 | encoding, this is not backward compatible. */ | 1064 | encoding, this is not backward compatible. Do not generate the |
1008 | else if ((dialect & PPC_OPCODE_POWER4) != 0 && (value & -value) == value) | 1065 | new form unless -mpower4 has been given, or -many and the two |
1066 | operand form of mfcr was used. */ | ||
1067 | else if ((value & -value) == value | ||
1068 | && ((dialect & PPC_OPCODE_POWER4) != 0 | ||
1069 | || ((dialect & PPC_OPCODE_ANY) != 0 | ||
1070 | && (insn & (0x3ff << 1)) == 19 << 1))) | ||
1009 | insn |= 1 << 20; | 1071 | insn |= 1 << 20; |
1010 | 1072 | ||
1011 | /* Any other value on mfcr is an error. */ | 1073 | /* Any other value on mfcr is an error. */ |
@@ -1020,7 +1082,7 @@ insert_fxm (unsigned long insn, | |||
1020 | 1082 | ||
1021 | static long | 1083 | static long |
1022 | extract_fxm (unsigned long insn, | 1084 | extract_fxm (unsigned long insn, |
1023 | int dialect, | 1085 | int dialect ATTRIBUTE_UNUSED, |
1024 | int *invalid) | 1086 | int *invalid) |
1025 | { | 1087 | { |
1026 | long mask = (insn >> 12) & 0xff; | 1088 | long mask = (insn >> 12) & 0xff; |
@@ -1028,14 +1090,9 @@ extract_fxm (unsigned long insn, | |||
1028 | /* Is this a Power4 insn? */ | 1090 | /* Is this a Power4 insn? */ |
1029 | if ((insn & (1 << 20)) != 0) | 1091 | if ((insn & (1 << 20)) != 0) |
1030 | { | 1092 | { |
1031 | if ((dialect & PPC_OPCODE_POWER4) == 0) | 1093 | /* Exactly one bit of MASK should be set. */ |
1094 | if (mask == 0 || (mask & -mask) != mask) | ||
1032 | *invalid = 1; | 1095 | *invalid = 1; |
1033 | else | ||
1034 | { | ||
1035 | /* Exactly one bit of MASK should be set. */ | ||
1036 | if (mask == 0 || (mask & -mask) != mask) | ||
1037 | *invalid = 1; | ||
1038 | } | ||
1039 | } | 1096 | } |
1040 | 1097 | ||
1041 | /* Check that non-power4 form of mfcr has a zero MASK. */ | 1098 | /* Check that non-power4 form of mfcr has a zero MASK. */ |
@@ -1051,7 +1108,6 @@ extract_fxm (unsigned long insn, | |||
1051 | /* The LI field in an I form instruction. The lower two bits are | 1108 | /* The LI field in an I form instruction. The lower two bits are |
1052 | forced to zero. */ | 1109 | forced to zero. */ |
1053 | 1110 | ||
1054 | /*ARGSUSED*/ | ||
1055 | static unsigned long | 1111 | static unsigned long |
1056 | insert_li (unsigned long insn, | 1112 | insert_li (unsigned long insn, |
1057 | long value, | 1113 | long value, |
@@ -1063,7 +1119,6 @@ insert_li (unsigned long insn, | |||
1063 | return insn | (value & 0x3fffffc); | 1119 | return insn | (value & 0x3fffffc); |
1064 | } | 1120 | } |
1065 | 1121 | ||
1066 | /*ARGSUSED*/ | ||
1067 | static long | 1122 | static long |
1068 | extract_li (unsigned long insn, | 1123 | extract_li (unsigned long insn, |
1069 | int dialect ATTRIBUTE_UNUSED, | 1124 | int dialect ATTRIBUTE_UNUSED, |
@@ -1163,7 +1218,6 @@ extract_mbe (unsigned long insn, | |||
1163 | /* The MB or ME field in an MD or MDS form instruction. The high bit | 1218 | /* The MB or ME field in an MD or MDS form instruction. The high bit |
1164 | is wrapped to the low end. */ | 1219 | is wrapped to the low end. */ |
1165 | 1220 | ||
1166 | /*ARGSUSED*/ | ||
1167 | static unsigned long | 1221 | static unsigned long |
1168 | insert_mb6 (unsigned long insn, | 1222 | insert_mb6 (unsigned long insn, |
1169 | long value, | 1223 | long value, |
@@ -1173,7 +1227,6 @@ insert_mb6 (unsigned long insn, | |||
1173 | return insn | ((value & 0x1f) << 6) | (value & 0x20); | 1227 | return insn | ((value & 0x1f) << 6) | (value & 0x20); |
1174 | } | 1228 | } |
1175 | 1229 | ||
1176 | /*ARGSUSED*/ | ||
1177 | static long | 1230 | static long |
1178 | extract_mb6 (unsigned long insn, | 1231 | extract_mb6 (unsigned long insn, |
1179 | int dialect ATTRIBUTE_UNUSED, | 1232 | int dialect ATTRIBUTE_UNUSED, |
@@ -1198,7 +1251,6 @@ insert_nb (unsigned long insn, | |||
1198 | return insn | ((value & 0x1f) << 11); | 1251 | return insn | ((value & 0x1f) << 11); |
1199 | } | 1252 | } |
1200 | 1253 | ||
1201 | /*ARGSUSED*/ | ||
1202 | static long | 1254 | static long |
1203 | extract_nb (unsigned long insn, | 1255 | extract_nb (unsigned long insn, |
1204 | int dialect ATTRIBUTE_UNUSED, | 1256 | int dialect ATTRIBUTE_UNUSED, |
@@ -1217,7 +1269,6 @@ extract_nb (unsigned long insn, | |||
1217 | invalid, since we never want to recognize an instruction which uses | 1269 | invalid, since we never want to recognize an instruction which uses |
1218 | a field of this type. */ | 1270 | a field of this type. */ |
1219 | 1271 | ||
1220 | /*ARGSUSED*/ | ||
1221 | static unsigned long | 1272 | static unsigned long |
1222 | insert_nsi (unsigned long insn, | 1273 | insert_nsi (unsigned long insn, |
1223 | long value, | 1274 | long value, |
@@ -1269,7 +1320,6 @@ insert_ram (unsigned long insn, | |||
1269 | /* The RA field in the DQ form lq instruction, which has special | 1320 | /* The RA field in the DQ form lq instruction, which has special |
1270 | value restrictions. */ | 1321 | value restrictions. */ |
1271 | 1322 | ||
1272 | /*ARGSUSED*/ | ||
1273 | static unsigned long | 1323 | static unsigned long |
1274 | insert_raq (unsigned long insn, | 1324 | insert_raq (unsigned long insn, |
1275 | long value, | 1325 | long value, |
@@ -1304,7 +1354,6 @@ insert_ras (unsigned long insn, | |||
1304 | function just copies the BT field into the BA field, and the | 1354 | function just copies the BT field into the BA field, and the |
1305 | extraction function just checks that the fields are the same. */ | 1355 | extraction function just checks that the fields are the same. */ |
1306 | 1356 | ||
1307 | /*ARGSUSED*/ | ||
1308 | static unsigned long | 1357 | static unsigned long |
1309 | insert_rbs (unsigned long insn, | 1358 | insert_rbs (unsigned long insn, |
1310 | long value ATTRIBUTE_UNUSED, | 1359 | long value ATTRIBUTE_UNUSED, |
@@ -1327,7 +1376,6 @@ extract_rbs (unsigned long insn, | |||
1327 | /* The RT field of the DQ form lq instruction, which has special | 1376 | /* The RT field of the DQ form lq instruction, which has special |
1328 | value restrictions. */ | 1377 | value restrictions. */ |
1329 | 1378 | ||
1330 | /*ARGSUSED*/ | ||
1331 | static unsigned long | 1379 | static unsigned long |
1332 | insert_rtq (unsigned long insn, | 1380 | insert_rtq (unsigned long insn, |
1333 | long value, | 1381 | long value, |
@@ -1342,7 +1390,6 @@ insert_rtq (unsigned long insn, | |||
1342 | /* The RS field of the DS form stq instruction, which has special | 1390 | /* The RS field of the DS form stq instruction, which has special |
1343 | value restrictions. */ | 1391 | value restrictions. */ |
1344 | 1392 | ||
1345 | /*ARGSUSED*/ | ||
1346 | static unsigned long | 1393 | static unsigned long |
1347 | insert_rsq (unsigned long insn, | 1394 | insert_rsq (unsigned long insn, |
1348 | long value ATTRIBUTE_UNUSED, | 1395 | long value ATTRIBUTE_UNUSED, |
@@ -1356,7 +1403,6 @@ insert_rsq (unsigned long insn, | |||
1356 | 1403 | ||
1357 | /* The SH field in an MD form instruction. This is split. */ | 1404 | /* The SH field in an MD form instruction. This is split. */ |
1358 | 1405 | ||
1359 | /*ARGSUSED*/ | ||
1360 | static unsigned long | 1406 | static unsigned long |
1361 | insert_sh6 (unsigned long insn, | 1407 | insert_sh6 (unsigned long insn, |
1362 | long value, | 1408 | long value, |
@@ -1366,7 +1412,6 @@ insert_sh6 (unsigned long insn, | |||
1366 | return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4); | 1412 | return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4); |
1367 | } | 1413 | } |
1368 | 1414 | ||
1369 | /*ARGSUSED*/ | ||
1370 | static long | 1415 | static long |
1371 | extract_sh6 (unsigned long insn, | 1416 | extract_sh6 (unsigned long insn, |
1372 | int dialect ATTRIBUTE_UNUSED, | 1417 | int dialect ATTRIBUTE_UNUSED, |
@@ -1395,6 +1440,47 @@ extract_spr (unsigned long insn, | |||
1395 | return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); | 1440 | return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); |
1396 | } | 1441 | } |
1397 | 1442 | ||
1443 | /* Some dialects have 8 SPRG registers instead of the standard 4. */ | ||
1444 | |||
1445 | static unsigned long | ||
1446 | insert_sprg (unsigned long insn, | ||
1447 | long value, | ||
1448 | int dialect, | ||
1449 | const char **errmsg) | ||
1450 | { | ||
1451 | /* This check uses PPC_OPCODE_403 because PPC405 is later defined | ||
1452 | as a synonym. If ever a 405 specific dialect is added this | ||
1453 | check should use that instead. */ | ||
1454 | if (value > 7 | ||
1455 | || (value > 3 | ||
1456 | && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0)) | ||
1457 | *errmsg = _("invalid sprg number"); | ||
1458 | |||
1459 | /* If this is mfsprg4..7 then use spr 260..263 which can be read in | ||
1460 | user mode. Anything else must use spr 272..279. */ | ||
1461 | if (value <= 3 || (insn & 0x100) != 0) | ||
1462 | value |= 0x10; | ||
1463 | |||
1464 | return insn | ((value & 0x17) << 16); | ||
1465 | } | ||
1466 | |||
1467 | static long | ||
1468 | extract_sprg (unsigned long insn, | ||
1469 | int dialect, | ||
1470 | int *invalid) | ||
1471 | { | ||
1472 | unsigned long val = (insn >> 16) & 0x1f; | ||
1473 | |||
1474 | /* mfsprg can use 260..263 and 272..279. mtsprg only uses spr 272..279 | ||
1475 | If not BOOKE or 405, then both use only 272..275. */ | ||
1476 | if (val <= 3 | ||
1477 | || (val < 0x10 && (insn & 0x100) != 0) | ||
1478 | || (val - 0x10 > 3 | ||
1479 | && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0)) | ||
1480 | *invalid = 1; | ||
1481 | return val & 7; | ||
1482 | } | ||
1483 | |||
1398 | /* The TBR field in an XFX instruction. This is just like SPR, but it | 1484 | /* The TBR field in an XFX instruction. This is just like SPR, but it |
1399 | is optional. When TBR is omitted, it must be inserted as 268 (the | 1485 | is optional. When TBR is omitted, it must be inserted as 268 (the |
1400 | magic number of the TB register). These functions treat 0 | 1486 | magic number of the TB register). These functions treat 0 |
@@ -1460,6 +1546,9 @@ extract_tbr (unsigned long insn, | |||
1460 | /* An A_MASK with the FRA and FRC fields fixed. */ | 1546 | /* An A_MASK with the FRA and FRC fields fixed. */ |
1461 | #define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK) | 1547 | #define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK) |
1462 | 1548 | ||
1549 | /* An AFRAFRC_MASK, but with L bit clear. */ | ||
1550 | #define AFRALFRC_MASK (AFRAFRC_MASK & ~((unsigned long) 1 << 16)) | ||
1551 | |||
1463 | /* A B form instruction. */ | 1552 | /* A B form instruction. */ |
1464 | #define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1)) | 1553 | #define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1)) |
1465 | #define B_MASK B (0x3f, 1, 1) | 1554 | #define B_MASK B (0x3f, 1, 1) |
@@ -1494,11 +1583,11 @@ extract_tbr (unsigned long insn, | |||
1494 | 1583 | ||
1495 | /* An Context form instruction. */ | 1584 | /* An Context form instruction. */ |
1496 | #define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7)) | 1585 | #define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7)) |
1497 | #define CTX_MASK CTX(0x3f, 0x7) | 1586 | #define CTX_MASK CTX(0x3f, 0x7) |
1498 | 1587 | ||
1499 | /* An User Context form instruction. */ | 1588 | /* An User Context form instruction. */ |
1500 | #define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f)) | 1589 | #define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f)) |
1501 | #define UCTX_MASK UCTX(0x3f, 0x1f) | 1590 | #define UCTX_MASK UCTX(0x3f, 0x1f) |
1502 | 1591 | ||
1503 | /* The main opcode mask with the RA field clear. */ | 1592 | /* The main opcode mask with the RA field clear. */ |
1504 | #define DRA_MASK (OP_MASK | RA_MASK) | 1593 | #define DRA_MASK (OP_MASK | RA_MASK) |
@@ -1570,12 +1659,21 @@ extract_tbr (unsigned long insn, | |||
1570 | /* An X form instruction. */ | 1659 | /* An X form instruction. */ |
1571 | #define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1)) | 1660 | #define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1)) |
1572 | 1661 | ||
1662 | /* A Z form instruction. */ | ||
1663 | #define Z(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1)) | ||
1664 | |||
1573 | /* An X form instruction with the RC bit specified. */ | 1665 | /* An X form instruction with the RC bit specified. */ |
1574 | #define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1)) | 1666 | #define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1)) |
1575 | 1667 | ||
1668 | /* A Z form instruction with the RC bit specified. */ | ||
1669 | #define ZRC(op, xop, rc) (Z ((op), (xop)) | ((rc) & 1)) | ||
1670 | |||
1576 | /* The mask for an X form instruction. */ | 1671 | /* The mask for an X form instruction. */ |
1577 | #define X_MASK XRC (0x3f, 0x3ff, 1) | 1672 | #define X_MASK XRC (0x3f, 0x3ff, 1) |
1578 | 1673 | ||
1674 | /* The mask for a Z form instruction. */ | ||
1675 | #define Z_MASK ZRC (0x3f, 0x1ff, 1) | ||
1676 | |||
1579 | /* An X_MASK with the RA field fixed. */ | 1677 | /* An X_MASK with the RA field fixed. */ |
1580 | #define XRA_MASK (X_MASK | RA_MASK) | 1678 | #define XRA_MASK (X_MASK | RA_MASK) |
1581 | 1679 | ||
@@ -1585,6 +1683,9 @@ extract_tbr (unsigned long insn, | |||
1585 | /* An X_MASK with the RT field fixed. */ | 1683 | /* An X_MASK with the RT field fixed. */ |
1586 | #define XRT_MASK (X_MASK | RT_MASK) | 1684 | #define XRT_MASK (X_MASK | RT_MASK) |
1587 | 1685 | ||
1686 | /* An XRT_MASK mask with the L bits clear. */ | ||
1687 | #define XLRT_MASK (XRT_MASK & ~((unsigned long) 0x3 << 21)) | ||
1688 | |||
1588 | /* An X_MASK with the RA and RB fields fixed. */ | 1689 | /* An X_MASK with the RA and RB fields fixed. */ |
1589 | #define XRARB_MASK (X_MASK | RA_MASK | RB_MASK) | 1690 | #define XRARB_MASK (X_MASK | RA_MASK | RB_MASK) |
1590 | 1691 | ||
@@ -1597,8 +1698,8 @@ extract_tbr (unsigned long insn, | |||
1597 | /* An XRTRA_MASK, but with L bit clear. */ | 1698 | /* An XRTRA_MASK, but with L bit clear. */ |
1598 | #define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21)) | 1699 | #define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21)) |
1599 | 1700 | ||
1600 | /* An X form comparison instruction. */ | 1701 | /* An X form instruction with the L bit specified. */ |
1601 | #define XCMPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21)) | 1702 | #define XOPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21)) |
1602 | 1703 | ||
1603 | /* The mask for an X form comparison instruction. */ | 1704 | /* The mask for an X form comparison instruction. */ |
1604 | #define XCMP_MASK (X_MASK | (((unsigned long)1) << 22)) | 1705 | #define XCMP_MASK (X_MASK | (((unsigned long)1) << 22)) |
@@ -1621,6 +1722,9 @@ extract_tbr (unsigned long insn, | |||
1621 | /* An X form sync instruction with everything filled in except the LS field. */ | 1722 | /* An X form sync instruction with everything filled in except the LS field. */ |
1622 | #define XSYNC_MASK (0xff9fffff) | 1723 | #define XSYNC_MASK (0xff9fffff) |
1623 | 1724 | ||
1725 | /* An X_MASK, but with the EH bit clear. */ | ||
1726 | #define XEH_MASK (X_MASK & ~((unsigned long )1)) | ||
1727 | |||
1624 | /* An X form AltiVec dss instruction. */ | 1728 | /* An X form AltiVec dss instruction. */ |
1625 | #define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25)) | 1729 | #define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25)) |
1626 | #define XDSS_MASK XDSS(0x3f, 0x3ff, 1) | 1730 | #define XDSS_MASK XDSS(0x3f, 0x3ff, 1) |
@@ -1663,6 +1767,9 @@ extract_tbr (unsigned long insn, | |||
1663 | #define XLYBB_MASK (XLYLK_MASK | BB_MASK) | 1767 | #define XLYBB_MASK (XLYLK_MASK | BB_MASK) |
1664 | #define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK) | 1768 | #define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK) |
1665 | 1769 | ||
1770 | /* A mask for branch instructions using the BH field. */ | ||
1771 | #define XLBH_MASK (XL_MASK | (0x1c << 11)) | ||
1772 | |||
1666 | /* An XL_MASK with the BO and BB fields fixed. */ | 1773 | /* An XL_MASK with the BO and BB fields fixed. */ |
1667 | #define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK) | 1774 | #define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK) |
1668 | 1775 | ||
@@ -1682,11 +1789,12 @@ extract_tbr (unsigned long insn, | |||
1682 | #define XS_MASK XS (0x3f, 0x1ff, 1) | 1789 | #define XS_MASK XS (0x3f, 0x1ff, 1) |
1683 | 1790 | ||
1684 | /* A mask for the FXM version of an XFX form instruction. */ | 1791 | /* A mask for the FXM version of an XFX form instruction. */ |
1685 | #define XFXFXM_MASK (X_MASK | (1 << 11)) | 1792 | #define XFXFXM_MASK (X_MASK | (1 << 11) | (1 << 20)) |
1686 | 1793 | ||
1687 | /* An XFX form instruction with the FXM field filled in. */ | 1794 | /* An XFX form instruction with the FXM field filled in. */ |
1688 | #define XFXM(op, xop, fxm) \ | 1795 | #define XFXM(op, xop, fxm, p4) \ |
1689 | (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12)) | 1796 | (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12) \ |
1797 | | ((unsigned long)(p4) << 20)) | ||
1690 | 1798 | ||
1691 | /* An XFX form instruction with the SPR field filled in. */ | 1799 | /* An XFX form instruction with the SPR field filled in. */ |
1692 | #define XSPR(op, xop, spr) \ | 1800 | #define XSPR(op, xop, spr) \ |
@@ -1699,7 +1807,7 @@ extract_tbr (unsigned long insn, | |||
1699 | 1807 | ||
1700 | /* An XFX form instruction with the SPR field filled in except for the | 1808 | /* An XFX form instruction with the SPR field filled in except for the |
1701 | SPRG field. */ | 1809 | SPRG field. */ |
1702 | #define XSPRG_MASK (XSPR_MASK &~ SPRG_MASK) | 1810 | #define XSPRG_MASK (XSPR_MASK & ~(0x17 << 16)) |
1703 | 1811 | ||
1704 | /* An X form instruction with everything filled in except the E field. */ | 1812 | /* An X form instruction with everything filled in except the E field. */ |
1705 | #define XE_MASK (0xffff7fff) | 1813 | #define XE_MASK (0xffff7fff) |
@@ -1769,6 +1877,9 @@ extract_tbr (unsigned long insn, | |||
1769 | #define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON | 1877 | #define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON |
1770 | #define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM | 1878 | #define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM |
1771 | #define POWER4 PPC_OPCODE_POWER4 | 1879 | #define POWER4 PPC_OPCODE_POWER4 |
1880 | #define POWER5 PPC_OPCODE_POWER5 | ||
1881 | #define POWER6 PPC_OPCODE_POWER6 | ||
1882 | #define CELL PPC_OPCODE_CELL | ||
1772 | #define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC | 1883 | #define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC |
1773 | #define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC | 1884 | #define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC |
1774 | #define PPC403 PPC_OPCODE_403 | 1885 | #define PPC403 PPC_OPCODE_403 |
@@ -1776,7 +1887,7 @@ extract_tbr (unsigned long insn, | |||
1776 | #define PPC440 PPC_OPCODE_440 | 1887 | #define PPC440 PPC_OPCODE_440 |
1777 | #define PPC750 PPC | 1888 | #define PPC750 PPC |
1778 | #define PPC860 PPC | 1889 | #define PPC860 PPC |
1779 | #define PPCVEC PPC_OPCODE_ALTIVEC | PPC_OPCODE_PPC | 1890 | #define PPCVEC PPC_OPCODE_ALTIVEC |
1780 | #define POWER PPC_OPCODE_POWER | 1891 | #define POWER PPC_OPCODE_POWER |
1781 | #define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | 1892 | #define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 |
1782 | #define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | 1893 | #define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2 |
@@ -1790,6 +1901,7 @@ extract_tbr (unsigned long insn, | |||
1790 | #define BOOKE PPC_OPCODE_BOOKE | 1901 | #define BOOKE PPC_OPCODE_BOOKE |
1791 | #define BOOKE64 PPC_OPCODE_BOOKE64 | 1902 | #define BOOKE64 PPC_OPCODE_BOOKE64 |
1792 | #define CLASSIC PPC_OPCODE_CLASSIC | 1903 | #define CLASSIC PPC_OPCODE_CLASSIC |
1904 | #define PPCE300 PPC_OPCODE_E300 | ||
1793 | #define PPCSPE PPC_OPCODE_SPE | 1905 | #define PPCSPE PPC_OPCODE_SPE |
1794 | #define PPCISEL PPC_OPCODE_ISEL | 1906 | #define PPCISEL PPC_OPCODE_ISEL |
1795 | #define PPCEFS PPC_OPCODE_EFS | 1907 | #define PPCEFS PPC_OPCODE_EFS |
@@ -1952,6 +2064,41 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
1952 | { "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, | 2064 | { "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, |
1953 | { "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } }, | 2065 | { "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } }, |
1954 | { "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } }, | 2066 | { "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } }, |
2067 | |||
2068 | /* Double-precision opcodes. */ | ||
2069 | /* Some of these conflict with AltiVec, so move them before, since | ||
2070 | PPCVEC includes the PPC_OPCODE_PPC set. */ | ||
2071 | { "efscfd", VX(4, 719), VX_MASK, PPCEFS, { RS, RB } }, | ||
2072 | { "efdabs", VX(4, 740), VX_MASK, PPCEFS, { RS, RA } }, | ||
2073 | { "efdnabs", VX(4, 741), VX_MASK, PPCEFS, { RS, RA } }, | ||
2074 | { "efdneg", VX(4, 742), VX_MASK, PPCEFS, { RS, RA } }, | ||
2075 | { "efdadd", VX(4, 736), VX_MASK, PPCEFS, { RS, RA, RB } }, | ||
2076 | { "efdsub", VX(4, 737), VX_MASK, PPCEFS, { RS, RA, RB } }, | ||
2077 | { "efdmul", VX(4, 744), VX_MASK, PPCEFS, { RS, RA, RB } }, | ||
2078 | { "efddiv", VX(4, 745), VX_MASK, PPCEFS, { RS, RA, RB } }, | ||
2079 | { "efdcmpgt", VX(4, 748), VX_MASK, PPCEFS, { CRFD, RA, RB } }, | ||
2080 | { "efdcmplt", VX(4, 749), VX_MASK, PPCEFS, { CRFD, RA, RB } }, | ||
2081 | { "efdcmpeq", VX(4, 750), VX_MASK, PPCEFS, { CRFD, RA, RB } }, | ||
2082 | { "efdtstgt", VX(4, 764), VX_MASK, PPCEFS, { CRFD, RA, RB } }, | ||
2083 | { "efdtstlt", VX(4, 765), VX_MASK, PPCEFS, { CRFD, RA, RB } }, | ||
2084 | { "efdtsteq", VX(4, 766), VX_MASK, PPCEFS, { CRFD, RA, RB } }, | ||
2085 | { "efdcfsi", VX(4, 753), VX_MASK, PPCEFS, { RS, RB } }, | ||
2086 | { "efdcfsid", VX(4, 739), VX_MASK, PPCEFS, { RS, RB } }, | ||
2087 | { "efdcfui", VX(4, 752), VX_MASK, PPCEFS, { RS, RB } }, | ||
2088 | { "efdcfuid", VX(4, 738), VX_MASK, PPCEFS, { RS, RB } }, | ||
2089 | { "efdcfsf", VX(4, 755), VX_MASK, PPCEFS, { RS, RB } }, | ||
2090 | { "efdcfuf", VX(4, 754), VX_MASK, PPCEFS, { RS, RB } }, | ||
2091 | { "efdctsi", VX(4, 757), VX_MASK, PPCEFS, { RS, RB } }, | ||
2092 | { "efdctsidz",VX(4, 747), VX_MASK, PPCEFS, { RS, RB } }, | ||
2093 | { "efdctsiz", VX(4, 762), VX_MASK, PPCEFS, { RS, RB } }, | ||
2094 | { "efdctui", VX(4, 756), VX_MASK, PPCEFS, { RS, RB } }, | ||
2095 | { "efdctuidz",VX(4, 746), VX_MASK, PPCEFS, { RS, RB } }, | ||
2096 | { "efdctuiz", VX(4, 760), VX_MASK, PPCEFS, { RS, RB } }, | ||
2097 | { "efdctsf", VX(4, 759), VX_MASK, PPCEFS, { RS, RB } }, | ||
2098 | { "efdctuf", VX(4, 758), VX_MASK, PPCEFS, { RS, RB } }, | ||
2099 | { "efdcfs", VX(4, 751), VX_MASK, PPCEFS, { RS, RB } }, | ||
2100 | /* End of double-precision opcodes. */ | ||
2101 | |||
1955 | { "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } }, | 2102 | { "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } }, |
1956 | { "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } }, | 2103 | { "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } }, |
1957 | { "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } }, | 2104 | { "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } }, |
@@ -2389,16 +2536,16 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
2389 | 2536 | ||
2390 | { "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } }, | 2537 | { "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } }, |
2391 | { "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } }, | 2538 | { "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } }, |
2392 | { "addi", OP(14), OP_MASK, PPCCOM, { RT, RA, SI } }, | 2539 | { "addi", OP(14), OP_MASK, PPCCOM, { RT, RA0, SI } }, |
2393 | { "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA } }, | 2540 | { "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA0 } }, |
2394 | { "subi", OP(14), OP_MASK, PPCCOM, { RT, RA, NSI } }, | 2541 | { "subi", OP(14), OP_MASK, PPCCOM, { RT, RA0, NSI } }, |
2395 | { "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA } }, | 2542 | { "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA0 } }, |
2396 | 2543 | ||
2397 | { "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } }, | 2544 | { "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } }, |
2398 | { "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } }, | 2545 | { "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } }, |
2399 | { "addis", OP(15), OP_MASK, PPCCOM, { RT,RA,SISIGNOPT } }, | 2546 | { "addis", OP(15), OP_MASK, PPCCOM, { RT,RA0,SISIGNOPT } }, |
2400 | { "cau", OP(15), OP_MASK, PWRCOM, { RT,RA,SISIGNOPT } }, | 2547 | { "cau", OP(15), OP_MASK, PWRCOM, { RT,RA0,SISIGNOPT } }, |
2401 | { "subis", OP(15), OP_MASK, PPCCOM, { RT, RA, NSI } }, | 2548 | { "subis", OP(15), OP_MASK, PPCCOM, { RT, RA0, NSI } }, |
2402 | 2549 | ||
2403 | { "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } }, | 2550 | { "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } }, |
2404 | { "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } }, | 2551 | { "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } }, |
@@ -2665,9 +2812,9 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
2665 | { "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } }, | 2812 | { "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } }, |
2666 | { "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } }, | 2813 | { "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } }, |
2667 | 2814 | ||
2668 | { "sc", SC(17,1,0), 0xffffffff, PPC, { 0 } }, | 2815 | { "sc", SC(17,1,0), SC_MASK, PPC, { LEV } }, |
2669 | { "svc", SC(17,0,0), SC_MASK, POWER, { LEV, FL1, FL2 } }, | 2816 | { "svc", SC(17,0,0), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, |
2670 | { "svcl", SC(17,0,1), SC_MASK, POWER, { LEV, FL1, FL2 } }, | 2817 | { "svcl", SC(17,0,1), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, |
2671 | { "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } }, | 2818 | { "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } }, |
2672 | { "svcla", SC(17,1,1), SC_MASK, POWER, { SV } }, | 2819 | { "svcla", SC(17,1,1), SC_MASK, POWER, { SV } }, |
2673 | 2820 | ||
@@ -2890,12 +3037,12 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
2890 | { "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, | 3037 | { "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, |
2891 | { "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, | 3038 | { "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, |
2892 | { "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, | 3039 | { "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, |
2893 | { "bclr", XLLK(19,16,0), XLYBB_MASK, PPCCOM, { BO, BI } }, | ||
2894 | { "bclrl", XLLK(19,16,1), XLYBB_MASK, PPCCOM, { BO, BI } }, | ||
2895 | { "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3040 | { "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
2896 | { "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3041 | { "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
2897 | { "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3042 | { "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
2898 | { "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3043 | { "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
3044 | { "bclr", XLLK(19,16,0), XLBH_MASK, PPCCOM, { BO, BI, BH } }, | ||
3045 | { "bclrl", XLLK(19,16,1), XLBH_MASK, PPCCOM, { BO, BI, BH } }, | ||
2899 | { "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } }, | 3046 | { "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } }, |
2900 | { "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } }, | 3047 | { "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } }, |
2901 | { "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } }, | 3048 | { "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } }, |
@@ -2924,14 +3071,23 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
2924 | 3071 | ||
2925 | { "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } }, | 3072 | { "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } }, |
2926 | 3073 | ||
3074 | { "hrfid", XL(19,274), 0xffffffff, POWER5 | CELL, { 0 } }, | ||
3075 | |||
2927 | { "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } }, | 3076 | { "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } }, |
2928 | { "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } }, | 3077 | { "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } }, |
2929 | 3078 | ||
3079 | { "doze", XL(19,402), 0xffffffff, POWER6, { 0 } }, | ||
3080 | |||
2930 | { "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } }, | 3081 | { "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } }, |
2931 | 3082 | ||
3083 | { "nap", XL(19,434), 0xffffffff, POWER6, { 0 } }, | ||
3084 | |||
2932 | { "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } }, | 3085 | { "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } }, |
2933 | { "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } }, | 3086 | { "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } }, |
2934 | 3087 | ||
3088 | { "sleep", XL(19,466), 0xffffffff, POWER6, { 0 } }, | ||
3089 | { "rvwinkle", XL(19,498), 0xffffffff, POWER6, { 0 } }, | ||
3090 | |||
2935 | { "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } }, | 3091 | { "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } }, |
2936 | { "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } }, | 3092 | { "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } }, |
2937 | { "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, | 3093 | { "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, |
@@ -3074,12 +3230,12 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3074 | { "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } }, | 3230 | { "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } }, |
3075 | { "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, | 3231 | { "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, |
3076 | { "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } }, | 3232 | { "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } }, |
3077 | { "bcctr", XLLK(19,528,0), XLYBB_MASK, PPCCOM, { BO, BI } }, | ||
3078 | { "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3233 | { "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
3079 | { "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3234 | { "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
3080 | { "bcctrl", XLLK(19,528,1), XLYBB_MASK, PPCCOM, { BO, BI } }, | ||
3081 | { "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3235 | { "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
3082 | { "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, | 3236 | { "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, |
3237 | { "bcctr", XLLK(19,528,0), XLBH_MASK, PPCCOM, { BO, BI, BH } }, | ||
3238 | { "bcctrl", XLLK(19,528,1), XLBH_MASK, PPCCOM, { BO, BI, BH } }, | ||
3083 | { "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } }, | 3239 | { "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } }, |
3084 | { "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } }, | 3240 | { "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } }, |
3085 | { "bcctre", XLLK(19,529,0), XLYBB_MASK, BOOKE64, { BO, BI } }, | 3241 | { "bcctre", XLLK(19,529,0), XLYBB_MASK, BOOKE64, { BO, BI } }, |
@@ -3158,8 +3314,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3158 | { "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, | 3314 | { "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, |
3159 | { "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, | 3315 | { "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, |
3160 | 3316 | ||
3161 | { "cmpw", XCMPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, | 3317 | { "cmpw", XOPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, |
3162 | { "cmpd", XCMPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, | 3318 | { "cmpd", XOPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, |
3163 | { "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } }, | 3319 | { "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } }, |
3164 | { "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, | 3320 | { "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, |
3165 | 3321 | ||
@@ -3228,17 +3384,18 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3228 | { "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } }, | 3384 | { "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } }, |
3229 | { "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } }, | 3385 | { "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } }, |
3230 | 3386 | ||
3231 | { "mfcr", X(31,19), XRARB_MASK, NOPOWER4, { RT } }, | 3387 | { "mfocrf", XFXM(31,19,0,1), XFXFXM_MASK, COM, { RT, FXM } }, |
3388 | { "mfcr", X(31,19), XRARB_MASK, NOPOWER4 | COM, { RT } }, | ||
3232 | { "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } }, | 3389 | { "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } }, |
3233 | 3390 | ||
3234 | { "lwarx", X(31,20), X_MASK, PPC, { RT, RA, RB } }, | 3391 | { "lwarx", X(31,20), XEH_MASK, PPC, { RT, RA0, RB, EH } }, |
3235 | 3392 | ||
3236 | { "ldx", X(31,21), X_MASK, PPC64, { RT, RA, RB } }, | 3393 | { "ldx", X(31,21), X_MASK, PPC64, { RT, RA0, RB } }, |
3237 | 3394 | ||
3238 | { "icbt", X(31,22), X_MASK, BOOKE, { CT, RA, RB } }, | 3395 | { "icbt", X(31,22), X_MASK, BOOKE|PPCE300, { CT, RA, RB } }, |
3239 | { "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } }, | 3396 | { "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } }, |
3240 | 3397 | ||
3241 | { "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA, RB } }, | 3398 | { "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA0, RB } }, |
3242 | { "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } }, | 3399 | { "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } }, |
3243 | 3400 | ||
3244 | { "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } }, | 3401 | { "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } }, |
@@ -3262,10 +3419,10 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3262 | 3419 | ||
3263 | { "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } }, | 3420 | { "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } }, |
3264 | 3421 | ||
3265 | { "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA, RB } }, | 3422 | { "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA0, RB } }, |
3266 | 3423 | ||
3267 | { "cmplw", XCMPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, | 3424 | { "cmplw", XOPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, |
3268 | { "cmpld", XCMPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, | 3425 | { "cmpld", XOPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, |
3269 | { "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } }, | 3426 | { "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } }, |
3270 | { "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, | 3427 | { "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, |
3271 | 3428 | ||
@@ -3324,15 +3481,16 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3324 | 3481 | ||
3325 | { "mfmsr", X(31,83), XRARB_MASK, COM, { RT } }, | 3482 | { "mfmsr", X(31,83), XRARB_MASK, COM, { RT } }, |
3326 | 3483 | ||
3327 | { "ldarx", X(31,84), X_MASK, PPC64, { RT, RA, RB } }, | 3484 | { "ldarx", X(31,84), XEH_MASK, PPC64, { RT, RA0, RB, EH } }, |
3328 | 3485 | ||
3329 | { "dcbf", X(31,86), XRT_MASK, PPC, { RA, RB } }, | 3486 | { "dcbfl", XOPL(31,86,1), XRT_MASK, POWER5, { RA, RB } }, |
3487 | { "dcbf", X(31,86), XLRT_MASK, PPC, { RA, RB, XRT_L } }, | ||
3330 | 3488 | ||
3331 | { "lbzx", X(31,87), X_MASK, COM, { RT, RA, RB } }, | 3489 | { "lbzx", X(31,87), X_MASK, COM, { RT, RA0, RB } }, |
3332 | 3490 | ||
3333 | { "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } }, | 3491 | { "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } }, |
3334 | 3492 | ||
3335 | { "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA, RB } }, | 3493 | { "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA0, RB } }, |
3336 | 3494 | ||
3337 | { "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } }, | 3495 | { "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } }, |
3338 | { "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } }, | 3496 | { "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } }, |
@@ -3350,12 +3508,14 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3350 | 3508 | ||
3351 | { "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } }, | 3509 | { "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } }, |
3352 | 3510 | ||
3511 | { "popcntb", X(31,122), XRB_MASK, POWER5, { RA, RS } }, | ||
3512 | |||
3353 | { "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } }, | 3513 | { "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } }, |
3354 | { "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } }, | 3514 | { "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } }, |
3355 | { "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } }, | 3515 | { "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } }, |
3356 | { "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } }, | 3516 | { "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } }, |
3357 | 3517 | ||
3358 | { "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA, RB } }, | 3518 | { "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA0, RB } }, |
3359 | 3519 | ||
3360 | { "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } }, | 3520 | { "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } }, |
3361 | 3521 | ||
@@ -3383,21 +3543,22 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3383 | 3543 | ||
3384 | { "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }}, | 3544 | { "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }}, |
3385 | 3545 | ||
3386 | { "mtcr", XFXM(31,144,0xff), XRARB_MASK, COM, { RS }}, | 3546 | { "mtocrf", XFXM(31,144,0,1), XFXFXM_MASK, COM, { FXM, RS } }, |
3547 | { "mtcr", XFXM(31,144,0xff,0), XRARB_MASK, COM, { RS }}, | ||
3387 | { "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } }, | 3548 | { "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } }, |
3388 | 3549 | ||
3389 | { "mtmsr", X(31,146), XRARB_MASK, COM, { RS } }, | 3550 | { "mtmsr", X(31,146), XRARB_MASK, COM, { RS } }, |
3390 | 3551 | ||
3391 | { "stdx", X(31,149), X_MASK, PPC64, { RS, RA, RB } }, | 3552 | { "stdx", X(31,149), X_MASK, PPC64, { RS, RA0, RB } }, |
3392 | 3553 | ||
3393 | { "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA, RB } }, | 3554 | { "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA0, RB } }, |
3394 | 3555 | ||
3395 | { "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA, RB } }, | 3556 | { "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA0, RB } }, |
3396 | { "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } }, | 3557 | { "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } }, |
3397 | 3558 | ||
3398 | { "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA, RB } }, | 3559 | { "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA0, RB } }, |
3399 | 3560 | ||
3400 | { "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA, RB } }, | 3561 | { "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA0, RB } }, |
3401 | 3562 | ||
3402 | { "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } }, | 3563 | { "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } }, |
3403 | { "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } }, | 3564 | { "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } }, |
@@ -3405,6 +3566,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3405 | { "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } }, | 3566 | { "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } }, |
3406 | { "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } }, | 3567 | { "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } }, |
3407 | 3568 | ||
3569 | { "prtyw", X(31,154), XRB_MASK, POWER6, { RA, RS } }, | ||
3570 | |||
3408 | { "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } }, | 3571 | { "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } }, |
3409 | 3572 | ||
3410 | { "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }}, | 3573 | { "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }}, |
@@ -3415,11 +3578,13 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3415 | { "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } }, | 3578 | { "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } }, |
3416 | 3579 | ||
3417 | { "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } }, | 3580 | { "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } }, |
3418 | { "stux", X(31,183), X_MASK, PWRCOM, { RS, RA, RB } }, | 3581 | { "stux", X(31,183), X_MASK, PWRCOM, { RS, RA0, RB } }, |
3419 | 3582 | ||
3420 | { "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } }, | 3583 | { "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } }, |
3421 | { "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } }, | 3584 | { "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } }, |
3422 | 3585 | ||
3586 | { "prtyd", X(31,186), XRB_MASK, POWER6, { RA, RS } }, | ||
3587 | |||
3423 | { "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } }, | 3588 | { "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } }, |
3424 | 3589 | ||
3425 | { "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } }, | 3590 | { "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } }, |
@@ -3442,9 +3607,9 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3442 | 3607 | ||
3443 | { "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } }, | 3608 | { "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } }, |
3444 | 3609 | ||
3445 | { "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA, RB } }, | 3610 | { "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA0, RB } }, |
3446 | 3611 | ||
3447 | { "stbx", X(31,215), X_MASK, COM, { RS, RA, RB } }, | 3612 | { "stbx", X(31,215), X_MASK, COM, { RS, RA0, RB } }, |
3448 | 3613 | ||
3449 | { "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } }, | 3614 | { "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } }, |
3450 | { "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } }, | 3615 | { "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } }, |
@@ -3452,7 +3617,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3452 | { "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } }, | 3617 | { "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } }, |
3453 | { "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } }, | 3618 | { "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } }, |
3454 | 3619 | ||
3455 | { "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA, RB } }, | 3620 | { "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA0, RB } }, |
3456 | 3621 | ||
3457 | { "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }}, | 3622 | { "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }}, |
3458 | 3623 | ||
@@ -3492,7 +3657,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3492 | { "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } }, | 3657 | { "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } }, |
3493 | { "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } }, | 3658 | { "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } }, |
3494 | 3659 | ||
3495 | { "dcbtst", X(31,246), XRT_MASK, PPC, { CT, RA, RB } }, | 3660 | { "dcbtst", X(31,246), X_MASK, PPC, { CT, RA, RB } }, |
3496 | 3661 | ||
3497 | { "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } }, | 3662 | { "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } }, |
3498 | 3663 | ||
@@ -3519,26 +3684,26 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3519 | { "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, | 3684 | { "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, |
3520 | { "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, | 3685 | { "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, |
3521 | 3686 | ||
3522 | { "tlbiel", X(31,274), XRTRA_MASK, POWER4, { RB } }, | 3687 | { "tlbiel", X(31,274), XRTLRA_MASK, POWER4, { RB, L } }, |
3523 | 3688 | ||
3524 | { "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } }, | 3689 | { "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } }, |
3525 | 3690 | ||
3526 | { "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } }, | 3691 | { "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } }, |
3527 | { "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } }, | 3692 | { "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } }, |
3528 | 3693 | ||
3529 | { "dcbt", X(31,278), XRT_MASK, PPC, { CT, RA, RB } }, | 3694 | { "dcbt", X(31,278), X_MASK, PPC, { CT, RA, RB } }, |
3530 | 3695 | ||
3531 | { "lhzx", X(31,279), X_MASK, COM, { RT, RA, RB } }, | 3696 | { "lhzx", X(31,279), X_MASK, COM, { RT, RA0, RB } }, |
3532 | 3697 | ||
3533 | { "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } }, | 3698 | { "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } }, |
3534 | { "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } }, | 3699 | { "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } }, |
3535 | 3700 | ||
3536 | { "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } }, | 3701 | { "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } }, |
3537 | 3702 | ||
3538 | { "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA, RB } }, | 3703 | { "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA0, RB } }, |
3539 | 3704 | ||
3540 | { "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } }, | 3705 | { "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } }, |
3541 | { "tlbi", X(31,306), XRT_MASK, POWER, { RA, RB } }, | 3706 | { "tlbi", X(31,306), XRT_MASK, POWER, { RA0, RB } }, |
3542 | 3707 | ||
3543 | { "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } }, | 3708 | { "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } }, |
3544 | 3709 | ||
@@ -3607,6 +3772,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3607 | { "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } }, | 3772 | { "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } }, |
3608 | { "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } }, | 3773 | { "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } }, |
3609 | { "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } }, | 3774 | { "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } }, |
3775 | { "mfcfar", XSPR(31,339,28), XSPR_MASK, POWER6, { RT } }, | ||
3610 | { "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } }, | 3776 | { "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } }, |
3611 | { "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } }, | 3777 | { "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } }, |
3612 | { "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } }, | 3778 | { "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } }, |
@@ -3634,21 +3800,21 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3634 | { "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } }, | 3800 | { "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } }, |
3635 | { "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } }, | 3801 | { "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } }, |
3636 | { "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } }, | 3802 | { "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } }, |
3637 | { "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405, { RT } }, | ||
3638 | { "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405, { RT } }, | ||
3639 | { "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405, { RT } }, | ||
3640 | { "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405, { RT } }, | ||
3641 | { "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } }, | 3803 | { "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } }, |
3642 | { "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, | 3804 | { "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, |
3643 | { "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } }, | 3805 | { "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } }, |
3644 | { "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, | 3806 | { "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, |
3645 | { "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } }, | 3807 | { "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } }, |
3646 | { "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } }, | 3808 | { "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } }, |
3647 | { "mfsprg", XSPR(31,339,272), XSPRG_MASK, PPC, { RT, SPRG } }, | 3809 | { "mfsprg", XSPR(31,339,256), XSPRG_MASK, PPC, { RT, SPRG } }, |
3648 | { "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } }, | 3810 | { "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } }, |
3649 | { "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } }, | 3811 | { "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } }, |
3650 | { "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } }, | 3812 | { "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } }, |
3651 | { "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } }, | 3813 | { "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } }, |
3814 | { "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405 | BOOKE, { RT } }, | ||
3815 | { "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405 | BOOKE, { RT } }, | ||
3816 | { "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405 | BOOKE, { RT } }, | ||
3817 | { "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405 | BOOKE, { RT } }, | ||
3652 | { "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } }, | 3818 | { "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } }, |
3653 | { "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } }, | 3819 | { "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } }, |
3654 | { "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } }, | 3820 | { "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } }, |
@@ -3699,6 +3865,10 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3699 | { "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } }, | 3865 | { "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } }, |
3700 | { "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } }, | 3866 | { "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } }, |
3701 | { "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } }, | 3867 | { "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } }, |
3868 | { "mfivor32", XSPR(31,339,528), XSPR_MASK, PPCSPE, { RT } }, | ||
3869 | { "mfivor33", XSPR(31,339,529), XSPR_MASK, PPCSPE, { RT } }, | ||
3870 | { "mfivor34", XSPR(31,339,530), XSPR_MASK, PPCSPE, { RT } }, | ||
3871 | { "mfivor35", XSPR(31,339,531), XSPR_MASK, PPCPMR, { RT } }, | ||
3702 | { "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, | 3872 | { "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, |
3703 | { "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, | 3873 | { "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, |
3704 | { "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, | 3874 | { "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, |
@@ -3708,10 +3878,11 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3708 | { "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } }, | 3878 | { "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } }, |
3709 | { "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } }, | 3879 | { "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } }, |
3710 | { "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } }, | 3880 | { "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } }, |
3711 | { "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } }, | ||
3712 | { "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } }, | 3881 | { "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } }, |
3882 | { "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } }, | ||
3713 | { "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } }, | 3883 | { "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } }, |
3714 | { "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } }, | 3884 | { "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } }, |
3885 | { "mfmcar", XSPR(31,339,573), XSPR_MASK, PPCRFMCI, { RT } }, | ||
3715 | { "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } }, | 3886 | { "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } }, |
3716 | { "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } }, | 3887 | { "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } }, |
3717 | { "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } }, | 3888 | { "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } }, |
@@ -3775,14 +3946,14 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3775 | { "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } }, | 3946 | { "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } }, |
3776 | { "mfspr", X(31,339), X_MASK, COM, { RT, SPR } }, | 3947 | { "mfspr", X(31,339), X_MASK, COM, { RT, SPR } }, |
3777 | 3948 | ||
3778 | { "lwax", X(31,341), X_MASK, PPC64, { RT, RA, RB } }, | 3949 | { "lwax", X(31,341), X_MASK, PPC64, { RT, RA0, RB } }, |
3779 | 3950 | ||
3780 | { "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, | 3951 | { "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, |
3781 | { "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, | 3952 | { "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, |
3782 | 3953 | ||
3783 | { "lhax", X(31,343), X_MASK, COM, { RT, RA, RB } }, | 3954 | { "lhax", X(31,343), X_MASK, COM, { RT, RA0, RB } }, |
3784 | 3955 | ||
3785 | { "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA, RB } }, | 3956 | { "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA0, RB } }, |
3786 | 3957 | ||
3787 | { "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, | 3958 | { "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, |
3788 | { "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, | 3959 | { "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, |
@@ -3821,14 +3992,20 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3821 | 3992 | ||
3822 | { "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } }, | 3993 | { "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } }, |
3823 | 3994 | ||
3824 | { "sthx", X(31,407), X_MASK, COM, { RS, RA, RB } }, | 3995 | { "sthx", X(31,407), X_MASK, COM, { RS, RA0, RB } }, |
3996 | |||
3997 | { "cmpb", X(31,508), X_MASK, POWER6, { RA, RS, RB } }, | ||
3825 | 3998 | ||
3826 | { "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } }, | 3999 | { "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } }, |
3827 | 4000 | ||
4001 | { "lfdpx", X(31,791), X_MASK, POWER6, { FRT, RA, RB } }, | ||
4002 | |||
3828 | { "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } }, | 4003 | { "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } }, |
3829 | 4004 | ||
3830 | { "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } }, | 4005 | { "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } }, |
3831 | 4006 | ||
4007 | { "stfdpx", X(31,919), X_MASK, POWER6, { FRS, RA, RB } }, | ||
4008 | |||
3832 | { "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } }, | 4009 | { "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } }, |
3833 | 4010 | ||
3834 | { "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } }, | 4011 | { "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } }, |
@@ -3837,7 +4014,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3837 | { "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } }, | 4014 | { "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } }, |
3838 | { "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } }, | 4015 | { "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } }, |
3839 | 4016 | ||
3840 | { "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA, RB } }, | 4017 | { "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA0, RB } }, |
3841 | 4018 | ||
3842 | { "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } }, | 4019 | { "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } }, |
3843 | 4020 | ||
@@ -3918,6 +4095,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3918 | { "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } }, | 4095 | { "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } }, |
3919 | { "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } }, | 4096 | { "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } }, |
3920 | { "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } }, | 4097 | { "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } }, |
4098 | { "mtcfar", XSPR(31,467,28), XSPR_MASK, POWER6, { RS } }, | ||
3921 | { "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } }, | 4099 | { "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } }, |
3922 | { "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } }, | 4100 | { "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } }, |
3923 | { "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } }, | 4101 | { "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } }, |
@@ -3946,7 +4124,7 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
3946 | { "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } }, | 4124 | { "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } }, |
3947 | { "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } }, | 4125 | { "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } }, |
3948 | { "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } }, | 4126 | { "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } }, |
3949 | { "mtsprg", XSPR(31,467,272), XSPRG_MASK,PPC, { SPRG, RS } }, | 4127 | { "mtsprg", XSPR(31,467,256), XSPRG_MASK,PPC, { SPRG, RS } }, |
3950 | { "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } }, | 4128 | { "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } }, |
3951 | { "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } }, | 4129 | { "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } }, |
3952 | { "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } }, | 4130 | { "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } }, |
@@ -4005,6 +4183,10 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4005 | { "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } }, | 4183 | { "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } }, |
4006 | { "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } }, | 4184 | { "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } }, |
4007 | { "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } }, | 4185 | { "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } }, |
4186 | { "mtivor32", XSPR(31,467,528), XSPR_MASK, PPCSPE, { RS } }, | ||
4187 | { "mtivor33", XSPR(31,467,529), XSPR_MASK, PPCSPE, { RS } }, | ||
4188 | { "mtivor34", XSPR(31,467,530), XSPR_MASK, PPCSPE, { RS } }, | ||
4189 | { "mtivor35", XSPR(31,467,531), XSPR_MASK, PPCPMR, { RS } }, | ||
4008 | { "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, | 4190 | { "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, |
4009 | { "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, | 4191 | { "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, |
4010 | { "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, | 4192 | { "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, |
@@ -4101,13 +4283,15 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4101 | 4283 | ||
4102 | { "clcs", X(31,531), XRB_MASK, M601, { RT, RA } }, | 4284 | { "clcs", X(31,531), XRB_MASK, M601, { RT, RA } }, |
4103 | 4285 | ||
4104 | { "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA, RB } }, | 4286 | { "ldbrx", X(31,532), X_MASK, CELL, { RT, RA0, RB } }, |
4287 | |||
4288 | { "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA0, RB } }, | ||
4105 | { "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } }, | 4289 | { "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } }, |
4106 | 4290 | ||
4107 | { "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA, RB } }, | 4291 | { "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA0, RB } }, |
4108 | { "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } }, | 4292 | { "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } }, |
4109 | 4293 | ||
4110 | { "lfsx", X(31,535), X_MASK, COM, { FRT, RA, RB } }, | 4294 | { "lfsx", X(31,535), X_MASK, COM, { FRT, RA0, RB } }, |
4111 | 4295 | ||
4112 | { "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } }, | 4296 | { "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } }, |
4113 | { "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } }, | 4297 | { "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } }, |
@@ -4123,11 +4307,12 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4123 | { "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } }, | 4307 | { "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } }, |
4124 | { "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } }, | 4308 | { "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } }, |
4125 | 4309 | ||
4126 | { "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA, RB } }, | 4310 | { "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA0, RB } }, |
4127 | 4311 | ||
4128 | { "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA, RB } }, | 4312 | { "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA0, RB } }, |
4129 | 4313 | ||
4130 | { "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }}, | 4314 | { "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }}, |
4315 | |||
4131 | { "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } }, | 4316 | { "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } }, |
4132 | 4317 | ||
4133 | { "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } }, | 4318 | { "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } }, |
@@ -4136,8 +4321,8 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4136 | 4321 | ||
4137 | { "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } }, | 4322 | { "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } }, |
4138 | 4323 | ||
4139 | { "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA, NB } }, | 4324 | { "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA0, NB } }, |
4140 | { "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA, NB } }, | 4325 | { "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA0, NB } }, |
4141 | 4326 | ||
4142 | { "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } }, | 4327 | { "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } }, |
4143 | { "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } }, | 4328 | { "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } }, |
@@ -4145,9 +4330,11 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4145 | { "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } }, | 4330 | { "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } }, |
4146 | { "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } }, | 4331 | { "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } }, |
4147 | 4332 | ||
4148 | { "lfdx", X(31,599), X_MASK, COM, { FRT, RA, RB } }, | 4333 | { "lfdx", X(31,599), X_MASK, COM, { FRT, RA0, RB } }, |
4334 | |||
4335 | { "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA0, RB } }, | ||
4149 | 4336 | ||
4150 | { "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA, RB } }, | 4337 | { "mffgpr", XRC(31,607,0), XRA_MASK, POWER6, { FRT, RB } }, |
4151 | 4338 | ||
4152 | { "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } }, | 4339 | { "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } }, |
4153 | 4340 | ||
@@ -4159,13 +4346,15 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4159 | 4346 | ||
4160 | { "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } }, | 4347 | { "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } }, |
4161 | 4348 | ||
4162 | { "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA, RB } }, | 4349 | { "stdbrx", X(31,660), X_MASK, CELL, { RS, RA0, RB } }, |
4163 | { "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA, RB } }, | 4350 | |
4351 | { "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA0, RB } }, | ||
4352 | { "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA0, RB } }, | ||
4164 | 4353 | ||
4165 | { "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA, RB } }, | 4354 | { "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA0, RB } }, |
4166 | { "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA, RB } }, | 4355 | { "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA0, RB } }, |
4167 | 4356 | ||
4168 | { "stfsx", X(31,663), X_MASK, COM, { FRS, RA, RB } }, | 4357 | { "stfsx", X(31,663), X_MASK, COM, { FRS, RA0, RB } }, |
4169 | 4358 | ||
4170 | { "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } }, | 4359 | { "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } }, |
4171 | { "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } }, | 4360 | { "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } }, |
@@ -4173,9 +4362,9 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4173 | { "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } }, | 4362 | { "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } }, |
4174 | { "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } }, | 4363 | { "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } }, |
4175 | 4364 | ||
4176 | { "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA, RB } }, | 4365 | { "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA0, RB } }, |
4177 | 4366 | ||
4178 | { "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA, RB } }, | 4367 | { "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA0, RB } }, |
4179 | 4368 | ||
4180 | { "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } }, | 4369 | { "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } }, |
4181 | 4370 | ||
@@ -4184,10 +4373,10 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4184 | 4373 | ||
4185 | { "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } }, | 4374 | { "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } }, |
4186 | 4375 | ||
4187 | { "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA, NB } }, | 4376 | { "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA0, NB } }, |
4188 | { "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA, NB } }, | 4377 | { "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA0, NB } }, |
4189 | 4378 | ||
4190 | { "stfdx", X(31,727), X_MASK, COM, { FRS, RA, RB } }, | 4379 | { "stfdx", X(31,727), X_MASK, COM, { FRS, RA0, RB } }, |
4191 | 4380 | ||
4192 | { "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } }, | 4381 | { "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } }, |
4193 | { "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } }, | 4382 | { "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } }, |
@@ -4195,7 +4384,9 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4195 | { "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } }, | 4384 | { "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } }, |
4196 | { "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } }, | 4385 | { "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } }, |
4197 | 4386 | ||
4198 | { "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA, RB } }, | 4387 | { "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA0, RB } }, |
4388 | |||
4389 | { "mftgpr", XRC(31,735,0), XRA_MASK, POWER6, { RT, FRB } }, | ||
4199 | 4390 | ||
4200 | { "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } }, | 4391 | { "dcba", X(31,758), XRT_MASK, PPC405 | BOOKE, { RA, RB } }, |
4201 | 4392 | ||
@@ -4211,7 +4402,9 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4211 | { "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } }, | 4402 | { "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } }, |
4212 | { "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } }, | 4403 | { "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } }, |
4213 | 4404 | ||
4214 | { "lhbrx", X(31,790), X_MASK, COM, { RT, RA, RB } }, | 4405 | { "lwzcix", X(31,789), X_MASK, POWER6, { RT, RA0, RB } }, |
4406 | |||
4407 | { "lhbrx", X(31,790), X_MASK, COM, { RT, RA0, RB } }, | ||
4215 | 4408 | ||
4216 | { "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } }, | 4409 | { "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } }, |
4217 | { "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } }, | 4410 | { "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } }, |
@@ -4221,13 +4414,15 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4221 | { "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } }, | 4414 | { "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } }, |
4222 | { "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } }, | 4415 | { "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } }, |
4223 | 4416 | ||
4224 | { "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA, RB } }, | 4417 | { "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA0, RB } }, |
4225 | 4418 | ||
4226 | { "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA, RB } }, | 4419 | { "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA0, RB } }, |
4227 | { "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA, RB } }, | 4420 | { "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA0, RB } }, |
4228 | 4421 | ||
4229 | { "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } }, | 4422 | { "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } }, |
4230 | 4423 | ||
4424 | { "lhzcix", X(31,821), X_MASK, POWER6, { RT, RA0, RB } }, | ||
4425 | |||
4231 | { "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } }, | 4426 | { "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } }, |
4232 | { "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } }, | 4427 | { "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } }, |
4233 | 4428 | ||
@@ -4238,19 +4433,25 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4238 | 4433 | ||
4239 | { "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } }, | 4434 | { "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } }, |
4240 | 4435 | ||
4436 | { "lbzcix", X(31,853), X_MASK, POWER6, { RT, RA0, RB } }, | ||
4437 | |||
4241 | { "mbar", X(31,854), X_MASK, BOOKE, { MO } }, | 4438 | { "mbar", X(31,854), X_MASK, BOOKE, { MO } }, |
4242 | { "eieio", X(31,854), 0xffffffff, PPC, { 0 } }, | 4439 | { "eieio", X(31,854), 0xffffffff, PPC, { 0 } }, |
4243 | 4440 | ||
4244 | { "tlbsx", XRC(31,914,0), X_MASK, BOOKE, { RA, RB } }, | 4441 | { "lfiwax", X(31,855), X_MASK, POWER6, { FRT, RA0, RB } }, |
4245 | { "tlbsx", XRC(31,914,0), X_MASK, PPC403, { RT, RA, RB } }, | 4442 | |
4246 | { "tlbsx.", XRC(31,914,1), X_MASK, BOOKE, { RA, RB } }, | 4443 | { "ldcix", X(31,885), X_MASK, POWER6, { RT, RA0, RB } }, |
4247 | { "tlbsx.", XRC(31,914,1), X_MASK, PPC403, { RT, RA, RB } }, | 4444 | |
4445 | { "tlbsx", XRC(31,914,0), X_MASK, PPC403|BOOKE, { RTO, RA, RB } }, | ||
4446 | { "tlbsx.", XRC(31,914,1), X_MASK, PPC403|BOOKE, { RTO, RA, RB } }, | ||
4248 | { "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RA, RB } }, | 4447 | { "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RA, RB } }, |
4249 | { "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RA, RB } }, | 4448 | { "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RA, RB } }, |
4250 | 4449 | ||
4251 | { "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } }, | 4450 | { "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } }, |
4252 | 4451 | ||
4253 | { "sthbrx", X(31,918), X_MASK, COM, { RS, RA, RB } }, | 4452 | { "stwcix", X(31,917), X_MASK, POWER6, { RS, RA0, RB } }, |
4453 | |||
4454 | { "sthbrx", X(31,918), X_MASK, COM, { RS, RA0, RB } }, | ||
4254 | 4455 | ||
4255 | { "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } }, | 4456 | { "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } }, |
4256 | { "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } }, | 4457 | { "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } }, |
@@ -4263,14 +4464,15 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4263 | { "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } }, | 4464 | { "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } }, |
4264 | { "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } }, | 4465 | { "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } }, |
4265 | 4466 | ||
4266 | { "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA, RB } }, | 4467 | { "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA0, RB } }, |
4267 | 4468 | ||
4268 | { "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA, RB } }, | 4469 | { "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA0, RB } }, |
4269 | 4470 | ||
4270 | { "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } }, | 4471 | { "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } }, |
4271 | { "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } }, | 4472 | { "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } }, |
4272 | { "tlbre", X(31,946), X_MASK, BOOKE, { 0 } }, | 4473 | { "tlbre", X(31,946), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } }, |
4273 | { "tlbre", X(31,946), X_MASK, PPC403, { RS, RA, SH } }, | 4474 | |
4475 | { "sthcix", X(31,949), X_MASK, POWER6, { RS, RA0, RB } }, | ||
4274 | 4476 | ||
4275 | { "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } }, | 4477 | { "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } }, |
4276 | { "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } }, | 4478 | { "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } }, |
@@ -4284,13 +4486,14 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4284 | 4486 | ||
4285 | { "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } }, | 4487 | { "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } }, |
4286 | { "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } }, | 4488 | { "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } }, |
4287 | { "tlbwe", X(31,978), X_MASK, BOOKE, { 0 } }, | 4489 | { "tlbwe", X(31,978), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } }, |
4288 | { "tlbwe", X(31,978), X_MASK, PPC403, { RS, RA, SH } }, | ||
4289 | { "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } }, | 4490 | { "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } }, |
4290 | 4491 | ||
4492 | { "stbcix", X(31,981), X_MASK, POWER6, { RS, RA0, RB } }, | ||
4493 | |||
4291 | { "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } }, | 4494 | { "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } }, |
4292 | 4495 | ||
4293 | { "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA, RB } }, | 4496 | { "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA0, RB } }, |
4294 | 4497 | ||
4295 | { "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } }, | 4498 | { "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } }, |
4296 | { "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } }, | 4499 | { "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } }, |
@@ -4298,10 +4501,13 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4298 | { "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } }, | 4501 | { "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } }, |
4299 | 4502 | ||
4300 | { "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } }, | 4503 | { "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } }, |
4301 | { "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA, RB } }, | 4504 | { "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA0, RB } }, |
4302 | 4505 | ||
4303 | { "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } }, | 4506 | { "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } }, |
4304 | 4507 | ||
4508 | { "stdcix", X(31,1013), X_MASK, POWER6, { RS, RA0, RB } }, | ||
4509 | |||
4510 | { "dcbzl", XOPL(31,1014,1), XRT_MASK,POWER4, { RA, RB } }, | ||
4305 | { "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, | 4511 | { "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, |
4306 | { "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, | 4512 | { "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, |
4307 | 4513 | ||
@@ -4320,86 +4526,104 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4320 | { "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } }, | 4526 | { "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } }, |
4321 | { "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } }, | 4527 | { "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } }, |
4322 | 4528 | ||
4323 | { "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA } }, | 4529 | /* New load/store left/right index vector instructions that are in the Cell only. */ |
4324 | { "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA } }, | 4530 | { "lvlx", X(31, 519), X_MASK, CELL, { VD, RA0, RB } }, |
4531 | { "lvlxl", X(31, 775), X_MASK, CELL, { VD, RA0, RB } }, | ||
4532 | { "lvrx", X(31, 551), X_MASK, CELL, { VD, RA0, RB } }, | ||
4533 | { "lvrxl", X(31, 807), X_MASK, CELL, { VD, RA0, RB } }, | ||
4534 | { "stvlx", X(31, 647), X_MASK, CELL, { VS, RA0, RB } }, | ||
4535 | { "stvlxl", X(31, 903), X_MASK, CELL, { VS, RA0, RB } }, | ||
4536 | { "stvrx", X(31, 679), X_MASK, CELL, { VS, RA0, RB } }, | ||
4537 | { "stvrxl", X(31, 935), X_MASK, CELL, { VS, RA0, RB } }, | ||
4538 | |||
4539 | { "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA0 } }, | ||
4540 | { "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA0 } }, | ||
4325 | 4541 | ||
4326 | { "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } }, | 4542 | { "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } }, |
4327 | { "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA } }, | 4543 | { "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA0 } }, |
4328 | 4544 | ||
4329 | { "lbz", OP(34), OP_MASK, COM, { RT, D, RA } }, | 4545 | { "lbz", OP(34), OP_MASK, COM, { RT, D, RA0 } }, |
4330 | 4546 | ||
4331 | { "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } }, | 4547 | { "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } }, |
4332 | 4548 | ||
4333 | { "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA } }, | 4549 | { "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA0 } }, |
4334 | { "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA } }, | 4550 | { "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA0 } }, |
4335 | 4551 | ||
4336 | { "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } }, | 4552 | { "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } }, |
4337 | { "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA } }, | 4553 | { "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA0 } }, |
4338 | 4554 | ||
4339 | { "stb", OP(38), OP_MASK, COM, { RS, D, RA } }, | 4555 | { "stb", OP(38), OP_MASK, COM, { RS, D, RA0 } }, |
4340 | 4556 | ||
4341 | { "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } }, | 4557 | { "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } }, |
4342 | 4558 | ||
4343 | { "lhz", OP(40), OP_MASK, COM, { RT, D, RA } }, | 4559 | { "lhz", OP(40), OP_MASK, COM, { RT, D, RA0 } }, |
4344 | 4560 | ||
4345 | { "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } }, | 4561 | { "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } }, |
4346 | 4562 | ||
4347 | { "lha", OP(42), OP_MASK, COM, { RT, D, RA } }, | 4563 | { "lha", OP(42), OP_MASK, COM, { RT, D, RA0 } }, |
4348 | 4564 | ||
4349 | { "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } }, | 4565 | { "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } }, |
4350 | 4566 | ||
4351 | { "sth", OP(44), OP_MASK, COM, { RS, D, RA } }, | 4567 | { "sth", OP(44), OP_MASK, COM, { RS, D, RA0 } }, |
4352 | 4568 | ||
4353 | { "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } }, | 4569 | { "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } }, |
4354 | 4570 | ||
4355 | { "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } }, | 4571 | { "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } }, |
4356 | { "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA } }, | 4572 | { "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA0 } }, |
4357 | 4573 | ||
4358 | { "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA } }, | 4574 | { "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA0 } }, |
4359 | { "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA } }, | 4575 | { "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA0 } }, |
4360 | 4576 | ||
4361 | { "lfs", OP(48), OP_MASK, COM, { FRT, D, RA } }, | 4577 | { "lfs", OP(48), OP_MASK, COM, { FRT, D, RA0 } }, |
4362 | 4578 | ||
4363 | { "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } }, | 4579 | { "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } }, |
4364 | 4580 | ||
4365 | { "lfd", OP(50), OP_MASK, COM, { FRT, D, RA } }, | 4581 | { "lfd", OP(50), OP_MASK, COM, { FRT, D, RA0 } }, |
4366 | 4582 | ||
4367 | { "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } }, | 4583 | { "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } }, |
4368 | 4584 | ||
4369 | { "stfs", OP(52), OP_MASK, COM, { FRS, D, RA } }, | 4585 | { "stfs", OP(52), OP_MASK, COM, { FRS, D, RA0 } }, |
4370 | 4586 | ||
4371 | { "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } }, | 4587 | { "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } }, |
4372 | 4588 | ||
4373 | { "stfd", OP(54), OP_MASK, COM, { FRS, D, RA } }, | 4589 | { "stfd", OP(54), OP_MASK, COM, { FRS, D, RA0 } }, |
4374 | 4590 | ||
4375 | { "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } }, | 4591 | { "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } }, |
4376 | 4592 | ||
4377 | { "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } }, | 4593 | { "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } }, |
4378 | 4594 | ||
4379 | { "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA } }, | 4595 | { "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA0 } }, |
4596 | |||
4597 | { "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA0 } }, | ||
4380 | 4598 | ||
4381 | { "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA } }, | 4599 | { "lfdp", OP(57), OP_MASK, POWER6, { FRT, D, RA0 } }, |
4382 | 4600 | ||
4383 | { "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA } }, | 4601 | { "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA0 } }, |
4384 | { "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } }, | 4602 | { "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } }, |
4385 | { "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA } }, | 4603 | { "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA0 } }, |
4386 | { "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } }, | 4604 | { "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } }, |
4387 | { "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA } }, | 4605 | { "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA0 } }, |
4388 | { "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } }, | 4606 | { "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } }, |
4389 | { "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA } }, | 4607 | { "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA0 } }, |
4390 | { "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } }, | 4608 | { "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } }, |
4391 | { "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA } }, | 4609 | { "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA0 } }, |
4392 | { "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } }, | 4610 | { "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } }, |
4393 | { "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA } }, | 4611 | { "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA0 } }, |
4394 | { "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } }, | 4612 | { "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } }, |
4395 | { "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA } }, | 4613 | { "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA0 } }, |
4396 | { "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } }, | 4614 | { "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } }, |
4397 | 4615 | ||
4398 | { "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA } }, | 4616 | { "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA0 } }, |
4399 | 4617 | ||
4400 | { "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } }, | 4618 | { "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } }, |
4401 | 4619 | ||
4402 | { "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA } }, | 4620 | { "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA0 } }, |
4621 | |||
4622 | { "dadd", XRC(59,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4623 | { "dadd.", XRC(59,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4624 | |||
4625 | { "dqua", ZRC(59,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4626 | { "dqua.", ZRC(59,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4403 | 4627 | ||
4404 | { "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, | 4628 | { "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, |
4405 | { "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, | 4629 | { "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, |
@@ -4413,12 +4637,15 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4413 | { "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, | 4637 | { "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, |
4414 | { "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, | 4638 | { "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, |
4415 | 4639 | ||
4416 | { "fres", A(59,24,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, | 4640 | { "fres", A(59,24,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, |
4417 | { "fres.", A(59,24,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, | 4641 | { "fres.", A(59,24,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, |
4418 | 4642 | ||
4419 | { "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } }, | 4643 | { "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } }, |
4420 | { "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } }, | 4644 | { "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } }, |
4421 | 4645 | ||
4646 | { "frsqrtes", A(59,26,0), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } }, | ||
4647 | { "frsqrtes.",A(59,26,1), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } }, | ||
4648 | |||
4422 | { "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, | 4649 | { "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, |
4423 | { "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, | 4650 | { "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, |
4424 | 4651 | ||
@@ -4431,31 +4658,103 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4431 | { "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, | 4658 | { "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, |
4432 | { "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, | 4659 | { "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, |
4433 | 4660 | ||
4661 | { "dmul", XRC(59,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4662 | { "dmul.", XRC(59,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4663 | |||
4664 | { "drrnd", ZRC(59,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4665 | { "drrnd.", ZRC(59,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4666 | |||
4667 | { "dscli", ZRC(59,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4668 | { "dscli.", ZRC(59,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4669 | |||
4670 | { "dquai", ZRC(59,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } }, | ||
4671 | { "dquai.", ZRC(59,67,1), Z_MASK, POWER6, { TE, FRT, FRB, RMC } }, | ||
4672 | |||
4673 | { "dscri", ZRC(59,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4674 | { "dscri.", ZRC(59,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4675 | |||
4676 | { "drintx", ZRC(59,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4677 | { "drintx.", ZRC(59,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4678 | |||
4679 | { "dcmpo", X(59,130), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4680 | |||
4681 | { "dtstex", X(59,162), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4682 | { "dtstdc", Z(59,194), Z_MASK, POWER6, { BF, FRA, DCM } }, | ||
4683 | { "dtstdg", Z(59,226), Z_MASK, POWER6, { BF, FRA, DGM } }, | ||
4684 | |||
4685 | { "drintn", ZRC(59,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4686 | { "drintn.", ZRC(59,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4687 | |||
4688 | { "dctdp", XRC(59,258,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4689 | { "dctdp.", XRC(59,258,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4690 | |||
4691 | { "dctfix", XRC(59,290,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4692 | { "dctfix.", XRC(59,290,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4693 | |||
4694 | { "ddedpd", XRC(59,322,0), X_MASK, POWER6, { SP, FRT, FRB } }, | ||
4695 | { "ddedpd.", XRC(59,322,1), X_MASK, POWER6, { SP, FRT, FRB } }, | ||
4696 | |||
4697 | { "dxex", XRC(59,354,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4698 | { "dxex.", XRC(59,354,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4699 | |||
4700 | { "dsub", XRC(59,514,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4701 | { "dsub.", XRC(59,514,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4702 | |||
4703 | { "ddiv", XRC(59,546,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4704 | { "ddiv.", XRC(59,546,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4705 | |||
4706 | { "dcmpu", X(59,642), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4707 | |||
4708 | { "dtstsf", X(59,674), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4709 | |||
4710 | { "drsp", XRC(59,770,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4711 | { "drsp.", XRC(59,770,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4712 | |||
4713 | { "dcffix", XRC(59,802,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4714 | { "dcffix.", XRC(59,802,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4715 | |||
4716 | { "denbcd", XRC(59,834,0), X_MASK, POWER6, { S, FRT, FRB } }, | ||
4717 | { "denbcd.", XRC(59,834,1), X_MASK, POWER6, { S, FRT, FRB } }, | ||
4718 | |||
4719 | { "diex", XRC(59,866,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4720 | { "diex.", XRC(59,866,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4721 | |||
4434 | { "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } }, | 4722 | { "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } }, |
4435 | 4723 | ||
4436 | { "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } }, | 4724 | { "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } }, |
4437 | 4725 | ||
4438 | { "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA } }, | 4726 | { "stfdp", OP(61), OP_MASK, POWER6, { FRT, D, RA0 } }, |
4439 | { "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA } }, | 4727 | |
4440 | { "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA } }, | 4728 | { "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA0 } }, |
4729 | { "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA0 } }, | ||
4730 | { "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA0 } }, | ||
4441 | { "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } }, | 4731 | { "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } }, |
4442 | { "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA } }, | 4732 | { "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA0 } }, |
4443 | { "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } }, | 4733 | { "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } }, |
4444 | { "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA } }, | 4734 | { "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA0 } }, |
4445 | { "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } }, | 4735 | { "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } }, |
4446 | { "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA } }, | 4736 | { "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA0 } }, |
4447 | { "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } }, | 4737 | { "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } }, |
4448 | { "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA } }, | 4738 | { "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA0 } }, |
4449 | { "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } }, | 4739 | { "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } }, |
4450 | 4740 | ||
4451 | { "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA } }, | 4741 | { "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA0 } }, |
4452 | 4742 | ||
4453 | { "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } }, | 4743 | { "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } }, |
4454 | 4744 | ||
4455 | { "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA } }, | 4745 | { "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA0 } }, |
4456 | 4746 | ||
4457 | { "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, | 4747 | { "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, |
4458 | 4748 | ||
4749 | { "daddq", XRC(63,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4750 | { "daddq.", XRC(63,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4751 | |||
4752 | { "dquaq", ZRC(63,3,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4753 | { "dquaq.", ZRC(63,3,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4754 | |||
4755 | { "fcpsgn", XRC(63,8,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4756 | { "fcpsgn.", XRC(63,8,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4757 | |||
4459 | { "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } }, | 4758 | { "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } }, |
4460 | { "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } }, | 4759 | { "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } }, |
4461 | 4760 | ||
@@ -4490,13 +4789,16 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4490 | { "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, | 4789 | { "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, |
4491 | { "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, | 4790 | { "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, |
4492 | 4791 | ||
4792 | { "fre", A(63,24,0), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } }, | ||
4793 | { "fre.", A(63,24,1), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } }, | ||
4794 | |||
4493 | { "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, | 4795 | { "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, |
4494 | { "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, | 4796 | { "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, |
4495 | { "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, | 4797 | { "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, |
4496 | { "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, | 4798 | { "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, |
4497 | 4799 | ||
4498 | { "frsqrte", A(63,26,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, | 4800 | { "frsqrte", A(63,26,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, |
4499 | { "frsqrte.",A(63,26,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, | 4801 | { "frsqrte.",A(63,26,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, |
4500 | 4802 | ||
4501 | { "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, | 4803 | { "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, |
4502 | { "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, | 4804 | { "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, |
@@ -4520,6 +4822,12 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4520 | 4822 | ||
4521 | { "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, | 4823 | { "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, |
4522 | 4824 | ||
4825 | { "dmulq", XRC(63,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4826 | { "dmulq.", XRC(63,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4827 | |||
4828 | { "drrndq", ZRC(63,35,0), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4829 | { "drrndq.", ZRC(63,35,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4830 | |||
4523 | { "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } }, | 4831 | { "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } }, |
4524 | { "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } }, | 4832 | { "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } }, |
4525 | 4833 | ||
@@ -4528,36 +4836,100 @@ const struct powerpc_opcode powerpc_opcodes[] = { | |||
4528 | 4836 | ||
4529 | { "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } }, | 4837 | { "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } }, |
4530 | 4838 | ||
4839 | { "dscliq", ZRC(63,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4840 | { "dscliq.", ZRC(63,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4841 | |||
4842 | { "dquaiq", ZRC(63,67,0), Z_MASK, POWER6, { TE, FRT, FRB, RMC } }, | ||
4843 | { "dquaiq.", ZRC(63,67,1), Z_MASK, POWER6, { FRT, FRA, FRB, RMC } }, | ||
4844 | |||
4531 | { "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } }, | 4845 | { "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } }, |
4532 | { "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } }, | 4846 | { "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } }, |
4533 | 4847 | ||
4534 | { "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } }, | 4848 | { "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } }, |
4535 | { "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } }, | 4849 | { "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } }, |
4536 | 4850 | ||
4851 | { "dscriq", ZRC(63,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4852 | { "dscriq.", ZRC(63,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, | ||
4853 | |||
4854 | { "drintxq", ZRC(63,99,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4855 | { "drintxq.",ZRC(63,99,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4856 | |||
4857 | { "dcmpoq", X(63,130), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4858 | |||
4537 | { "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, | 4859 | { "mtfsfi", XRC(63,134,0), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, |
4538 | { "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, | 4860 | { "mtfsfi.", XRC(63,134,1), XRA_MASK|(3<<21)|(1<<11), COM, { BF, U } }, |
4539 | 4861 | ||
4540 | { "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } }, | 4862 | { "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } }, |
4541 | { "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } }, | 4863 | { "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } }, |
4542 | 4864 | ||
4865 | { "dtstexq", X(63,162), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4866 | { "dtstdcq", Z(63,194), Z_MASK, POWER6, { BF, FRA, DCM } }, | ||
4867 | { "dtstdgq", Z(63,226), Z_MASK, POWER6, { BF, FRA, DGM } }, | ||
4868 | |||
4869 | { "drintnq", ZRC(63,227,0), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4870 | { "drintnq.",ZRC(63,227,1), Z_MASK, POWER6, { R, FRT, FRB, RMC } }, | ||
4871 | |||
4872 | { "dctqpq", XRC(63,258,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4873 | { "dctqpq.", XRC(63,258,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4874 | |||
4543 | { "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } }, | 4875 | { "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } }, |
4544 | { "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } }, | 4876 | { "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } }, |
4545 | 4877 | ||
4878 | { "dctfixq", XRC(63,290,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4879 | { "dctfixq.",XRC(63,290,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4880 | |||
4881 | { "ddedpdq", XRC(63,322,0), X_MASK, POWER6, { SP, FRT, FRB } }, | ||
4882 | { "ddedpdq.",XRC(63,322,1), X_MASK, POWER6, { SP, FRT, FRB } }, | ||
4883 | |||
4884 | { "dxexq", XRC(63,354,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4885 | { "dxexq.", XRC(63,354,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4886 | |||
4887 | { "frin", XRC(63,392,0), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4888 | { "frin.", XRC(63,392,1), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4889 | { "friz", XRC(63,424,0), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4890 | { "friz.", XRC(63,424,1), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4891 | { "frip", XRC(63,456,0), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4892 | { "frip.", XRC(63,456,1), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4893 | { "frim", XRC(63,488,0), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4894 | { "frim.", XRC(63,488,1), XRA_MASK, POWER5, { FRT, FRB } }, | ||
4895 | |||
4896 | { "dsubq", XRC(63,514,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4897 | { "dsubq.", XRC(63,514,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4898 | |||
4899 | { "ddivq", XRC(63,546,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4900 | { "ddivq.", XRC(63,546,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4901 | |||
4546 | { "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } }, | 4902 | { "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } }, |
4547 | { "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } }, | 4903 | { "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } }, |
4548 | 4904 | ||
4905 | { "dcmpuq", X(63,642), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4906 | |||
4907 | { "dtstsfq", X(63,674), X_MASK, POWER6, { BF, FRA, FRB } }, | ||
4908 | |||
4549 | { "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } }, | 4909 | { "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB } }, |
4550 | { "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } }, | 4910 | { "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB } }, |
4551 | 4911 | ||
4912 | { "drdpq", XRC(63,770,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4913 | { "drdpq.", XRC(63,770,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4914 | |||
4915 | { "dcffixq", XRC(63,802,0), X_MASK, POWER6, { FRT, FRB } }, | ||
4916 | { "dcffixq.",XRC(63,802,1), X_MASK, POWER6, { FRT, FRB } }, | ||
4917 | |||
4552 | { "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } }, | 4918 | { "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } }, |
4553 | { "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } }, | 4919 | { "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } }, |
4554 | 4920 | ||
4555 | { "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } }, | 4921 | { "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } }, |
4556 | { "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } }, | 4922 | { "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } }, |
4557 | 4923 | ||
4924 | { "denbcdq", XRC(63,834,0), X_MASK, POWER6, { S, FRT, FRB } }, | ||
4925 | { "denbcdq.",XRC(63,834,1), X_MASK, POWER6, { S, FRT, FRB } }, | ||
4926 | |||
4558 | { "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } }, | 4927 | { "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } }, |
4559 | { "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } }, | 4928 | { "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } }, |
4560 | 4929 | ||
4930 | { "diexq", XRC(63,866,0), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4931 | { "diexq.", XRC(63,866,1), X_MASK, POWER6, { FRT, FRA, FRB } }, | ||
4932 | |||
4561 | }; | 4933 | }; |
4562 | 4934 | ||
4563 | const int powerpc_num_opcodes = | 4935 | const int powerpc_num_opcodes = |
diff --git a/arch/powerpc/xmon/ppc.h b/arch/powerpc/xmon/ppc.h index 342237e8dd6..110df96354b 100644 --- a/arch/powerpc/xmon/ppc.h +++ b/arch/powerpc/xmon/ppc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* ppc.h -- Header file for PowerPC opcode table | 1 | /* ppc.h -- Header file for PowerPC opcode table |
2 | Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003 | 2 | Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 |
3 | Free Software Foundation, Inc. | 3 | Free Software Foundation, Inc. |
4 | Written by Ian Lance Taylor, Cygnus Support | 4 | Written by Ian Lance Taylor, Cygnus Support |
5 | 5 | ||
@@ -17,7 +17,7 @@ the GNU General Public License for more details. | |||
17 | 17 | ||
18 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License |
19 | along with this file; see the file COPYING. If not, write to the Free | 19 | along with this file; see the file COPYING. If not, write to the Free |
20 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 20 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ |
21 | 21 | ||
22 | #ifndef PPC_H | 22 | #ifndef PPC_H |
23 | #define PPC_H | 23 | #define PPC_H |
@@ -134,6 +134,18 @@ extern const int powerpc_num_opcodes; | |||
134 | /* Opcode is supported by machine check APU. */ | 134 | /* Opcode is supported by machine check APU. */ |
135 | #define PPC_OPCODE_RFMCI 0x800000 | 135 | #define PPC_OPCODE_RFMCI 0x800000 |
136 | 136 | ||
137 | /* Opcode is only supported by Power5 architecture. */ | ||
138 | #define PPC_OPCODE_POWER5 0x1000000 | ||
139 | |||
140 | /* Opcode is supported by PowerPC e300 family. */ | ||
141 | #define PPC_OPCODE_E300 0x2000000 | ||
142 | |||
143 | /* Opcode is only supported by Power6 architecture. */ | ||
144 | #define PPC_OPCODE_POWER6 0x4000000 | ||
145 | |||
146 | /* Opcode is only supported by PowerPC Cell family. */ | ||
147 | #define PPC_OPCODE_CELL 0x8000000 | ||
148 | |||
137 | /* A macro to extract the major opcode from an instruction. */ | 149 | /* A macro to extract the major opcode from an instruction. */ |
138 | #define PPC_OP(i) (((i) >> 26) & 0x3f) | 150 | #define PPC_OP(i) (((i) >> 26) & 0x3f) |
139 | 151 | ||
@@ -233,25 +245,28 @@ extern const struct powerpc_operand powerpc_operands[]; | |||
233 | register names with a leading 'r'. */ | 245 | register names with a leading 'r'. */ |
234 | #define PPC_OPERAND_GPR (040) | 246 | #define PPC_OPERAND_GPR (040) |
235 | 247 | ||
248 | /* Like PPC_OPERAND_GPR, but don't print a leading 'r' for r0. */ | ||
249 | #define PPC_OPERAND_GPR_0 (0100) | ||
250 | |||
236 | /* This operand names a floating point register. The disassembler | 251 | /* This operand names a floating point register. The disassembler |
237 | prints these with a leading 'f'. */ | 252 | prints these with a leading 'f'. */ |
238 | #define PPC_OPERAND_FPR (0100) | 253 | #define PPC_OPERAND_FPR (0200) |
239 | 254 | ||
240 | /* This operand is a relative branch displacement. The disassembler | 255 | /* This operand is a relative branch displacement. The disassembler |
241 | prints these symbolically if possible. */ | 256 | prints these symbolically if possible. */ |
242 | #define PPC_OPERAND_RELATIVE (0200) | 257 | #define PPC_OPERAND_RELATIVE (0400) |
243 | 258 | ||
244 | /* This operand is an absolute branch address. The disassembler | 259 | /* This operand is an absolute branch address. The disassembler |
245 | prints these symbolically if possible. */ | 260 | prints these symbolically if possible. */ |
246 | #define PPC_OPERAND_ABSOLUTE (0400) | 261 | #define PPC_OPERAND_ABSOLUTE (01000) |
247 | 262 | ||
248 | /* This operand is optional, and is zero if omitted. This is used for | 263 | /* This operand is optional, and is zero if omitted. This is used for |
249 | the optional BF and L fields in the comparison instructions. The | 264 | example, in the optional BF field in the comparison instructions. The |
250 | assembler must count the number of operands remaining on the line, | 265 | assembler must count the number of operands remaining on the line, |
251 | and the number of operands remaining for the opcode, and decide | 266 | and the number of operands remaining for the opcode, and decide |
252 | whether this operand is present or not. The disassembler should | 267 | whether this operand is present or not. The disassembler should |
253 | print this operand out only if it is not zero. */ | 268 | print this operand out only if it is not zero. */ |
254 | #define PPC_OPERAND_OPTIONAL (01000) | 269 | #define PPC_OPERAND_OPTIONAL (02000) |
255 | 270 | ||
256 | /* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand | 271 | /* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand |
257 | is omitted, then for the next operand use this operand value plus | 272 | is omitted, then for the next operand use this operand value plus |
@@ -259,24 +274,24 @@ extern const struct powerpc_operand powerpc_operands[]; | |||
259 | hack is needed because the Power rotate instructions can take | 274 | hack is needed because the Power rotate instructions can take |
260 | either 4 or 5 operands. The disassembler should print this operand | 275 | either 4 or 5 operands. The disassembler should print this operand |
261 | out regardless of the PPC_OPERAND_OPTIONAL field. */ | 276 | out regardless of the PPC_OPERAND_OPTIONAL field. */ |
262 | #define PPC_OPERAND_NEXT (02000) | 277 | #define PPC_OPERAND_NEXT (04000) |
263 | 278 | ||
264 | /* This operand should be regarded as a negative number for the | 279 | /* This operand should be regarded as a negative number for the |
265 | purposes of overflow checking (i.e., the normal most negative | 280 | purposes of overflow checking (i.e., the normal most negative |
266 | number is disallowed and one more than the normal most positive | 281 | number is disallowed and one more than the normal most positive |
267 | number is allowed). This flag will only be set for a signed | 282 | number is allowed). This flag will only be set for a signed |
268 | operand. */ | 283 | operand. */ |
269 | #define PPC_OPERAND_NEGATIVE (04000) | 284 | #define PPC_OPERAND_NEGATIVE (010000) |
270 | 285 | ||
271 | /* This operand names a vector unit register. The disassembler | 286 | /* This operand names a vector unit register. The disassembler |
272 | prints these with a leading 'v'. */ | 287 | prints these with a leading 'v'. */ |
273 | #define PPC_OPERAND_VR (010000) | 288 | #define PPC_OPERAND_VR (020000) |
274 | 289 | ||
275 | /* This operand is for the DS field in a DS form instruction. */ | 290 | /* This operand is for the DS field in a DS form instruction. */ |
276 | #define PPC_OPERAND_DS (020000) | 291 | #define PPC_OPERAND_DS (040000) |
277 | 292 | ||
278 | /* This operand is for the DQ field in a DQ form instruction. */ | 293 | /* This operand is for the DQ field in a DQ form instruction. */ |
279 | #define PPC_OPERAND_DQ (040000) | 294 | #define PPC_OPERAND_DQ (0100000) |
280 | 295 | ||
281 | /* The POWER and PowerPC assemblers use a few macros. We keep them | 296 | /* The POWER and PowerPC assemblers use a few macros. We keep them |
282 | with the operands table for simplicity. The macro table is an | 297 | with the operands table for simplicity. The macro table is an |
diff --git a/arch/powerpc/xmon/spu-dis.c b/arch/powerpc/xmon/spu-dis.c new file mode 100644 index 00000000000..ee929c641bf --- /dev/null +++ b/arch/powerpc/xmon/spu-dis.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* Disassemble SPU instructions | ||
2 | |||
3 | Copyright 2006 Free Software Foundation, Inc. | ||
4 | |||
5 | This file is part of GDB, GAS, and the GNU binutils. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License along | ||
18 | with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
20 | |||
21 | #include <linux/string.h> | ||
22 | #include "nonstdio.h" | ||
23 | #include "ansidecl.h" | ||
24 | #include "spu.h" | ||
25 | #include "dis-asm.h" | ||
26 | |||
27 | /* This file provides a disassembler function which uses | ||
28 | the disassembler interface defined in dis-asm.h. */ | ||
29 | |||
30 | extern const struct spu_opcode spu_opcodes[]; | ||
31 | extern const int spu_num_opcodes; | ||
32 | |||
33 | #define SPU_DISASM_TBL_SIZE (1 << 11) | ||
34 | static const struct spu_opcode *spu_disassemble_table[SPU_DISASM_TBL_SIZE]; | ||
35 | |||
36 | static void | ||
37 | init_spu_disassemble (void) | ||
38 | { | ||
39 | int i; | ||
40 | |||
41 | /* If two instructions have the same opcode then we prefer the first | ||
42 | * one. In most cases it is just an alternate mnemonic. */ | ||
43 | for (i = 0; i < spu_num_opcodes; i++) | ||
44 | { | ||
45 | int o = spu_opcodes[i].opcode; | ||
46 | if (o >= SPU_DISASM_TBL_SIZE) | ||
47 | continue; /* abort (); */ | ||
48 | if (spu_disassemble_table[o] == 0) | ||
49 | spu_disassemble_table[o] = &spu_opcodes[i]; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | /* Determine the instruction from the 10 least significant bits. */ | ||
54 | static const struct spu_opcode * | ||
55 | get_index_for_opcode (unsigned int insn) | ||
56 | { | ||
57 | const struct spu_opcode *index; | ||
58 | unsigned int opcode = insn >> (32-11); | ||
59 | |||
60 | /* Init the table. This assumes that element 0/opcode 0 (currently | ||
61 | * NOP) is always used */ | ||
62 | if (spu_disassemble_table[0] == 0) | ||
63 | init_spu_disassemble (); | ||
64 | |||
65 | if ((index = spu_disassemble_table[opcode & 0x780]) != 0 | ||
66 | && index->insn_type == RRR) | ||
67 | return index; | ||
68 | |||
69 | if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0 | ||
70 | && (index->insn_type == RI18 || index->insn_type == LBT)) | ||
71 | return index; | ||
72 | |||
73 | if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0 | ||
74 | && index->insn_type == RI10) | ||
75 | return index; | ||
76 | |||
77 | if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0 | ||
78 | && (index->insn_type == RI16)) | ||
79 | return index; | ||
80 | |||
81 | if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0 | ||
82 | && (index->insn_type == RI8)) | ||
83 | return index; | ||
84 | |||
85 | if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0) | ||
86 | return index; | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | /* Print a Spu instruction. */ | ||
92 | |||
93 | int | ||
94 | print_insn_spu (unsigned long insn, unsigned long memaddr) | ||
95 | { | ||
96 | int value; | ||
97 | int hex_value; | ||
98 | const struct spu_opcode *index; | ||
99 | enum spu_insns tag; | ||
100 | |||
101 | index = get_index_for_opcode (insn); | ||
102 | |||
103 | if (index == 0) | ||
104 | { | ||
105 | printf(".long 0x%x", insn); | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | int i; | ||
110 | int paren = 0; | ||
111 | tag = (enum spu_insns)(index - spu_opcodes); | ||
112 | printf("%s", index->mnemonic); | ||
113 | if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED | ||
114 | || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ | ||
115 | || tag == M_SYNC || tag == M_HBR) | ||
116 | { | ||
117 | int fb = (insn >> (32-18)) & 0x7f; | ||
118 | if (fb & 0x40) | ||
119 | printf(tag == M_SYNC ? "c" : "p"); | ||
120 | if (fb & 0x20) | ||
121 | printf("d"); | ||
122 | if (fb & 0x10) | ||
123 | printf("e"); | ||
124 | } | ||
125 | if (index->arg[0] != 0) | ||
126 | printf("\t"); | ||
127 | hex_value = 0; | ||
128 | for (i = 1; i <= index->arg[0]; i++) | ||
129 | { | ||
130 | int arg = index->arg[i]; | ||
131 | if (arg != A_P && !paren && i > 1) | ||
132 | printf(","); | ||
133 | |||
134 | switch (arg) | ||
135 | { | ||
136 | case A_T: | ||
137 | printf("$%d", | ||
138 | DECODE_INSN_RT (insn)); | ||
139 | break; | ||
140 | case A_A: | ||
141 | printf("$%d", | ||
142 | DECODE_INSN_RA (insn)); | ||
143 | break; | ||
144 | case A_B: | ||
145 | printf("$%d", | ||
146 | DECODE_INSN_RB (insn)); | ||
147 | break; | ||
148 | case A_C: | ||
149 | printf("$%d", | ||
150 | DECODE_INSN_RC (insn)); | ||
151 | break; | ||
152 | case A_S: | ||
153 | printf("$sp%d", | ||
154 | DECODE_INSN_RA (insn)); | ||
155 | break; | ||
156 | case A_H: | ||
157 | printf("$ch%d", | ||
158 | DECODE_INSN_RA (insn)); | ||
159 | break; | ||
160 | case A_P: | ||
161 | paren++; | ||
162 | printf("("); | ||
163 | break; | ||
164 | case A_U7A: | ||
165 | printf("%d", | ||
166 | 173 - DECODE_INSN_U8 (insn)); | ||
167 | break; | ||
168 | case A_U7B: | ||
169 | printf("%d", | ||
170 | 155 - DECODE_INSN_U8 (insn)); | ||
171 | break; | ||
172 | case A_S3: | ||
173 | case A_S6: | ||
174 | case A_S7: | ||
175 | case A_S7N: | ||
176 | case A_U3: | ||
177 | case A_U5: | ||
178 | case A_U6: | ||
179 | case A_U7: | ||
180 | hex_value = DECODE_INSN_I7 (insn); | ||
181 | printf("%d", hex_value); | ||
182 | break; | ||
183 | case A_S11: | ||
184 | print_address(memaddr + DECODE_INSN_I9a (insn) * 4); | ||
185 | break; | ||
186 | case A_S11I: | ||
187 | print_address(memaddr + DECODE_INSN_I9b (insn) * 4); | ||
188 | break; | ||
189 | case A_S10: | ||
190 | case A_S10B: | ||
191 | hex_value = DECODE_INSN_I10 (insn); | ||
192 | printf("%d", hex_value); | ||
193 | break; | ||
194 | case A_S14: | ||
195 | hex_value = DECODE_INSN_I10 (insn) * 16; | ||
196 | printf("%d", hex_value); | ||
197 | break; | ||
198 | case A_S16: | ||
199 | hex_value = DECODE_INSN_I16 (insn); | ||
200 | printf("%d", hex_value); | ||
201 | break; | ||
202 | case A_X16: | ||
203 | hex_value = DECODE_INSN_U16 (insn); | ||
204 | printf("%u", hex_value); | ||
205 | break; | ||
206 | case A_R18: | ||
207 | value = DECODE_INSN_I16 (insn) * 4; | ||
208 | if (value == 0) | ||
209 | printf("%d", value); | ||
210 | else | ||
211 | { | ||
212 | hex_value = memaddr + value; | ||
213 | print_address(hex_value & 0x3ffff); | ||
214 | } | ||
215 | break; | ||
216 | case A_S18: | ||
217 | value = DECODE_INSN_U16 (insn) * 4; | ||
218 | if (value == 0) | ||
219 | printf("%d", value); | ||
220 | else | ||
221 | print_address(value); | ||
222 | break; | ||
223 | case A_U18: | ||
224 | value = DECODE_INSN_U18 (insn); | ||
225 | if (value == 0 || 1) | ||
226 | { | ||
227 | hex_value = value; | ||
228 | printf("%u", value); | ||
229 | } | ||
230 | else | ||
231 | print_address(value); | ||
232 | break; | ||
233 | case A_U14: | ||
234 | hex_value = DECODE_INSN_U14 (insn); | ||
235 | printf("%u", hex_value); | ||
236 | break; | ||
237 | } | ||
238 | if (arg != A_P && paren) | ||
239 | { | ||
240 | printf(")"); | ||
241 | paren--; | ||
242 | } | ||
243 | } | ||
244 | if (hex_value > 16) | ||
245 | printf("\t# %x", hex_value); | ||
246 | } | ||
247 | return 4; | ||
248 | } | ||
diff --git a/arch/powerpc/xmon/spu-insns.h b/arch/powerpc/xmon/spu-insns.h new file mode 100644 index 00000000000..99dc452821a --- /dev/null +++ b/arch/powerpc/xmon/spu-insns.h | |||
@@ -0,0 +1,410 @@ | |||
1 | /* SPU ELF support for BFD. | ||
2 | |||
3 | Copyright 2006 Free Software Foundation, Inc. | ||
4 | |||
5 | This file is part of BFD, the Binary File Descriptor library. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software Foundation, | ||
19 | Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
20 | |||
21 | /* SPU Opcode Table | ||
22 | |||
23 | -=-=-= FORMAT =-=-=- | ||
24 | |||
25 | +----+-------+-------+-------+-------+ +------------+-------+-------+-------+ | ||
26 | RRR | op | RC | RB | RA | RT | RI7 | op | I7 | RA | RT | | ||
27 | +----+-------+-------+-------+-------+ +------------+-------+-------+-------+ | ||
28 | 0 3 1 1 2 3 0 1 1 2 3 | ||
29 | 0 7 4 1 0 7 4 1 | ||
30 | |||
31 | +-----------+--------+-------+-------+ +---------+----------+-------+-------+ | ||
32 | RI8 | op | I8 | RA | RT | RI10 | op | I10 | RA | RT | | ||
33 | +-----------+--------+-------+-------+ +---------+----------+-------+-------+ | ||
34 | 0 9 1 2 3 0 7 1 2 3 | ||
35 | 7 4 1 7 4 1 | ||
36 | |||
37 | +----------+-----------------+-------+ +--------+-------------------+-------+ | ||
38 | RI16 | op | I16 | RT | RI18 | op | I18 | RT | | ||
39 | +----------+-----------------+-------+ +--------+-------------------+-------+ | ||
40 | 0 8 2 3 0 6 2 3 | ||
41 | 4 1 4 1 | ||
42 | |||
43 | +------------+-------+-------+-------+ +-------+--+-----------------+-------+ | ||
44 | RR | op | RB | RA | RT | LBT | op |RO| I16 | RO | | ||
45 | +------------+-------+-------+-------+ +-------+--+-----------------+-------+ | ||
46 | 0 1 1 2 3 0 6 8 2 3 | ||
47 | 0 7 4 1 4 1 | ||
48 | |||
49 | +------------+----+--+-------+-------+ | ||
50 | LBTI | op | // |RO| RA | RO | | ||
51 | +------------+----+--+-------+-------+ | ||
52 | 0 1 1 1 2 3 | ||
53 | 0 5 7 4 1 | ||
54 | |||
55 | -=-=-= OPCODE =-=-=- | ||
56 | |||
57 | OPCODE field specifies the most significant 11bit of the instruction. Some formats don't have 11bits for opcode field, and in this | ||
58 | case, bit field other than op are defined as 0s. For example, opcode of fma instruction which is RRR format is defined as 0x700, | ||
59 | since 0x700 -> 11'b11100000000, this means opcode is 4'b1110, and other 7bits are defined as 7'b0000000. | ||
60 | |||
61 | -=-=-= ASM_FORMAT =-=-=- | ||
62 | |||
63 | RRR category RI7 category | ||
64 | ASM_RRR mnemonic RC, RA, RB, RT ASM_RI4 mnemonic RT, RA, I4 | ||
65 | ASM_RI7 mnemonic RT, RA, I7 | ||
66 | |||
67 | RI8 category RI10 category | ||
68 | ASM_RUI8 mnemonic RT, RA, UI8 ASM_AI10 mnemonic RA, I10 | ||
69 | ASM_RI10 mnemonic RT, RA, R10 | ||
70 | ASM_RI10IDX mnemonic RT, I10(RA) | ||
71 | |||
72 | RI16 category RI18 category | ||
73 | ASM_I16W mnemonic I16W ASM_RI18 mnemonic RT, I18 | ||
74 | ASM_RI16 mnemonic RT, I16 | ||
75 | ASM_RI16W mnemonic RT, I16W | ||
76 | |||
77 | RR category LBT category | ||
78 | ASM_MFSPR mnemonic RT, SA ASM_LBT mnemonic brinst, brtarg | ||
79 | ASM_MTSPR mnemonic SA, RT | ||
80 | ASM_NOOP mnemonic LBTI category | ||
81 | ASM_RA mnemonic RA ASM_LBTI mnemonic brinst, RA | ||
82 | ASM_RAB mnemonic RA, RB | ||
83 | ASM_RDCH mnemonic RT, CA | ||
84 | ASM_RR mnemonic RT, RA, RB | ||
85 | ASM_RT mnemonic RT | ||
86 | ASM_RTA mnemonic RT, RA | ||
87 | ASM_WRCH mnemonic CA, RT | ||
88 | |||
89 | Note that RRR instructions have the names for RC and RT reversed from | ||
90 | what's in the ISA, in order to put RT in the same position it appears | ||
91 | for other formats. | ||
92 | |||
93 | -=-=-= DEPENDENCY =-=-=- | ||
94 | |||
95 | DEPENDENCY filed consists of 5 digits. This represents which register is used as source and which register is used as target. | ||
96 | The first(most significant) digit is always 0. Then it is followd by RC, RB, RA and RT digits. | ||
97 | If the digit is 0, this means the corresponding register is not used in the instruction. | ||
98 | If the digit is 1, this means the corresponding register is used as a source in the instruction. | ||
99 | If the digit is 2, this means the corresponding register is used as a target in the instruction. | ||
100 | If the digit is 3, this means the corresponding register is used as both source and target in the instruction. | ||
101 | For example, fms instruction has 00113 as the DEPENDENCY field. This means RC is not used in this operation, RB and RA are | ||
102 | used as sources and RT is the target. | ||
103 | |||
104 | -=-=-= PIPE =-=-=- | ||
105 | |||
106 | This field shows which execution pipe is used for the instruction | ||
107 | |||
108 | pipe0 execution pipelines: | ||
109 | FP6 SP floating pipeline | ||
110 | FP7 integer operations executed in SP floating pipeline | ||
111 | FPD DP floating pipeline | ||
112 | FX2 FXU pipeline | ||
113 | FX3 Rotate/Shift pipeline | ||
114 | FXB Byte pipeline | ||
115 | NOP No pipeline | ||
116 | |||
117 | pipe1 execution pipelines: | ||
118 | BR Branch pipeline | ||
119 | LNOP No pipeline | ||
120 | LS Load/Store pipeline | ||
121 | SHUF Shuffle pipeline | ||
122 | SPR SPR/CH pipeline | ||
123 | |||
124 | */ | ||
125 | |||
126 | #define _A0() {0} | ||
127 | #define _A1(a) {1,a} | ||
128 | #define _A2(a,b) {2,a,b} | ||
129 | #define _A3(a,b,c) {3,a,b,c} | ||
130 | #define _A4(a,b,c,d) {4,a,b,c,d} | ||
131 | |||
132 | /* TAG FORMAT OPCODE MNEMONIC ASM_FORMAT DEPENDENCY PIPE COMMENT */ | ||
133 | /* 0[RC][RB][RA][RT] */ | ||
134 | /* 1:src, 2:target */ | ||
135 | |||
136 | APUOP(M_BR, RI16, 0x190, "br", _A1(A_R18), 00000, BR) /* BRel IP<-IP+I16 */ | ||
137 | APUOP(M_BRSL, RI16, 0x198, "brsl", _A2(A_T,A_R18), 00002, BR) /* BRelSetLink RT,IP<-IP,IP+I16 */ | ||
138 | APUOP(M_BRA, RI16, 0x180, "bra", _A1(A_S18), 00000, BR) /* BRAbs IP<-I16 */ | ||
139 | APUOP(M_BRASL, RI16, 0x188, "brasl", _A2(A_T,A_S18), 00002, BR) /* BRAbsSetLink RT,IP<-IP,I16 */ | ||
140 | APUOP(M_FSMBI, RI16, 0x194, "fsmbi", _A2(A_T,A_X16), 00002, SHUF) /* FormSelMask%I RT<-fsm(I16) */ | ||
141 | APUOP(M_LQA, RI16, 0x184, "lqa", _A2(A_T,A_S18), 00002, LS) /* LoadQAbs RT<-M[I16] */ | ||
142 | APUOP(M_LQR, RI16, 0x19C, "lqr", _A2(A_T,A_R18), 00002, LS) /* LoadQRel RT<-M[IP+I16] */ | ||
143 | APUOP(M_STOP, RR, 0x000, "stop", _A0(), 00000, BR) /* STOP stop */ | ||
144 | APUOP(M_STOP2, RR, 0x000, "stop", _A1(A_U14), 00000, BR) /* STOP stop */ | ||
145 | APUOP(M_STOPD, RR, 0x140, "stopd", _A3(A_T,A_A,A_B), 00111, BR) /* STOPD stop (with register dependencies) */ | ||
146 | APUOP(M_LNOP, RR, 0x001, "lnop", _A0(), 00000, LNOP) /* LNOP no_operation */ | ||
147 | APUOP(M_SYNC, RR, 0x002, "sync", _A0(), 00000, BR) /* SYNC flush_pipe */ | ||
148 | APUOP(M_DSYNC, RR, 0x003, "dsync", _A0(), 00000, BR) /* DSYNC flush_store_queue */ | ||
149 | APUOP(M_MFSPR, RR, 0x00c, "mfspr", _A2(A_T,A_S), 00002, SPR) /* MFSPR RT<-SA */ | ||
150 | APUOP(M_RDCH, RR, 0x00d, "rdch", _A2(A_T,A_H), 00002, SPR) /* ReaDCHannel RT<-CA:data */ | ||
151 | APUOP(M_RCHCNT, RR, 0x00f, "rchcnt", _A2(A_T,A_H), 00002, SPR) /* ReaDCHanCouNT RT<-CA:count */ | ||
152 | APUOP(M_HBRA, LBT, 0x080, "hbra", _A2(A_S11,A_S18), 00000, LS) /* HBRA BTB[B9]<-M[I16] */ | ||
153 | APUOP(M_HBRR, LBT, 0x090, "hbrr", _A2(A_S11,A_R18), 00000, LS) /* HBRR BTB[B9]<-M[IP+I16] */ | ||
154 | APUOP(M_BRZ, RI16, 0x100, "brz", _A2(A_T,A_R18), 00001, BR) /* BRZ IP<-IP+I16_if(RT) */ | ||
155 | APUOP(M_BRNZ, RI16, 0x108, "brnz", _A2(A_T,A_R18), 00001, BR) /* BRNZ IP<-IP+I16_if(RT) */ | ||
156 | APUOP(M_BRHZ, RI16, 0x110, "brhz", _A2(A_T,A_R18), 00001, BR) /* BRHZ IP<-IP+I16_if(RT) */ | ||
157 | APUOP(M_BRHNZ, RI16, 0x118, "brhnz", _A2(A_T,A_R18), 00001, BR) /* BRHNZ IP<-IP+I16_if(RT) */ | ||
158 | APUOP(M_STQA, RI16, 0x104, "stqa", _A2(A_T,A_S18), 00001, LS) /* SToreQAbs M[I16]<-RT */ | ||
159 | APUOP(M_STQR, RI16, 0x11C, "stqr", _A2(A_T,A_R18), 00001, LS) /* SToreQRel M[IP+I16]<-RT */ | ||
160 | APUOP(M_MTSPR, RR, 0x10c, "mtspr", _A2(A_S,A_T), 00001, SPR) /* MTSPR SA<-RT */ | ||
161 | APUOP(M_WRCH, RR, 0x10d, "wrch", _A2(A_H,A_T), 00001, SPR) /* ChanWRite CA<-RT */ | ||
162 | APUOP(M_LQD, RI10, 0x1a0, "lqd", _A4(A_T,A_S14,A_P,A_A), 00012, LS) /* LoadQDisp RT<-M[Ra+I10] */ | ||
163 | APUOP(M_BI, RR, 0x1a8, "bi", _A1(A_A), 00010, BR) /* BI IP<-RA */ | ||
164 | APUOP(M_BISL, RR, 0x1a9, "bisl", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */ | ||
165 | APUOP(M_IRET, RR, 0x1aa, "iret", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */ | ||
166 | APUOP(M_IRET2, RR, 0x1aa, "iret", _A0(), 00010, BR) /* IRET IP<-SRR0 */ | ||
167 | APUOP(M_BISLED, RR, 0x1ab, "bisled", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */ | ||
168 | APUOP(M_HBR, LBTI, 0x1ac, "hbr", _A2(A_S11I,A_A), 00010, LS) /* HBR BTB[B9]<-M[Ra] */ | ||
169 | APUOP(M_FREST, RR, 0x1b8, "frest", _A2(A_T,A_A), 00012, SHUF) /* FREST RT<-recip(RA) */ | ||
170 | APUOP(M_FRSQEST, RR, 0x1b9, "frsqest", _A2(A_T,A_A), 00012, SHUF) /* FRSQEST RT<-rsqrt(RA) */ | ||
171 | APUOP(M_FSM, RR, 0x1b4, "fsm", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */ | ||
172 | APUOP(M_FSMH, RR, 0x1b5, "fsmh", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */ | ||
173 | APUOP(M_FSMB, RR, 0x1b6, "fsmb", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */ | ||
174 | APUOP(M_GB, RR, 0x1b0, "gb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */ | ||
175 | APUOP(M_GBH, RR, 0x1b1, "gbh", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */ | ||
176 | APUOP(M_GBB, RR, 0x1b2, "gbb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */ | ||
177 | APUOP(M_CBD, RI7, 0x1f4, "cbd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ | ||
178 | APUOP(M_CHD, RI7, 0x1f5, "chd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ | ||
179 | APUOP(M_CWD, RI7, 0x1f6, "cwd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ | ||
180 | APUOP(M_CDD, RI7, 0x1f7, "cdd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ | ||
181 | APUOP(M_ROTQBII, RI7, 0x1f8, "rotqbii", _A3(A_T,A_A,A_U3), 00012, SHUF) /* ROTQBII RT<-RA<<<I7 */ | ||
182 | APUOP(M_ROTQBYI, RI7, 0x1fc, "rotqbyi", _A3(A_T,A_A,A_S7N), 00012, SHUF) /* ROTQBYI RT<-RA<<<(I7*8) */ | ||
183 | APUOP(M_ROTQMBII, RI7, 0x1f9, "rotqmbii", _A3(A_T,A_A,A_S3), 00012, SHUF) /* ROTQMBII RT<-RA<<I7 */ | ||
184 | APUOP(M_ROTQMBYI, RI7, 0x1fd, "rotqmbyi", _A3(A_T,A_A,A_S6), 00012, SHUF) /* ROTQMBYI RT<-RA<<I7 */ | ||
185 | APUOP(M_SHLQBII, RI7, 0x1fb, "shlqbii", _A3(A_T,A_A,A_U3), 00012, SHUF) /* SHLQBII RT<-RA<<I7 */ | ||
186 | APUOP(M_SHLQBYI, RI7, 0x1ff, "shlqbyi", _A3(A_T,A_A,A_U5), 00012, SHUF) /* SHLQBYI RT<-RA<<I7 */ | ||
187 | APUOP(M_STQD, RI10, 0x120, "stqd", _A4(A_T,A_S14,A_P,A_A), 00011, LS) /* SToreQDisp M[Ra+I10]<-RT */ | ||
188 | APUOP(M_BIHNZ, RR, 0x12b, "bihnz", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */ | ||
189 | APUOP(M_BIHZ, RR, 0x12a, "bihz", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */ | ||
190 | APUOP(M_BINZ, RR, 0x129, "binz", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */ | ||
191 | APUOP(M_BIZ, RR, 0x128, "biz", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */ | ||
192 | APUOP(M_CBX, RR, 0x1d4, "cbx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */ | ||
193 | APUOP(M_CHX, RR, 0x1d5, "chx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */ | ||
194 | APUOP(M_CWX, RR, 0x1d6, "cwx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */ | ||
195 | APUOP(M_CDX, RR, 0x1d7, "cdx", _A3(A_T,A_A,A_B), 00112, SHUF) /* genCtl%%insX RT<-sta(Ra+Rb,siz) */ | ||
196 | APUOP(M_LQX, RR, 0x1c4, "lqx", _A3(A_T,A_A,A_B), 00112, LS) /* LoadQindeX RT<-M[Ra+Rb] */ | ||
197 | APUOP(M_ROTQBI, RR, 0x1d8, "rotqbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBI RT<-RA<<<Rb */ | ||
198 | APUOP(M_ROTQMBI, RR, 0x1d9, "rotqmbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBI RT<-RA<<Rb */ | ||
199 | APUOP(M_SHLQBI, RR, 0x1db, "shlqbi", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBI RT<-RA<<Rb */ | ||
200 | APUOP(M_ROTQBY, RR, 0x1dc, "rotqby", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBY RT<-RA<<<(Rb*8) */ | ||
201 | APUOP(M_ROTQMBY, RR, 0x1dd, "rotqmby", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBY RT<-RA<<Rb */ | ||
202 | APUOP(M_SHLQBY, RR, 0x1df, "shlqby", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBY RT<-RA<<Rb */ | ||
203 | APUOP(M_ROTQBYBI, RR, 0x1cc, "rotqbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQBYBI RT<-RA<<Rb */ | ||
204 | APUOP(M_ROTQMBYBI, RR, 0x1cd, "rotqmbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* ROTQMBYBI RT<-RA<<Rb */ | ||
205 | APUOP(M_SHLQBYBI, RR, 0x1cf, "shlqbybi", _A3(A_T,A_A,A_B), 00112, SHUF) /* SHLQBYBI RT<-RA<<Rb */ | ||
206 | APUOP(M_STQX, RR, 0x144, "stqx", _A3(A_T,A_A,A_B), 00111, LS) /* SToreQindeX M[Ra+Rb]<-RT */ | ||
207 | APUOP(M_SHUFB, RRR, 0x580, "shufb", _A4(A_C,A_A,A_B,A_T), 02111, SHUF) /* SHUFfleBytes RC<-f(RA,RB,RT) */ | ||
208 | APUOP(M_IL, RI16, 0x204, "il", _A2(A_T,A_S16), 00002, FX2) /* ImmLoad RT<-sxt(I16) */ | ||
209 | APUOP(M_ILH, RI16, 0x20c, "ilh", _A2(A_T,A_X16), 00002, FX2) /* ImmLoadH RT<-I16 */ | ||
210 | APUOP(M_ILHU, RI16, 0x208, "ilhu", _A2(A_T,A_X16), 00002, FX2) /* ImmLoadHUpper RT<-I16<<16 */ | ||
211 | APUOP(M_ILA, RI18, 0x210, "ila", _A2(A_T,A_U18), 00002, FX2) /* ImmLoadAddr RT<-zxt(I18) */ | ||
212 | APUOP(M_NOP, RR, 0x201, "nop", _A1(A_T), 00000, NOP) /* XNOP no_operation */ | ||
213 | APUOP(M_NOP2, RR, 0x201, "nop", _A0(), 00000, NOP) /* XNOP no_operation */ | ||
214 | APUOP(M_IOHL, RI16, 0x304, "iohl", _A2(A_T,A_X16), 00003, FX2) /* AddImmeXt RT<-RT+sxt(I16) */ | ||
215 | APUOP(M_ANDBI, RI10, 0x0b0, "andbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* AND%I RT<-RA&I10 */ | ||
216 | APUOP(M_ANDHI, RI10, 0x0a8, "andhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* AND%I RT<-RA&I10 */ | ||
217 | APUOP(M_ANDI, RI10, 0x0a0, "andi", _A3(A_T,A_A,A_S10), 00012, FX2) /* AND%I RT<-RA&I10 */ | ||
218 | APUOP(M_ORBI, RI10, 0x030, "orbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* OR%I RT<-RA|I10 */ | ||
219 | APUOP(M_ORHI, RI10, 0x028, "orhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* OR%I RT<-RA|I10 */ | ||
220 | APUOP(M_ORI, RI10, 0x020, "ori", _A3(A_T,A_A,A_S10), 00012, FX2) /* OR%I RT<-RA|I10 */ | ||
221 | APUOP(M_ORX, RR, 0x1f0, "orx", _A2(A_T,A_A), 00012, BR) /* ORX RT<-RA.w0|RA.w1|RA.w2|RA.w3 */ | ||
222 | APUOP(M_XORBI, RI10, 0x230, "xorbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* XOR%I RT<-RA^I10 */ | ||
223 | APUOP(M_XORHI, RI10, 0x228, "xorhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* XOR%I RT<-RA^I10 */ | ||
224 | APUOP(M_XORI, RI10, 0x220, "xori", _A3(A_T,A_A,A_S10), 00012, FX2) /* XOR%I RT<-RA^I10 */ | ||
225 | APUOP(M_AHI, RI10, 0x0e8, "ahi", _A3(A_T,A_A,A_S10), 00012, FX2) /* Add%Immed RT<-RA+I10 */ | ||
226 | APUOP(M_AI, RI10, 0x0e0, "ai", _A3(A_T,A_A,A_S10), 00012, FX2) /* Add%Immed RT<-RA+I10 */ | ||
227 | APUOP(M_SFHI, RI10, 0x068, "sfhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* SubFrom%Imm RT<-I10-RA */ | ||
228 | APUOP(M_SFI, RI10, 0x060, "sfi", _A3(A_T,A_A,A_S10), 00012, FX2) /* SubFrom%Imm RT<-I10-RA */ | ||
229 | APUOP(M_CGTBI, RI10, 0x270, "cgtbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CGT%I RT<-(RA>I10) */ | ||
230 | APUOP(M_CGTHI, RI10, 0x268, "cgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */ | ||
231 | APUOP(M_CGTI, RI10, 0x260, "cgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */ | ||
232 | APUOP(M_CLGTBI, RI10, 0x2f0, "clgtbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CLGT%I RT<-(RA>I10) */ | ||
233 | APUOP(M_CLGTHI, RI10, 0x2e8, "clgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */ | ||
234 | APUOP(M_CLGTI, RI10, 0x2e0, "clgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */ | ||
235 | APUOP(M_CEQBI, RI10, 0x3f0, "ceqbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CEQ%I RT<-(RA=I10) */ | ||
236 | APUOP(M_CEQHI, RI10, 0x3e8, "ceqhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */ | ||
237 | APUOP(M_CEQI, RI10, 0x3e0, "ceqi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */ | ||
238 | APUOP(M_HGTI, RI10, 0x278, "hgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */ | ||
239 | APUOP(M_HGTI2, RI10, 0x278, "hgti", _A2(A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */ | ||
240 | APUOP(M_HLGTI, RI10, 0x2f8, "hlgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */ | ||
241 | APUOP(M_HLGTI2, RI10, 0x2f8, "hlgti", _A2(A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */ | ||
242 | APUOP(M_HEQI, RI10, 0x3f8, "heqi", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */ | ||
243 | APUOP(M_HEQI2, RI10, 0x3f8, "heqi", _A2(A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */ | ||
244 | APUOP(M_MPYI, RI10, 0x3a0, "mpyi", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYI RT<-RA*I10 */ | ||
245 | APUOP(M_MPYUI, RI10, 0x3a8, "mpyui", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYUI RT<-RA*I10 */ | ||
246 | APUOP(M_CFLTS, RI8, 0x3b0, "cflts", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTS RT<-int(RA,I8) */ | ||
247 | APUOP(M_CFLTU, RI8, 0x3b2, "cfltu", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTU RT<-int(RA,I8) */ | ||
248 | APUOP(M_CSFLT, RI8, 0x3b4, "csflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CSFLT RT<-flt(RA,I8) */ | ||
249 | APUOP(M_CUFLT, RI8, 0x3b6, "cuflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CUFLT RT<-flt(RA,I8) */ | ||
250 | APUOP(M_FESD, RR, 0x3b8, "fesd", _A2(A_T,A_A), 00012, FPD) /* FESD RT<-double(RA) */ | ||
251 | APUOP(M_FRDS, RR, 0x3b9, "frds", _A2(A_T,A_A), 00012, FPD) /* FRDS RT<-single(RA) */ | ||
252 | APUOP(M_FSCRRD, RR, 0x398, "fscrrd", _A1(A_T), 00002, FPD) /* FSCRRD RT<-FP_status */ | ||
253 | APUOP(M_FSCRWR, RR, 0x3ba, "fscrwr", _A2(A_T,A_A), 00010, FP7) /* FSCRWR FP_status<-RA */ | ||
254 | APUOP(M_FSCRWR2, RR, 0x3ba, "fscrwr", _A1(A_A), 00010, FP7) /* FSCRWR FP_status<-RA */ | ||
255 | APUOP(M_CLZ, RR, 0x2a5, "clz", _A2(A_T,A_A), 00012, FX2) /* CLZ RT<-clz(RA) */ | ||
256 | APUOP(M_CNTB, RR, 0x2b4, "cntb", _A2(A_T,A_A), 00012, FXB) /* CNT RT<-pop(RA) */ | ||
257 | APUOP(M_XSBH, RR, 0x2b6, "xsbh", _A2(A_T,A_A), 00012, FX2) /* eXtSignBtoH RT<-sign_ext(RA) */ | ||
258 | APUOP(M_XSHW, RR, 0x2ae, "xshw", _A2(A_T,A_A), 00012, FX2) /* eXtSignHtoW RT<-sign_ext(RA) */ | ||
259 | APUOP(M_XSWD, RR, 0x2a6, "xswd", _A2(A_T,A_A), 00012, FX2) /* eXtSignWtoD RT<-sign_ext(RA) */ | ||
260 | APUOP(M_ROTI, RI7, 0x078, "roti", _A3(A_T,A_A,A_S7N), 00012, FX3) /* ROT%I RT<-RA<<<I7 */ | ||
261 | APUOP(M_ROTMI, RI7, 0x079, "rotmi", _A3(A_T,A_A,A_S7), 00012, FX3) /* ROT%MI RT<-RA<<I7 */ | ||
262 | APUOP(M_ROTMAI, RI7, 0x07a, "rotmai", _A3(A_T,A_A,A_S7), 00012, FX3) /* ROTMA%I RT<-RA<<I7 */ | ||
263 | APUOP(M_SHLI, RI7, 0x07b, "shli", _A3(A_T,A_A,A_U6), 00012, FX3) /* SHL%I RT<-RA<<I7 */ | ||
264 | APUOP(M_ROTHI, RI7, 0x07c, "rothi", _A3(A_T,A_A,A_S7N), 00012, FX3) /* ROT%I RT<-RA<<<I7 */ | ||
265 | APUOP(M_ROTHMI, RI7, 0x07d, "rothmi", _A3(A_T,A_A,A_S6), 00012, FX3) /* ROT%MI RT<-RA<<I7 */ | ||
266 | APUOP(M_ROTMAHI, RI7, 0x07e, "rotmahi", _A3(A_T,A_A,A_S6), 00012, FX3) /* ROTMA%I RT<-RA<<I7 */ | ||
267 | APUOP(M_SHLHI, RI7, 0x07f, "shlhi", _A3(A_T,A_A,A_U5), 00012, FX3) /* SHL%I RT<-RA<<I7 */ | ||
268 | APUOP(M_A, RR, 0x0c0, "a", _A3(A_T,A_A,A_B), 00112, FX2) /* Add% RT<-RA+RB */ | ||
269 | APUOP(M_AH, RR, 0x0c8, "ah", _A3(A_T,A_A,A_B), 00112, FX2) /* Add% RT<-RA+RB */ | ||
270 | APUOP(M_SF, RR, 0x040, "sf", _A3(A_T,A_A,A_B), 00112, FX2) /* SubFrom% RT<-RB-RA */ | ||
271 | APUOP(M_SFH, RR, 0x048, "sfh", _A3(A_T,A_A,A_B), 00112, FX2) /* SubFrom% RT<-RB-RA */ | ||
272 | APUOP(M_CGT, RR, 0x240, "cgt", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */ | ||
273 | APUOP(M_CGTB, RR, 0x250, "cgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */ | ||
274 | APUOP(M_CGTH, RR, 0x248, "cgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */ | ||
275 | APUOP(M_CLGT, RR, 0x2c0, "clgt", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */ | ||
276 | APUOP(M_CLGTB, RR, 0x2d0, "clgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */ | ||
277 | APUOP(M_CLGTH, RR, 0x2c8, "clgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */ | ||
278 | APUOP(M_CEQ, RR, 0x3c0, "ceq", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */ | ||
279 | APUOP(M_CEQB, RR, 0x3d0, "ceqb", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */ | ||
280 | APUOP(M_CEQH, RR, 0x3c8, "ceqh", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */ | ||
281 | APUOP(M_HGT, RR, 0x258, "hgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */ | ||
282 | APUOP(M_HGT2, RR, 0x258, "hgt", _A2(A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */ | ||
283 | APUOP(M_HLGT, RR, 0x2d8, "hlgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */ | ||
284 | APUOP(M_HLGT2, RR, 0x2d8, "hlgt", _A2(A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */ | ||
285 | APUOP(M_HEQ, RR, 0x3d8, "heq", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */ | ||
286 | APUOP(M_HEQ2, RR, 0x3d8, "heq", _A2(A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */ | ||
287 | APUOP(M_FCEQ, RR, 0x3c2, "fceq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCEQ RT<-(RA=RB) */ | ||
288 | APUOP(M_FCMEQ, RR, 0x3ca, "fcmeq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCMEQ RT<-(|RA|=|RB|) */ | ||
289 | APUOP(M_FCGT, RR, 0x2c2, "fcgt", _A3(A_T,A_A,A_B), 00112, FX2) /* FCGT RT<-(RA<RB) */ | ||
290 | APUOP(M_FCMGT, RR, 0x2ca, "fcmgt", _A3(A_T,A_A,A_B), 00112, FX2) /* FCMGT RT<-(|RA|<|RB|) */ | ||
291 | APUOP(M_AND, RR, 0x0c1, "and", _A3(A_T,A_A,A_B), 00112, FX2) /* AND RT<-RA&RB */ | ||
292 | APUOP(M_NAND, RR, 0x0c9, "nand", _A3(A_T,A_A,A_B), 00112, FX2) /* NAND RT<-!(RA&RB) */ | ||
293 | APUOP(M_OR, RR, 0x041, "or", _A3(A_T,A_A,A_B), 00112, FX2) /* OR RT<-RA|RB */ | ||
294 | APUOP(M_NOR, RR, 0x049, "nor", _A3(A_T,A_A,A_B), 00112, FX2) /* NOR RT<-!(RA&RB) */ | ||
295 | APUOP(M_XOR, RR, 0x241, "xor", _A3(A_T,A_A,A_B), 00112, FX2) /* XOR RT<-RA^RB */ | ||
296 | APUOP(M_EQV, RR, 0x249, "eqv", _A3(A_T,A_A,A_B), 00112, FX2) /* EQuiValent RT<-!(RA^RB) */ | ||
297 | APUOP(M_ANDC, RR, 0x2c1, "andc", _A3(A_T,A_A,A_B), 00112, FX2) /* ANDComplement RT<-RA&!RB */ | ||
298 | APUOP(M_ORC, RR, 0x2c9, "orc", _A3(A_T,A_A,A_B), 00112, FX2) /* ORComplement RT<-RA|!RB */ | ||
299 | APUOP(M_ABSDB, RR, 0x053, "absdb", _A3(A_T,A_A,A_B), 00112, FXB) /* ABSoluteDiff RT<-|RA-RB| */ | ||
300 | APUOP(M_AVGB, RR, 0x0d3, "avgb", _A3(A_T,A_A,A_B), 00112, FXB) /* AVG% RT<-(RA+RB+1)/2 */ | ||
301 | APUOP(M_SUMB, RR, 0x253, "sumb", _A3(A_T,A_A,A_B), 00112, FXB) /* SUM% RT<-f(RA,RB) */ | ||
302 | APUOP(M_DFA, RR, 0x2cc, "dfa", _A3(A_T,A_A,A_B), 00112, FPD) /* DFAdd RT<-RA+RB */ | ||
303 | APUOP(M_DFM, RR, 0x2ce, "dfm", _A3(A_T,A_A,A_B), 00112, FPD) /* DFMul RT<-RA*RB */ | ||
304 | APUOP(M_DFS, RR, 0x2cd, "dfs", _A3(A_T,A_A,A_B), 00112, FPD) /* DFSub RT<-RA-RB */ | ||
305 | APUOP(M_FA, RR, 0x2c4, "fa", _A3(A_T,A_A,A_B), 00112, FP6) /* FAdd RT<-RA+RB */ | ||
306 | APUOP(M_FM, RR, 0x2c6, "fm", _A3(A_T,A_A,A_B), 00112, FP6) /* FMul RT<-RA*RB */ | ||
307 | APUOP(M_FS, RR, 0x2c5, "fs", _A3(A_T,A_A,A_B), 00112, FP6) /* FSub RT<-RA-RB */ | ||
308 | APUOP(M_MPY, RR, 0x3c4, "mpy", _A3(A_T,A_A,A_B), 00112, FP7) /* MPY RT<-RA*RB */ | ||
309 | APUOP(M_MPYH, RR, 0x3c5, "mpyh", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYH RT<-(RAh*RB)<<16 */ | ||
310 | APUOP(M_MPYHH, RR, 0x3c6, "mpyhh", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYHH RT<-RAh*RBh */ | ||
311 | APUOP(M_MPYHHU, RR, 0x3ce, "mpyhhu", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYHHU RT<-RAh*RBh */ | ||
312 | APUOP(M_MPYS, RR, 0x3c7, "mpys", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYS RT<-(RA*RB)>>16 */ | ||
313 | APUOP(M_MPYU, RR, 0x3cc, "mpyu", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYU RT<-RA*RB */ | ||
314 | APUOP(M_FI, RR, 0x3d4, "fi", _A3(A_T,A_A,A_B), 00112, FP7) /* FInterpolate RT<-f(RA,RB) */ | ||
315 | APUOP(M_ROT, RR, 0x058, "rot", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT% RT<-RA<<<RB */ | ||
316 | APUOP(M_ROTM, RR, 0x059, "rotm", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT%M RT<-RA<<Rb */ | ||
317 | APUOP(M_ROTMA, RR, 0x05a, "rotma", _A3(A_T,A_A,A_B), 00112, FX3) /* ROTMA% RT<-RA<<Rb */ | ||
318 | APUOP(M_SHL, RR, 0x05b, "shl", _A3(A_T,A_A,A_B), 00112, FX3) /* SHL% RT<-RA<<Rb */ | ||
319 | APUOP(M_ROTH, RR, 0x05c, "roth", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT% RT<-RA<<<RB */ | ||
320 | APUOP(M_ROTHM, RR, 0x05d, "rothm", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT%M RT<-RA<<Rb */ | ||
321 | APUOP(M_ROTMAH, RR, 0x05e, "rotmah", _A3(A_T,A_A,A_B), 00112, FX3) /* ROTMA% RT<-RA<<Rb */ | ||
322 | APUOP(M_SHLH, RR, 0x05f, "shlh", _A3(A_T,A_A,A_B), 00112, FX3) /* SHL% RT<-RA<<Rb */ | ||
323 | APUOP(M_MPYHHA, RR, 0x346, "mpyhha", _A3(A_T,A_A,A_B), 00113, FP7) /* MPYHHA RT<-RAh*RBh+RT */ | ||
324 | APUOP(M_MPYHHAU, RR, 0x34e, "mpyhhau", _A3(A_T,A_A,A_B), 00113, FP7) /* MPYHHAU RT<-RAh*RBh+RT */ | ||
325 | APUOP(M_DFMA, RR, 0x35c, "dfma", _A3(A_T,A_A,A_B), 00113, FPD) /* DFMAdd RT<-RT+RA*RB */ | ||
326 | APUOP(M_DFMS, RR, 0x35d, "dfms", _A3(A_T,A_A,A_B), 00113, FPD) /* DFMSub RT<-RA*RB-RT */ | ||
327 | APUOP(M_DFNMS, RR, 0x35e, "dfnms", _A3(A_T,A_A,A_B), 00113, FPD) /* DFNMSub RT<-RT-RA*RB */ | ||
328 | APUOP(M_DFNMA, RR, 0x35f, "dfnma", _A3(A_T,A_A,A_B), 00113, FPD) /* DFNMAdd RT<-(-RT)-RA*RB */ | ||
329 | APUOP(M_FMA, RRR, 0x700, "fma", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FMAdd RC<-RT+RA*RB */ | ||
330 | APUOP(M_FMS, RRR, 0x780, "fms", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FMSub RC<-RA*RB-RT */ | ||
331 | APUOP(M_FNMS, RRR, 0x680, "fnms", _A4(A_C,A_A,A_B,A_T), 02111, FP6) /* FNMSub RC<-RT-RA*RB */ | ||
332 | APUOP(M_MPYA, RRR, 0x600, "mpya", _A4(A_C,A_A,A_B,A_T), 02111, FP7) /* MPYA RC<-RA*RB+RT */ | ||
333 | APUOP(M_SELB, RRR, 0x400, "selb", _A4(A_C,A_A,A_B,A_T), 02111, FX2) /* SELectBits RC<-RA&RT|RB&!RT */ | ||
334 | /* for system function call, this uses op-code of mtspr */ | ||
335 | APUOP(M_SYSCALL, RI7, 0x10c, "syscall", _A3(A_T,A_A,A_S7N), 00002, SPR) /* System Call */ | ||
336 | /* | ||
337 | pseudo instruction: | ||
338 | system call | ||
339 | value of I9 operation | ||
340 | 0 halt | ||
341 | 1 rt[0] = open(MEM[ra[0]], ra[1]) | ||
342 | 2 rt[0] = close(ra[0]) | ||
343 | 3 rt[0] = read(ra[0], MEM[ra[1]], ra[2]) | ||
344 | 4 rt[0] = write(ra[0], MEM[ra[1]], ra[2]) | ||
345 | 5 printf(MEM[ra[0]], ra[1], ra[2], ra[3]) | ||
346 | 42 rt[0] = clock() | ||
347 | 52 rt[0] = lseek(ra0, ra1, ra2) | ||
348 | |||
349 | */ | ||
350 | |||
351 | |||
352 | /* new multiprecision add/sub */ | ||
353 | APUOP(M_ADDX, RR, 0x340, "addx", _A3(A_T,A_A,A_B), 00113, FX2) /* Add_eXtended RT<-RA+RB+RT */ | ||
354 | APUOP(M_CG, RR, 0x0c2, "cg", _A3(A_T,A_A,A_B), 00112, FX2) /* CarryGenerate RT<-cout(RA+RB) */ | ||
355 | APUOP(M_CGX, RR, 0x342, "cgx", _A3(A_T,A_A,A_B), 00113, FX2) /* CarryGen_eXtd RT<-cout(RA+RB+RT) */ | ||
356 | APUOP(M_SFX, RR, 0x341, "sfx", _A3(A_T,A_A,A_B), 00113, FX2) /* Add_eXtended RT<-RA+RB+RT */ | ||
357 | APUOP(M_BG, RR, 0x042, "bg", _A3(A_T,A_A,A_B), 00112, FX2) /* CarryGenerate RT<-cout(RA+RB) */ | ||
358 | APUOP(M_BGX, RR, 0x343, "bgx", _A3(A_T,A_A,A_B), 00113, FX2) /* CarryGen_eXtd RT<-cout(RA+RB+RT) */ | ||
359 | |||
360 | /* | ||
361 | |||
362 | The following ops are a subset of above except with feature bits set. | ||
363 | Feature bits are bits 11-17 of the instruction: | ||
364 | |||
365 | 11 - C & P feature bit | ||
366 | 12 - disable interrupts | ||
367 | 13 - enable interrupts | ||
368 | |||
369 | */ | ||
370 | APUOPFB(M_BID, RR, 0x1a8, 0x20, "bid", _A1(A_A), 00010, BR) /* BI IP<-RA */ | ||
371 | APUOPFB(M_BIE, RR, 0x1a8, 0x10, "bie", _A1(A_A), 00010, BR) /* BI IP<-RA */ | ||
372 | APUOPFB(M_BISLD, RR, 0x1a9, 0x20, "bisld", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */ | ||
373 | APUOPFB(M_BISLE, RR, 0x1a9, 0x10, "bisle", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */ | ||
374 | APUOPFB(M_IRETD, RR, 0x1aa, 0x20, "iretd", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */ | ||
375 | APUOPFB(M_IRETD2, RR, 0x1aa, 0x20, "iretd", _A0(), 00010, BR) /* IRET IP<-SRR0 */ | ||
376 | APUOPFB(M_IRETE, RR, 0x1aa, 0x10, "irete", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */ | ||
377 | APUOPFB(M_IRETE2, RR, 0x1aa, 0x10, "irete", _A0(), 00010, BR) /* IRET IP<-SRR0 */ | ||
378 | APUOPFB(M_BISLEDD, RR, 0x1ab, 0x20, "bisledd", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */ | ||
379 | APUOPFB(M_BISLEDE, RR, 0x1ab, 0x10, "bislede", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */ | ||
380 | APUOPFB(M_BIHNZD, RR, 0x12b, 0x20, "bihnzd", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */ | ||
381 | APUOPFB(M_BIHNZE, RR, 0x12b, 0x10, "bihnze", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */ | ||
382 | APUOPFB(M_BIHZD, RR, 0x12a, 0x20, "bihzd", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */ | ||
383 | APUOPFB(M_BIHZE, RR, 0x12a, 0x10, "bihze", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */ | ||
384 | APUOPFB(M_BINZD, RR, 0x129, 0x20, "binzd", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */ | ||
385 | APUOPFB(M_BINZE, RR, 0x129, 0x10, "binze", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */ | ||
386 | APUOPFB(M_BIZD, RR, 0x128, 0x20, "bizd", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */ | ||
387 | APUOPFB(M_BIZE, RR, 0x128, 0x10, "bize", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */ | ||
388 | APUOPFB(M_SYNCC, RR, 0x002, 0x40, "syncc", _A0(), 00000, BR) /* SYNCC flush_pipe */ | ||
389 | APUOPFB(M_HBRP, LBTI, 0x1ac, 0x40, "hbrp", _A0(), 00010, LS) /* HBR BTB[B9]<-M[Ra] */ | ||
390 | |||
391 | /* Synonyms required by the AS manual. */ | ||
392 | APUOP(M_LR, RI10, 0x020, "lr", _A2(A_T,A_A), 00012, FX2) /* OR%I RT<-RA|I10 */ | ||
393 | APUOP(M_BIHT, RR, 0x12b, "biht", _A2(A_T,A_A), 00011, BR) /* BIHNZ IP<-RA_if(RT) */ | ||
394 | APUOP(M_BIHF, RR, 0x12a, "bihf", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */ | ||
395 | APUOP(M_BIT, RR, 0x129, "bit", _A2(A_T,A_A), 00011, BR) /* BINZ IP<-RA_if(RT) */ | ||
396 | APUOP(M_BIF, RR, 0x128, "bif", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */ | ||
397 | APUOPFB(M_BIHTD, RR, 0x12b, 0x20, "bihtd", _A2(A_T,A_A), 00011, BR) /* BIHNF IP<-RA_if(RT) */ | ||
398 | APUOPFB(M_BIHTE, RR, 0x12b, 0x10, "bihte", _A2(A_T,A_A), 00011, BR) /* BIHNF IP<-RA_if(RT) */ | ||
399 | APUOPFB(M_BIHFD, RR, 0x12a, 0x20, "bihfd", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */ | ||
400 | APUOPFB(M_BIHFE, RR, 0x12a, 0x10, "bihfe", _A2(A_T,A_A), 00011, BR) /* BIHZ IP<-RA_if(RT) */ | ||
401 | APUOPFB(M_BITD, RR, 0x129, 0x20, "bitd", _A2(A_T,A_A), 00011, BR) /* BINF IP<-RA_if(RT) */ | ||
402 | APUOPFB(M_BITE, RR, 0x129, 0x10, "bite", _A2(A_T,A_A), 00011, BR) /* BINF IP<-RA_if(RT) */ | ||
403 | APUOPFB(M_BIFD, RR, 0x128, 0x20, "bifd", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */ | ||
404 | APUOPFB(M_BIFE, RR, 0x128, 0x10, "bife", _A2(A_T,A_A), 00011, BR) /* BIZ IP<-RA_if(RT) */ | ||
405 | |||
406 | #undef _A0 | ||
407 | #undef _A1 | ||
408 | #undef _A2 | ||
409 | #undef _A3 | ||
410 | #undef _A4 | ||
diff --git a/arch/powerpc/xmon/spu-opc.c b/arch/powerpc/xmon/spu-opc.c new file mode 100644 index 00000000000..efffde9edc6 --- /dev/null +++ b/arch/powerpc/xmon/spu-opc.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* SPU opcode list | ||
2 | |||
3 | Copyright 2006 Free Software Foundation, Inc. | ||
4 | |||
5 | This file is part of GDB, GAS, and the GNU binutils. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License along | ||
18 | with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
20 | |||
21 | #include "spu.h" | ||
22 | |||
23 | /* This file holds the Spu opcode table */ | ||
24 | |||
25 | |||
26 | /* | ||
27 | Example contents of spu-insn.h | ||
28 | id_tag mode mode type opcode mnemonic asmtype dependency FPU L/S? branch? instruction | ||
29 | QUAD WORD (0,RC,RB,RA,RT) latency | ||
30 | APUOP(M_LQD, 1, 0, RI9, 0x1f8, "lqd", ASM_RI9IDX, 00012, FXU, 1, 0) Load Quadword d-form | ||
31 | */ | ||
32 | |||
33 | const struct spu_opcode spu_opcodes[] = { | ||
34 | #define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \ | ||
35 | { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT }, | ||
36 | #define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \ | ||
37 | { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT }, | ||
38 | #include "spu-insns.h" | ||
39 | #undef APUOP | ||
40 | #undef APUOPFB | ||
41 | }; | ||
42 | |||
43 | const int spu_num_opcodes = | ||
44 | sizeof (spu_opcodes) / sizeof (spu_opcodes[0]); | ||
diff --git a/arch/powerpc/xmon/spu.h b/arch/powerpc/xmon/spu.h new file mode 100644 index 00000000000..c761fc8f35d --- /dev/null +++ b/arch/powerpc/xmon/spu.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* SPU ELF support for BFD. | ||
2 | |||
3 | Copyright 2006 Free Software Foundation, Inc. | ||
4 | |||
5 | This file is part of GDB, GAS, and the GNU binutils. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software Foundation, | ||
19 | Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
20 | |||
21 | |||
22 | /* These two enums are from rel_apu/common/spu_asm_format.h */ | ||
23 | /* definition of instruction format */ | ||
24 | typedef enum { | ||
25 | RRR, | ||
26 | RI18, | ||
27 | RI16, | ||
28 | RI10, | ||
29 | RI8, | ||
30 | RI7, | ||
31 | RR, | ||
32 | LBT, | ||
33 | LBTI, | ||
34 | IDATA, | ||
35 | UNKNOWN_IFORMAT | ||
36 | } spu_iformat; | ||
37 | |||
38 | /* These values describe assembly instruction arguments. They indicate | ||
39 | * how to encode, range checking and which relocation to use. */ | ||
40 | typedef enum { | ||
41 | A_T, /* register at pos 0 */ | ||
42 | A_A, /* register at pos 7 */ | ||
43 | A_B, /* register at pos 14 */ | ||
44 | A_C, /* register at pos 21 */ | ||
45 | A_S, /* special purpose register at pos 7 */ | ||
46 | A_H, /* channel register at pos 7 */ | ||
47 | A_P, /* parenthesis, this has to separate regs from immediates */ | ||
48 | A_S3, | ||
49 | A_S6, | ||
50 | A_S7N, | ||
51 | A_S7, | ||
52 | A_U7A, | ||
53 | A_U7B, | ||
54 | A_S10B, | ||
55 | A_S10, | ||
56 | A_S11, | ||
57 | A_S11I, | ||
58 | A_S14, | ||
59 | A_S16, | ||
60 | A_S18, | ||
61 | A_R18, | ||
62 | A_U3, | ||
63 | A_U5, | ||
64 | A_U6, | ||
65 | A_U7, | ||
66 | A_U14, | ||
67 | A_X16, | ||
68 | A_U18, | ||
69 | A_MAX | ||
70 | } spu_aformat; | ||
71 | |||
72 | enum spu_insns { | ||
73 | #define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \ | ||
74 | TAG, | ||
75 | #define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \ | ||
76 | TAG, | ||
77 | #include "spu-insns.h" | ||
78 | #undef APUOP | ||
79 | #undef APUOPFB | ||
80 | M_SPU_MAX | ||
81 | }; | ||
82 | |||
83 | struct spu_opcode | ||
84 | { | ||
85 | spu_iformat insn_type; | ||
86 | unsigned int opcode; | ||
87 | char *mnemonic; | ||
88 | int arg[5]; | ||
89 | }; | ||
90 | |||
91 | #define SIGNED_EXTRACT(insn,size,pos) (((int)((insn) << (32-size-pos))) >> (32-size)) | ||
92 | #define UNSIGNED_EXTRACT(insn,size,pos) (((insn) >> pos) & ((1 << size)-1)) | ||
93 | |||
94 | #define DECODE_INSN_RT(insn) (insn & 0x7f) | ||
95 | #define DECODE_INSN_RA(insn) ((insn >> 7) & 0x7f) | ||
96 | #define DECODE_INSN_RB(insn) ((insn >> 14) & 0x7f) | ||
97 | #define DECODE_INSN_RC(insn) ((insn >> 21) & 0x7f) | ||
98 | |||
99 | #define DECODE_INSN_I10(insn) SIGNED_EXTRACT(insn,10,14) | ||
100 | #define DECODE_INSN_U10(insn) UNSIGNED_EXTRACT(insn,10,14) | ||
101 | |||
102 | /* For branching, immediate loads, hbr and lqa/stqa. */ | ||
103 | #define DECODE_INSN_I16(insn) SIGNED_EXTRACT(insn,16,7) | ||
104 | #define DECODE_INSN_U16(insn) UNSIGNED_EXTRACT(insn,16,7) | ||
105 | |||
106 | /* for stop */ | ||
107 | #define DECODE_INSN_U14(insn) UNSIGNED_EXTRACT(insn,14,0) | ||
108 | |||
109 | /* For ila */ | ||
110 | #define DECODE_INSN_I18(insn) SIGNED_EXTRACT(insn,18,7) | ||
111 | #define DECODE_INSN_U18(insn) UNSIGNED_EXTRACT(insn,18,7) | ||
112 | |||
113 | /* For rotate and shift and generate control mask */ | ||
114 | #define DECODE_INSN_I7(insn) SIGNED_EXTRACT(insn,7,14) | ||
115 | #define DECODE_INSN_U7(insn) UNSIGNED_EXTRACT(insn,7,14) | ||
116 | |||
117 | /* For float <-> int conversion */ | ||
118 | #define DECODE_INSN_I8(insn) SIGNED_EXTRACT(insn,8,14) | ||
119 | #define DECODE_INSN_U8(insn) UNSIGNED_EXTRACT(insn,8,14) | ||
120 | |||
121 | /* For hbr */ | ||
122 | #define DECODE_INSN_I9a(insn) ((SIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0)) | ||
123 | #define DECODE_INSN_I9b(insn) ((SIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0)) | ||
124 | #define DECODE_INSN_U9a(insn) ((UNSIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0)) | ||
125 | #define DECODE_INSN_U9b(insn) ((UNSIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0)) | ||
126 | |||
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index f56ffef4def..a34ed49e035 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -37,13 +37,18 @@ | |||
37 | #include <asm/sstep.h> | 37 | #include <asm/sstep.h> |
38 | #include <asm/bug.h> | 38 | #include <asm/bug.h> |
39 | #include <asm/irq_regs.h> | 39 | #include <asm/irq_regs.h> |
40 | #include <asm/spu.h> | ||
41 | #include <asm/spu_priv1.h> | ||
42 | #include <asm/firmware.h> | ||
40 | 43 | ||
41 | #ifdef CONFIG_PPC64 | 44 | #ifdef CONFIG_PPC64 |
42 | #include <asm/hvcall.h> | 45 | #include <asm/hvcall.h> |
43 | #include <asm/paca.h> | 46 | #include <asm/paca.h> |
47 | #include <asm/iseries/it_lp_reg_save.h> | ||
44 | #endif | 48 | #endif |
45 | 49 | ||
46 | #include "nonstdio.h" | 50 | #include "nonstdio.h" |
51 | #include "dis-asm.h" | ||
47 | 52 | ||
48 | #define scanhex xmon_scanhex | 53 | #define scanhex xmon_scanhex |
49 | #define skipbl xmon_skipbl | 54 | #define skipbl xmon_skipbl |
@@ -107,7 +112,6 @@ static int bsesc(void); | |||
107 | static void dump(void); | 112 | static void dump(void); |
108 | static void prdump(unsigned long, long); | 113 | static void prdump(unsigned long, long); |
109 | static int ppc_inst_dump(unsigned long, long, int); | 114 | static int ppc_inst_dump(unsigned long, long, int); |
110 | void print_address(unsigned long); | ||
111 | static void backtrace(struct pt_regs *); | 115 | static void backtrace(struct pt_regs *); |
112 | static void excprint(struct pt_regs *); | 116 | static void excprint(struct pt_regs *); |
113 | static void prregs(struct pt_regs *); | 117 | static void prregs(struct pt_regs *); |
@@ -147,9 +151,9 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
147 | const char *after); | 151 | const char *after); |
148 | static const char *getvecname(unsigned long vec); | 152 | static const char *getvecname(unsigned long vec); |
149 | 153 | ||
150 | int xmon_no_auto_backtrace; | 154 | static int do_spu_cmd(void); |
151 | 155 | ||
152 | extern int print_insn_powerpc(unsigned long, unsigned long, int); | 156 | int xmon_no_auto_backtrace; |
153 | 157 | ||
154 | extern void xmon_enter(void); | 158 | extern void xmon_enter(void); |
155 | extern void xmon_leave(void); | 159 | extern void xmon_leave(void); |
@@ -209,8 +213,15 @@ Commands:\n\ | |||
209 | mi show information about memory allocation\n\ | 213 | mi show information about memory allocation\n\ |
210 | p call a procedure\n\ | 214 | p call a procedure\n\ |
211 | r print registers\n\ | 215 | r print registers\n\ |
212 | s single step\n\ | 216 | s single step\n" |
213 | S print special registers\n\ | 217 | #ifdef CONFIG_SPU_BASE |
218 | " ss stop execution on all spus\n\ | ||
219 | sr restore execution on stopped spus\n\ | ||
220 | sf # dump spu fields for spu # (in hex)\n\ | ||
221 | sd # dump spu local store for spu # (in hex)\ | ||
222 | sdi # disassemble spu local store for spu # (in hex)\n" | ||
223 | #endif | ||
224 | " S print special registers\n\ | ||
214 | t print backtrace\n\ | 225 | t print backtrace\n\ |
215 | x exit monitor and recover\n\ | 226 | x exit monitor and recover\n\ |
216 | X exit monitor and dont recover\n" | 227 | X exit monitor and dont recover\n" |
@@ -518,6 +529,7 @@ int xmon(struct pt_regs *excp) | |||
518 | xmon_save_regs(®s); | 529 | xmon_save_regs(®s); |
519 | excp = ®s; | 530 | excp = ®s; |
520 | } | 531 | } |
532 | |||
521 | return xmon_core(excp, 0); | 533 | return xmon_core(excp, 0); |
522 | } | 534 | } |
523 | EXPORT_SYMBOL(xmon); | 535 | EXPORT_SYMBOL(xmon); |
@@ -809,6 +821,8 @@ cmds(struct pt_regs *excp) | |||
809 | cacheflush(); | 821 | cacheflush(); |
810 | break; | 822 | break; |
811 | case 's': | 823 | case 's': |
824 | if (do_spu_cmd() == 0) | ||
825 | break; | ||
812 | if (do_step(excp)) | 826 | if (do_step(excp)) |
813 | return cmd; | 827 | return cmd; |
814 | break; | 828 | break; |
@@ -1555,11 +1569,6 @@ void super_regs(void) | |||
1555 | { | 1569 | { |
1556 | int cmd; | 1570 | int cmd; |
1557 | unsigned long val; | 1571 | unsigned long val; |
1558 | #ifdef CONFIG_PPC_ISERIES | ||
1559 | struct paca_struct *ptrPaca = NULL; | ||
1560 | struct lppaca *ptrLpPaca = NULL; | ||
1561 | struct ItLpRegSave *ptrLpRegSave = NULL; | ||
1562 | #endif | ||
1563 | 1572 | ||
1564 | cmd = skipbl(); | 1573 | cmd = skipbl(); |
1565 | if (cmd == '\n') { | 1574 | if (cmd == '\n') { |
@@ -1576,26 +1585,32 @@ void super_regs(void) | |||
1576 | printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); | 1585 | printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); |
1577 | printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); | 1586 | printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); |
1578 | #ifdef CONFIG_PPC_ISERIES | 1587 | #ifdef CONFIG_PPC_ISERIES |
1579 | // Dump out relevant Paca data areas. | 1588 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { |
1580 | printf("Paca: \n"); | 1589 | struct paca_struct *ptrPaca; |
1581 | ptrPaca = get_paca(); | 1590 | struct lppaca *ptrLpPaca; |
1582 | 1591 | struct ItLpRegSave *ptrLpRegSave; | |
1583 | printf(" Local Processor Control Area (LpPaca): \n"); | 1592 | |
1584 | ptrLpPaca = ptrPaca->lppaca_ptr; | 1593 | /* Dump out relevant Paca data areas. */ |
1585 | printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", | 1594 | printf("Paca: \n"); |
1586 | ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); | 1595 | ptrPaca = get_paca(); |
1587 | printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", | 1596 | |
1588 | ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); | 1597 | printf(" Local Processor Control Area (LpPaca): \n"); |
1589 | printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); | 1598 | ptrLpPaca = ptrPaca->lppaca_ptr; |
1590 | 1599 | printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", | |
1591 | printf(" Local Processor Register Save Area (LpRegSave): \n"); | 1600 | ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); |
1592 | ptrLpRegSave = ptrPaca->reg_save_ptr; | 1601 | printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", |
1593 | printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", | 1602 | ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); |
1594 | ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); | 1603 | printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); |
1595 | printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", | 1604 | |
1596 | ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); | 1605 | printf(" Local Processor Register Save Area (LpRegSave): \n"); |
1597 | printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", | 1606 | ptrLpRegSave = ptrPaca->reg_save_ptr; |
1598 | ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); | 1607 | printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", |
1608 | ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); | ||
1609 | printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", | ||
1610 | ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); | ||
1611 | printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", | ||
1612 | ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); | ||
1613 | } | ||
1599 | #endif | 1614 | #endif |
1600 | 1615 | ||
1601 | return; | 1616 | return; |
@@ -2053,8 +2068,11 @@ prdump(unsigned long adrs, long ndump) | |||
2053 | } | 2068 | } |
2054 | } | 2069 | } |
2055 | 2070 | ||
2071 | typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr); | ||
2072 | |||
2056 | int | 2073 | int |
2057 | ppc_inst_dump(unsigned long adr, long count, int praddr) | 2074 | generic_inst_dump(unsigned long adr, long count, int praddr, |
2075 | instruction_dump_func dump_func) | ||
2058 | { | 2076 | { |
2059 | int nr, dotted; | 2077 | int nr, dotted; |
2060 | unsigned long first_adr; | 2078 | unsigned long first_adr; |
@@ -2084,12 +2102,18 @@ ppc_inst_dump(unsigned long adr, long count, int praddr) | |||
2084 | if (praddr) | 2102 | if (praddr) |
2085 | printf(REG" %.8x", adr, inst); | 2103 | printf(REG" %.8x", adr, inst); |
2086 | printf("\t"); | 2104 | printf("\t"); |
2087 | print_insn_powerpc(inst, adr, 0); /* always returns 4 */ | 2105 | dump_func(inst, adr); |
2088 | printf("\n"); | 2106 | printf("\n"); |
2089 | } | 2107 | } |
2090 | return adr - first_adr; | 2108 | return adr - first_adr; |
2091 | } | 2109 | } |
2092 | 2110 | ||
2111 | int | ||
2112 | ppc_inst_dump(unsigned long adr, long count, int praddr) | ||
2113 | { | ||
2114 | return generic_inst_dump(adr, count, praddr, print_insn_powerpc); | ||
2115 | } | ||
2116 | |||
2093 | void | 2117 | void |
2094 | print_address(unsigned long addr) | 2118 | print_address(unsigned long addr) |
2095 | { | 2119 | { |
@@ -2557,6 +2581,10 @@ void dump_segments(void) | |||
2557 | 2581 | ||
2558 | void xmon_init(int enable) | 2582 | void xmon_init(int enable) |
2559 | { | 2583 | { |
2584 | #ifdef CONFIG_PPC_ISERIES | ||
2585 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
2586 | return; | ||
2587 | #endif | ||
2560 | if (enable) { | 2588 | if (enable) { |
2561 | __debugger = xmon; | 2589 | __debugger = xmon; |
2562 | __debugger_ipi = xmon_ipi; | 2590 | __debugger_ipi = xmon_ipi; |
@@ -2594,6 +2622,10 @@ static struct sysrq_key_op sysrq_xmon_op = | |||
2594 | 2622 | ||
2595 | static int __init setup_xmon_sysrq(void) | 2623 | static int __init setup_xmon_sysrq(void) |
2596 | { | 2624 | { |
2625 | #ifdef CONFIG_PPC_ISERIES | ||
2626 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
2627 | return 0; | ||
2628 | #endif | ||
2597 | register_sysrq_key('x', &sysrq_xmon_op); | 2629 | register_sysrq_key('x', &sysrq_xmon_op); |
2598 | return 0; | 2630 | return 0; |
2599 | } | 2631 | } |
@@ -2630,3 +2662,263 @@ void __init xmon_setup(void) | |||
2630 | if (xmon_early) | 2662 | if (xmon_early) |
2631 | debugger(NULL); | 2663 | debugger(NULL); |
2632 | } | 2664 | } |
2665 | |||
2666 | #ifdef CONFIG_SPU_BASE | ||
2667 | |||
2668 | struct spu_info { | ||
2669 | struct spu *spu; | ||
2670 | u64 saved_mfc_sr1_RW; | ||
2671 | u32 saved_spu_runcntl_RW; | ||
2672 | unsigned long dump_addr; | ||
2673 | u8 stopped_ok; | ||
2674 | }; | ||
2675 | |||
2676 | #define XMON_NUM_SPUS 16 /* Enough for current hardware */ | ||
2677 | |||
2678 | static struct spu_info spu_info[XMON_NUM_SPUS]; | ||
2679 | |||
2680 | void xmon_register_spus(struct list_head *list) | ||
2681 | { | ||
2682 | struct spu *spu; | ||
2683 | |||
2684 | list_for_each_entry(spu, list, full_list) { | ||
2685 | if (spu->number >= XMON_NUM_SPUS) { | ||
2686 | WARN_ON(1); | ||
2687 | continue; | ||
2688 | } | ||
2689 | |||
2690 | spu_info[spu->number].spu = spu; | ||
2691 | spu_info[spu->number].stopped_ok = 0; | ||
2692 | spu_info[spu->number].dump_addr = (unsigned long) | ||
2693 | spu_info[spu->number].spu->local_store; | ||
2694 | } | ||
2695 | } | ||
2696 | |||
2697 | static void stop_spus(void) | ||
2698 | { | ||
2699 | struct spu *spu; | ||
2700 | int i; | ||
2701 | u64 tmp; | ||
2702 | |||
2703 | for (i = 0; i < XMON_NUM_SPUS; i++) { | ||
2704 | if (!spu_info[i].spu) | ||
2705 | continue; | ||
2706 | |||
2707 | if (setjmp(bus_error_jmp) == 0) { | ||
2708 | catch_memory_errors = 1; | ||
2709 | sync(); | ||
2710 | |||
2711 | spu = spu_info[i].spu; | ||
2712 | |||
2713 | spu_info[i].saved_spu_runcntl_RW = | ||
2714 | in_be32(&spu->problem->spu_runcntl_RW); | ||
2715 | |||
2716 | tmp = spu_mfc_sr1_get(spu); | ||
2717 | spu_info[i].saved_mfc_sr1_RW = tmp; | ||
2718 | |||
2719 | tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
2720 | spu_mfc_sr1_set(spu, tmp); | ||
2721 | |||
2722 | sync(); | ||
2723 | __delay(200); | ||
2724 | |||
2725 | spu_info[i].stopped_ok = 1; | ||
2726 | |||
2727 | printf("Stopped spu %.2d (was %s)\n", i, | ||
2728 | spu_info[i].saved_spu_runcntl_RW ? | ||
2729 | "running" : "stopped"); | ||
2730 | } else { | ||
2731 | catch_memory_errors = 0; | ||
2732 | printf("*** Error stopping spu %.2d\n", i); | ||
2733 | } | ||
2734 | catch_memory_errors = 0; | ||
2735 | } | ||
2736 | } | ||
2737 | |||
2738 | static void restart_spus(void) | ||
2739 | { | ||
2740 | struct spu *spu; | ||
2741 | int i; | ||
2742 | |||
2743 | for (i = 0; i < XMON_NUM_SPUS; i++) { | ||
2744 | if (!spu_info[i].spu) | ||
2745 | continue; | ||
2746 | |||
2747 | if (!spu_info[i].stopped_ok) { | ||
2748 | printf("*** Error, spu %d was not successfully stopped" | ||
2749 | ", not restarting\n", i); | ||
2750 | continue; | ||
2751 | } | ||
2752 | |||
2753 | if (setjmp(bus_error_jmp) == 0) { | ||
2754 | catch_memory_errors = 1; | ||
2755 | sync(); | ||
2756 | |||
2757 | spu = spu_info[i].spu; | ||
2758 | spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW); | ||
2759 | out_be32(&spu->problem->spu_runcntl_RW, | ||
2760 | spu_info[i].saved_spu_runcntl_RW); | ||
2761 | |||
2762 | sync(); | ||
2763 | __delay(200); | ||
2764 | |||
2765 | printf("Restarted spu %.2d\n", i); | ||
2766 | } else { | ||
2767 | catch_memory_errors = 0; | ||
2768 | printf("*** Error restarting spu %.2d\n", i); | ||
2769 | } | ||
2770 | catch_memory_errors = 0; | ||
2771 | } | ||
2772 | } | ||
2773 | |||
2774 | #define DUMP_WIDTH 23 | ||
2775 | #define DUMP_VALUE(format, field, value) \ | ||
2776 | do { \ | ||
2777 | if (setjmp(bus_error_jmp) == 0) { \ | ||
2778 | catch_memory_errors = 1; \ | ||
2779 | sync(); \ | ||
2780 | printf(" %-*s = "format"\n", DUMP_WIDTH, \ | ||
2781 | #field, value); \ | ||
2782 | sync(); \ | ||
2783 | __delay(200); \ | ||
2784 | } else { \ | ||
2785 | catch_memory_errors = 0; \ | ||
2786 | printf(" %-*s = *** Error reading field.\n", \ | ||
2787 | DUMP_WIDTH, #field); \ | ||
2788 | } \ | ||
2789 | catch_memory_errors = 0; \ | ||
2790 | } while (0) | ||
2791 | |||
2792 | #define DUMP_FIELD(obj, format, field) \ | ||
2793 | DUMP_VALUE(format, field, obj->field) | ||
2794 | |||
2795 | static void dump_spu_fields(struct spu *spu) | ||
2796 | { | ||
2797 | printf("Dumping spu fields at address %p:\n", spu); | ||
2798 | |||
2799 | DUMP_FIELD(spu, "0x%x", number); | ||
2800 | DUMP_FIELD(spu, "%s", name); | ||
2801 | DUMP_FIELD(spu, "0x%lx", local_store_phys); | ||
2802 | DUMP_FIELD(spu, "0x%p", local_store); | ||
2803 | DUMP_FIELD(spu, "0x%lx", ls_size); | ||
2804 | DUMP_FIELD(spu, "0x%x", node); | ||
2805 | DUMP_FIELD(spu, "0x%lx", flags); | ||
2806 | DUMP_FIELD(spu, "0x%lx", dar); | ||
2807 | DUMP_FIELD(spu, "0x%lx", dsisr); | ||
2808 | DUMP_FIELD(spu, "%d", class_0_pending); | ||
2809 | DUMP_FIELD(spu, "0x%lx", irqs[0]); | ||
2810 | DUMP_FIELD(spu, "0x%lx", irqs[1]); | ||
2811 | DUMP_FIELD(spu, "0x%lx", irqs[2]); | ||
2812 | DUMP_FIELD(spu, "0x%x", slb_replace); | ||
2813 | DUMP_FIELD(spu, "%d", pid); | ||
2814 | DUMP_FIELD(spu, "%d", prio); | ||
2815 | DUMP_FIELD(spu, "0x%p", mm); | ||
2816 | DUMP_FIELD(spu, "0x%p", ctx); | ||
2817 | DUMP_FIELD(spu, "0x%p", rq); | ||
2818 | DUMP_FIELD(spu, "0x%p", timestamp); | ||
2819 | DUMP_FIELD(spu, "0x%lx", problem_phys); | ||
2820 | DUMP_FIELD(spu, "0x%p", problem); | ||
2821 | DUMP_VALUE("0x%x", problem->spu_runcntl_RW, | ||
2822 | in_be32(&spu->problem->spu_runcntl_RW)); | ||
2823 | DUMP_VALUE("0x%x", problem->spu_status_R, | ||
2824 | in_be32(&spu->problem->spu_status_R)); | ||
2825 | DUMP_VALUE("0x%x", problem->spu_npc_RW, | ||
2826 | in_be32(&spu->problem->spu_npc_RW)); | ||
2827 | DUMP_FIELD(spu, "0x%p", priv2); | ||
2828 | DUMP_FIELD(spu, "0x%p", pdata); | ||
2829 | } | ||
2830 | |||
2831 | int | ||
2832 | spu_inst_dump(unsigned long adr, long count, int praddr) | ||
2833 | { | ||
2834 | return generic_inst_dump(adr, count, praddr, print_insn_spu); | ||
2835 | } | ||
2836 | |||
2837 | static void dump_spu_ls(unsigned long num, int subcmd) | ||
2838 | { | ||
2839 | unsigned long offset, addr, ls_addr; | ||
2840 | |||
2841 | if (setjmp(bus_error_jmp) == 0) { | ||
2842 | catch_memory_errors = 1; | ||
2843 | sync(); | ||
2844 | ls_addr = (unsigned long)spu_info[num].spu->local_store; | ||
2845 | sync(); | ||
2846 | __delay(200); | ||
2847 | } else { | ||
2848 | catch_memory_errors = 0; | ||
2849 | printf("*** Error: accessing spu info for spu %d\n", num); | ||
2850 | return; | ||
2851 | } | ||
2852 | catch_memory_errors = 0; | ||
2853 | |||
2854 | if (scanhex(&offset)) | ||
2855 | addr = ls_addr + offset; | ||
2856 | else | ||
2857 | addr = spu_info[num].dump_addr; | ||
2858 | |||
2859 | if (addr >= ls_addr + LS_SIZE) { | ||
2860 | printf("*** Error: address outside of local store\n"); | ||
2861 | return; | ||
2862 | } | ||
2863 | |||
2864 | switch (subcmd) { | ||
2865 | case 'i': | ||
2866 | addr += spu_inst_dump(addr, 16, 1); | ||
2867 | last_cmd = "sdi\n"; | ||
2868 | break; | ||
2869 | default: | ||
2870 | prdump(addr, 64); | ||
2871 | addr += 64; | ||
2872 | last_cmd = "sd\n"; | ||
2873 | break; | ||
2874 | } | ||
2875 | |||
2876 | spu_info[num].dump_addr = addr; | ||
2877 | } | ||
2878 | |||
2879 | static int do_spu_cmd(void) | ||
2880 | { | ||
2881 | static unsigned long num = 0; | ||
2882 | int cmd, subcmd = 0; | ||
2883 | |||
2884 | cmd = inchar(); | ||
2885 | switch (cmd) { | ||
2886 | case 's': | ||
2887 | stop_spus(); | ||
2888 | break; | ||
2889 | case 'r': | ||
2890 | restart_spus(); | ||
2891 | break; | ||
2892 | case 'd': | ||
2893 | subcmd = inchar(); | ||
2894 | if (isxdigit(subcmd) || subcmd == '\n') | ||
2895 | termch = subcmd; | ||
2896 | case 'f': | ||
2897 | scanhex(&num); | ||
2898 | if (num >= XMON_NUM_SPUS || !spu_info[num].spu) { | ||
2899 | printf("*** Error: invalid spu number\n"); | ||
2900 | return 0; | ||
2901 | } | ||
2902 | |||
2903 | switch (cmd) { | ||
2904 | case 'f': | ||
2905 | dump_spu_fields(spu_info[num].spu); | ||
2906 | break; | ||
2907 | default: | ||
2908 | dump_spu_ls(num, subcmd); | ||
2909 | break; | ||
2910 | } | ||
2911 | |||
2912 | break; | ||
2913 | default: | ||
2914 | return -1; | ||
2915 | } | ||
2916 | |||
2917 | return 0; | ||
2918 | } | ||
2919 | #else /* ! CONFIG_SPU_BASE */ | ||
2920 | static int do_spu_cmd(void) | ||
2921 | { | ||
2922 | return -1; | ||
2923 | } | ||
2924 | #endif | ||
diff --git a/arch/ppc/.gitignore b/arch/ppc/.gitignore new file mode 100644 index 00000000000..a1a869c8c84 --- /dev/null +++ b/arch/ppc/.gitignore | |||
@@ -0,0 +1 @@ | |||
include | |||
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index ef018e25fb0..edf71a4ecc9 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig | |||
@@ -77,9 +77,11 @@ config 6xx | |||
77 | 77 | ||
78 | config 40x | 78 | config 40x |
79 | bool "40x" | 79 | bool "40x" |
80 | select PPC_DCR_NATIVE | ||
80 | 81 | ||
81 | config 44x | 82 | config 44x |
82 | bool "44x" | 83 | bool "44x" |
84 | select PPC_DCR_NATIVE | ||
83 | 85 | ||
84 | config 8xx | 86 | config 8xx |
85 | bool "8xx" | 87 | bool "8xx" |
@@ -95,6 +97,15 @@ endchoice | |||
95 | config PPC_FPU | 97 | config PPC_FPU |
96 | bool | 98 | bool |
97 | 99 | ||
100 | config PPC_DCR_NATIVE | ||
101 | bool | ||
102 | default n | ||
103 | |||
104 | config PPC_DCR | ||
105 | bool | ||
106 | depends on PPC_DCR_NATIVE | ||
107 | default y | ||
108 | |||
98 | config BOOKE | 109 | config BOOKE |
99 | bool | 110 | bool |
100 | depends on E200 || E500 | 111 | depends on E200 || E500 |
diff --git a/arch/ppc/boot/images/.gitignore b/arch/ppc/boot/images/.gitignore new file mode 100644 index 00000000000..21c2dc5b6b7 --- /dev/null +++ b/arch/ppc/boot/images/.gitignore | |||
@@ -0,0 +1,6 @@ | |||
1 | sImage | ||
2 | vmapus | ||
3 | vmlinux* | ||
4 | miboot* | ||
5 | zImage* | ||
6 | uImage | ||
diff --git a/arch/ppc/boot/lib/.gitignore b/arch/ppc/boot/lib/.gitignore new file mode 100644 index 00000000000..1629a616775 --- /dev/null +++ b/arch/ppc/boot/lib/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | inffast.c | ||
2 | inflate.c | ||
3 | inftrees.c | ||
diff --git a/arch/ppc/boot/utils/.gitignore b/arch/ppc/boot/utils/.gitignore new file mode 100644 index 00000000000..bbdfb3b9c53 --- /dev/null +++ b/arch/ppc/boot/utils/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | mkprep | ||
2 | mkbugboot | ||
3 | mktree | ||
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 27faeca2c7a..3c506af1988 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c | |||
@@ -313,7 +313,7 @@ early_init(int r3, int r4, int r5) | |||
313 | * Identify the CPU type and fix up code sections | 313 | * Identify the CPU type and fix up code sections |
314 | * that depend on which cpu we have. | 314 | * that depend on which cpu we have. |
315 | */ | 315 | */ |
316 | spec = identify_cpu(offset); | 316 | spec = identify_cpu(offset, mfspr(SPRN_PVR)); |
317 | do_feature_fixups(spec->cpu_features, | 317 | do_feature_fixups(spec->cpu_features, |
318 | PTRRELOC(&__start___ftr_fixup), | 318 | PTRRELOC(&__start___ftr_fixup), |
319 | PTRRELOC(&__stop___ftr_fixup)); | 319 | PTRRELOC(&__stop___ftr_fixup)); |
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 9661a91183b..2f835b9e95e 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c | |||
@@ -316,7 +316,7 @@ void machine_check_exception(struct pt_regs *regs) | |||
316 | if (reason & MCSR_BUS_RBERR) | 316 | if (reason & MCSR_BUS_RBERR) |
317 | printk("Bus - Read Data Bus Error\n"); | 317 | printk("Bus - Read Data Bus Error\n"); |
318 | if (reason & MCSR_BUS_WBERR) | 318 | if (reason & MCSR_BUS_WBERR) |
319 | printk("Bus - Read Data Bus Error\n"); | 319 | printk("Bus - Write Data Bus Error\n"); |
320 | if (reason & MCSR_BUS_IPERR) | 320 | if (reason & MCSR_BUS_IPERR) |
321 | printk("Bus - Instruction Parity Error\n"); | 321 | printk("Bus - Instruction Parity Error\n"); |
322 | if (reason & MCSR_BUS_RPERR) | 322 | if (reason & MCSR_BUS_RPERR) |
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c index 4009f4983ca..75857b38e89 100644 --- a/arch/ppc/platforms/4xx/bubinga.c +++ b/arch/ppc/platforms/4xx/bubinga.c | |||
@@ -116,6 +116,7 @@ bubinga_early_serial_map(void) | |||
116 | void __init | 116 | void __init |
117 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | 117 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) |
118 | { | 118 | { |
119 | #ifdef CONFIG_PCI | ||
119 | 120 | ||
120 | unsigned int bar_response, bar; | 121 | unsigned int bar_response, bar; |
121 | /* | 122 | /* |
@@ -212,6 +213,7 @@ bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | |||
212 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | 213 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); |
213 | 214 | ||
214 | #endif | 215 | #endif |
216 | #endif | ||
215 | } | 217 | } |
216 | 218 | ||
217 | void __init | 219 | void __init |
diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c index 367430998fc..8474b05b795 100644 --- a/arch/ppc/platforms/4xx/cpci405.c +++ b/arch/ppc/platforms/4xx/cpci405.c | |||
@@ -126,6 +126,7 @@ cpci405_setup_arch(void) | |||
126 | void __init | 126 | void __init |
127 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | 127 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) |
128 | { | 128 | { |
129 | #ifdef CONFIG_PCI | ||
129 | unsigned int bar_response, bar; | 130 | unsigned int bar_response, bar; |
130 | 131 | ||
131 | /* Disable region first */ | 132 | /* Disable region first */ |
@@ -167,6 +168,7 @@ bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | |||
167 | PCI_FUNC(hose->first_busno), bar, | 168 | PCI_FUNC(hose->first_busno), bar, |
168 | &bar_response); | 169 | &bar_response); |
169 | } | 170 | } |
171 | #endif | ||
170 | } | 172 | } |
171 | 173 | ||
172 | void __init | 174 | void __init |
diff --git a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c index ae5c82081c9..e5adf9ba1fc 100644 --- a/arch/ppc/platforms/4xx/ep405.c +++ b/arch/ppc/platforms/4xx/ep405.c | |||
@@ -68,6 +68,7 @@ ep405_setup_arch(void) | |||
68 | void __init | 68 | void __init |
69 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | 69 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) |
70 | { | 70 | { |
71 | #ifdef CONFIG_PCI | ||
71 | unsigned int bar_response, bar; | 72 | unsigned int bar_response, bar; |
72 | /* | 73 | /* |
73 | * Expected PCI mapping: | 74 | * Expected PCI mapping: |
@@ -130,6 +131,7 @@ bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | |||
130 | PCI_FUNC(hose->first_busno), bar, bar_response); | 131 | PCI_FUNC(hose->first_busno), bar, bar_response); |
131 | } | 132 | } |
132 | /* end work arround */ | 133 | /* end work arround */ |
134 | #endif | ||
133 | } | 135 | } |
134 | 136 | ||
135 | void __init | 137 | void __init |
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index 3397f0de159..b84f8df325c 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c | |||
@@ -121,8 +121,8 @@ mpc834x_sys_setup_arch(void) | |||
121 | 121 | ||
122 | mdata->irq[0] = MPC83xx_IRQ_EXT1; | 122 | mdata->irq[0] = MPC83xx_IRQ_EXT1; |
123 | mdata->irq[1] = MPC83xx_IRQ_EXT2; | 123 | mdata->irq[1] = MPC83xx_IRQ_EXT2; |
124 | mdata->irq[2] = -1; | 124 | mdata->irq[2] = PHY_POLL; |
125 | mdata->irq[31] = -1; | 125 | mdata->irq[31] = PHY_POLL; |
126 | 126 | ||
127 | /* setup the board related information for the enet controllers */ | 127 | /* setup the board related information for the enet controllers */ |
128 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); | 128 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); |
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index 4f839da6782..00a3ba57063 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c | |||
@@ -92,9 +92,9 @@ mpc8540ads_setup_arch(void) | |||
92 | 92 | ||
93 | mdata->irq[0] = MPC85xx_IRQ_EXT5; | 93 | mdata->irq[0] = MPC85xx_IRQ_EXT5; |
94 | mdata->irq[1] = MPC85xx_IRQ_EXT5; | 94 | mdata->irq[1] = MPC85xx_IRQ_EXT5; |
95 | mdata->irq[2] = -1; | 95 | mdata->irq[2] = PHY_POLL; |
96 | mdata->irq[3] = MPC85xx_IRQ_EXT5; | 96 | mdata->irq[3] = MPC85xx_IRQ_EXT5; |
97 | mdata->irq[31] = -1; | 97 | mdata->irq[31] = PHY_POLL; |
98 | 98 | ||
99 | /* setup the board related information for the enet controllers */ | 99 | /* setup the board related information for the enet controllers */ |
100 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 100 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 14ecec7bbed..3a060468dd9 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c | |||
@@ -156,9 +156,9 @@ mpc8560ads_setup_arch(void) | |||
156 | 156 | ||
157 | mdata->irq[0] = MPC85xx_IRQ_EXT5; | 157 | mdata->irq[0] = MPC85xx_IRQ_EXT5; |
158 | mdata->irq[1] = MPC85xx_IRQ_EXT5; | 158 | mdata->irq[1] = MPC85xx_IRQ_EXT5; |
159 | mdata->irq[2] = -1; | 159 | mdata->irq[2] = PHY_POLL; |
160 | mdata->irq[3] = MPC85xx_IRQ_EXT5; | 160 | mdata->irq[3] = MPC85xx_IRQ_EXT5; |
161 | mdata->irq[31] = -1; | 161 | mdata->irq[31] = PHY_POLL; |
162 | 162 | ||
163 | /* setup the board related information for the enet controllers */ | 163 | /* setup the board related information for the enet controllers */ |
164 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 164 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 5ce0f69c1db..2d59eb776c9 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c | |||
@@ -451,9 +451,9 @@ mpc85xx_cds_setup_arch(void) | |||
451 | 451 | ||
452 | mdata->irq[0] = MPC85xx_IRQ_EXT5; | 452 | mdata->irq[0] = MPC85xx_IRQ_EXT5; |
453 | mdata->irq[1] = MPC85xx_IRQ_EXT5; | 453 | mdata->irq[1] = MPC85xx_IRQ_EXT5; |
454 | mdata->irq[2] = -1; | 454 | mdata->irq[2] = PHY_POLL; |
455 | mdata->irq[3] = -1; | 455 | mdata->irq[3] = PHY_POLL; |
456 | mdata->irq[31] = -1; | 456 | mdata->irq[31] = PHY_POLL; |
457 | 457 | ||
458 | /* setup the board related information for the enet controllers */ | 458 | /* setup the board related information for the enet controllers */ |
459 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 459 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 764d580ff53..1d10ab98f66 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c | |||
@@ -129,7 +129,7 @@ sbc8560_setup_arch(void) | |||
129 | 129 | ||
130 | mdata->irq[25] = MPC85xx_IRQ_EXT6; | 130 | mdata->irq[25] = MPC85xx_IRQ_EXT6; |
131 | mdata->irq[26] = MPC85xx_IRQ_EXT7; | 131 | mdata->irq[26] = MPC85xx_IRQ_EXT7; |
132 | mdata->irq[31] = -1; | 132 | mdata->irq[31] = PHY_POLL; |
133 | 133 | ||
134 | /* setup the board related information for the enet controllers */ | 134 | /* setup the board related information for the enet controllers */ |
135 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 135 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 4bb18ab2767..b1f5b737c70 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c | |||
@@ -123,7 +123,7 @@ gp3_setup_arch(void) | |||
123 | 123 | ||
124 | mdata->irq[2] = MPC85xx_IRQ_EXT5; | 124 | mdata->irq[2] = MPC85xx_IRQ_EXT5; |
125 | mdata->irq[4] = MPC85xx_IRQ_EXT5; | 125 | mdata->irq[4] = MPC85xx_IRQ_EXT5; |
126 | mdata->irq[31] = -1; | 126 | mdata->irq[31] = PHY_POLL; |
127 | 127 | ||
128 | /* setup the board related information for the enet controllers */ | 128 | /* setup the board related information for the enet controllers */ |
129 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 129 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index dd45f2e1844..4ee2bd156dc 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c | |||
@@ -137,9 +137,9 @@ tqm85xx_setup_arch(void) | |||
137 | 137 | ||
138 | mdata->irq[0] = MPC85xx_IRQ_EXT8; | 138 | mdata->irq[0] = MPC85xx_IRQ_EXT8; |
139 | mdata->irq[1] = MPC85xx_IRQ_EXT8; | 139 | mdata->irq[1] = MPC85xx_IRQ_EXT8; |
140 | mdata->irq[2] = -1; | 140 | mdata->irq[2] = PHY_POLL; |
141 | mdata->irq[3] = MPC85xx_IRQ_EXT8; | 141 | mdata->irq[3] = MPC85xx_IRQ_EXT8; |
142 | mdata->irq[31] = -1; | 142 | mdata->irq[31] = PHY_POLL; |
143 | 143 | ||
144 | /* setup the board related information for the enet controllers */ | 144 | /* setup the board related information for the enet controllers */ |
145 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | 145 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); |
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c index 1f9ea36837b..0bc06768cf2 100644 --- a/arch/ppc/platforms/mpc8272ads_setup.c +++ b/arch/ppc/platforms/mpc8272ads_setup.c | |||
@@ -266,10 +266,10 @@ static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev, | |||
266 | int idx) | 266 | int idx) |
267 | { | 267 | { |
268 | m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT; | 268 | m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT; |
269 | m82xx_mii_bb_pdata.irq[1] = -1; | 269 | m82xx_mii_bb_pdata.irq[1] = PHY_POLL; |
270 | m82xx_mii_bb_pdata.irq[2] = -1; | 270 | m82xx_mii_bb_pdata.irq[2] = PHY_POLL; |
271 | m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT; | 271 | m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT; |
272 | m82xx_mii_bb_pdata.irq[31] = -1; | 272 | m82xx_mii_bb_pdata.irq[31] = PHY_POLL; |
273 | 273 | ||
274 | 274 | ||
275 | m82xx_mii_bb_pdata.mdio_dat.offset = | 275 | m82xx_mii_bb_pdata.mdio_dat.offset = |
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c index e95d2c11174..8a0c07eb444 100644 --- a/arch/ppc/platforms/mpc866ads_setup.c +++ b/arch/ppc/platforms/mpc866ads_setup.c | |||
@@ -361,7 +361,7 @@ int __init mpc866ads_init(void) | |||
361 | 361 | ||
362 | fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; | 362 | fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; |
363 | /* No PHY interrupt line here */ | 363 | /* No PHY interrupt line here */ |
364 | fmpi->irq[0xf] = -1; | 364 | fmpi->irq[0xf] = PHY_POLL; |
365 | 365 | ||
366 | /* Since either of the uarts could be used as console, they need to ready */ | 366 | /* Since either of the uarts could be used as console, they need to ready */ |
367 | #ifdef CONFIG_SERIAL_CPM_SMC1 | 367 | #ifdef CONFIG_SERIAL_CPM_SMC1 |
@@ -380,7 +380,7 @@ int __init mpc866ads_init(void) | |||
380 | 380 | ||
381 | fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; | 381 | fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; |
382 | /* No PHY interrupt line here */ | 382 | /* No PHY interrupt line here */ |
383 | fmpi->irq[0xf] = -1; | 383 | fmpi->irq[0xf] = PHY_POLL; |
384 | 384 | ||
385 | return 0; | 385 | return 0; |
386 | } | 386 | } |
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c index cf5ab47487a..31fb56593d1 100644 --- a/arch/ppc/syslib/mpc8xx_devices.c +++ b/arch/ppc/syslib/mpc8xx_devices.c | |||
@@ -78,7 +78,7 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
78 | { | 78 | { |
79 | .name = "pram", | 79 | .name = "pram", |
80 | .start = 0x3c00, | 80 | .start = 0x3c00, |
81 | .end = 0x3c80, | 81 | .end = 0x3c7f, |
82 | .flags = IORESOURCE_MEM, | 82 | .flags = IORESOURCE_MEM, |
83 | }, | 83 | }, |
84 | { | 84 | { |
@@ -103,7 +103,7 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
103 | { | 103 | { |
104 | .name = "pram", | 104 | .name = "pram", |
105 | .start = 0x3d00, | 105 | .start = 0x3d00, |
106 | .end = 0x3d80, | 106 | .end = 0x3d7f, |
107 | .flags = IORESOURCE_MEM, | 107 | .flags = IORESOURCE_MEM, |
108 | }, | 108 | }, |
109 | 109 | ||
@@ -129,7 +129,7 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
129 | { | 129 | { |
130 | .name = "pram", | 130 | .name = "pram", |
131 | .start = 0x3e00, | 131 | .start = 0x3e00, |
132 | .end = 0x3e80, | 132 | .end = 0x3e7f, |
133 | .flags = IORESOURCE_MEM, | 133 | .flags = IORESOURCE_MEM, |
134 | }, | 134 | }, |
135 | 135 | ||
@@ -155,7 +155,7 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
155 | { | 155 | { |
156 | .name = "pram", | 156 | .name = "pram", |
157 | .start = 0x3f00, | 157 | .start = 0x3f00, |
158 | .end = 0x3f80, | 158 | .end = 0x3f7f, |
159 | .flags = IORESOURCE_MEM, | 159 | .flags = IORESOURCE_MEM, |
160 | }, | 160 | }, |
161 | 161 | ||
diff --git a/drivers/Makefile b/drivers/Makefile index 4ac14dab307..67711770b1d 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -77,3 +77,4 @@ obj-$(CONFIG_CRYPTO) += crypto/ | |||
77 | obj-$(CONFIG_SUPERH) += sh/ | 77 | obj-$(CONFIG_SUPERH) += sh/ |
78 | obj-$(CONFIG_GENERIC_TIME) += clocksource/ | 78 | obj-$(CONFIG_GENERIC_TIME) += clocksource/ |
79 | obj-$(CONFIG_DMA_ENGINE) += dma/ | 79 | obj-$(CONFIG_DMA_ENGINE) += dma/ |
80 | obj-$(CONFIG_PPC_PS3) += ps3/ | ||
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index ec5a1b90a0a..e19ba4ebcd4 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -759,6 +759,8 @@ static struct vio_driver viodasd_driver = { | |||
759 | } | 759 | } |
760 | }; | 760 | }; |
761 | 761 | ||
762 | static int need_delete_probe; | ||
763 | |||
762 | /* | 764 | /* |
763 | * Initialize the whole device driver. Handle module and non-module | 765 | * Initialize the whole device driver. Handle module and non-module |
764 | * versions | 766 | * versions |
@@ -773,46 +775,67 @@ static int __init viodasd_init(void) | |||
773 | 775 | ||
774 | if (viopath_hostLp == HvLpIndexInvalid) { | 776 | if (viopath_hostLp == HvLpIndexInvalid) { |
775 | printk(VIOD_KERN_WARNING "invalid hosting partition\n"); | 777 | printk(VIOD_KERN_WARNING "invalid hosting partition\n"); |
776 | return -EIO; | 778 | rc = -EIO; |
779 | goto early_fail; | ||
777 | } | 780 | } |
778 | 781 | ||
779 | printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n", | 782 | printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n", |
780 | viopath_hostLp); | 783 | viopath_hostLp); |
781 | 784 | ||
782 | /* register the block device */ | 785 | /* register the block device */ |
783 | if (register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME)) { | 786 | rc = register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); |
787 | if (rc) { | ||
784 | printk(VIOD_KERN_WARNING | 788 | printk(VIOD_KERN_WARNING |
785 | "Unable to get major number %d for %s\n", | 789 | "Unable to get major number %d for %s\n", |
786 | VIODASD_MAJOR, VIOD_GENHD_NAME); | 790 | VIODASD_MAJOR, VIOD_GENHD_NAME); |
787 | return -EIO; | 791 | goto early_fail; |
788 | } | 792 | } |
789 | /* Actually open the path to the hosting partition */ | 793 | /* Actually open the path to the hosting partition */ |
790 | if (viopath_open(viopath_hostLp, viomajorsubtype_blockio, | 794 | rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, |
791 | VIOMAXREQ + 2)) { | 795 | VIOMAXREQ + 2); |
796 | if (rc) { | ||
792 | printk(VIOD_KERN_WARNING | 797 | printk(VIOD_KERN_WARNING |
793 | "error opening path to host partition %d\n", | 798 | "error opening path to host partition %d\n", |
794 | viopath_hostLp); | 799 | viopath_hostLp); |
795 | unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); | 800 | goto unregister_blk; |
796 | return -EIO; | ||
797 | } | 801 | } |
798 | 802 | ||
799 | /* Initialize our request handler */ | 803 | /* Initialize our request handler */ |
800 | vio_setHandler(viomajorsubtype_blockio, handle_block_event); | 804 | vio_setHandler(viomajorsubtype_blockio, handle_block_event); |
801 | 805 | ||
802 | rc = vio_register_driver(&viodasd_driver); | 806 | rc = vio_register_driver(&viodasd_driver); |
803 | if (rc == 0) | 807 | if (rc) { |
804 | driver_create_file(&viodasd_driver.driver, &driver_attr_probe); | 808 | printk(VIOD_KERN_WARNING "vio_register_driver failed\n"); |
809 | goto unset_handler; | ||
810 | } | ||
811 | |||
812 | /* | ||
813 | * If this call fails, it just means that we cannot dynamically | ||
814 | * add virtual disks, but the driver will still work fine for | ||
815 | * all existing disk, so ignore the failure. | ||
816 | */ | ||
817 | if (!driver_create_file(&viodasd_driver.driver, &driver_attr_probe)) | ||
818 | need_delete_probe = 1; | ||
819 | |||
820 | return 0; | ||
821 | |||
822 | unset_handler: | ||
823 | vio_clearHandler(viomajorsubtype_blockio); | ||
824 | viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2); | ||
825 | unregister_blk: | ||
826 | unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); | ||
827 | early_fail: | ||
805 | return rc; | 828 | return rc; |
806 | } | 829 | } |
807 | module_init(viodasd_init); | 830 | module_init(viodasd_init); |
808 | 831 | ||
809 | void viodasd_exit(void) | 832 | void __exit viodasd_exit(void) |
810 | { | 833 | { |
811 | driver_remove_file(&viodasd_driver.driver, &driver_attr_probe); | 834 | if (need_delete_probe) |
835 | driver_remove_file(&viodasd_driver.driver, &driver_attr_probe); | ||
812 | vio_unregister_driver(&viodasd_driver); | 836 | vio_unregister_driver(&viodasd_driver); |
813 | vio_clearHandler(viomajorsubtype_blockio); | 837 | vio_clearHandler(viomajorsubtype_blockio); |
814 | unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); | ||
815 | viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2); | 838 | viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2); |
839 | unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); | ||
816 | } | 840 | } |
817 | |||
818 | module_exit(viodasd_exit); | 841 | module_exit(viodasd_exit); |
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 2af634d7acf..eb7ab112c05 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/ide.h> | 35 | #include <linux/ide.h> |
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | 37 | ||
38 | #ifdef CONFIG_PPC_MULTIPLATFORM | 38 | #ifdef CONFIG_PPC_CHRP |
39 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
40 | #endif | 40 | #endif |
41 | 41 | ||
@@ -442,7 +442,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) | |||
442 | hwif->speedproc = &via_set_drive; | 442 | hwif->speedproc = &via_set_drive; |
443 | 443 | ||
444 | 444 | ||
445 | #if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32) | 445 | #ifdef CONFIG_PPC_CHRP |
446 | if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) { | 446 | if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) { |
447 | hwif->irq = hwif->channel ? 15 : 14; | 447 | hwif->irq = hwif->channel ? 15 : 14; |
448 | } | 448 | } |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 7f8477d3a66..92ccee85e2a 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -228,4 +228,11 @@ config ANSLCD | |||
228 | tristate "Support for ANS LCD display" | 228 | tristate "Support for ANS LCD display" |
229 | depends on ADB_CUDA && PPC_PMAC | 229 | depends on ADB_CUDA && PPC_PMAC |
230 | 230 | ||
231 | config PMAC_RACKMETER | ||
232 | tristate "Support for Apple XServe front panel LEDs" | ||
233 | depends on PPC_PMAC | ||
234 | help | ||
235 | This driver procides some support to control the front panel | ||
236 | blue LEDs "vu-meter" of the XServer macs. | ||
237 | |||
231 | endmenu | 238 | endmenu |
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index b53d45f87b0..2dfc3f4eaf4 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile | |||
@@ -42,3 +42,4 @@ obj-$(CONFIG_WINDFARM_PM112) += windfarm_pm112.o windfarm_smu_sat.o \ | |||
42 | windfarm_smu_sensors.o \ | 42 | windfarm_smu_sensors.o \ |
43 | windfarm_max6690_sensor.o \ | 43 | windfarm_max6690_sensor.o \ |
44 | windfarm_lm75_sensor.o windfarm_pid.o | 44 | windfarm_lm75_sensor.o windfarm_pid.o |
45 | obj-$(CONFIG_PMAC_RACKMETER) += rack-meter.o | ||
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c new file mode 100644 index 00000000000..f1b6f563673 --- /dev/null +++ b/drivers/macintosh/rack-meter.c | |||
@@ -0,0 +1,612 @@ | |||
1 | /* | ||
2 | * RackMac vu-meter driver | ||
3 | * | ||
4 | * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. | ||
5 | * <benh@kernel.crashing.org> | ||
6 | * | ||
7 | * Released under the term of the GNU GPL v2. | ||
8 | * | ||
9 | * Support the CPU-meter LEDs of the Xserve G5 | ||
10 | * | ||
11 | * TODO: Implement PWM to do variable intensity and provide userland | ||
12 | * interface for fun. Also, the CPU-meter could be made nicer by being | ||
13 | * a bit less "immediate" but giving instead a more average load over | ||
14 | * time. Patches welcome :-) | ||
15 | * | ||
16 | */ | ||
17 | #undef DEBUG | ||
18 | |||
19 | #include <linux/types.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/kernel_stat.h> | ||
27 | |||
28 | #include <asm/io.h> | ||
29 | #include <asm/prom.h> | ||
30 | #include <asm/machdep.h> | ||
31 | #include <asm/pmac_feature.h> | ||
32 | #include <asm/dbdma.h> | ||
33 | #include <asm/dbdma.h> | ||
34 | #include <asm/macio.h> | ||
35 | #include <asm/keylargo.h> | ||
36 | |||
37 | /* Number of samples in a sample buffer */ | ||
38 | #define SAMPLE_COUNT 256 | ||
39 | |||
40 | /* CPU meter sampling rate in ms */ | ||
41 | #define CPU_SAMPLING_RATE 250 | ||
42 | |||
43 | struct rackmeter_dma { | ||
44 | struct dbdma_cmd cmd[4] ____cacheline_aligned; | ||
45 | u32 mark ____cacheline_aligned; | ||
46 | u32 buf1[SAMPLE_COUNT] ____cacheline_aligned; | ||
47 | u32 buf2[SAMPLE_COUNT] ____cacheline_aligned; | ||
48 | } ____cacheline_aligned; | ||
49 | |||
50 | struct rackmeter_cpu { | ||
51 | struct work_struct sniffer; | ||
52 | cputime64_t prev_wall; | ||
53 | cputime64_t prev_idle; | ||
54 | int zero; | ||
55 | } ____cacheline_aligned; | ||
56 | |||
57 | struct rackmeter { | ||
58 | struct macio_dev *mdev; | ||
59 | unsigned int irq; | ||
60 | struct device_node *i2s; | ||
61 | u8 *ubuf; | ||
62 | struct dbdma_regs __iomem *dma_regs; | ||
63 | void __iomem *i2s_regs; | ||
64 | dma_addr_t dma_buf_p; | ||
65 | struct rackmeter_dma *dma_buf_v; | ||
66 | int stale_irq; | ||
67 | struct rackmeter_cpu cpu[2]; | ||
68 | int paused; | ||
69 | struct mutex sem; | ||
70 | }; | ||
71 | |||
72 | /* To be set as a tunable */ | ||
73 | static int rackmeter_ignore_nice; | ||
74 | |||
75 | /* This GPIO is whacked by the OS X driver when initializing */ | ||
76 | #define RACKMETER_MAGIC_GPIO 0x78 | ||
77 | |||
78 | /* This is copied from cpufreq_ondemand, maybe we should put it in | ||
79 | * a common header somewhere | ||
80 | */ | ||
81 | static inline cputime64_t get_cpu_idle_time(unsigned int cpu) | ||
82 | { | ||
83 | cputime64_t retval; | ||
84 | |||
85 | retval = cputime64_add(kstat_cpu(cpu).cpustat.idle, | ||
86 | kstat_cpu(cpu).cpustat.iowait); | ||
87 | |||
88 | if (rackmeter_ignore_nice) | ||
89 | retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice); | ||
90 | |||
91 | return retval; | ||
92 | } | ||
93 | |||
94 | static void rackmeter_setup_i2s(struct rackmeter *rm) | ||
95 | { | ||
96 | struct macio_chip *macio = rm->mdev->bus->chip; | ||
97 | |||
98 | /* First whack magic GPIO */ | ||
99 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, RACKMETER_MAGIC_GPIO, 5); | ||
100 | |||
101 | |||
102 | /* Call feature code to enable the sound channel and the proper | ||
103 | * clock sources | ||
104 | */ | ||
105 | pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, rm->i2s, 0, 1); | ||
106 | |||
107 | /* Power i2s and stop i2s clock. We whack MacIO FCRs directly for now. | ||
108 | * This is a bit racy, thus we should add new platform functions to | ||
109 | * handle that. snd-aoa needs that too | ||
110 | */ | ||
111 | MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE); | ||
112 | MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT); | ||
113 | (void)MACIO_IN32(KEYLARGO_FCR1); | ||
114 | udelay(10); | ||
115 | |||
116 | /* Then setup i2s. For now, we use the same magic value that | ||
117 | * the OS X driver seems to use. We might want to play around | ||
118 | * with the clock divisors later | ||
119 | */ | ||
120 | out_le32(rm->i2s_regs + 0x10, 0x01fa0000); | ||
121 | (void)in_le32(rm->i2s_regs + 0x10); | ||
122 | udelay(10); | ||
123 | |||
124 | /* Fully restart i2s*/ | ||
125 | MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE | | ||
126 | KL1_I2S0_CLK_ENABLE_BIT); | ||
127 | (void)MACIO_IN32(KEYLARGO_FCR1); | ||
128 | udelay(10); | ||
129 | } | ||
130 | |||
131 | static void rackmeter_set_default_pattern(struct rackmeter *rm) | ||
132 | { | ||
133 | int i; | ||
134 | |||
135 | for (i = 0; i < 16; i++) { | ||
136 | if (i < 8) | ||
137 | rm->ubuf[i] = (i & 1) * 255; | ||
138 | else | ||
139 | rm->ubuf[i] = ((~i) & 1) * 255; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static void rackmeter_do_pause(struct rackmeter *rm, int pause) | ||
144 | { | ||
145 | struct rackmeter_dma *rdma = rm->dma_buf_v; | ||
146 | |||
147 | pr_debug("rackmeter: %s\n", pause ? "paused" : "started"); | ||
148 | |||
149 | rm->paused = pause; | ||
150 | if (pause) { | ||
151 | DBDMA_DO_STOP(rm->dma_regs); | ||
152 | return; | ||
153 | } | ||
154 | memset(rdma->buf1, 0, SAMPLE_COUNT & sizeof(u32)); | ||
155 | memset(rdma->buf2, 0, SAMPLE_COUNT & sizeof(u32)); | ||
156 | |||
157 | rm->dma_buf_v->mark = 0; | ||
158 | |||
159 | mb(); | ||
160 | out_le32(&rm->dma_regs->cmdptr_hi, 0); | ||
161 | out_le32(&rm->dma_regs->cmdptr, rm->dma_buf_p); | ||
162 | out_le32(&rm->dma_regs->control, (RUN << 16) | RUN); | ||
163 | } | ||
164 | |||
165 | static void rackmeter_setup_dbdma(struct rackmeter *rm) | ||
166 | { | ||
167 | struct rackmeter_dma *db = rm->dma_buf_v; | ||
168 | struct dbdma_cmd *cmd = db->cmd; | ||
169 | |||
170 | /* Make sure dbdma is reset */ | ||
171 | DBDMA_DO_RESET(rm->dma_regs); | ||
172 | |||
173 | pr_debug("rackmeter: mark offset=0x%lx\n", | ||
174 | offsetof(struct rackmeter_dma, mark)); | ||
175 | pr_debug("rackmeter: buf1 offset=0x%lx\n", | ||
176 | offsetof(struct rackmeter_dma, buf1)); | ||
177 | pr_debug("rackmeter: buf2 offset=0x%lx\n", | ||
178 | offsetof(struct rackmeter_dma, buf2)); | ||
179 | |||
180 | /* Prepare 4 dbdma commands for the 2 buffers */ | ||
181 | memset(cmd, 0, 4 * sizeof(struct dbdma_cmd)); | ||
182 | st_le16(&cmd->req_count, 4); | ||
183 | st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); | ||
184 | st_le32(&cmd->phy_addr, rm->dma_buf_p + | ||
185 | offsetof(struct rackmeter_dma, mark)); | ||
186 | st_le32(&cmd->cmd_dep, 0x02000000); | ||
187 | cmd++; | ||
188 | |||
189 | st_le16(&cmd->req_count, SAMPLE_COUNT * 4); | ||
190 | st_le16(&cmd->command, OUTPUT_MORE); | ||
191 | st_le32(&cmd->phy_addr, rm->dma_buf_p + | ||
192 | offsetof(struct rackmeter_dma, buf1)); | ||
193 | cmd++; | ||
194 | |||
195 | st_le16(&cmd->req_count, 4); | ||
196 | st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); | ||
197 | st_le32(&cmd->phy_addr, rm->dma_buf_p + | ||
198 | offsetof(struct rackmeter_dma, mark)); | ||
199 | st_le32(&cmd->cmd_dep, 0x01000000); | ||
200 | cmd++; | ||
201 | |||
202 | st_le16(&cmd->req_count, SAMPLE_COUNT * 4); | ||
203 | st_le16(&cmd->command, OUTPUT_MORE | BR_ALWAYS); | ||
204 | st_le32(&cmd->phy_addr, rm->dma_buf_p + | ||
205 | offsetof(struct rackmeter_dma, buf2)); | ||
206 | st_le32(&cmd->cmd_dep, rm->dma_buf_p); | ||
207 | |||
208 | rackmeter_do_pause(rm, 0); | ||
209 | } | ||
210 | |||
211 | static void rackmeter_do_timer(void *data) | ||
212 | { | ||
213 | struct rackmeter *rm = data; | ||
214 | unsigned int cpu = smp_processor_id(); | ||
215 | struct rackmeter_cpu *rcpu = &rm->cpu[cpu]; | ||
216 | cputime64_t cur_jiffies, total_idle_ticks; | ||
217 | unsigned int total_ticks, idle_ticks; | ||
218 | int i, offset, load, cumm, pause; | ||
219 | |||
220 | cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); | ||
221 | total_ticks = (unsigned int)cputime64_sub(cur_jiffies, | ||
222 | rcpu->prev_wall); | ||
223 | rcpu->prev_wall = cur_jiffies; | ||
224 | |||
225 | total_idle_ticks = get_cpu_idle_time(cpu); | ||
226 | idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks, | ||
227 | rcpu->prev_idle); | ||
228 | rcpu->prev_idle = total_idle_ticks; | ||
229 | |||
230 | /* We do a very dumb calculation to update the LEDs for now, | ||
231 | * we'll do better once we have actual PWM implemented | ||
232 | */ | ||
233 | load = (9 * (total_ticks - idle_ticks)) / total_ticks; | ||
234 | |||
235 | offset = cpu << 3; | ||
236 | cumm = 0; | ||
237 | for (i = 0; i < 8; i++) { | ||
238 | u8 ub = (load > i) ? 0xff : 0; | ||
239 | rm->ubuf[i + offset] = ub; | ||
240 | cumm |= ub; | ||
241 | } | ||
242 | rcpu->zero = (cumm == 0); | ||
243 | |||
244 | /* Now check if LEDs are all 0, we can stop DMA */ | ||
245 | pause = (rm->cpu[0].zero && rm->cpu[1].zero); | ||
246 | if (pause != rm->paused) { | ||
247 | mutex_lock(&rm->sem); | ||
248 | pause = (rm->cpu[0].zero && rm->cpu[1].zero); | ||
249 | rackmeter_do_pause(rm, pause); | ||
250 | mutex_unlock(&rm->sem); | ||
251 | } | ||
252 | schedule_delayed_work_on(cpu, &rcpu->sniffer, | ||
253 | msecs_to_jiffies(CPU_SAMPLING_RATE)); | ||
254 | } | ||
255 | |||
256 | static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm) | ||
257 | { | ||
258 | unsigned int cpu; | ||
259 | |||
260 | /* This driver works only with 1 or 2 CPUs numbered 0 and 1, | ||
261 | * but that's really all we have on Apple Xserve. It doesn't | ||
262 | * play very nice with CPU hotplug neither but we don't do that | ||
263 | * on those machines yet | ||
264 | */ | ||
265 | |||
266 | INIT_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer, rm); | ||
267 | INIT_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer, rm); | ||
268 | |||
269 | for_each_online_cpu(cpu) { | ||
270 | struct rackmeter_cpu *rcpu; | ||
271 | |||
272 | if (cpu > 1) | ||
273 | continue; | ||
274 | rcpu = &rm->cpu[cpu];; | ||
275 | rcpu->prev_idle = get_cpu_idle_time(cpu); | ||
276 | rcpu->prev_wall = jiffies64_to_cputime64(get_jiffies_64()); | ||
277 | schedule_delayed_work_on(cpu, &rm->cpu[cpu].sniffer, | ||
278 | msecs_to_jiffies(CPU_SAMPLING_RATE)); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm) | ||
283 | { | ||
284 | cancel_rearming_delayed_work(&rm->cpu[0].sniffer); | ||
285 | cancel_rearming_delayed_work(&rm->cpu[1].sniffer); | ||
286 | } | ||
287 | |||
288 | static int rackmeter_setup(struct rackmeter *rm) | ||
289 | { | ||
290 | pr_debug("rackmeter: setting up i2s..\n"); | ||
291 | rackmeter_setup_i2s(rm); | ||
292 | |||
293 | pr_debug("rackmeter: setting up default pattern..\n"); | ||
294 | rackmeter_set_default_pattern(rm); | ||
295 | |||
296 | pr_debug("rackmeter: setting up dbdma..\n"); | ||
297 | rackmeter_setup_dbdma(rm); | ||
298 | |||
299 | pr_debug("rackmeter: start CPU measurements..\n"); | ||
300 | rackmeter_init_cpu_sniffer(rm); | ||
301 | |||
302 | printk(KERN_INFO "RackMeter initialized\n"); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | /* XXX FIXME: No PWM yet, this is 0/1 */ | ||
308 | static u32 rackmeter_calc_sample(struct rackmeter *rm, unsigned int index) | ||
309 | { | ||
310 | int led; | ||
311 | u32 sample = 0; | ||
312 | |||
313 | for (led = 0; led < 16; led++) { | ||
314 | sample >>= 1; | ||
315 | sample |= ((rm->ubuf[led] >= 0x80) << 15); | ||
316 | } | ||
317 | return (sample << 17) | (sample >> 15); | ||
318 | } | ||
319 | |||
320 | static irqreturn_t rackmeter_irq(int irq, void *arg) | ||
321 | { | ||
322 | struct rackmeter *rm = arg; | ||
323 | struct rackmeter_dma *db = rm->dma_buf_v; | ||
324 | unsigned int mark, i; | ||
325 | u32 *buf; | ||
326 | |||
327 | /* Flush PCI buffers with an MMIO read. Maybe we could actually | ||
328 | * check the status one day ... in case things go wrong, though | ||
329 | * this never happened to me | ||
330 | */ | ||
331 | (void)in_le32(&rm->dma_regs->status); | ||
332 | |||
333 | /* Make sure the CPU gets us in order */ | ||
334 | rmb(); | ||
335 | |||
336 | /* Read mark */ | ||
337 | mark = db->mark; | ||
338 | if (mark != 1 && mark != 2) { | ||
339 | printk(KERN_WARNING "rackmeter: Incorrect DMA mark 0x%08x\n", | ||
340 | mark); | ||
341 | /* We allow for 3 errors like that (stale DBDMA irqs) */ | ||
342 | if (++rm->stale_irq > 3) { | ||
343 | printk(KERN_ERR "rackmeter: Too many errors," | ||
344 | " stopping DMA\n"); | ||
345 | DBDMA_DO_RESET(rm->dma_regs); | ||
346 | } | ||
347 | return IRQ_HANDLED; | ||
348 | } | ||
349 | |||
350 | /* Next buffer we need to fill is mark value */ | ||
351 | buf = mark == 1 ? db->buf1 : db->buf2; | ||
352 | |||
353 | /* Fill it now. This routine converts the 8 bits depth sample array | ||
354 | * into the PWM bitmap for each LED. | ||
355 | */ | ||
356 | for (i = 0; i < SAMPLE_COUNT; i++) | ||
357 | buf[i] = rackmeter_calc_sample(rm, i); | ||
358 | |||
359 | |||
360 | return IRQ_HANDLED; | ||
361 | } | ||
362 | |||
363 | static int __devinit rackmeter_probe(struct macio_dev* mdev, | ||
364 | const struct of_device_id *match) | ||
365 | { | ||
366 | struct device_node *i2s = NULL, *np = NULL; | ||
367 | struct rackmeter *rm = NULL; | ||
368 | struct resource ri2s, rdma; | ||
369 | int rc = -ENODEV; | ||
370 | |||
371 | pr_debug("rackmeter_probe()\n"); | ||
372 | |||
373 | /* Get i2s-a node */ | ||
374 | while ((i2s = of_get_next_child(mdev->ofdev.node, i2s)) != NULL) | ||
375 | if (strcmp(i2s->name, "i2s-a") == 0) | ||
376 | break; | ||
377 | if (i2s == NULL) { | ||
378 | pr_debug(" i2s-a child not found\n"); | ||
379 | goto bail; | ||
380 | } | ||
381 | /* Get lightshow or virtual sound */ | ||
382 | while ((np = of_get_next_child(i2s, np)) != NULL) { | ||
383 | if (strcmp(np->name, "lightshow") == 0) | ||
384 | break; | ||
385 | if ((strcmp(np->name, "sound") == 0) && | ||
386 | get_property(np, "virtual", NULL) != NULL) | ||
387 | break; | ||
388 | } | ||
389 | if (np == NULL) { | ||
390 | pr_debug(" lightshow or sound+virtual child not found\n"); | ||
391 | goto bail; | ||
392 | } | ||
393 | |||
394 | /* Create and initialize our instance data */ | ||
395 | rm = kzalloc(sizeof(struct rackmeter), GFP_KERNEL); | ||
396 | if (rm == NULL) { | ||
397 | printk(KERN_ERR "rackmeter: failed to allocate memory !\n"); | ||
398 | rc = -ENOMEM; | ||
399 | goto bail_release; | ||
400 | } | ||
401 | rm->mdev = mdev; | ||
402 | rm->i2s = i2s; | ||
403 | mutex_init(&rm->sem); | ||
404 | dev_set_drvdata(&mdev->ofdev.dev, rm); | ||
405 | /* Check resources availability. We need at least resource 0 and 1 */ | ||
406 | #if 0 /* Use that when i2s-a is finally an mdev per-se */ | ||
407 | if (macio_resource_count(mdev) < 2 || macio_irq_count(mdev) < 2) { | ||
408 | printk(KERN_ERR | ||
409 | "rackmeter: found match but lacks resources: %s" | ||
410 | " (%d resources, %d interrupts)\n", | ||
411 | mdev->ofdev.node->full_name); | ||
412 | rc = -ENXIO; | ||
413 | goto bail_free; | ||
414 | } | ||
415 | if (macio_request_resources(mdev, "rackmeter")) { | ||
416 | printk(KERN_ERR | ||
417 | "rackmeter: failed to request resources: %s\n", | ||
418 | mdev->ofdev.node->full_name); | ||
419 | rc = -EBUSY; | ||
420 | goto bail_free; | ||
421 | } | ||
422 | rm->irq = macio_irq(mdev, 1); | ||
423 | #else | ||
424 | rm->irq = irq_of_parse_and_map(i2s, 1); | ||
425 | if (rm->irq == NO_IRQ || | ||
426 | of_address_to_resource(i2s, 0, &ri2s) || | ||
427 | of_address_to_resource(i2s, 1, &rdma)) { | ||
428 | printk(KERN_ERR | ||
429 | "rackmeter: found match but lacks resources: %s", | ||
430 | mdev->ofdev.node->full_name); | ||
431 | rc = -ENXIO; | ||
432 | goto bail_free; | ||
433 | } | ||
434 | #endif | ||
435 | |||
436 | pr_debug(" i2s @0x%08x\n", (unsigned int)ri2s.start); | ||
437 | pr_debug(" dma @0x%08x\n", (unsigned int)rdma.start); | ||
438 | pr_debug(" irq %d\n", rm->irq); | ||
439 | |||
440 | rm->ubuf = (u8 *)__get_free_page(GFP_KERNEL); | ||
441 | if (rm->ubuf == NULL) { | ||
442 | printk(KERN_ERR | ||
443 | "rackmeter: failed to allocate samples page !\n"); | ||
444 | rc = -ENOMEM; | ||
445 | goto bail_release; | ||
446 | } | ||
447 | |||
448 | rm->dma_buf_v = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev, | ||
449 | sizeof(struct rackmeter_dma), | ||
450 | &rm->dma_buf_p, GFP_KERNEL); | ||
451 | if (rm->dma_buf_v == NULL) { | ||
452 | printk(KERN_ERR | ||
453 | "rackmeter: failed to allocate dma buffer !\n"); | ||
454 | rc = -ENOMEM; | ||
455 | goto bail_free_samples; | ||
456 | } | ||
457 | #if 0 | ||
458 | rm->i2s_regs = ioremap(macio_resource_start(mdev, 0), 0x1000); | ||
459 | #else | ||
460 | rm->i2s_regs = ioremap(ri2s.start, 0x1000); | ||
461 | #endif | ||
462 | if (rm->i2s_regs == NULL) { | ||
463 | printk(KERN_ERR | ||
464 | "rackmeter: failed to map i2s registers !\n"); | ||
465 | rc = -ENXIO; | ||
466 | goto bail_free_dma; | ||
467 | } | ||
468 | #if 0 | ||
469 | rm->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x100); | ||
470 | #else | ||
471 | rm->dma_regs = ioremap(rdma.start, 0x100); | ||
472 | #endif | ||
473 | if (rm->dma_regs == NULL) { | ||
474 | printk(KERN_ERR | ||
475 | "rackmeter: failed to map dma registers !\n"); | ||
476 | rc = -ENXIO; | ||
477 | goto bail_unmap_i2s; | ||
478 | } | ||
479 | |||
480 | rc = rackmeter_setup(rm); | ||
481 | if (rc) { | ||
482 | printk(KERN_ERR | ||
483 | "rackmeter: failed to initialize !\n"); | ||
484 | rc = -ENXIO; | ||
485 | goto bail_unmap_dma; | ||
486 | } | ||
487 | |||
488 | rc = request_irq(rm->irq, rackmeter_irq, 0, "rackmeter", rm); | ||
489 | if (rc != 0) { | ||
490 | printk(KERN_ERR | ||
491 | "rackmeter: failed to request interrupt !\n"); | ||
492 | goto bail_stop_dma; | ||
493 | } | ||
494 | of_node_put(np); | ||
495 | return 0; | ||
496 | |||
497 | bail_stop_dma: | ||
498 | DBDMA_DO_RESET(rm->dma_regs); | ||
499 | bail_unmap_dma: | ||
500 | iounmap(rm->dma_regs); | ||
501 | bail_unmap_i2s: | ||
502 | iounmap(rm->i2s_regs); | ||
503 | bail_free_dma: | ||
504 | dma_free_coherent(&macio_get_pci_dev(mdev)->dev, | ||
505 | sizeof(struct rackmeter_dma), | ||
506 | rm->dma_buf_v, rm->dma_buf_p); | ||
507 | bail_free_samples: | ||
508 | free_page((unsigned long)rm->ubuf); | ||
509 | bail_release: | ||
510 | #if 0 | ||
511 | macio_release_resources(mdev); | ||
512 | #endif | ||
513 | bail_free: | ||
514 | kfree(rm); | ||
515 | bail: | ||
516 | of_node_put(i2s); | ||
517 | of_node_put(np); | ||
518 | dev_set_drvdata(&mdev->ofdev.dev, NULL); | ||
519 | return rc; | ||
520 | } | ||
521 | |||
522 | static int __devexit rackmeter_remove(struct macio_dev* mdev) | ||
523 | { | ||
524 | struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev); | ||
525 | |||
526 | /* Stop CPU sniffer timer & work queues */ | ||
527 | rackmeter_stop_cpu_sniffer(rm); | ||
528 | |||
529 | /* Clear reference to private data */ | ||
530 | dev_set_drvdata(&mdev->ofdev.dev, NULL); | ||
531 | |||
532 | /* Stop/reset dbdma */ | ||
533 | DBDMA_DO_RESET(rm->dma_regs); | ||
534 | |||
535 | /* Release the IRQ */ | ||
536 | free_irq(rm->irq, rm); | ||
537 | |||
538 | /* Unmap registers */ | ||
539 | iounmap(rm->dma_regs); | ||
540 | iounmap(rm->i2s_regs); | ||
541 | |||
542 | /* Free DMA */ | ||
543 | dma_free_coherent(&macio_get_pci_dev(mdev)->dev, | ||
544 | sizeof(struct rackmeter_dma), | ||
545 | rm->dma_buf_v, rm->dma_buf_p); | ||
546 | |||
547 | /* Free samples */ | ||
548 | free_page((unsigned long)rm->ubuf); | ||
549 | |||
550 | #if 0 | ||
551 | /* Release resources */ | ||
552 | macio_release_resources(mdev); | ||
553 | #endif | ||
554 | |||
555 | /* Get rid of me */ | ||
556 | kfree(rm); | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int rackmeter_shutdown(struct macio_dev* mdev) | ||
562 | { | ||
563 | struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev); | ||
564 | |||
565 | if (rm == NULL) | ||
566 | return -ENODEV; | ||
567 | |||
568 | /* Stop CPU sniffer timer & work queues */ | ||
569 | rackmeter_stop_cpu_sniffer(rm); | ||
570 | |||
571 | /* Stop/reset dbdma */ | ||
572 | DBDMA_DO_RESET(rm->dma_regs); | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static struct of_device_id rackmeter_match[] = { | ||
578 | { .name = "i2s" }, | ||
579 | { } | ||
580 | }; | ||
581 | |||
582 | static struct macio_driver rackmeter_drv = { | ||
583 | .name = "rackmeter", | ||
584 | .owner = THIS_MODULE, | ||
585 | .match_table = rackmeter_match, | ||
586 | .probe = rackmeter_probe, | ||
587 | .remove = rackmeter_remove, | ||
588 | .shutdown = rackmeter_shutdown, | ||
589 | }; | ||
590 | |||
591 | |||
592 | static int __init rackmeter_init(void) | ||
593 | { | ||
594 | pr_debug("rackmeter_init()\n"); | ||
595 | |||
596 | return macio_register_driver(&rackmeter_drv); | ||
597 | } | ||
598 | |||
599 | static void __exit rackmeter_exit(void) | ||
600 | { | ||
601 | pr_debug("rackmeter_exit()\n"); | ||
602 | |||
603 | macio_unregister_driver(&rackmeter_drv); | ||
604 | } | ||
605 | |||
606 | module_init(rackmeter_init); | ||
607 | module_exit(rackmeter_exit); | ||
608 | |||
609 | |||
610 | MODULE_LICENSE("GPL"); | ||
611 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
612 | MODULE_DESCRIPTION("RackMeter: Support vu-meter on XServe front panel"); | ||
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index ade25b3fbb3..4f724cdd2ef 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/abs_addr.h> | 46 | #include <asm/abs_addr.h> |
47 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
48 | #include <asm/of_device.h> | 48 | #include <asm/of_device.h> |
49 | #include <asm/of_platform.h> | ||
49 | 50 | ||
50 | #define VERSION "0.7" | 51 | #define VERSION "0.7" |
51 | #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." | 52 | #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." |
@@ -653,7 +654,7 @@ static int __init smu_init_sysfs(void) | |||
653 | * I'm a bit too far from figuring out how that works with those | 654 | * I'm a bit too far from figuring out how that works with those |
654 | * new chipsets, but that will come back and bite us | 655 | * new chipsets, but that will come back and bite us |
655 | */ | 656 | */ |
656 | of_register_driver(&smu_of_platform_driver); | 657 | of_register_platform_driver(&smu_of_platform_driver); |
657 | return 0; | 658 | return 0; |
658 | } | 659 | } |
659 | 660 | ||
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index a0f30d0853e..13b953ae8eb 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
32 | #include <asm/sections.h> | 32 | #include <asm/sections.h> |
33 | #include <asm/of_device.h> | 33 | #include <asm/of_platform.h> |
34 | 34 | ||
35 | #undef DEBUG | 35 | #undef DEBUG |
36 | 36 | ||
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index d00c0c37a12..2e4ad44a863 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c | |||
@@ -129,6 +129,7 @@ | |||
129 | #include <asm/sections.h> | 129 | #include <asm/sections.h> |
130 | #include <asm/of_device.h> | 130 | #include <asm/of_device.h> |
131 | #include <asm/macio.h> | 131 | #include <asm/macio.h> |
132 | #include <asm/of_platform.h> | ||
132 | 133 | ||
133 | #include "therm_pm72.h" | 134 | #include "therm_pm72.h" |
134 | 135 | ||
@@ -2236,14 +2237,14 @@ static int __init therm_pm72_init(void) | |||
2236 | return -ENODEV; | 2237 | return -ENODEV; |
2237 | } | 2238 | } |
2238 | 2239 | ||
2239 | of_register_driver(&fcu_of_platform_driver); | 2240 | of_register_platform_driver(&fcu_of_platform_driver); |
2240 | 2241 | ||
2241 | return 0; | 2242 | return 0; |
2242 | } | 2243 | } |
2243 | 2244 | ||
2244 | static void __exit therm_pm72_exit(void) | 2245 | static void __exit therm_pm72_exit(void) |
2245 | { | 2246 | { |
2246 | of_unregister_driver(&fcu_of_platform_driver); | 2247 | of_unregister_platform_driver(&fcu_of_platform_driver); |
2247 | 2248 | ||
2248 | if (of_dev) | 2249 | if (of_dev) |
2249 | of_device_unregister(of_dev); | 2250 | of_device_unregister(of_dev); |
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 738faab1b22..a1d3a987cb3 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c | |||
@@ -36,12 +36,13 @@ | |||
36 | #include <linux/i2c.h> | 36 | #include <linux/i2c.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | |||
39 | #include <asm/prom.h> | 40 | #include <asm/prom.h> |
40 | #include <asm/machdep.h> | 41 | #include <asm/machdep.h> |
41 | #include <asm/io.h> | 42 | #include <asm/io.h> |
42 | #include <asm/system.h> | 43 | #include <asm/system.h> |
43 | #include <asm/sections.h> | 44 | #include <asm/sections.h> |
44 | #include <asm/of_device.h> | 45 | #include <asm/of_platform.h> |
45 | #include <asm/macio.h> | 46 | #include <asm/macio.h> |
46 | 47 | ||
47 | #define LOG_TEMP 0 /* continously log temperature */ | 48 | #define LOG_TEMP 0 /* continously log temperature */ |
@@ -511,14 +512,14 @@ g4fan_init( void ) | |||
511 | return -ENODEV; | 512 | return -ENODEV; |
512 | } | 513 | } |
513 | 514 | ||
514 | of_register_driver( &therm_of_driver ); | 515 | of_register_platform_driver( &therm_of_driver ); |
515 | return 0; | 516 | return 0; |
516 | } | 517 | } |
517 | 518 | ||
518 | static void __exit | 519 | static void __exit |
519 | g4fan_exit( void ) | 520 | g4fan_exit( void ) |
520 | { | 521 | { |
521 | of_unregister_driver( &therm_of_driver ); | 522 | of_unregister_platform_driver( &therm_of_driver ); |
522 | 523 | ||
523 | if( x.of_dev ) | 524 | if( x.of_dev ) |
524 | of_device_unregister( x.of_dev ); | 525 | of_device_unregister( x.of_dev ); |
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h index f73f10a0a56..407d2acbf7c 100644 --- a/drivers/net/ibm_emac/ibm_emac_mal.h +++ b/drivers/net/ibm_emac/ibm_emac_mal.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | 25 | ||
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/dcr.h> | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * These MAL "versions" probably aren't the real versions IBM uses for these | 30 | * These MAL "versions" probably aren't the real versions IBM uses for these |
@@ -191,6 +192,7 @@ struct mal_commac { | |||
191 | 192 | ||
192 | struct ibm_ocp_mal { | 193 | struct ibm_ocp_mal { |
193 | int dcrbase; | 194 | int dcrbase; |
195 | dcr_host_t dcrhost; | ||
194 | 196 | ||
195 | struct list_head poll_list; | 197 | struct list_head poll_list; |
196 | struct net_device poll_dev; | 198 | struct net_device poll_dev; |
@@ -207,12 +209,12 @@ struct ibm_ocp_mal { | |||
207 | 209 | ||
208 | static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg) | 210 | static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg) |
209 | { | 211 | { |
210 | return mfdcr(mal->dcrbase + reg); | 212 | return dcr_read(mal->dcrhost, mal->dcrbase + reg); |
211 | } | 213 | } |
212 | 214 | ||
213 | static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val) | 215 | static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val) |
214 | { | 216 | { |
215 | mtdcr(mal->dcrbase + reg, val); | 217 | dcr_write(mal->dcrhost, mal->dcrbase + reg, val); |
216 | } | 218 | } |
217 | 219 | ||
218 | /* Register MAL devices */ | 220 | /* Register MAL devices */ |
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 44c9f993dcc..99343b5836b 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <asm/semaphore.h> | 50 | #include <asm/semaphore.h> |
51 | #include <asm/hvcall.h> | 51 | #include <asm/hvcall.h> |
52 | #include <asm/atomic.h> | 52 | #include <asm/atomic.h> |
53 | #include <asm/iommu.h> | ||
54 | #include <asm/vio.h> | 53 | #include <asm/vio.h> |
55 | #include <asm/uaccess.h> | 54 | #include <asm/uaccess.h> |
56 | #include <linux/seq_file.h> | 55 | #include <linux/seq_file.h> |
@@ -1000,8 +999,6 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_ | |||
1000 | adapter->mac_addr = 0; | 999 | adapter->mac_addr = 0; |
1001 | memcpy(&adapter->mac_addr, mac_addr_p, 6); | 1000 | memcpy(&adapter->mac_addr, mac_addr_p, 6); |
1002 | 1001 | ||
1003 | adapter->liobn = dev->iommu_table->it_index; | ||
1004 | |||
1005 | netdev->irq = dev->irq; | 1002 | netdev->irq = dev->irq; |
1006 | netdev->open = ibmveth_open; | 1003 | netdev->open = ibmveth_open; |
1007 | netdev->poll = ibmveth_poll; | 1004 | netdev->poll = ibmveth_poll; |
@@ -1115,7 +1112,6 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v) | |||
1115 | seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); | 1112 | seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); |
1116 | 1113 | ||
1117 | seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); | 1114 | seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); |
1118 | seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn); | ||
1119 | seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", | 1115 | seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", |
1120 | current_mac[0], current_mac[1], current_mac[2], | 1116 | current_mac[0], current_mac[1], current_mac[2], |
1121 | current_mac[3], current_mac[4], current_mac[5]); | 1117 | current_mac[3], current_mac[4], current_mac[5]); |
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h index f5b25bff154..bb69ccae8ac 100644 --- a/drivers/net/ibmveth.h +++ b/drivers/net/ibmveth.h | |||
@@ -118,7 +118,6 @@ struct ibmveth_adapter { | |||
118 | struct net_device_stats stats; | 118 | struct net_device_stats stats; |
119 | unsigned int mcastFilterSize; | 119 | unsigned int mcastFilterSize; |
120 | unsigned long mac_addr; | 120 | unsigned long mac_addr; |
121 | unsigned long liobn; | ||
122 | void * buffer_list_addr; | 121 | void * buffer_list_addr; |
123 | void * filter_list_addr; | 122 | void * filter_list_addr; |
124 | dma_addr_t buffer_list_dma; | 123 | dma_addr_t buffer_list_dma; |
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index f14e99276db..096d4a100bf 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c | |||
@@ -254,7 +254,7 @@ static int fixed_mdio_register_device(int number, int speed, int duplex) | |||
254 | goto device_create_fail; | 254 | goto device_create_fail; |
255 | } | 255 | } |
256 | 256 | ||
257 | phydev->irq = -1; | 257 | phydev->irq = PHY_IGNORE_INTERRUPT; |
258 | phydev->dev.bus = &mdio_bus_type; | 258 | phydev->dev.bus = &mdio_bus_type; |
259 | 259 | ||
260 | if(number) | 260 | if(number) |
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index cef7e6671c4..13e0a43e423 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -88,12 +88,11 @@ MODULE_DEVICE_TABLE(pci, spider_net_pci_tbl); | |||
88 | static inline u32 | 88 | static inline u32 |
89 | spider_net_read_reg(struct spider_net_card *card, u32 reg) | 89 | spider_net_read_reg(struct spider_net_card *card, u32 reg) |
90 | { | 90 | { |
91 | u32 value; | 91 | /* We use the powerpc specific variants instead of readl_be() because |
92 | 92 | * we know spidernet is not a real PCI device and we can thus avoid the | |
93 | value = readl(card->regs + reg); | 93 | * performance hit caused by the PCI workarounds. |
94 | value = le32_to_cpu(value); | 94 | */ |
95 | 95 | return in_be32(card->regs + reg); | |
96 | return value; | ||
97 | } | 96 | } |
98 | 97 | ||
99 | /** | 98 | /** |
@@ -105,8 +104,11 @@ spider_net_read_reg(struct spider_net_card *card, u32 reg) | |||
105 | static inline void | 104 | static inline void |
106 | spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value) | 105 | spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value) |
107 | { | 106 | { |
108 | value = cpu_to_le32(value); | 107 | /* We use the powerpc specific variants instead of writel_be() because |
109 | writel(value, card->regs + reg); | 108 | * we know spidernet is not a real PCI device and we can thus avoid the |
109 | * performance hit caused by the PCI workarounds. | ||
110 | */ | ||
111 | out_be32(card->regs + reg, value); | ||
110 | } | 112 | } |
111 | 113 | ||
112 | /** spider_net_write_phy - write to phy register | 114 | /** spider_net_write_phy - write to phy register |
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 3f4b6408b75..4b3cd3d8b62 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c | |||
@@ -473,9 +473,9 @@ | |||
473 | #include <asm/byteorder.h> | 473 | #include <asm/byteorder.h> |
474 | #include <asm/unaligned.h> | 474 | #include <asm/unaligned.h> |
475 | #include <asm/uaccess.h> | 475 | #include <asm/uaccess.h> |
476 | #ifdef CONFIG_PPC_MULTIPLATFORM | 476 | #ifdef CONFIG_PPC_PMAC |
477 | #include <asm/machdep.h> | 477 | #include <asm/machdep.h> |
478 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 478 | #endif /* CONFIG_PPC_PMAC */ |
479 | 479 | ||
480 | #include "de4x5.h" | 480 | #include "de4x5.h" |
481 | 481 | ||
@@ -4151,7 +4151,7 @@ get_hw_addr(struct net_device *dev) | |||
4151 | /* If possible, try to fix a broken card - SMC only so far */ | 4151 | /* If possible, try to fix a broken card - SMC only so far */ |
4152 | srom_repair(dev, broken); | 4152 | srom_repair(dev, broken); |
4153 | 4153 | ||
4154 | #ifdef CONFIG_PPC_MULTIPLATFORM | 4154 | #ifdef CONFIG_PPC_PMAC |
4155 | /* | 4155 | /* |
4156 | ** If the address starts with 00 a0, we have to bit-reverse | 4156 | ** If the address starts with 00 a0, we have to bit-reverse |
4157 | ** each byte of the address. | 4157 | ** each byte of the address. |
@@ -4168,7 +4168,7 @@ get_hw_addr(struct net_device *dev) | |||
4168 | dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1); | 4168 | dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1); |
4169 | } | 4169 | } |
4170 | } | 4170 | } |
4171 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 4171 | #endif /* CONFIG_PPC_PMAC */ |
4172 | 4172 | ||
4173 | /* Test for a bad enet address */ | 4173 | /* Test for a bad enet address */ |
4174 | status = test_bad_enet(dev, status); | 4174 | status = test_bad_enet(dev, status); |
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile new file mode 100644 index 00000000000..b52d547b7a7 --- /dev/null +++ b/drivers/ps3/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y += system-bus.o | |||
diff --git a/drivers/ps3/system-bus.c b/drivers/ps3/system-bus.c new file mode 100644 index 00000000000..d79f949bcb2 --- /dev/null +++ b/drivers/ps3/system-bus.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * PS3 system bus driver. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/err.h> | ||
26 | |||
27 | #include <asm/udbg.h> | ||
28 | #include <asm/ps3.h> | ||
29 | #include <asm/lv1call.h> | ||
30 | #include <asm/firmware.h> | ||
31 | |||
32 | #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) | ||
33 | static void _dump_mmio_region(const struct ps3_mmio_region* r, | ||
34 | const char* func, int line) | ||
35 | { | ||
36 | pr_debug("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, | ||
37 | r->did.dev_id); | ||
38 | pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | ||
39 | pr_debug("%s:%d: len %lxh\n", func, line, r->len); | ||
40 | pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); | ||
41 | } | ||
42 | |||
43 | int ps3_mmio_region_create(struct ps3_mmio_region *r) | ||
44 | { | ||
45 | int result; | ||
46 | |||
47 | result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id, | ||
48 | r->bus_addr, r->len, r->page_size, &r->lpar_addr); | ||
49 | |||
50 | if (result) { | ||
51 | pr_debug("%s:%d: lv1_map_device_mmio_region failed: %s\n", | ||
52 | __func__, __LINE__, ps3_result(result)); | ||
53 | r->lpar_addr = r->len = r->bus_addr = 0; | ||
54 | } | ||
55 | |||
56 | dump_mmio_region(r); | ||
57 | return result; | ||
58 | } | ||
59 | |||
60 | int ps3_free_mmio_region(struct ps3_mmio_region *r) | ||
61 | { | ||
62 | int result; | ||
63 | |||
64 | result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id, | ||
65 | r->bus_addr); | ||
66 | |||
67 | if (result) | ||
68 | pr_debug("%s:%d: lv1_unmap_device_mmio_region failed: %s\n", | ||
69 | __func__, __LINE__, ps3_result(result)); | ||
70 | |||
71 | r->lpar_addr = r->len = r->bus_addr = 0; | ||
72 | return result; | ||
73 | } | ||
74 | |||
75 | static int ps3_system_bus_match(struct device *_dev, | ||
76 | struct device_driver *_drv) | ||
77 | { | ||
78 | int result; | ||
79 | struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv); | ||
80 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
81 | |||
82 | result = dev->match_id == drv->match_id; | ||
83 | |||
84 | pr_info("%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, __LINE__, | ||
85 | dev->match_id, dev->core.bus_id, drv->match_id, drv->core.name, | ||
86 | (result ? "match" : "miss")); | ||
87 | return result; | ||
88 | } | ||
89 | |||
90 | static int ps3_system_bus_probe(struct device *_dev) | ||
91 | { | ||
92 | int result; | ||
93 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
94 | struct ps3_system_bus_driver *drv = | ||
95 | to_ps3_system_bus_driver(_dev->driver); | ||
96 | |||
97 | result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0); | ||
98 | |||
99 | if (result) { | ||
100 | pr_debug("%s:%d: lv1_open_device failed (%d)\n", | ||
101 | __func__, __LINE__, result); | ||
102 | result = -EACCES; | ||
103 | goto clean_none; | ||
104 | } | ||
105 | |||
106 | if (dev->d_region->did.bus_id) { | ||
107 | result = ps3_dma_region_create(dev->d_region); | ||
108 | |||
109 | if (result) { | ||
110 | pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n", | ||
111 | __func__, __LINE__, result); | ||
112 | BUG_ON("check region type"); | ||
113 | result = -EINVAL; | ||
114 | goto clean_device; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | BUG_ON(!drv); | ||
119 | |||
120 | if (drv->probe) | ||
121 | result = drv->probe(dev); | ||
122 | else | ||
123 | pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, | ||
124 | dev->core.bus_id); | ||
125 | |||
126 | if (result) { | ||
127 | pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__); | ||
128 | goto clean_dma; | ||
129 | } | ||
130 | |||
131 | return result; | ||
132 | |||
133 | clean_dma: | ||
134 | ps3_dma_region_free(dev->d_region); | ||
135 | clean_device: | ||
136 | lv1_close_device(dev->did.bus_id, dev->did.dev_id); | ||
137 | clean_none: | ||
138 | return result; | ||
139 | } | ||
140 | |||
141 | static int ps3_system_bus_remove(struct device *_dev) | ||
142 | { | ||
143 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
144 | struct ps3_system_bus_driver *drv = | ||
145 | to_ps3_system_bus_driver(_dev->driver); | ||
146 | |||
147 | if (drv->remove) | ||
148 | drv->remove(dev); | ||
149 | else | ||
150 | pr_info("%s:%d: %s no remove method\n", __func__, __LINE__, | ||
151 | dev->core.bus_id); | ||
152 | |||
153 | ps3_dma_region_free(dev->d_region); | ||
154 | ps3_free_mmio_region(dev->m_region); | ||
155 | lv1_close_device(dev->did.bus_id, dev->did.dev_id); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | struct bus_type ps3_system_bus_type = { | ||
161 | .name = "ps3_system_bus", | ||
162 | .match = ps3_system_bus_match, | ||
163 | .probe = ps3_system_bus_probe, | ||
164 | .remove = ps3_system_bus_remove, | ||
165 | }; | ||
166 | |||
167 | int __init ps3_system_bus_init(void) | ||
168 | { | ||
169 | int result; | ||
170 | |||
171 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
172 | return 0; | ||
173 | |||
174 | result = bus_register(&ps3_system_bus_type); | ||
175 | BUG_ON(result); | ||
176 | return result; | ||
177 | } | ||
178 | |||
179 | core_initcall(ps3_system_bus_init); | ||
180 | |||
181 | /* Allocates a contiguous real buffer and creates mappings over it. | ||
182 | * Returns the virtual address of the buffer and sets dma_handle | ||
183 | * to the dma address (mapping) of the first page. | ||
184 | */ | ||
185 | |||
186 | static void * ps3_alloc_coherent(struct device *_dev, size_t size, | ||
187 | dma_addr_t *dma_handle, gfp_t flag) | ||
188 | { | ||
189 | int result; | ||
190 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
191 | unsigned long virt_addr; | ||
192 | |||
193 | BUG_ON(!dev->d_region->bus_addr); | ||
194 | |||
195 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM); | ||
196 | flag |= __GFP_ZERO; | ||
197 | |||
198 | virt_addr = __get_free_pages(flag, get_order(size)); | ||
199 | |||
200 | if (!virt_addr) { | ||
201 | pr_debug("%s:%d: get_free_pages failed\n", __func__, __LINE__); | ||
202 | goto clean_none; | ||
203 | } | ||
204 | |||
205 | result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle); | ||
206 | |||
207 | if (result) { | ||
208 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | ||
209 | __func__, __LINE__, result); | ||
210 | BUG_ON("check region type"); | ||
211 | goto clean_alloc; | ||
212 | } | ||
213 | |||
214 | return (void*)virt_addr; | ||
215 | |||
216 | clean_alloc: | ||
217 | free_pages(virt_addr, get_order(size)); | ||
218 | clean_none: | ||
219 | dma_handle = NULL; | ||
220 | return NULL; | ||
221 | } | ||
222 | |||
223 | static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, | ||
224 | dma_addr_t dma_handle) | ||
225 | { | ||
226 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
227 | |||
228 | ps3_dma_unmap(dev->d_region, dma_handle, size); | ||
229 | free_pages((unsigned long)vaddr, get_order(size)); | ||
230 | } | ||
231 | |||
232 | /* Creates TCEs for a user provided buffer. The user buffer must be | ||
233 | * contiguous real kernel storage (not vmalloc). The address of the buffer | ||
234 | * passed here is the kernel (virtual) address of the buffer. The buffer | ||
235 | * need not be page aligned, the dma_addr_t returned will point to the same | ||
236 | * byte within the page as vaddr. | ||
237 | */ | ||
238 | |||
239 | static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size, | ||
240 | enum dma_data_direction direction) | ||
241 | { | ||
242 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
243 | int result; | ||
244 | unsigned long bus_addr; | ||
245 | |||
246 | result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, | ||
247 | &bus_addr); | ||
248 | |||
249 | if (result) { | ||
250 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | ||
251 | __func__, __LINE__, result); | ||
252 | } | ||
253 | |||
254 | return bus_addr; | ||
255 | } | ||
256 | |||
257 | static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, | ||
258 | size_t size, enum dma_data_direction direction) | ||
259 | { | ||
260 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
261 | int result; | ||
262 | |||
263 | result = ps3_dma_unmap(dev->d_region, dma_addr, size); | ||
264 | |||
265 | if (result) { | ||
266 | pr_debug("%s:%d: ps3_dma_unmap failed (%d)\n", | ||
267 | __func__, __LINE__, result); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, | ||
272 | enum dma_data_direction direction) | ||
273 | { | ||
274 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | ||
275 | BUG_ON("do"); | ||
276 | #endif | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg, | ||
281 | int nents, enum dma_data_direction direction) | ||
282 | { | ||
283 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | ||
284 | BUG_ON("do"); | ||
285 | #endif | ||
286 | } | ||
287 | |||
288 | static int ps3_dma_supported(struct device *_dev, u64 mask) | ||
289 | { | ||
290 | return 1; | ||
291 | } | ||
292 | |||
293 | static struct dma_mapping_ops ps3_dma_ops = { | ||
294 | .alloc_coherent = ps3_alloc_coherent, | ||
295 | .free_coherent = ps3_free_coherent, | ||
296 | .map_single = ps3_map_single, | ||
297 | .unmap_single = ps3_unmap_single, | ||
298 | .map_sg = ps3_map_sg, | ||
299 | .unmap_sg = ps3_unmap_sg, | ||
300 | .dma_supported = ps3_dma_supported | ||
301 | }; | ||
302 | |||
303 | /** | ||
304 | * ps3_system_bus_release_device - remove a device from the system bus | ||
305 | */ | ||
306 | |||
307 | static void ps3_system_bus_release_device(struct device *_dev) | ||
308 | { | ||
309 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | ||
310 | kfree(dev); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * ps3_system_bus_device_register - add a device to the system bus | ||
315 | * | ||
316 | * ps3_system_bus_device_register() expects the dev object to be allocated | ||
317 | * dynamically by the caller. The system bus takes ownership of the dev | ||
318 | * object and frees the object in ps3_system_bus_release_device(). | ||
319 | */ | ||
320 | |||
321 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) | ||
322 | { | ||
323 | int result; | ||
324 | static unsigned int dev_count = 1; | ||
325 | |||
326 | dev->core.parent = NULL; | ||
327 | dev->core.bus = &ps3_system_bus_type; | ||
328 | dev->core.release = ps3_system_bus_release_device; | ||
329 | |||
330 | dev->core.archdata.of_node = NULL; | ||
331 | dev->core.archdata.dma_ops = &ps3_dma_ops; | ||
332 | dev->core.archdata.numa_node = 0; | ||
333 | |||
334 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x", | ||
335 | dev_count++); | ||
336 | |||
337 | pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); | ||
338 | |||
339 | result = device_register(&dev->core); | ||
340 | return result; | ||
341 | } | ||
342 | |||
343 | EXPORT_SYMBOL_GPL(ps3_system_bus_device_register); | ||
344 | |||
345 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv) | ||
346 | { | ||
347 | int result; | ||
348 | |||
349 | drv->core.bus = &ps3_system_bus_type; | ||
350 | |||
351 | result = driver_register(&drv->core); | ||
352 | return result; | ||
353 | } | ||
354 | |||
355 | EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register); | ||
356 | |||
357 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) | ||
358 | { | ||
359 | driver_unregister(&drv->core); | ||
360 | } | ||
361 | |||
362 | EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index b691d3e1475..787a8f13467 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -282,7 +282,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo) | |||
282 | } | 282 | } |
283 | 283 | ||
284 | /* Setup any dynamic params in the uart desc */ | 284 | /* Setup any dynamic params in the uart desc */ |
285 | int cpm_uart_init_portdesc(void) | 285 | int __init cpm_uart_init_portdesc(void) |
286 | { | 286 | { |
287 | #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2) | 287 | #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2) |
288 | u32 addr; | 288 | u32 addr; |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 4f80c5b4a75..6dd579ed977 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/mpc52xx_uart.c | ||
3 | * | ||
4 | * Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs. | 2 | * Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs. |
5 | * | 3 | * |
6 | * FIXME According to the usermanual the status bits in the status register | 4 | * FIXME According to the usermanual the status bits in the status register |
@@ -14,18 +12,20 @@ | |||
14 | * | 12 | * |
15 | * | 13 | * |
16 | * Maintainer : Sylvain Munaut <tnt@246tNt.com> | 14 | * Maintainer : Sylvain Munaut <tnt@246tNt.com> |
17 | * | 15 | * |
18 | * Some of the code has been inspired/copied from the 2.4 code written | 16 | * Some of the code has been inspired/copied from the 2.4 code written |
19 | * by Dale Farnsworth <dfarnsworth@mvista.com>. | 17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. |
20 | * | 18 | * |
21 | * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com> | 19 | * Copyright (C) 2006 Secret Lab Technologies Ltd. |
20 | * Grant Likely <grant.likely@secretlab.ca> | ||
21 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> | ||
22 | * Copyright (C) 2003 MontaVista, Software, Inc. | 22 | * Copyright (C) 2003 MontaVista, Software, Inc. |
23 | * | 23 | * |
24 | * This file is licensed under the terms of the GNU General Public License | 24 | * This file is licensed under the terms of the GNU General Public License |
25 | * version 2. This program is licensed "as is" without any warranty of any | 25 | * version 2. This program is licensed "as is" without any warranty of any |
26 | * kind, whether express or implied. | 26 | * kind, whether express or implied. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | /* Platform device Usage : | 29 | /* Platform device Usage : |
30 | * | 30 | * |
31 | * Since PSCs can have multiple function, the correct driver for each one | 31 | * Since PSCs can have multiple function, the correct driver for each one |
@@ -44,7 +44,24 @@ | |||
44 | * will be mapped to. | 44 | * will be mapped to. |
45 | */ | 45 | */ |
46 | 46 | ||
47 | #include <linux/platform_device.h> | 47 | /* OF Platform device Usage : |
48 | * | ||
49 | * This driver is only used for PSCs configured in uart mode. The device | ||
50 | * tree will have a node for each PSC in uart mode w/ device_type = "serial" | ||
51 | * and "mpc52xx-psc-uart" in the compatible string | ||
52 | * | ||
53 | * By default, PSC devices are enumerated in the order they are found. However | ||
54 | * a particular PSC number can be forces by adding 'device_no = <port#>' | ||
55 | * to the device node. | ||
56 | * | ||
57 | * The driver init all necessary registers to place the PSC in uart mode without | ||
58 | * DCD. However, the pin multiplexing aren't changed and should be set either | ||
59 | * by the bootloader or in the platform init code. | ||
60 | */ | ||
61 | |||
62 | #undef DEBUG | ||
63 | |||
64 | #include <linux/device.h> | ||
48 | #include <linux/module.h> | 65 | #include <linux/module.h> |
49 | #include <linux/tty.h> | 66 | #include <linux/tty.h> |
50 | #include <linux/serial.h> | 67 | #include <linux/serial.h> |
@@ -54,6 +71,12 @@ | |||
54 | #include <asm/delay.h> | 71 | #include <asm/delay.h> |
55 | #include <asm/io.h> | 72 | #include <asm/io.h> |
56 | 73 | ||
74 | #if defined(CONFIG_PPC_MERGE) | ||
75 | #include <asm/of_platform.h> | ||
76 | #else | ||
77 | #include <linux/platform_device.h> | ||
78 | #endif | ||
79 | |||
57 | #include <asm/mpc52xx.h> | 80 | #include <asm/mpc52xx.h> |
58 | #include <asm/mpc52xx_psc.h> | 81 | #include <asm/mpc52xx_psc.h> |
59 | 82 | ||
@@ -80,6 +103,12 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM]; | |||
80 | * it's cleared, then a memset(...,0,...) should be added to | 103 | * it's cleared, then a memset(...,0,...) should be added to |
81 | * the console_init | 104 | * the console_init |
82 | */ | 105 | */ |
106 | #if defined(CONFIG_PPC_MERGE) | ||
107 | /* lookup table for matching device nodes to index numbers */ | ||
108 | static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM]; | ||
109 | |||
110 | static void mpc52xx_uart_of_enumerate(void); | ||
111 | #endif | ||
83 | 112 | ||
84 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) | 113 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) |
85 | 114 | ||
@@ -96,32 +125,40 @@ static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id); | |||
96 | #define uart_console(port) (0) | 125 | #define uart_console(port) (0) |
97 | #endif | 126 | #endif |
98 | 127 | ||
128 | #if defined(CONFIG_PPC_MERGE) | ||
129 | static struct of_device_id mpc52xx_uart_of_match[] = { | ||
130 | { .type = "serial", .compatible = "mpc52xx-psc-uart", }, | ||
131 | { .type = "serial", .compatible = "mpc5200-psc", }, /* Efika only! */ | ||
132 | {}, | ||
133 | }; | ||
134 | #endif | ||
135 | |||
99 | 136 | ||
100 | /* ======================================================================== */ | 137 | /* ======================================================================== */ |
101 | /* UART operations */ | 138 | /* UART operations */ |
102 | /* ======================================================================== */ | 139 | /* ======================================================================== */ |
103 | 140 | ||
104 | static unsigned int | 141 | static unsigned int |
105 | mpc52xx_uart_tx_empty(struct uart_port *port) | 142 | mpc52xx_uart_tx_empty(struct uart_port *port) |
106 | { | 143 | { |
107 | int status = in_be16(&PSC(port)->mpc52xx_psc_status); | 144 | int status = in_be16(&PSC(port)->mpc52xx_psc_status); |
108 | return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0; | 145 | return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0; |
109 | } | 146 | } |
110 | 147 | ||
111 | static void | 148 | static void |
112 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | 149 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
113 | { | 150 | { |
114 | /* Not implemented */ | 151 | /* Not implemented */ |
115 | } | 152 | } |
116 | 153 | ||
117 | static unsigned int | 154 | static unsigned int |
118 | mpc52xx_uart_get_mctrl(struct uart_port *port) | 155 | mpc52xx_uart_get_mctrl(struct uart_port *port) |
119 | { | 156 | { |
120 | /* Not implemented */ | 157 | /* Not implemented */ |
121 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | 158 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; |
122 | } | 159 | } |
123 | 160 | ||
124 | static void | 161 | static void |
125 | mpc52xx_uart_stop_tx(struct uart_port *port) | 162 | mpc52xx_uart_stop_tx(struct uart_port *port) |
126 | { | 163 | { |
127 | /* port->lock taken by caller */ | 164 | /* port->lock taken by caller */ |
@@ -129,7 +166,7 @@ mpc52xx_uart_stop_tx(struct uart_port *port) | |||
129 | out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); | 166 | out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); |
130 | } | 167 | } |
131 | 168 | ||
132 | static void | 169 | static void |
133 | mpc52xx_uart_start_tx(struct uart_port *port) | 170 | mpc52xx_uart_start_tx(struct uart_port *port) |
134 | { | 171 | { |
135 | /* port->lock taken by caller */ | 172 | /* port->lock taken by caller */ |
@@ -137,12 +174,12 @@ mpc52xx_uart_start_tx(struct uart_port *port) | |||
137 | out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); | 174 | out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); |
138 | } | 175 | } |
139 | 176 | ||
140 | static void | 177 | static void |
141 | mpc52xx_uart_send_xchar(struct uart_port *port, char ch) | 178 | mpc52xx_uart_send_xchar(struct uart_port *port, char ch) |
142 | { | 179 | { |
143 | unsigned long flags; | 180 | unsigned long flags; |
144 | spin_lock_irqsave(&port->lock, flags); | 181 | spin_lock_irqsave(&port->lock, flags); |
145 | 182 | ||
146 | port->x_char = ch; | 183 | port->x_char = ch; |
147 | if (ch) { | 184 | if (ch) { |
148 | /* Make sure tx interrupts are on */ | 185 | /* Make sure tx interrupts are on */ |
@@ -150,7 +187,7 @@ mpc52xx_uart_send_xchar(struct uart_port *port, char ch) | |||
150 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 187 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; |
151 | out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); | 188 | out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask); |
152 | } | 189 | } |
153 | 190 | ||
154 | spin_unlock_irqrestore(&port->lock, flags); | 191 | spin_unlock_irqrestore(&port->lock, flags); |
155 | } | 192 | } |
156 | 193 | ||
@@ -178,7 +215,7 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | |||
178 | out_8(&PSC(port)->command,MPC52xx_PSC_START_BRK); | 215 | out_8(&PSC(port)->command,MPC52xx_PSC_START_BRK); |
179 | else | 216 | else |
180 | out_8(&PSC(port)->command,MPC52xx_PSC_STOP_BRK); | 217 | out_8(&PSC(port)->command,MPC52xx_PSC_STOP_BRK); |
181 | 218 | ||
182 | spin_unlock_irqrestore(&port->lock, flags); | 219 | spin_unlock_irqrestore(&port->lock, flags); |
183 | } | 220 | } |
184 | 221 | ||
@@ -197,11 +234,11 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
197 | /* Reset/activate the port, clear and enable interrupts */ | 234 | /* Reset/activate the port, clear and enable interrupts */ |
198 | out_8(&psc->command,MPC52xx_PSC_RST_RX); | 235 | out_8(&psc->command,MPC52xx_PSC_RST_RX); |
199 | out_8(&psc->command,MPC52xx_PSC_RST_TX); | 236 | out_8(&psc->command,MPC52xx_PSC_RST_TX); |
200 | 237 | ||
201 | out_be32(&psc->sicr,0); /* UART mode DCD ignored */ | 238 | out_be32(&psc->sicr,0); /* UART mode DCD ignored */ |
202 | 239 | ||
203 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */ | 240 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */ |
204 | 241 | ||
205 | out_8(&psc->rfcntl, 0x00); | 242 | out_8(&psc->rfcntl, 0x00); |
206 | out_be16(&psc->rfalarm, 0x1ff); | 243 | out_be16(&psc->rfalarm, 0x1ff); |
207 | out_8(&psc->tfcntl, 0x07); | 244 | out_8(&psc->tfcntl, 0x07); |
@@ -209,10 +246,10 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
209 | 246 | ||
210 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | 247 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; |
211 | out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask); | 248 | out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask); |
212 | 249 | ||
213 | out_8(&psc->command,MPC52xx_PSC_TX_ENABLE); | 250 | out_8(&psc->command,MPC52xx_PSC_TX_ENABLE); |
214 | out_8(&psc->command,MPC52xx_PSC_RX_ENABLE); | 251 | out_8(&psc->command,MPC52xx_PSC_RX_ENABLE); |
215 | 252 | ||
216 | return 0; | 253 | return 0; |
217 | } | 254 | } |
218 | 255 | ||
@@ -220,19 +257,19 @@ static void | |||
220 | mpc52xx_uart_shutdown(struct uart_port *port) | 257 | mpc52xx_uart_shutdown(struct uart_port *port) |
221 | { | 258 | { |
222 | struct mpc52xx_psc __iomem *psc = PSC(port); | 259 | struct mpc52xx_psc __iomem *psc = PSC(port); |
223 | 260 | ||
224 | /* Shut down the port, interrupt and all */ | 261 | /* Shut down the port, interrupt and all */ |
225 | out_8(&psc->command,MPC52xx_PSC_RST_RX); | 262 | out_8(&psc->command,MPC52xx_PSC_RST_RX); |
226 | out_8(&psc->command,MPC52xx_PSC_RST_TX); | 263 | out_8(&psc->command,MPC52xx_PSC_RST_TX); |
227 | 264 | ||
228 | port->read_status_mask = 0; | 265 | port->read_status_mask = 0; |
229 | out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask); | 266 | out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask); |
230 | 267 | ||
231 | /* Release interrupt */ | 268 | /* Release interrupt */ |
232 | free_irq(port->irq, port); | 269 | free_irq(port->irq, port); |
233 | } | 270 | } |
234 | 271 | ||
235 | static void | 272 | static void |
236 | mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, | 273 | mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, |
237 | struct termios *old) | 274 | struct termios *old) |
238 | { | 275 | { |
@@ -241,10 +278,10 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, | |||
241 | unsigned char mr1, mr2; | 278 | unsigned char mr1, mr2; |
242 | unsigned short ctr; | 279 | unsigned short ctr; |
243 | unsigned int j, baud, quot; | 280 | unsigned int j, baud, quot; |
244 | 281 | ||
245 | /* Prepare what we're gonna write */ | 282 | /* Prepare what we're gonna write */ |
246 | mr1 = 0; | 283 | mr1 = 0; |
247 | 284 | ||
248 | switch (new->c_cflag & CSIZE) { | 285 | switch (new->c_cflag & CSIZE) { |
249 | case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS; | 286 | case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS; |
250 | break; | 287 | break; |
@@ -261,8 +298,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, | |||
261 | MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN; | 298 | MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN; |
262 | } else | 299 | } else |
263 | mr1 |= MPC52xx_PSC_MODE_PARNONE; | 300 | mr1 |= MPC52xx_PSC_MODE_PARNONE; |
264 | 301 | ||
265 | 302 | ||
266 | mr2 = 0; | 303 | mr2 = 0; |
267 | 304 | ||
268 | if (new->c_cflag & CSTOPB) | 305 | if (new->c_cflag & CSTOPB) |
@@ -276,7 +313,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, | |||
276 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); | 313 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); |
277 | quot = uart_get_divisor(port, baud); | 314 | quot = uart_get_divisor(port, baud); |
278 | ctr = quot & 0xffff; | 315 | ctr = quot & 0xffff; |
279 | 316 | ||
280 | /* Get the lock */ | 317 | /* Get the lock */ |
281 | spin_lock_irqsave(&port->lock, flags); | 318 | spin_lock_irqsave(&port->lock, flags); |
282 | 319 | ||
@@ -290,14 +327,14 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, | |||
290 | * boot for the console, all stuff is not yet ready to receive at that | 327 | * boot for the console, all stuff is not yet ready to receive at that |
291 | * time and that just makes the kernel oops */ | 328 | * time and that just makes the kernel oops */ |
292 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ | 329 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ |
293 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 330 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && |
294 | --j) | 331 | --j) |
295 | udelay(1); | 332 | udelay(1); |
296 | 333 | ||
297 | if (!j) | 334 | if (!j) |
298 | printk( KERN_ERR "mpc52xx_uart.c: " | 335 | printk( KERN_ERR "mpc52xx_uart.c: " |
299 | "Unable to flush RX & TX fifos in-time in set_termios." | 336 | "Unable to flush RX & TX fifos in-time in set_termios." |
300 | "Some chars may have been lost.\n" ); | 337 | "Some chars may have been lost.\n" ); |
301 | 338 | ||
302 | /* Reset the TX & RX */ | 339 | /* Reset the TX & RX */ |
303 | out_8(&psc->command,MPC52xx_PSC_RST_RX); | 340 | out_8(&psc->command,MPC52xx_PSC_RST_RX); |
@@ -309,7 +346,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, | |||
309 | out_8(&psc->mode,mr2); | 346 | out_8(&psc->mode,mr2); |
310 | out_8(&psc->ctur,ctr >> 8); | 347 | out_8(&psc->ctur,ctr >> 8); |
311 | out_8(&psc->ctlr,ctr & 0xff); | 348 | out_8(&psc->ctlr,ctr & 0xff); |
312 | 349 | ||
313 | /* Reenable TX & RX */ | 350 | /* Reenable TX & RX */ |
314 | out_8(&psc->command,MPC52xx_PSC_TX_ENABLE); | 351 | out_8(&psc->command,MPC52xx_PSC_TX_ENABLE); |
315 | out_8(&psc->command,MPC52xx_PSC_RX_ENABLE); | 352 | out_8(&psc->command,MPC52xx_PSC_RX_ENABLE); |
@@ -332,7 +369,7 @@ mpc52xx_uart_release_port(struct uart_port *port) | |||
332 | port->membase = NULL; | 369 | port->membase = NULL; |
333 | } | 370 | } |
334 | 371 | ||
335 | release_mem_region(port->mapbase, MPC52xx_PSC_SIZE); | 372 | release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); |
336 | } | 373 | } |
337 | 374 | ||
338 | static int | 375 | static int |
@@ -341,12 +378,13 @@ mpc52xx_uart_request_port(struct uart_port *port) | |||
341 | int err; | 378 | int err; |
342 | 379 | ||
343 | if (port->flags & UPF_IOREMAP) /* Need to remap ? */ | 380 | if (port->flags & UPF_IOREMAP) /* Need to remap ? */ |
344 | port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE); | 381 | port->membase = ioremap(port->mapbase, |
382 | sizeof(struct mpc52xx_psc)); | ||
345 | 383 | ||
346 | if (!port->membase) | 384 | if (!port->membase) |
347 | return -EINVAL; | 385 | return -EINVAL; |
348 | 386 | ||
349 | err = request_mem_region(port->mapbase, MPC52xx_PSC_SIZE, | 387 | err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc), |
350 | "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; | 388 | "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; |
351 | 389 | ||
352 | if (err && (port->flags & UPF_IOREMAP)) { | 390 | if (err && (port->flags & UPF_IOREMAP)) { |
@@ -373,7 +411,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
373 | 411 | ||
374 | if ( (ser->irq != port->irq) || | 412 | if ( (ser->irq != port->irq) || |
375 | (ser->io_type != SERIAL_IO_MEM) || | 413 | (ser->io_type != SERIAL_IO_MEM) || |
376 | (ser->baud_base != port->uartclk) || | 414 | (ser->baud_base != port->uartclk) || |
377 | (ser->iomem_base != (void*)port->mapbase) || | 415 | (ser->iomem_base != (void*)port->mapbase) || |
378 | (ser->hub6 != 0 ) ) | 416 | (ser->hub6 != 0 ) ) |
379 | return -EINVAL; | 417 | return -EINVAL; |
@@ -404,11 +442,11 @@ static struct uart_ops mpc52xx_uart_ops = { | |||
404 | .verify_port = mpc52xx_uart_verify_port | 442 | .verify_port = mpc52xx_uart_verify_port |
405 | }; | 443 | }; |
406 | 444 | ||
407 | 445 | ||
408 | /* ======================================================================== */ | 446 | /* ======================================================================== */ |
409 | /* Interrupt handling */ | 447 | /* Interrupt handling */ |
410 | /* ======================================================================== */ | 448 | /* ======================================================================== */ |
411 | 449 | ||
412 | static inline int | 450 | static inline int |
413 | mpc52xx_uart_int_rx_chars(struct uart_port *port) | 451 | mpc52xx_uart_int_rx_chars(struct uart_port *port) |
414 | { | 452 | { |
@@ -435,11 +473,11 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
435 | 473 | ||
436 | flag = TTY_NORMAL; | 474 | flag = TTY_NORMAL; |
437 | port->icount.rx++; | 475 | port->icount.rx++; |
438 | 476 | ||
439 | if ( status & (MPC52xx_PSC_SR_PE | | 477 | if ( status & (MPC52xx_PSC_SR_PE | |
440 | MPC52xx_PSC_SR_FE | | 478 | MPC52xx_PSC_SR_FE | |
441 | MPC52xx_PSC_SR_RB) ) { | 479 | MPC52xx_PSC_SR_RB) ) { |
442 | 480 | ||
443 | if (status & MPC52xx_PSC_SR_RB) { | 481 | if (status & MPC52xx_PSC_SR_RB) { |
444 | flag = TTY_BREAK; | 482 | flag = TTY_BREAK; |
445 | uart_handle_break(port); | 483 | uart_handle_break(port); |
@@ -464,7 +502,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
464 | } | 502 | } |
465 | 503 | ||
466 | tty_flip_buffer_push(tty); | 504 | tty_flip_buffer_push(tty); |
467 | 505 | ||
468 | return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY; | 506 | return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY; |
469 | } | 507 | } |
470 | 508 | ||
@@ -509,25 +547,25 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
509 | return 1; | 547 | return 1; |
510 | } | 548 | } |
511 | 549 | ||
512 | static irqreturn_t | 550 | static irqreturn_t |
513 | mpc52xx_uart_int(int irq, void *dev_id) | 551 | mpc52xx_uart_int(int irq, void *dev_id) |
514 | { | 552 | { |
515 | struct uart_port *port = dev_id; | 553 | struct uart_port *port = dev_id; |
516 | unsigned long pass = ISR_PASS_LIMIT; | 554 | unsigned long pass = ISR_PASS_LIMIT; |
517 | unsigned int keepgoing; | 555 | unsigned int keepgoing; |
518 | unsigned short status; | 556 | unsigned short status; |
519 | 557 | ||
520 | spin_lock(&port->lock); | 558 | spin_lock(&port->lock); |
521 | 559 | ||
522 | /* While we have stuff to do, we continue */ | 560 | /* While we have stuff to do, we continue */ |
523 | do { | 561 | do { |
524 | /* If we don't find anything to do, we stop */ | 562 | /* If we don't find anything to do, we stop */ |
525 | keepgoing = 0; | 563 | keepgoing = 0; |
526 | 564 | ||
527 | /* Read status */ | 565 | /* Read status */ |
528 | status = in_be16(&PSC(port)->mpc52xx_psc_isr); | 566 | status = in_be16(&PSC(port)->mpc52xx_psc_isr); |
529 | status &= port->read_status_mask; | 567 | status &= port->read_status_mask; |
530 | 568 | ||
531 | /* Do we need to receive chars ? */ | 569 | /* Do we need to receive chars ? */ |
532 | /* For this RX interrupts must be on and some chars waiting */ | 570 | /* For this RX interrupts must be on and some chars waiting */ |
533 | if ( status & MPC52xx_PSC_IMR_RXRDY ) | 571 | if ( status & MPC52xx_PSC_IMR_RXRDY ) |
@@ -537,15 +575,15 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
537 | /* For this, TX must be ready and TX interrupt enabled */ | 575 | /* For this, TX must be ready and TX interrupt enabled */ |
538 | if ( status & MPC52xx_PSC_IMR_TXRDY ) | 576 | if ( status & MPC52xx_PSC_IMR_TXRDY ) |
539 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 577 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
540 | 578 | ||
541 | /* Limit number of iteration */ | 579 | /* Limit number of iteration */ |
542 | if ( !(--pass) ) | 580 | if ( !(--pass) ) |
543 | keepgoing = 0; | 581 | keepgoing = 0; |
544 | 582 | ||
545 | } while (keepgoing); | 583 | } while (keepgoing); |
546 | 584 | ||
547 | spin_unlock(&port->lock); | 585 | spin_unlock(&port->lock); |
548 | 586 | ||
549 | return IRQ_HANDLED; | 587 | return IRQ_HANDLED; |
550 | } | 588 | } |
551 | 589 | ||
@@ -563,13 +601,18 @@ mpc52xx_console_get_options(struct uart_port *port, | |||
563 | struct mpc52xx_psc __iomem *psc = PSC(port); | 601 | struct mpc52xx_psc __iomem *psc = PSC(port); |
564 | unsigned char mr1; | 602 | unsigned char mr1; |
565 | 603 | ||
604 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); | ||
605 | |||
566 | /* Read the mode registers */ | 606 | /* Read the mode registers */ |
567 | out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1); | 607 | out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1); |
568 | mr1 = in_8(&psc->mode); | 608 | mr1 = in_8(&psc->mode); |
569 | 609 | ||
570 | /* CT{U,L}R are write-only ! */ | 610 | /* CT{U,L}R are write-only ! */ |
571 | *baud = __res.bi_baudrate ? | 611 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; |
572 | __res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | 612 | #if !defined(CONFIG_PPC_MERGE) |
613 | if (__res.bi_baudrate) | ||
614 | *baud = __res.bi_baudrate; | ||
615 | #endif | ||
573 | 616 | ||
574 | /* Parse them */ | 617 | /* Parse them */ |
575 | switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { | 618 | switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { |
@@ -579,26 +622,26 @@ mpc52xx_console_get_options(struct uart_port *port, | |||
579 | case MPC52xx_PSC_MODE_8_BITS: | 622 | case MPC52xx_PSC_MODE_8_BITS: |
580 | default: *bits = 8; | 623 | default: *bits = 8; |
581 | } | 624 | } |
582 | 625 | ||
583 | if (mr1 & MPC52xx_PSC_MODE_PARNONE) | 626 | if (mr1 & MPC52xx_PSC_MODE_PARNONE) |
584 | *parity = 'n'; | 627 | *parity = 'n'; |
585 | else | 628 | else |
586 | *parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e'; | 629 | *parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e'; |
587 | } | 630 | } |
588 | 631 | ||
589 | static void | 632 | static void |
590 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | 633 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) |
591 | { | 634 | { |
592 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | 635 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; |
593 | struct mpc52xx_psc __iomem *psc = PSC(port); | 636 | struct mpc52xx_psc __iomem *psc = PSC(port); |
594 | unsigned int i, j; | 637 | unsigned int i, j; |
595 | 638 | ||
596 | /* Disable interrupts */ | 639 | /* Disable interrupts */ |
597 | out_be16(&psc->mpc52xx_psc_imr, 0); | 640 | out_be16(&psc->mpc52xx_psc_imr, 0); |
598 | 641 | ||
599 | /* Wait the TX buffer to be empty */ | 642 | /* Wait the TX buffer to be empty */ |
600 | j = 5000000; /* Maximum wait */ | 643 | j = 5000000; /* Maximum wait */ |
601 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 644 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && |
602 | --j) | 645 | --j) |
603 | udelay(1); | 646 | udelay(1); |
604 | 647 | ||
@@ -607,13 +650,13 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | |||
607 | /* Line return handling */ | 650 | /* Line return handling */ |
608 | if (*s == '\n') | 651 | if (*s == '\n') |
609 | out_8(&psc->mpc52xx_psc_buffer_8, '\r'); | 652 | out_8(&psc->mpc52xx_psc_buffer_8, '\r'); |
610 | 653 | ||
611 | /* Send the char */ | 654 | /* Send the char */ |
612 | out_8(&psc->mpc52xx_psc_buffer_8, *s); | 655 | out_8(&psc->mpc52xx_psc_buffer_8, *s); |
613 | 656 | ||
614 | /* Wait the TX buffer to be empty */ | 657 | /* Wait the TX buffer to be empty */ |
615 | j = 20000; /* Maximum wait */ | 658 | j = 20000; /* Maximum wait */ |
616 | while (!(in_be16(&psc->mpc52xx_psc_status) & | 659 | while (!(in_be16(&psc->mpc52xx_psc_status) & |
617 | MPC52xx_PSC_SR_TXEMP) && --j) | 660 | MPC52xx_PSC_SR_TXEMP) && --j) |
618 | udelay(1); | 661 | udelay(1); |
619 | } | 662 | } |
@@ -622,6 +665,7 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | |||
622 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 665 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); |
623 | } | 666 | } |
624 | 667 | ||
668 | #if !defined(CONFIG_PPC_MERGE) | ||
625 | static int __init | 669 | static int __init |
626 | mpc52xx_console_setup(struct console *co, char *options) | 670 | mpc52xx_console_setup(struct console *co, char *options) |
627 | { | 671 | { |
@@ -634,7 +678,7 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
634 | 678 | ||
635 | if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM) | 679 | if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM) |
636 | return -EINVAL; | 680 | return -EINVAL; |
637 | 681 | ||
638 | /* Basic port init. Needed since we use some uart_??? func before | 682 | /* Basic port init. Needed since we use some uart_??? func before |
639 | * real init for early access */ | 683 | * real init for early access */ |
640 | spin_lock_init(&port->lock); | 684 | spin_lock_init(&port->lock); |
@@ -656,6 +700,78 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
656 | return uart_set_options(port, co, baud, parity, bits, flow); | 700 | return uart_set_options(port, co, baud, parity, bits, flow); |
657 | } | 701 | } |
658 | 702 | ||
703 | #else | ||
704 | |||
705 | static int __init | ||
706 | mpc52xx_console_setup(struct console *co, char *options) | ||
707 | { | ||
708 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | ||
709 | struct device_node *np = mpc52xx_uart_nodes[co->index]; | ||
710 | unsigned int ipb_freq; | ||
711 | struct resource res; | ||
712 | int ret; | ||
713 | |||
714 | int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | ||
715 | int bits = 8; | ||
716 | int parity = 'n'; | ||
717 | int flow = 'n'; | ||
718 | |||
719 | pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n", | ||
720 | co, co->index, options); | ||
721 | |||
722 | if ((co->index < 0) || (co->index > MPC52xx_PSC_MAXNUM)) { | ||
723 | pr_debug("PSC%x out of range\n", co->index); | ||
724 | return -EINVAL; | ||
725 | } | ||
726 | |||
727 | if (!np) { | ||
728 | pr_debug("PSC%x not found in device tree\n", co->index); | ||
729 | return -EINVAL; | ||
730 | } | ||
731 | |||
732 | pr_debug("Console on ttyPSC%x is %s\n", | ||
733 | co->index, mpc52xx_uart_nodes[co->index]->full_name); | ||
734 | |||
735 | /* Fetch register locations */ | ||
736 | if ((ret = of_address_to_resource(np, 0, &res)) != 0) { | ||
737 | pr_debug("Could not get resources for PSC%x\n", co->index); | ||
738 | return ret; | ||
739 | } | ||
740 | |||
741 | /* Search for bus-frequency property in this node or a parent */ | ||
742 | if ((ipb_freq = mpc52xx_find_ipb_freq(np)) == 0) { | ||
743 | pr_debug("Could not find IPB bus frequency!\n"); | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | /* Basic port init. Needed since we use some uart_??? func before | ||
748 | * real init for early access */ | ||
749 | spin_lock_init(&port->lock); | ||
750 | port->uartclk = ipb_freq / 2; | ||
751 | port->ops = &mpc52xx_uart_ops; | ||
752 | port->mapbase = res.start; | ||
753 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); | ||
754 | port->irq = irq_of_parse_and_map(np, 0); | ||
755 | |||
756 | if (port->membase == NULL) | ||
757 | return -EINVAL; | ||
758 | |||
759 | pr_debug("mpc52xx-psc uart at %lx, mapped to %p, irq=%x, freq=%i\n", | ||
760 | port->mapbase, port->membase, port->irq, port->uartclk); | ||
761 | |||
762 | /* Setup the port parameters accoding to options */ | ||
763 | if (options) | ||
764 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
765 | else | ||
766 | mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow); | ||
767 | |||
768 | pr_debug("Setting console parameters: %i %i%c1 flow=%c\n", | ||
769 | baud, bits, parity, flow); | ||
770 | |||
771 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
772 | } | ||
773 | #endif /* defined(CONFIG_PPC_MERGE) */ | ||
774 | |||
659 | 775 | ||
660 | static struct uart_driver mpc52xx_uart_driver; | 776 | static struct uart_driver mpc52xx_uart_driver; |
661 | 777 | ||
@@ -669,10 +785,11 @@ static struct console mpc52xx_console = { | |||
669 | .data = &mpc52xx_uart_driver, | 785 | .data = &mpc52xx_uart_driver, |
670 | }; | 786 | }; |
671 | 787 | ||
672 | 788 | ||
673 | static int __init | 789 | static int __init |
674 | mpc52xx_console_init(void) | 790 | mpc52xx_console_init(void) |
675 | { | 791 | { |
792 | mpc52xx_uart_of_enumerate(); | ||
676 | register_console(&mpc52xx_console); | 793 | register_console(&mpc52xx_console); |
677 | return 0; | 794 | return 0; |
678 | } | 795 | } |
@@ -700,6 +817,7 @@ static struct uart_driver mpc52xx_uart_driver = { | |||
700 | }; | 817 | }; |
701 | 818 | ||
702 | 819 | ||
820 | #if !defined(CONFIG_PPC_MERGE) | ||
703 | /* ======================================================================== */ | 821 | /* ======================================================================== */ |
704 | /* Platform Driver */ | 822 | /* Platform Driver */ |
705 | /* ======================================================================== */ | 823 | /* ======================================================================== */ |
@@ -723,8 +841,6 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
723 | /* Init the port structure */ | 841 | /* Init the port structure */ |
724 | port = &mpc52xx_uart_ports[idx]; | 842 | port = &mpc52xx_uart_ports[idx]; |
725 | 843 | ||
726 | memset(port, 0x00, sizeof(struct uart_port)); | ||
727 | |||
728 | spin_lock_init(&port->lock); | 844 | spin_lock_init(&port->lock); |
729 | port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ | 845 | port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */ |
730 | port->fifosize = 512; | 846 | port->fifosize = 512; |
@@ -733,6 +849,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
733 | ( uart_console(port) ? 0 : UPF_IOREMAP ); | 849 | ( uart_console(port) ? 0 : UPF_IOREMAP ); |
734 | port->line = idx; | 850 | port->line = idx; |
735 | port->ops = &mpc52xx_uart_ops; | 851 | port->ops = &mpc52xx_uart_ops; |
852 | port->dev = &dev->dev; | ||
736 | 853 | ||
737 | /* Search for IRQ and mapbase */ | 854 | /* Search for IRQ and mapbase */ |
738 | for (i=0 ; i<dev->num_resources ; i++, res++) { | 855 | for (i=0 ; i<dev->num_resources ; i++, res++) { |
@@ -771,7 +888,7 @@ mpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state) | |||
771 | { | 888 | { |
772 | struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev); | 889 | struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev); |
773 | 890 | ||
774 | if (sport) | 891 | if (port) |
775 | uart_suspend_port(&mpc52xx_uart_driver, port); | 892 | uart_suspend_port(&mpc52xx_uart_driver, port); |
776 | 893 | ||
777 | return 0; | 894 | return 0; |
@@ -789,6 +906,7 @@ mpc52xx_uart_resume(struct platform_device *dev) | |||
789 | } | 906 | } |
790 | #endif | 907 | #endif |
791 | 908 | ||
909 | |||
792 | static struct platform_driver mpc52xx_uart_platform_driver = { | 910 | static struct platform_driver mpc52xx_uart_platform_driver = { |
793 | .probe = mpc52xx_uart_probe, | 911 | .probe = mpc52xx_uart_probe, |
794 | .remove = mpc52xx_uart_remove, | 912 | .remove = mpc52xx_uart_remove, |
@@ -800,6 +918,184 @@ static struct platform_driver mpc52xx_uart_platform_driver = { | |||
800 | .name = "mpc52xx-psc", | 918 | .name = "mpc52xx-psc", |
801 | }, | 919 | }, |
802 | }; | 920 | }; |
921 | #endif /* !defined(CONFIG_PPC_MERGE) */ | ||
922 | |||
923 | |||
924 | #if defined(CONFIG_PPC_MERGE) | ||
925 | /* ======================================================================== */ | ||
926 | /* OF Platform Driver */ | ||
927 | /* ======================================================================== */ | ||
928 | |||
929 | static int __devinit | ||
930 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | ||
931 | { | ||
932 | int idx = -1; | ||
933 | unsigned int ipb_freq; | ||
934 | struct uart_port *port = NULL; | ||
935 | struct resource res; | ||
936 | int ret; | ||
937 | |||
938 | dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match); | ||
939 | |||
940 | /* Check validity & presence */ | ||
941 | for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++) | ||
942 | if (mpc52xx_uart_nodes[idx] == op->node) | ||
943 | break; | ||
944 | if (idx >= MPC52xx_PSC_MAXNUM) | ||
945 | return -EINVAL; | ||
946 | pr_debug("Found %s assigned to ttyPSC%x\n", | ||
947 | mpc52xx_uart_nodes[idx]->full_name, idx); | ||
948 | |||
949 | /* Search for bus-frequency property in this node or a parent */ | ||
950 | if ((ipb_freq = mpc52xx_find_ipb_freq(op->node)) == 0) { | ||
951 | dev_dbg(&op->dev, "Could not find IPB bus frequency!\n"); | ||
952 | return -EINVAL; | ||
953 | } | ||
954 | |||
955 | /* Init the port structure */ | ||
956 | port = &mpc52xx_uart_ports[idx]; | ||
957 | |||
958 | spin_lock_init(&port->lock); | ||
959 | port->uartclk = ipb_freq / 2; | ||
960 | port->fifosize = 512; | ||
961 | port->iotype = UPIO_MEM; | ||
962 | port->flags = UPF_BOOT_AUTOCONF | | ||
963 | ( uart_console(port) ? 0 : UPF_IOREMAP ); | ||
964 | port->line = idx; | ||
965 | port->ops = &mpc52xx_uart_ops; | ||
966 | port->dev = &op->dev; | ||
967 | |||
968 | /* Search for IRQ and mapbase */ | ||
969 | if ((ret = of_address_to_resource(op->node, 0, &res)) != 0) | ||
970 | return ret; | ||
971 | |||
972 | port->mapbase = res.start; | ||
973 | port->irq = irq_of_parse_and_map(op->node, 0); | ||
974 | |||
975 | dev_dbg(&op->dev, "mpc52xx-psc uart at %lx, irq=%x, freq=%i\n", | ||
976 | port->mapbase, port->irq, port->uartclk); | ||
977 | |||
978 | if ((port->irq==NO_IRQ) || !port->mapbase) { | ||
979 | printk(KERN_ERR "Could not allocate resources for PSC\n"); | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | /* Add the port to the uart sub-system */ | ||
984 | ret = uart_add_one_port(&mpc52xx_uart_driver, port); | ||
985 | if (!ret) | ||
986 | dev_set_drvdata(&op->dev, (void*)port); | ||
987 | |||
988 | return ret; | ||
989 | } | ||
990 | |||
991 | static int | ||
992 | mpc52xx_uart_of_remove(struct of_device *op) | ||
993 | { | ||
994 | struct uart_port *port = dev_get_drvdata(&op->dev); | ||
995 | dev_set_drvdata(&op->dev, NULL); | ||
996 | |||
997 | if (port) | ||
998 | uart_remove_one_port(&mpc52xx_uart_driver, port); | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | #ifdef CONFIG_PM | ||
1004 | static int | ||
1005 | mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) | ||
1006 | { | ||
1007 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | ||
1008 | |||
1009 | if (port) | ||
1010 | uart_suspend_port(&mpc52xx_uart_driver, port); | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static int | ||
1016 | mpc52xx_uart_of_resume(struct of_device *op) | ||
1017 | { | ||
1018 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | ||
1019 | |||
1020 | if (port) | ||
1021 | uart_resume_port(&mpc52xx_uart_driver, port); | ||
1022 | |||
1023 | return 0; | ||
1024 | } | ||
1025 | #endif | ||
1026 | |||
1027 | static void | ||
1028 | mpc52xx_uart_of_assign(struct device_node *np, int idx) | ||
1029 | { | ||
1030 | int free_idx = -1; | ||
1031 | int i; | ||
1032 | |||
1033 | /* Find the first free node */ | ||
1034 | for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { | ||
1035 | if (mpc52xx_uart_nodes[i] == NULL) { | ||
1036 | free_idx = i; | ||
1037 | break; | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | if ((idx < 0) || (idx >= MPC52xx_PSC_MAXNUM)) | ||
1042 | idx = free_idx; | ||
1043 | |||
1044 | if (idx < 0) | ||
1045 | return; /* No free slot; abort */ | ||
1046 | |||
1047 | /* If the slot is already occupied, then swap slots */ | ||
1048 | if (mpc52xx_uart_nodes[idx] && (free_idx != -1)) | ||
1049 | mpc52xx_uart_nodes[free_idx] = mpc52xx_uart_nodes[idx]; | ||
1050 | mpc52xx_uart_nodes[i] = np; | ||
1051 | } | ||
1052 | |||
1053 | static void | ||
1054 | mpc52xx_uart_of_enumerate(void) | ||
1055 | { | ||
1056 | static int enum_done = 0; | ||
1057 | struct device_node *np; | ||
1058 | const unsigned int *devno; | ||
1059 | int i; | ||
1060 | |||
1061 | if (enum_done) | ||
1062 | return; | ||
1063 | |||
1064 | for_each_node_by_type(np, "serial") { | ||
1065 | if (!of_match_node(mpc52xx_uart_of_match, np)) | ||
1066 | continue; | ||
1067 | |||
1068 | /* Is a particular device number requested? */ | ||
1069 | devno = get_property(np, "device_no", NULL); | ||
1070 | mpc52xx_uart_of_assign(of_node_get(np), devno ? *devno : -1); | ||
1071 | } | ||
1072 | |||
1073 | enum_done = 1; | ||
1074 | |||
1075 | for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { | ||
1076 | if (mpc52xx_uart_nodes[i]) | ||
1077 | pr_debug("%s assigned to ttyPSC%x\n", | ||
1078 | mpc52xx_uart_nodes[i]->full_name, i); | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match); | ||
1083 | |||
1084 | static struct of_platform_driver mpc52xx_uart_of_driver = { | ||
1085 | .owner = THIS_MODULE, | ||
1086 | .name = "mpc52xx-psc-uart", | ||
1087 | .match_table = mpc52xx_uart_of_match, | ||
1088 | .probe = mpc52xx_uart_of_probe, | ||
1089 | .remove = mpc52xx_uart_of_remove, | ||
1090 | #ifdef CONFIG_PM | ||
1091 | .suspend = mpc52xx_uart_of_suspend, | ||
1092 | .resume = mpc52xx_uart_of_resume, | ||
1093 | #endif | ||
1094 | .driver = { | ||
1095 | .name = "mpc52xx-psc-uart", | ||
1096 | }, | ||
1097 | }; | ||
1098 | #endif /* defined(CONFIG_PPC_MERGE) */ | ||
803 | 1099 | ||
804 | 1100 | ||
805 | /* ======================================================================== */ | 1101 | /* ======================================================================== */ |
@@ -811,22 +1107,45 @@ mpc52xx_uart_init(void) | |||
811 | { | 1107 | { |
812 | int ret; | 1108 | int ret; |
813 | 1109 | ||
814 | printk(KERN_INFO "Serial: MPC52xx PSC driver\n"); | 1110 | printk(KERN_INFO "Serial: MPC52xx PSC UART driver\n"); |
815 | 1111 | ||
816 | ret = uart_register_driver(&mpc52xx_uart_driver); | 1112 | if ((ret = uart_register_driver(&mpc52xx_uart_driver)) != 0) { |
817 | if (ret == 0) { | 1113 | printk(KERN_ERR "%s: uart_register_driver failed (%i)\n", |
818 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); | 1114 | __FILE__, ret); |
819 | if (ret) | 1115 | return ret; |
820 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
821 | } | 1116 | } |
822 | 1117 | ||
823 | return ret; | 1118 | #if defined(CONFIG_PPC_MERGE) |
1119 | mpc52xx_uart_of_enumerate(); | ||
1120 | |||
1121 | ret = of_register_platform_driver(&mpc52xx_uart_of_driver); | ||
1122 | if (ret) { | ||
1123 | printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n", | ||
1124 | __FILE__, ret); | ||
1125 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
1126 | return ret; | ||
1127 | } | ||
1128 | #else | ||
1129 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); | ||
1130 | if (ret) { | ||
1131 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", | ||
1132 | __FILE__, ret); | ||
1133 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
1134 | return ret; | ||
1135 | } | ||
1136 | #endif | ||
1137 | |||
1138 | return 0; | ||
824 | } | 1139 | } |
825 | 1140 | ||
826 | static void __exit | 1141 | static void __exit |
827 | mpc52xx_uart_exit(void) | 1142 | mpc52xx_uart_exit(void) |
828 | { | 1143 | { |
1144 | #if defined(CONFIG_PPC_MERGE) | ||
1145 | of_unregister_platform_driver(&mpc52xx_uart_of_driver); | ||
1146 | #else | ||
829 | platform_driver_unregister(&mpc52xx_uart_platform_driver); | 1147 | platform_driver_unregister(&mpc52xx_uart_platform_driver); |
1148 | #endif | ||
830 | uart_unregister_driver(&mpc52xx_uart_driver); | 1149 | uart_unregister_driver(&mpc52xx_uart_driver); |
831 | } | 1150 | } |
832 | 1151 | ||
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index fdb33cd21a2..cb26c6df058 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
36 | #include <asm/of_device.h> | 36 | #include <asm/of_device.h> |
37 | #include <asm/of_platform.h> | ||
37 | 38 | ||
38 | #include "macmodes.h" | 39 | #include "macmodes.h" |
39 | #include "platinumfb.h" | 40 | #include "platinumfb.h" |
@@ -682,14 +683,14 @@ static int __init platinumfb_init(void) | |||
682 | return -ENODEV; | 683 | return -ENODEV; |
683 | platinumfb_setup(option); | 684 | platinumfb_setup(option); |
684 | #endif | 685 | #endif |
685 | of_register_driver(&platinum_driver); | 686 | of_register_platform_driver(&platinum_driver); |
686 | 687 | ||
687 | return 0; | 688 | return 0; |
688 | } | 689 | } |
689 | 690 | ||
690 | static void __exit platinumfb_exit(void) | 691 | static void __exit platinumfb_exit(void) |
691 | { | 692 | { |
692 | of_unregister_driver(&platinum_driver); | 693 | of_unregister_platform_driver(&platinum_driver); |
693 | } | 694 | } |
694 | 695 | ||
695 | MODULE_LICENSE("GPL"); | 696 | MODULE_LICENSE("GPL"); |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 79b05a1a436..cc72bb43061 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1582,6 +1582,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
1582 | 1582 | ||
1583 | sz += thread_status_size; | 1583 | sz += thread_status_size; |
1584 | 1584 | ||
1585 | #ifdef ELF_CORE_WRITE_EXTRA_NOTES | ||
1586 | sz += ELF_CORE_EXTRA_NOTES_SIZE; | ||
1587 | #endif | ||
1588 | |||
1585 | fill_elf_note_phdr(&phdr, sz, offset); | 1589 | fill_elf_note_phdr(&phdr, sz, offset); |
1586 | offset += sz; | 1590 | offset += sz; |
1587 | DUMP_WRITE(&phdr, sizeof(phdr)); | 1591 | DUMP_WRITE(&phdr, sizeof(phdr)); |
@@ -1622,6 +1626,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
1622 | if (!writenote(notes + i, file, &foffset)) | 1626 | if (!writenote(notes + i, file, &foffset)) |
1623 | goto end_coredump; | 1627 | goto end_coredump; |
1624 | 1628 | ||
1629 | #ifdef ELF_CORE_WRITE_EXTRA_NOTES | ||
1630 | ELF_CORE_WRITE_EXTRA_NOTES; | ||
1631 | #endif | ||
1632 | |||
1625 | /* write out the thread status notes section */ | 1633 | /* write out the thread status notes section */ |
1626 | list_for_each(t, &thread_list) { | 1634 | list_for_each(t, &thread_list) { |
1627 | struct elf_thread_status *tmp = | 1635 | struct elf_thread_status *tmp = |
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild index 9827849953a..1e637381c11 100644 --- a/include/asm-powerpc/Kbuild +++ b/include/asm-powerpc/Kbuild | |||
@@ -17,6 +17,7 @@ header-y += ipc.h | |||
17 | header-y += poll.h | 17 | header-y += poll.h |
18 | header-y += shmparam.h | 18 | header-y += shmparam.h |
19 | header-y += sockios.h | 19 | header-y += sockios.h |
20 | header-y += spu_info.h | ||
20 | header-y += ucontext.h | 21 | header-y += ucontext.h |
21 | header-y += ioctl.h | 22 | header-y += ioctl.h |
22 | header-y += linkage.h | 23 | header-y += linkage.h |
diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h new file mode 100644 index 00000000000..e8c2ebd3ddd --- /dev/null +++ b/include/asm-powerpc/cell-pmu.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Cell Broadband Engine Performance Monitor | ||
3 | * | ||
4 | * (C) Copyright IBM Corporation 2006 | ||
5 | * | ||
6 | * Author: | ||
7 | * David Erb (djerb@us.ibm.com) | ||
8 | * Kevin Corry (kevcorry@us.ibm.com) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2, or (at your option) | ||
13 | * any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #ifndef __ASM_CELL_PMU_H__ | ||
26 | #define __ASM_CELL_PMU_H__ | ||
27 | |||
28 | /* The Cell PMU has four hardware performance counters, which can be | ||
29 | * configured as four 32-bit counters or eight 16-bit counters. | ||
30 | */ | ||
31 | #define NR_PHYS_CTRS 4 | ||
32 | #define NR_CTRS (NR_PHYS_CTRS * 2) | ||
33 | |||
34 | /* Macros for the pm_control register. */ | ||
35 | #define CBE_PM_16BIT_CTR(ctr) (1 << (24 - ((ctr) & (NR_PHYS_CTRS - 1)))) | ||
36 | #define CBE_PM_ENABLE_PERF_MON 0x80000000 | ||
37 | #define CBE_PM_STOP_AT_MAX 0x40000000 | ||
38 | #define CBE_PM_TRACE_MODE_GET(pm_control) (((pm_control) >> 28) & 0x3) | ||
39 | #define CBE_PM_TRACE_MODE_SET(mode) (((mode) & 0x3) << 28) | ||
40 | #define CBE_PM_COUNT_MODE_SET(count) (((count) & 0x3) << 18) | ||
41 | #define CBE_PM_FREEZE_ALL_CTRS 0x00100000 | ||
42 | #define CBE_PM_ENABLE_EXT_TRACE 0x00008000 | ||
43 | |||
44 | /* Macros for the trace_address register. */ | ||
45 | #define CBE_PM_TRACE_BUF_FULL 0x00000800 | ||
46 | #define CBE_PM_TRACE_BUF_EMPTY 0x00000400 | ||
47 | #define CBE_PM_TRACE_BUF_DATA_COUNT(ta) ((ta) & 0x3ff) | ||
48 | #define CBE_PM_TRACE_BUF_MAX_COUNT 0x400 | ||
49 | |||
50 | /* Macros for the pm07_control registers. */ | ||
51 | #define CBE_PM_CTR_INPUT_MUX(pm07_control) (((pm07_control) >> 26) & 0x3f) | ||
52 | #define CBE_PM_CTR_INPUT_CONTROL 0x02000000 | ||
53 | #define CBE_PM_CTR_POLARITY 0x01000000 | ||
54 | #define CBE_PM_CTR_COUNT_CYCLES 0x00800000 | ||
55 | #define CBE_PM_CTR_ENABLE 0x00400000 | ||
56 | |||
57 | /* Macros for the pm_status register. */ | ||
58 | #define CBE_PM_CTR_OVERFLOW_INTR(ctr) (1 << (31 - ((ctr) & 7))) | ||
59 | |||
60 | enum pm_reg_name { | ||
61 | group_control, | ||
62 | debug_bus_control, | ||
63 | trace_address, | ||
64 | ext_tr_timer, | ||
65 | pm_status, | ||
66 | pm_control, | ||
67 | pm_interval, | ||
68 | pm_start_stop, | ||
69 | }; | ||
70 | |||
71 | /* Routines for reading/writing the PMU registers. */ | ||
72 | extern u32 cbe_read_phys_ctr(u32 cpu, u32 phys_ctr); | ||
73 | extern void cbe_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val); | ||
74 | extern u32 cbe_read_ctr(u32 cpu, u32 ctr); | ||
75 | extern void cbe_write_ctr(u32 cpu, u32 ctr, u32 val); | ||
76 | |||
77 | extern u32 cbe_read_pm07_control(u32 cpu, u32 ctr); | ||
78 | extern void cbe_write_pm07_control(u32 cpu, u32 ctr, u32 val); | ||
79 | extern u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg); | ||
80 | extern void cbe_write_pm(u32 cpu, enum pm_reg_name reg, u32 val); | ||
81 | |||
82 | extern u32 cbe_get_ctr_size(u32 cpu, u32 phys_ctr); | ||
83 | extern void cbe_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size); | ||
84 | |||
85 | extern void cbe_enable_pm(u32 cpu); | ||
86 | extern void cbe_disable_pm(u32 cpu); | ||
87 | |||
88 | extern void cbe_read_trace_buffer(u32 cpu, u64 *buf); | ||
89 | |||
90 | extern void cbe_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask); | ||
91 | extern void cbe_disable_pm_interrupts(u32 cpu); | ||
92 | extern u32 cbe_query_pm_interrupts(u32 cpu); | ||
93 | extern u32 cbe_clear_pm_interrupts(u32 cpu); | ||
94 | extern void cbe_sync_irq(int node); | ||
95 | |||
96 | /* Utility functions, macros */ | ||
97 | extern u32 cbe_get_hw_thread_id(int cpu); | ||
98 | |||
99 | #define cbe_cpu_to_node(cpu) ((cpu) >> 1) | ||
100 | |||
101 | #define CBE_COUNT_SUPERVISOR_MODE 0 | ||
102 | #define CBE_COUNT_HYPERVISOR_MODE 1 | ||
103 | #define CBE_COUNT_PROBLEM_MODE 2 | ||
104 | #define CBE_COUNT_ALL_MODES 3 | ||
105 | |||
106 | /* Macros for the pm07_control registers. */ | ||
107 | #define PM07_CTR_INPUT_MUX(x) (((x) & 0x3F) << 26) | ||
108 | #define PM07_CTR_INPUT_CONTROL(x) (((x) & 1) << 25) | ||
109 | #define PM07_CTR_POLARITY(x) (((x) & 1) << 24) | ||
110 | #define PM07_CTR_COUNT_CYCLES(x) (((x) & 1) << 23) | ||
111 | #define PM07_CTR_ENABLE(x) (((x) & 1) << 22) | ||
112 | |||
113 | #endif /* __ASM_CELL_PMU_H__ */ | ||
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index a9a40149a7c..6fe5c9d4ca3 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h | |||
@@ -24,6 +24,8 @@ | |||
24 | #define PPC_FEATURE_ICACHE_SNOOP 0x00002000 | 24 | #define PPC_FEATURE_ICACHE_SNOOP 0x00002000 |
25 | #define PPC_FEATURE_ARCH_2_05 0x00001000 | 25 | #define PPC_FEATURE_ARCH_2_05 0x00001000 |
26 | #define PPC_FEATURE_PA6T 0x00000800 | 26 | #define PPC_FEATURE_PA6T 0x00000800 |
27 | #define PPC_FEATURE_HAS_DFP 0x00000400 | ||
28 | #define PPC_FEATURE_POWER6_EXT 0x00000200 | ||
27 | 29 | ||
28 | #define PPC_FEATURE_TRUE_LE 0x00000002 | 30 | #define PPC_FEATURE_TRUE_LE 0x00000002 |
29 | #define PPC_FEATURE_PPC_LE 0x00000001 | 31 | #define PPC_FEATURE_PPC_LE 0x00000001 |
@@ -45,6 +47,7 @@ enum powerpc_oprofile_type { | |||
45 | PPC_OPROFILE_POWER4 = 2, | 47 | PPC_OPROFILE_POWER4 = 2, |
46 | PPC_OPROFILE_G4 = 3, | 48 | PPC_OPROFILE_G4 = 3, |
47 | PPC_OPROFILE_BOOKE = 4, | 49 | PPC_OPROFILE_BOOKE = 4, |
50 | PPC_OPROFILE_CELL = 5, | ||
48 | }; | 51 | }; |
49 | 52 | ||
50 | struct cpu_spec { | 53 | struct cpu_spec { |
@@ -91,7 +94,7 @@ extern struct cpu_spec *cur_cpu_spec; | |||
91 | 94 | ||
92 | extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; | 95 | extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; |
93 | 96 | ||
94 | extern struct cpu_spec *identify_cpu(unsigned long offset); | 97 | extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr); |
95 | extern void do_feature_fixups(unsigned long value, void *fixup_start, | 98 | extern void do_feature_fixups(unsigned long value, void *fixup_start, |
96 | void *fixup_end); | 99 | void *fixup_end); |
97 | 100 | ||
@@ -148,19 +151,13 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
148 | #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) | 151 | #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) |
149 | #define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) | 152 | #define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) |
150 | #define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000) | 153 | #define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000) |
154 | #define CPU_FTR_SPURR LONG_ASM_CONST(0x0001000000000000) | ||
151 | 155 | ||
152 | #ifndef __ASSEMBLY__ | 156 | #ifndef __ASSEMBLY__ |
153 | 157 | ||
154 | #define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ | 158 | #define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_SLB | \ |
155 | CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ | 159 | CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ |
156 | CPU_FTR_NODSISRALIGN) | 160 | CPU_FTR_NODSISRALIGN | CPU_FTR_16M_PAGE) |
157 | |||
158 | /* iSeries doesn't support large pages */ | ||
159 | #ifdef CONFIG_PPC_ISERIES | ||
160 | #define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) | ||
161 | #else | ||
162 | #define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) | ||
163 | #endif /* CONFIG_PPC_ISERIES */ | ||
164 | 161 | ||
165 | /* We only set the altivec features if the kernel was compiled with altivec | 162 | /* We only set the altivec features if the kernel was compiled with altivec |
166 | * support | 163 | * support |
@@ -311,7 +308,8 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
311 | #define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 308 | #define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ |
312 | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN) | 309 | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN) |
313 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) | 310 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) |
314 | #ifdef __powerpc64__ | 311 | |
312 | /* 64-bit CPUs */ | ||
315 | #define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 313 | #define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ |
316 | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE) | 314 | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE) |
317 | #define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 315 | #define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ |
@@ -332,7 +330,13 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
332 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 330 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
333 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 331 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
334 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 332 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
335 | CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE) | 333 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE) |
334 | #define CPU_FTRS_POWER6X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | ||
335 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | ||
336 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | ||
337 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | ||
338 | CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | \ | ||
339 | CPU_FTR_SPURR | CPU_FTR_REAL_LE) | ||
336 | #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 340 | #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ |
337 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 341 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
338 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 342 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
@@ -343,7 +347,6 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, | |||
343 | CPU_FTR_PURR | CPU_FTR_REAL_LE) | 347 | CPU_FTR_PURR | CPU_FTR_REAL_LE) |
344 | #define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ | 348 | #define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ |
345 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) | 349 | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) |
346 | #endif | ||
347 | 350 | ||
348 | #ifdef __powerpc64__ | 351 | #ifdef __powerpc64__ |
349 | #define CPU_FTRS_POSSIBLE \ | 352 | #define CPU_FTRS_POSSIBLE \ |
diff --git a/include/asm-powerpc/dbdma.h b/include/asm-powerpc/dbdma.h index 8973565f95d..e23f07e73cb 100644 --- a/include/asm-powerpc/dbdma.h +++ b/include/asm-powerpc/dbdma.h | |||
@@ -95,7 +95,13 @@ struct dbdma_cmd { | |||
95 | #define DBDMA_DO_STOP(regs) do { \ | 95 | #define DBDMA_DO_STOP(regs) do { \ |
96 | out_le32(&((regs)->control), (RUN|FLUSH)<<16); \ | 96 | out_le32(&((regs)->control), (RUN|FLUSH)<<16); \ |
97 | while(in_le32(&((regs)->status)) & (ACTIVE|FLUSH)) \ | 97 | while(in_le32(&((regs)->status)) & (ACTIVE|FLUSH)) \ |
98 | ; \ | 98 | ; \ |
99 | } while(0) | ||
100 | |||
101 | #define DBDMA_DO_RESET(regs) do { \ | ||
102 | out_le32(&((regs)->control), (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);\ | ||
103 | while(in_le32(&((regs)->status)) & (RUN)) \ | ||
104 | ; \ | ||
99 | } while(0) | 105 | } while(0) |
100 | 106 | ||
101 | #endif /* _ASM_DBDMA_H_ */ | 107 | #endif /* _ASM_DBDMA_H_ */ |
diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h new file mode 100644 index 00000000000..5dbfca8dde3 --- /dev/null +++ b/include/asm-powerpc/dcr-mmio.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. | ||
3 | * <benh@kernel.crashing.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
13 | * the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #ifndef _ASM_POWERPC_DCR_MMIO_H | ||
21 | #define _ASM_POWERPC_DCR_MMIO_H | ||
22 | #ifdef __KERNEL__ | ||
23 | |||
24 | #include <asm/io.h> | ||
25 | |||
26 | typedef struct { void __iomem *token; unsigned int stride; } dcr_host_t; | ||
27 | |||
28 | #define DCR_MAP_OK(host) ((host).token != NULL) | ||
29 | |||
30 | extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, | ||
31 | unsigned int dcr_c); | ||
32 | extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c); | ||
33 | |||
34 | static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n) | ||
35 | { | ||
36 | return in_be32(host.token + dcr_n * host.stride); | ||
37 | } | ||
38 | |||
39 | static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value) | ||
40 | { | ||
41 | out_be32(host.token + dcr_n * host.stride, value); | ||
42 | } | ||
43 | |||
44 | extern u64 of_translate_dcr_address(struct device_node *dev, | ||
45 | unsigned int dcr_n, | ||
46 | unsigned int *stride); | ||
47 | |||
48 | #endif /* __KERNEL__ */ | ||
49 | #endif /* _ASM_POWERPC_DCR_MMIO_H */ | ||
50 | |||
51 | |||
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h new file mode 100644 index 00000000000..fd4a5f5e33d --- /dev/null +++ b/include/asm-powerpc/dcr-native.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. | ||
3 | * <benh@kernel.crashing.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
13 | * the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #ifndef _ASM_POWERPC_DCR_NATIVE_H | ||
21 | #define _ASM_POWERPC_DCR_NATIVE_H | ||
22 | #ifdef __KERNEL__ | ||
23 | |||
24 | #include <asm/reg.h> | ||
25 | |||
26 | typedef struct {} dcr_host_t; | ||
27 | |||
28 | #define DCR_MAP_OK(host) (1) | ||
29 | |||
30 | #define dcr_map(dev, dcr_n, dcr_c) {} | ||
31 | #define dcr_unmap(host, dcr_n, dcr_c) {} | ||
32 | #define dcr_read(host, dcr_n) mfdcr(dcr_n) | ||
33 | #define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value) | ||
34 | |||
35 | |||
36 | #endif /* __KERNEL__ */ | ||
37 | #endif /* _ASM_POWERPC_DCR_NATIVE_H */ | ||
38 | |||
39 | |||
diff --git a/include/asm-powerpc/dcr.h b/include/asm-powerpc/dcr.h new file mode 100644 index 00000000000..473f2c7fd89 --- /dev/null +++ b/include/asm-powerpc/dcr.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp. | ||
3 | * <benh@kernel.crashing.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
13 | * the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #ifndef _ASM_POWERPC_DCR_H | ||
21 | #define _ASM_POWERPC_DCR_H | ||
22 | #ifdef __KERNEL__ | ||
23 | |||
24 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
25 | #include <asm/dcr-native.h> | ||
26 | #else | ||
27 | #include <asm/dcr-mmio.h> | ||
28 | #endif | ||
29 | |||
30 | /* | ||
31 | * On CONFIG_PPC_MERGE, we have additional helpers to read the DCR | ||
32 | * base from the device-tree | ||
33 | */ | ||
34 | #ifdef CONFIG_PPC_MERGE | ||
35 | extern unsigned int dcr_resource_start(struct device_node *np, | ||
36 | unsigned int index); | ||
37 | extern unsigned int dcr_resource_len(struct device_node *np, | ||
38 | unsigned int index); | ||
39 | #endif /* CONFIG_PPC_MERGE */ | ||
40 | |||
41 | #endif /* __KERNEL__ */ | ||
42 | #endif /* _ASM_POWERPC_DCR_H */ | ||
diff --git a/include/asm-powerpc/device.h b/include/asm-powerpc/device.h index d8f9872b0e2..228ab2a315b 100644 --- a/include/asm-powerpc/device.h +++ b/include/asm-powerpc/device.h | |||
@@ -3,5 +3,22 @@ | |||
3 | * | 3 | * |
4 | * This file is released under the GPLv2 | 4 | * This file is released under the GPLv2 |
5 | */ | 5 | */ |
6 | #include <asm-generic/device.h> | 6 | #ifndef _ASM_POWERPC_DEVICE_H |
7 | #define _ASM_POWERPC_DEVICE_H | ||
7 | 8 | ||
9 | struct dma_mapping_ops; | ||
10 | struct device_node; | ||
11 | |||
12 | struct dev_archdata { | ||
13 | /* Optional pointer to an OF device node */ | ||
14 | struct device_node *of_node; | ||
15 | |||
16 | /* DMA operations on that device */ | ||
17 | struct dma_mapping_ops *dma_ops; | ||
18 | void *dma_data; | ||
19 | |||
20 | /* NUMA node if applicable */ | ||
21 | int numa_node; | ||
22 | }; | ||
23 | |||
24 | #endif /* _ASM_POWERPC_DEVICE_H */ | ||
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h index 2ab9baf78bb..7e38b5fddad 100644 --- a/include/asm-powerpc/dma-mapping.h +++ b/include/asm-powerpc/dma-mapping.h | |||
@@ -44,26 +44,150 @@ extern void __dma_sync_page(struct page *page, unsigned long offset, | |||
44 | #endif /* ! CONFIG_NOT_COHERENT_CACHE */ | 44 | #endif /* ! CONFIG_NOT_COHERENT_CACHE */ |
45 | 45 | ||
46 | #ifdef CONFIG_PPC64 | 46 | #ifdef CONFIG_PPC64 |
47 | /* | ||
48 | * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO | ||
49 | */ | ||
50 | struct dma_mapping_ops { | ||
51 | void * (*alloc_coherent)(struct device *dev, size_t size, | ||
52 | dma_addr_t *dma_handle, gfp_t flag); | ||
53 | void (*free_coherent)(struct device *dev, size_t size, | ||
54 | void *vaddr, dma_addr_t dma_handle); | ||
55 | dma_addr_t (*map_single)(struct device *dev, void *ptr, | ||
56 | size_t size, enum dma_data_direction direction); | ||
57 | void (*unmap_single)(struct device *dev, dma_addr_t dma_addr, | ||
58 | size_t size, enum dma_data_direction direction); | ||
59 | int (*map_sg)(struct device *dev, struct scatterlist *sg, | ||
60 | int nents, enum dma_data_direction direction); | ||
61 | void (*unmap_sg)(struct device *dev, struct scatterlist *sg, | ||
62 | int nents, enum dma_data_direction direction); | ||
63 | int (*dma_supported)(struct device *dev, u64 mask); | ||
64 | int (*dac_dma_supported)(struct device *dev, u64 mask); | ||
65 | int (*set_dma_mask)(struct device *dev, u64 dma_mask); | ||
66 | }; | ||
67 | |||
68 | static inline struct dma_mapping_ops *get_dma_ops(struct device *dev) | ||
69 | { | ||
70 | /* We don't handle the NULL dev case for ISA for now. We could | ||
71 | * do it via an out of line call but it is not needed for now. The | ||
72 | * only ISA DMA device we support is the floppy and we have a hack | ||
73 | * in the floppy driver directly to get a device for us. | ||
74 | */ | ||
75 | if (unlikely(dev == NULL || dev->archdata.dma_ops == NULL)) | ||
76 | return NULL; | ||
77 | return dev->archdata.dma_ops; | ||
78 | } | ||
47 | 79 | ||
48 | extern int dma_supported(struct device *dev, u64 mask); | 80 | static inline int dma_supported(struct device *dev, u64 mask) |
49 | extern int dma_set_mask(struct device *dev, u64 dma_mask); | 81 | { |
50 | extern void *dma_alloc_coherent(struct device *dev, size_t size, | 82 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
51 | dma_addr_t *dma_handle, gfp_t flag); | 83 | |
52 | extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | 84 | if (unlikely(dma_ops == NULL)) |
53 | dma_addr_t dma_handle); | 85 | return 0; |
54 | extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | 86 | if (dma_ops->dma_supported == NULL) |
55 | size_t size, enum dma_data_direction direction); | 87 | return 1; |
56 | extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | 88 | return dma_ops->dma_supported(dev, mask); |
57 | size_t size, enum dma_data_direction direction); | 89 | } |
58 | extern dma_addr_t dma_map_page(struct device *dev, struct page *page, | 90 | |
59 | unsigned long offset, size_t size, | 91 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) |
60 | enum dma_data_direction direction); | 92 | { |
61 | extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | 93 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
62 | size_t size, enum dma_data_direction direction); | 94 | |
63 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 95 | if (unlikely(dma_ops == NULL)) |
64 | enum dma_data_direction direction); | 96 | return -EIO; |
65 | extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | 97 | if (dma_ops->set_dma_mask != NULL) |
66 | int nhwentries, enum dma_data_direction direction); | 98 | return dma_ops->set_dma_mask(dev, dma_mask); |
99 | if (!dev->dma_mask || !dma_supported(dev, *dev->dma_mask)) | ||
100 | return -EIO; | ||
101 | *dev->dma_mask = dma_mask; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, | ||
106 | dma_addr_t *dma_handle, gfp_t flag) | ||
107 | { | ||
108 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
109 | |||
110 | BUG_ON(!dma_ops); | ||
111 | return dma_ops->alloc_coherent(dev, size, dma_handle, flag); | ||
112 | } | ||
113 | |||
114 | static inline void dma_free_coherent(struct device *dev, size_t size, | ||
115 | void *cpu_addr, dma_addr_t dma_handle) | ||
116 | { | ||
117 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
118 | |||
119 | BUG_ON(!dma_ops); | ||
120 | dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); | ||
121 | } | ||
122 | |||
123 | static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | ||
124 | size_t size, | ||
125 | enum dma_data_direction direction) | ||
126 | { | ||
127 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
128 | |||
129 | BUG_ON(!dma_ops); | ||
130 | return dma_ops->map_single(dev, cpu_addr, size, direction); | ||
131 | } | ||
132 | |||
133 | static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
134 | size_t size, | ||
135 | enum dma_data_direction direction) | ||
136 | { | ||
137 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
138 | |||
139 | BUG_ON(!dma_ops); | ||
140 | dma_ops->unmap_single(dev, dma_addr, size, direction); | ||
141 | } | ||
142 | |||
143 | static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
144 | unsigned long offset, size_t size, | ||
145 | enum dma_data_direction direction) | ||
146 | { | ||
147 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
148 | |||
149 | BUG_ON(!dma_ops); | ||
150 | return dma_ops->map_single(dev, page_address(page) + offset, size, | ||
151 | direction); | ||
152 | } | ||
153 | |||
154 | static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
155 | size_t size, | ||
156 | enum dma_data_direction direction) | ||
157 | { | ||
158 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
159 | |||
160 | BUG_ON(!dma_ops); | ||
161 | dma_ops->unmap_single(dev, dma_address, size, direction); | ||
162 | } | ||
163 | |||
164 | static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
165 | int nents, enum dma_data_direction direction) | ||
166 | { | ||
167 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
168 | |||
169 | BUG_ON(!dma_ops); | ||
170 | return dma_ops->map_sg(dev, sg, nents, direction); | ||
171 | } | ||
172 | |||
173 | static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
174 | int nhwentries, | ||
175 | enum dma_data_direction direction) | ||
176 | { | ||
177 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
178 | |||
179 | BUG_ON(!dma_ops); | ||
180 | dma_ops->unmap_sg(dev, sg, nhwentries, direction); | ||
181 | } | ||
182 | |||
183 | |||
184 | /* | ||
185 | * Available generic sets of operations | ||
186 | */ | ||
187 | extern struct dma_mapping_ops dma_iommu_ops; | ||
188 | extern struct dma_mapping_ops dma_direct_ops; | ||
189 | |||
190 | extern unsigned long dma_direct_offset; | ||
67 | 191 | ||
68 | #else /* CONFIG_PPC64 */ | 192 | #else /* CONFIG_PPC64 */ |
69 | 193 | ||
@@ -261,25 +385,5 @@ static inline void dma_cache_sync(void *vaddr, size_t size, | |||
261 | __dma_sync(vaddr, size, (int)direction); | 385 | __dma_sync(vaddr, size, (int)direction); |
262 | } | 386 | } |
263 | 387 | ||
264 | /* | ||
265 | * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO | ||
266 | */ | ||
267 | struct dma_mapping_ops { | ||
268 | void * (*alloc_coherent)(struct device *dev, size_t size, | ||
269 | dma_addr_t *dma_handle, gfp_t flag); | ||
270 | void (*free_coherent)(struct device *dev, size_t size, | ||
271 | void *vaddr, dma_addr_t dma_handle); | ||
272 | dma_addr_t (*map_single)(struct device *dev, void *ptr, | ||
273 | size_t size, enum dma_data_direction direction); | ||
274 | void (*unmap_single)(struct device *dev, dma_addr_t dma_addr, | ||
275 | size_t size, enum dma_data_direction direction); | ||
276 | int (*map_sg)(struct device *dev, struct scatterlist *sg, | ||
277 | int nents, enum dma_data_direction direction); | ||
278 | void (*unmap_sg)(struct device *dev, struct scatterlist *sg, | ||
279 | int nents, enum dma_data_direction direction); | ||
280 | int (*dma_supported)(struct device *dev, u64 mask); | ||
281 | int (*dac_dma_supported)(struct device *dev, u64 mask); | ||
282 | }; | ||
283 | |||
284 | #endif /* __KERNEL__ */ | 388 | #endif /* __KERNEL__ */ |
285 | #endif /* _ASM_DMA_MAPPING_H */ | 389 | #endif /* _ASM_DMA_MAPPING_H */ |
diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h index 6a784396660..b886bec6701 100644 --- a/include/asm-powerpc/eeh.h +++ b/include/asm-powerpc/eeh.h | |||
@@ -120,10 +120,6 @@ static inline u8 eeh_readb(const volatile void __iomem *addr) | |||
120 | return eeh_check_failure(addr, val); | 120 | return eeh_check_failure(addr, val); |
121 | return val; | 121 | return val; |
122 | } | 122 | } |
123 | static inline void eeh_writeb(u8 val, volatile void __iomem *addr) | ||
124 | { | ||
125 | out_8(addr, val); | ||
126 | } | ||
127 | 123 | ||
128 | static inline u16 eeh_readw(const volatile void __iomem *addr) | 124 | static inline u16 eeh_readw(const volatile void __iomem *addr) |
129 | { | 125 | { |
@@ -132,21 +128,6 @@ static inline u16 eeh_readw(const volatile void __iomem *addr) | |||
132 | return eeh_check_failure(addr, val); | 128 | return eeh_check_failure(addr, val); |
133 | return val; | 129 | return val; |
134 | } | 130 | } |
135 | static inline void eeh_writew(u16 val, volatile void __iomem *addr) | ||
136 | { | ||
137 | out_le16(addr, val); | ||
138 | } | ||
139 | static inline u16 eeh_raw_readw(const volatile void __iomem *addr) | ||
140 | { | ||
141 | u16 val = in_be16(addr); | ||
142 | if (EEH_POSSIBLE_ERROR(val, u16)) | ||
143 | return eeh_check_failure(addr, val); | ||
144 | return val; | ||
145 | } | ||
146 | static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) { | ||
147 | volatile u16 __iomem *vaddr = (volatile u16 __iomem *) addr; | ||
148 | out_be16(vaddr, val); | ||
149 | } | ||
150 | 131 | ||
151 | static inline u32 eeh_readl(const volatile void __iomem *addr) | 132 | static inline u32 eeh_readl(const volatile void __iomem *addr) |
152 | { | 133 | { |
@@ -155,205 +136,75 @@ static inline u32 eeh_readl(const volatile void __iomem *addr) | |||
155 | return eeh_check_failure(addr, val); | 136 | return eeh_check_failure(addr, val); |
156 | return val; | 137 | return val; |
157 | } | 138 | } |
158 | static inline void eeh_writel(u32 val, volatile void __iomem *addr) | 139 | |
159 | { | 140 | static inline u64 eeh_readq(const volatile void __iomem *addr) |
160 | out_le32(addr, val); | ||
161 | } | ||
162 | static inline u32 eeh_raw_readl(const volatile void __iomem *addr) | ||
163 | { | 141 | { |
164 | u32 val = in_be32(addr); | 142 | u64 val = in_le64(addr); |
165 | if (EEH_POSSIBLE_ERROR(val, u32)) | 143 | if (EEH_POSSIBLE_ERROR(val, u64)) |
166 | return eeh_check_failure(addr, val); | 144 | return eeh_check_failure(addr, val); |
167 | return val; | 145 | return val; |
168 | } | 146 | } |
169 | static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr) | ||
170 | { | ||
171 | out_be32(addr, val); | ||
172 | } | ||
173 | 147 | ||
174 | static inline u64 eeh_readq(const volatile void __iomem *addr) | 148 | static inline u16 eeh_readw_be(const volatile void __iomem *addr) |
175 | { | 149 | { |
176 | u64 val = in_le64(addr); | 150 | u16 val = in_be16(addr); |
177 | if (EEH_POSSIBLE_ERROR(val, u64)) | 151 | if (EEH_POSSIBLE_ERROR(val, u16)) |
178 | return eeh_check_failure(addr, val); | 152 | return eeh_check_failure(addr, val); |
179 | return val; | 153 | return val; |
180 | } | 154 | } |
181 | static inline void eeh_writeq(u64 val, volatile void __iomem *addr) | 155 | |
156 | static inline u32 eeh_readl_be(const volatile void __iomem *addr) | ||
182 | { | 157 | { |
183 | out_le64(addr, val); | 158 | u32 val = in_be32(addr); |
159 | if (EEH_POSSIBLE_ERROR(val, u32)) | ||
160 | return eeh_check_failure(addr, val); | ||
161 | return val; | ||
184 | } | 162 | } |
185 | static inline u64 eeh_raw_readq(const volatile void __iomem *addr) | 163 | |
164 | static inline u64 eeh_readq_be(const volatile void __iomem *addr) | ||
186 | { | 165 | { |
187 | u64 val = in_be64(addr); | 166 | u64 val = in_be64(addr); |
188 | if (EEH_POSSIBLE_ERROR(val, u64)) | 167 | if (EEH_POSSIBLE_ERROR(val, u64)) |
189 | return eeh_check_failure(addr, val); | 168 | return eeh_check_failure(addr, val); |
190 | return val; | 169 | return val; |
191 | } | 170 | } |
192 | static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr) | ||
193 | { | ||
194 | out_be64(addr, val); | ||
195 | } | ||
196 | |||
197 | #define EEH_CHECK_ALIGN(v,a) \ | ||
198 | ((((unsigned long)(v)) & ((a) - 1)) == 0) | ||
199 | 171 | ||
200 | static inline void eeh_memset_io(volatile void __iomem *addr, int c, | 172 | static inline void eeh_memcpy_fromio(void *dest, const |
201 | unsigned long n) | 173 | volatile void __iomem *src, |
202 | { | ||
203 | void *p = (void __force *)addr; | ||
204 | u32 lc = c; | ||
205 | lc |= lc << 8; | ||
206 | lc |= lc << 16; | ||
207 | |||
208 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
209 | while(n && !EEH_CHECK_ALIGN(p, 4)) { | ||
210 | *((volatile u8 *)p) = c; | ||
211 | p++; | ||
212 | n--; | ||
213 | } | ||
214 | while(n >= 4) { | ||
215 | *((volatile u32 *)p) = lc; | ||
216 | p += 4; | ||
217 | n -= 4; | ||
218 | } | ||
219 | while(n) { | ||
220 | *((volatile u8 *)p) = c; | ||
221 | p++; | ||
222 | n--; | ||
223 | } | ||
224 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
225 | } | ||
226 | static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src, | ||
227 | unsigned long n) | 174 | unsigned long n) |
228 | { | 175 | { |
229 | void *vsrc = (void __force *) src; | 176 | _memcpy_fromio(dest, src, n); |
230 | void *destsave = dest; | ||
231 | unsigned long nsave = n; | ||
232 | |||
233 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
234 | while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) { | ||
235 | *((u8 *)dest) = *((volatile u8 *)vsrc); | ||
236 | __asm__ __volatile__ ("eieio" : : : "memory"); | ||
237 | vsrc++; | ||
238 | dest++; | ||
239 | n--; | ||
240 | } | ||
241 | while(n > 4) { | ||
242 | *((u32 *)dest) = *((volatile u32 *)vsrc); | ||
243 | __asm__ __volatile__ ("eieio" : : : "memory"); | ||
244 | vsrc += 4; | ||
245 | dest += 4; | ||
246 | n -= 4; | ||
247 | } | ||
248 | while(n) { | ||
249 | *((u8 *)dest) = *((volatile u8 *)vsrc); | ||
250 | __asm__ __volatile__ ("eieio" : : : "memory"); | ||
251 | vsrc++; | ||
252 | dest++; | ||
253 | n--; | ||
254 | } | ||
255 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
256 | 177 | ||
257 | /* Look for ffff's here at dest[n]. Assume that at least 4 bytes | 178 | /* Look for ffff's here at dest[n]. Assume that at least 4 bytes |
258 | * were copied. Check all four bytes. | 179 | * were copied. Check all four bytes. |
259 | */ | 180 | */ |
260 | if ((nsave >= 4) && | 181 | if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32)) |
261 | (EEH_POSSIBLE_ERROR((*((u32 *) destsave+nsave-4)), u32))) { | 182 | eeh_check_failure(src, *((u32 *)(dest + n - 4))); |
262 | eeh_check_failure(src, (*((u32 *) destsave+nsave-4))); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, | ||
267 | unsigned long n) | ||
268 | { | ||
269 | void *vdest = (void __force *) dest; | ||
270 | |||
271 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
272 | while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) { | ||
273 | *((volatile u8 *)vdest) = *((u8 *)src); | ||
274 | src++; | ||
275 | vdest++; | ||
276 | n--; | ||
277 | } | ||
278 | while(n > 4) { | ||
279 | *((volatile u32 *)vdest) = *((volatile u32 *)src); | ||
280 | src += 4; | ||
281 | vdest += 4; | ||
282 | n-=4; | ||
283 | } | ||
284 | while(n) { | ||
285 | *((volatile u8 *)vdest) = *((u8 *)src); | ||
286 | src++; | ||
287 | vdest++; | ||
288 | n--; | ||
289 | } | ||
290 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
291 | } | ||
292 | |||
293 | #undef EEH_CHECK_ALIGN | ||
294 | |||
295 | static inline u8 eeh_inb(unsigned long port) | ||
296 | { | ||
297 | u8 val; | ||
298 | val = in_8((u8 __iomem *)(port+pci_io_base)); | ||
299 | if (EEH_POSSIBLE_ERROR(val, u8)) | ||
300 | return eeh_check_failure((void __iomem *)(port), val); | ||
301 | return val; | ||
302 | } | ||
303 | |||
304 | static inline void eeh_outb(u8 val, unsigned long port) | ||
305 | { | ||
306 | out_8((u8 __iomem *)(port+pci_io_base), val); | ||
307 | } | ||
308 | |||
309 | static inline u16 eeh_inw(unsigned long port) | ||
310 | { | ||
311 | u16 val; | ||
312 | val = in_le16((u16 __iomem *)(port+pci_io_base)); | ||
313 | if (EEH_POSSIBLE_ERROR(val, u16)) | ||
314 | return eeh_check_failure((void __iomem *)(port), val); | ||
315 | return val; | ||
316 | } | ||
317 | |||
318 | static inline void eeh_outw(u16 val, unsigned long port) | ||
319 | { | ||
320 | out_le16((u16 __iomem *)(port+pci_io_base), val); | ||
321 | } | ||
322 | |||
323 | static inline u32 eeh_inl(unsigned long port) | ||
324 | { | ||
325 | u32 val; | ||
326 | val = in_le32((u32 __iomem *)(port+pci_io_base)); | ||
327 | if (EEH_POSSIBLE_ERROR(val, u32)) | ||
328 | return eeh_check_failure((void __iomem *)(port), val); | ||
329 | return val; | ||
330 | } | ||
331 | |||
332 | static inline void eeh_outl(u32 val, unsigned long port) | ||
333 | { | ||
334 | out_le32((u32 __iomem *)(port+pci_io_base), val); | ||
335 | } | 183 | } |
336 | 184 | ||
337 | /* in-string eeh macros */ | 185 | /* in-string eeh macros */ |
338 | static inline void eeh_insb(unsigned long port, void * buf, int ns) | 186 | static inline void eeh_readsb(const volatile void __iomem *addr, void * buf, |
187 | int ns) | ||
339 | { | 188 | { |
340 | _insb((u8 __iomem *)(port+pci_io_base), buf, ns); | 189 | _insb(addr, buf, ns); |
341 | if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8)) | 190 | if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8)) |
342 | eeh_check_failure((void __iomem *)(port), *(u8*)buf); | 191 | eeh_check_failure(addr, *(u8*)buf); |
343 | } | 192 | } |
344 | 193 | ||
345 | static inline void eeh_insw_ns(unsigned long port, void * buf, int ns) | 194 | static inline void eeh_readsw(const volatile void __iomem *addr, void * buf, |
195 | int ns) | ||
346 | { | 196 | { |
347 | _insw_ns((u16 __iomem *)(port+pci_io_base), buf, ns); | 197 | _insw(addr, buf, ns); |
348 | if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16)) | 198 | if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16)) |
349 | eeh_check_failure((void __iomem *)(port), *(u16*)buf); | 199 | eeh_check_failure(addr, *(u16*)buf); |
350 | } | 200 | } |
351 | 201 | ||
352 | static inline void eeh_insl_ns(unsigned long port, void * buf, int nl) | 202 | static inline void eeh_readsl(const volatile void __iomem *addr, void * buf, |
203 | int nl) | ||
353 | { | 204 | { |
354 | _insl_ns((u32 __iomem *)(port+pci_io_base), buf, nl); | 205 | _insl(addr, buf, nl); |
355 | if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32)) | 206 | if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32)) |
356 | eeh_check_failure((void __iomem *)(port), *(u32*)buf); | 207 | eeh_check_failure(addr, *(u32*)buf); |
357 | } | 208 | } |
358 | 209 | ||
359 | #endif /* __KERNEL__ */ | 210 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 9a83a987d39..b5436642a10 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h | |||
@@ -411,4 +411,17 @@ do { \ | |||
411 | /* Keep this the last entry. */ | 411 | /* Keep this the last entry. */ |
412 | #define R_PPC64_NUM 107 | 412 | #define R_PPC64_NUM 107 |
413 | 413 | ||
414 | #ifdef CONFIG_SPU_BASE | ||
415 | /* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */ | ||
416 | #define NT_SPU 1 | ||
417 | |||
418 | extern int arch_notes_size(void); | ||
419 | extern void arch_write_notes(struct file *file); | ||
420 | |||
421 | #define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size() | ||
422 | #define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file) | ||
423 | |||
424 | #define ARCH_HAVE_EXTRA_ELF_NOTES | ||
425 | #endif /* CONFIG_PPC_CELL */ | ||
426 | |||
414 | #endif /* _ASM_POWERPC_ELF_H */ | 427 | #endif /* _ASM_POWERPC_ELF_H */ |
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h index fdf9aff7115..98f7b62422c 100644 --- a/include/asm-powerpc/firmware.h +++ b/include/asm-powerpc/firmware.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define FW_FEATURE_SPLPAR ASM_CONST(0x0000000000100000) | 42 | #define FW_FEATURE_SPLPAR ASM_CONST(0x0000000000100000) |
43 | #define FW_FEATURE_ISERIES ASM_CONST(0x0000000000200000) | 43 | #define FW_FEATURE_ISERIES ASM_CONST(0x0000000000200000) |
44 | #define FW_FEATURE_LPAR ASM_CONST(0x0000000000400000) | 44 | #define FW_FEATURE_LPAR ASM_CONST(0x0000000000400000) |
45 | #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) | ||
45 | 46 | ||
46 | #ifndef __ASSEMBLY__ | 47 | #ifndef __ASSEMBLY__ |
47 | 48 | ||
@@ -58,6 +59,10 @@ enum { | |||
58 | FW_FEATURE_PSERIES_ALWAYS = 0, | 59 | FW_FEATURE_PSERIES_ALWAYS = 0, |
59 | FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, | 60 | FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
60 | FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, | 61 | FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
62 | FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, | ||
63 | FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, | ||
64 | FW_FEATURE_NATIVE_POSSIBLE = 0, | ||
65 | FW_FEATURE_NATIVE_ALWAYS = 0, | ||
61 | FW_FEATURE_POSSIBLE = | 66 | FW_FEATURE_POSSIBLE = |
62 | #ifdef CONFIG_PPC_PSERIES | 67 | #ifdef CONFIG_PPC_PSERIES |
63 | FW_FEATURE_PSERIES_POSSIBLE | | 68 | FW_FEATURE_PSERIES_POSSIBLE | |
@@ -65,6 +70,12 @@ enum { | |||
65 | #ifdef CONFIG_PPC_ISERIES | 70 | #ifdef CONFIG_PPC_ISERIES |
66 | FW_FEATURE_ISERIES_POSSIBLE | | 71 | FW_FEATURE_ISERIES_POSSIBLE | |
67 | #endif | 72 | #endif |
73 | #ifdef CONFIG_PPC_PS3 | ||
74 | FW_FEATURE_PS3_POSSIBLE | | ||
75 | #endif | ||
76 | #ifdef CONFIG_PPC_NATIVE | ||
77 | FW_FEATURE_NATIVE_ALWAYS | | ||
78 | #endif | ||
68 | 0, | 79 | 0, |
69 | FW_FEATURE_ALWAYS = | 80 | FW_FEATURE_ALWAYS = |
70 | #ifdef CONFIG_PPC_PSERIES | 81 | #ifdef CONFIG_PPC_PSERIES |
@@ -73,6 +84,12 @@ enum { | |||
73 | #ifdef CONFIG_PPC_ISERIES | 84 | #ifdef CONFIG_PPC_ISERIES |
74 | FW_FEATURE_ISERIES_ALWAYS & | 85 | FW_FEATURE_ISERIES_ALWAYS & |
75 | #endif | 86 | #endif |
87 | #ifdef CONFIG_PPC_PS3 | ||
88 | FW_FEATURE_PS3_ALWAYS & | ||
89 | #endif | ||
90 | #ifdef CONFIG_PPC_NATIVE | ||
91 | FW_FEATURE_NATIVE_ALWAYS & | ||
92 | #endif | ||
76 | FW_FEATURE_POSSIBLE, | 93 | FW_FEATURE_POSSIBLE, |
77 | 94 | ||
78 | #else /* CONFIG_PPC64 */ | 95 | #else /* CONFIG_PPC64 */ |
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h index d40359204ab..d604863d72f 100644 --- a/include/asm-powerpc/hw_irq.h +++ b/include/asm-powerpc/hw_irq.h | |||
@@ -7,16 +7,40 @@ | |||
7 | #ifdef __KERNEL__ | 7 | #ifdef __KERNEL__ |
8 | 8 | ||
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/compiler.h> | ||
10 | #include <asm/ptrace.h> | 11 | #include <asm/ptrace.h> |
11 | #include <asm/processor.h> | 12 | #include <asm/processor.h> |
12 | 13 | ||
13 | extern void timer_interrupt(struct pt_regs *); | 14 | extern void timer_interrupt(struct pt_regs *); |
14 | 15 | ||
15 | #ifdef CONFIG_PPC_ISERIES | 16 | #ifdef CONFIG_PPC64 |
17 | #include <asm/paca.h> | ||
18 | |||
19 | static inline unsigned long local_get_flags(void) | ||
20 | { | ||
21 | unsigned long flags; | ||
22 | |||
23 | __asm__ __volatile__("lbz %0,%1(13)" | ||
24 | : "=r" (flags) | ||
25 | : "i" (offsetof(struct paca_struct, soft_enabled))); | ||
26 | |||
27 | return flags; | ||
28 | } | ||
29 | |||
30 | static inline unsigned long local_irq_disable(void) | ||
31 | { | ||
32 | unsigned long flags, zero; | ||
33 | |||
34 | __asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)" | ||
35 | : "=r" (flags), "=&r" (zero) | ||
36 | : "i" (offsetof(struct paca_struct, soft_enabled)) | ||
37 | : "memory"); | ||
38 | |||
39 | return flags; | ||
40 | } | ||
16 | 41 | ||
17 | extern unsigned long local_get_flags(void); | ||
18 | extern unsigned long local_irq_disable(void); | ||
19 | extern void local_irq_restore(unsigned long); | 42 | extern void local_irq_restore(unsigned long); |
43 | extern void iseries_handle_interrupts(void); | ||
20 | 44 | ||
21 | #define local_irq_enable() local_irq_restore(1) | 45 | #define local_irq_enable() local_irq_restore(1) |
22 | #define local_save_flags(flags) ((flags) = local_get_flags()) | 46 | #define local_save_flags(flags) ((flags) = local_get_flags()) |
@@ -24,17 +48,14 @@ extern void local_irq_restore(unsigned long); | |||
24 | 48 | ||
25 | #define irqs_disabled() (local_get_flags() == 0) | 49 | #define irqs_disabled() (local_get_flags() == 0) |
26 | 50 | ||
51 | #define hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) | ||
52 | #define hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) | ||
53 | |||
27 | #else | 54 | #else |
28 | 55 | ||
29 | #if defined(CONFIG_BOOKE) | 56 | #if defined(CONFIG_BOOKE) |
30 | #define SET_MSR_EE(x) mtmsr(x) | 57 | #define SET_MSR_EE(x) mtmsr(x) |
31 | #define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") | 58 | #define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") |
32 | #elif defined(__powerpc64__) | ||
33 | #define SET_MSR_EE(x) __mtmsrd(x, 1) | ||
34 | #define local_irq_restore(flags) do { \ | ||
35 | __asm__ __volatile__("": : :"memory"); \ | ||
36 | __mtmsrd((flags), 1); \ | ||
37 | } while(0) | ||
38 | #else | 59 | #else |
39 | #define SET_MSR_EE(x) mtmsr(x) | 60 | #define SET_MSR_EE(x) mtmsr(x) |
40 | #define local_irq_restore(flags) mtmsr(flags) | 61 | #define local_irq_restore(flags) mtmsr(flags) |
@@ -81,7 +102,10 @@ static inline void local_irq_save_ptr(unsigned long *flags) | |||
81 | #define local_irq_save(flags) local_irq_save_ptr(&flags) | 102 | #define local_irq_save(flags) local_irq_save_ptr(&flags) |
82 | #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) | 103 | #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) |
83 | 104 | ||
84 | #endif /* CONFIG_PPC_ISERIES */ | 105 | #define hard_irq_enable() local_irq_enable() |
106 | #define hard_irq_disable() local_irq_disable() | ||
107 | |||
108 | #endif /* CONFIG_PPC64 */ | ||
85 | 109 | ||
86 | #define mask_irq(irq) \ | 110 | #define mask_irq(irq) \ |
87 | ({ \ | 111 | ({ \ |
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h index 3493429b70f..66112114b8c 100644 --- a/include/asm-powerpc/ibmebus.h +++ b/include/asm-powerpc/ibmebus.h | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/mod_devicetable.h> | 44 | #include <linux/mod_devicetable.h> |
45 | #include <asm/of_device.h> | 45 | #include <asm/of_device.h> |
46 | 46 | ||
47 | extern struct dma_mapping_ops ibmebus_dma_ops; | ||
48 | extern struct bus_type ibmebus_bus_type; | 47 | extern struct bus_type ibmebus_bus_type; |
49 | 48 | ||
50 | struct ibmebus_dev { | 49 | struct ibmebus_dev { |
diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h index c8390f9485d..0f66f0f82c3 100644 --- a/include/asm-powerpc/ide.h +++ b/include/asm-powerpc/ide.h | |||
@@ -22,10 +22,10 @@ | |||
22 | #endif | 22 | #endif |
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | #define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c)) | 25 | #define __ide_mm_insw(p, a, c) readsw((void __iomem *)(p), (a), (c)) |
26 | #define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c)) | 26 | #define __ide_mm_insl(p, a, c) readsl((void __iomem *)(p), (a), (c)) |
27 | #define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c)) | 27 | #define __ide_mm_outsw(p, a, c) writesw((void __iomem *)(p), (a), (c)) |
28 | #define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c)) | 28 | #define __ide_mm_outsl(p, a, c) writesl((void __iomem *)(p), (a), (c)) |
29 | 29 | ||
30 | #ifndef __powerpc64__ | 30 | #ifndef __powerpc64__ |
31 | #include <linux/hdreg.h> | 31 | #include <linux/hdreg.h> |
diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h index ce12f85fff9..9fdd0491f6a 100644 --- a/include/asm-powerpc/immap_qe.h +++ b/include/asm-powerpc/immap_qe.h | |||
@@ -136,22 +136,7 @@ struct qe_timers { | |||
136 | 136 | ||
137 | /* BRG */ | 137 | /* BRG */ |
138 | struct qe_brg { | 138 | struct qe_brg { |
139 | __be32 brgc1; /* BRG1 configuration register */ | 139 | __be32 brgc[16]; /* BRG configuration registers */ |
140 | __be32 brgc2; /* BRG2 configuration register */ | ||
141 | __be32 brgc3; /* BRG3 configuration register */ | ||
142 | __be32 brgc4; /* BRG4 configuration register */ | ||
143 | __be32 brgc5; /* BRG5 configuration register */ | ||
144 | __be32 brgc6; /* BRG6 configuration register */ | ||
145 | __be32 brgc7; /* BRG7 configuration register */ | ||
146 | __be32 brgc8; /* BRG8 configuration register */ | ||
147 | __be32 brgc9; /* BRG9 configuration register */ | ||
148 | __be32 brgc10; /* BRG10 configuration register */ | ||
149 | __be32 brgc11; /* BRG11 configuration register */ | ||
150 | __be32 brgc12; /* BRG12 configuration register */ | ||
151 | __be32 brgc13; /* BRG13 configuration register */ | ||
152 | __be32 brgc14; /* BRG14 configuration register */ | ||
153 | __be32 brgc15; /* BRG15 configuration register */ | ||
154 | __be32 brgc16; /* BRG16 configuration register */ | ||
155 | u8 res0[0x40]; | 140 | u8 res0[0x40]; |
156 | } __attribute__ ((packed)); | 141 | } __attribute__ ((packed)); |
157 | 142 | ||
diff --git a/include/asm-powerpc/io-defs.h b/include/asm-powerpc/io-defs.h new file mode 100644 index 00000000000..03691ab6921 --- /dev/null +++ b/include/asm-powerpc/io-defs.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* This file is meant to be include multiple times by other headers */ | ||
2 | |||
3 | DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr)) | ||
4 | DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr)) | ||
5 | DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr)) | ||
6 | DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr)) | ||
7 | DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr)) | ||
8 | DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr)) | ||
9 | DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr)) | ||
10 | DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr)) | ||
11 | DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr)) | ||
12 | DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr)) | ||
13 | |||
14 | #ifdef __powerpc64__ | ||
15 | DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr)) | ||
16 | DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr)) | ||
17 | DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr)) | ||
18 | DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr)) | ||
19 | #endif /* __powerpc64__ */ | ||
20 | |||
21 | DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port)) | ||
22 | DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port)) | ||
23 | DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port)) | ||
24 | DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port)) | ||
25 | DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port)) | ||
26 | DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port)) | ||
27 | |||
28 | DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c), \ | ||
29 | (a, b, c)) | ||
30 | DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c), \ | ||
31 | (a, b, c)) | ||
32 | DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c), \ | ||
33 | (a, b, c)) | ||
34 | DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c), \ | ||
35 | (a, b, c)) | ||
36 | DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c), \ | ||
37 | (a, b, c)) | ||
38 | DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c), \ | ||
39 | (a, b, c)) | ||
40 | |||
41 | DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c), \ | ||
42 | (p, b, c)) | ||
43 | DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c), \ | ||
44 | (p, b, c)) | ||
45 | DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c), \ | ||
46 | (p, b, c)) | ||
47 | DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c), \ | ||
48 | (p, b, c)) | ||
49 | DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c), \ | ||
50 | (p, b, c)) | ||
51 | DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c), \ | ||
52 | (p, b, c)) | ||
53 | |||
54 | DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n), \ | ||
55 | (a, c, n)) | ||
56 | DEF_PCI_AC_NORET(memcpy_fromio,(void *d,const PCI_IO_ADDR s,unsigned long n), \ | ||
57 | (d, s, n)) | ||
58 | DEF_PCI_AC_NORET(memcpy_toio,(PCI_IO_ADDR d,const void *s,unsigned long n), \ | ||
59 | (d, s, n)) | ||
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index c2c5f14b5f5..1cd532379c3 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h | |||
@@ -13,154 +13,530 @@ | |||
13 | extern int check_legacy_ioport(unsigned long base_port); | 13 | extern int check_legacy_ioport(unsigned long base_port); |
14 | #define PNPBIOS_BASE 0xf000 /* only relevant for PReP */ | 14 | #define PNPBIOS_BASE 0xf000 /* only relevant for PReP */ |
15 | 15 | ||
16 | #ifndef CONFIG_PPC64 | ||
17 | #include <asm-ppc/io.h> | ||
18 | #else | ||
19 | |||
20 | #include <linux/compiler.h> | 16 | #include <linux/compiler.h> |
21 | #include <asm/page.h> | 17 | #include <asm/page.h> |
22 | #include <asm/byteorder.h> | 18 | #include <asm/byteorder.h> |
23 | #include <asm/paca.h> | ||
24 | #include <asm/synch.h> | 19 | #include <asm/synch.h> |
25 | #include <asm/delay.h> | 20 | #include <asm/delay.h> |
21 | #include <asm/mmu.h> | ||
26 | 22 | ||
27 | #include <asm-generic/iomap.h> | 23 | #include <asm-generic/iomap.h> |
28 | 24 | ||
25 | #ifdef CONFIG_PPC64 | ||
26 | #include <asm/paca.h> | ||
27 | #endif | ||
28 | |||
29 | #define SIO_CONFIG_RA 0x398 | 29 | #define SIO_CONFIG_RA 0x398 |
30 | #define SIO_CONFIG_RD 0x399 | 30 | #define SIO_CONFIG_RD 0x399 |
31 | 31 | ||
32 | #define SLOW_DOWN_IO | 32 | #define SLOW_DOWN_IO |
33 | 33 | ||
34 | /* 32 bits uses slightly different variables for the various IO | ||
35 | * bases. Most of this file only uses _IO_BASE though which we | ||
36 | * define properly based on the platform | ||
37 | */ | ||
38 | #ifndef CONFIG_PCI | ||
39 | #define _IO_BASE 0 | ||
40 | #define _ISA_MEM_BASE 0 | ||
41 | #define PCI_DRAM_OFFSET 0 | ||
42 | #elif defined(CONFIG_PPC32) | ||
43 | #define _IO_BASE isa_io_base | ||
44 | #define _ISA_MEM_BASE isa_mem_base | ||
45 | #define PCI_DRAM_OFFSET pci_dram_offset | ||
46 | #else | ||
47 | #define _IO_BASE pci_io_base | ||
48 | #define _ISA_MEM_BASE 0 | ||
49 | #define PCI_DRAM_OFFSET 0 | ||
50 | #endif | ||
51 | |||
34 | extern unsigned long isa_io_base; | 52 | extern unsigned long isa_io_base; |
53 | extern unsigned long isa_mem_base; | ||
35 | extern unsigned long pci_io_base; | 54 | extern unsigned long pci_io_base; |
55 | extern unsigned long pci_dram_offset; | ||
56 | |||
57 | #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_INDIRECT_IO) | ||
58 | #error CONFIG_PPC_INDIRECT_IO is not yet supported on 32 bits | ||
59 | #endif | ||
60 | |||
61 | /* | ||
62 | * | ||
63 | * Low level MMIO accessors | ||
64 | * | ||
65 | * This provides the non-bus specific accessors to MMIO. Those are PowerPC | ||
66 | * specific and thus shouldn't be used in generic code. The accessors | ||
67 | * provided here are: | ||
68 | * | ||
69 | * in_8, in_le16, in_be16, in_le32, in_be32, in_le64, in_be64 | ||
70 | * out_8, out_le16, out_be16, out_le32, out_be32, out_le64, out_be64 | ||
71 | * _insb, _insw_ns, _insl_ns, _outsb, _outsw_ns, _outsl_ns | ||
72 | * | ||
73 | * Those operate directly on a kernel virtual address. Note that the prototype | ||
74 | * for the out_* accessors has the arguments in opposite order from the usual | ||
75 | * linux PCI accessors. Unlike those, they take the address first and the value | ||
76 | * next. | ||
77 | * | ||
78 | * Note: I might drop the _ns suffix on the stream operations soon as it is | ||
79 | * simply normal for stream operations to not swap in the first place. | ||
80 | * | ||
81 | */ | ||
82 | |||
83 | #ifdef CONFIG_PPC64 | ||
84 | #define IO_SET_SYNC_FLAG() do { get_paca()->io_sync = 1; } while(0) | ||
85 | #else | ||
86 | #define IO_SET_SYNC_FLAG() | ||
87 | #endif | ||
88 | |||
89 | #define DEF_MMIO_IN(name, type, insn) \ | ||
90 | static inline type name(const volatile type __iomem *addr) \ | ||
91 | { \ | ||
92 | type ret; \ | ||
93 | __asm__ __volatile__("sync;" insn ";twi 0,%0,0;isync" \ | ||
94 | : "=r" (ret) : "r" (addr), "m" (*addr)); \ | ||
95 | return ret; \ | ||
96 | } | ||
97 | |||
98 | #define DEF_MMIO_OUT(name, type, insn) \ | ||
99 | static inline void name(volatile type __iomem *addr, type val) \ | ||
100 | { \ | ||
101 | __asm__ __volatile__("sync;" insn \ | ||
102 | : "=m" (*addr) : "r" (val), "r" (addr)); \ | ||
103 | IO_SET_SYNC_FLAG(); \ | ||
104 | } | ||
105 | |||
106 | |||
107 | #define DEF_MMIO_IN_BE(name, size, insn) \ | ||
108 | DEF_MMIO_IN(name, u##size, __stringify(insn)"%U2%X2 %0,%2") | ||
109 | #define DEF_MMIO_IN_LE(name, size, insn) \ | ||
110 | DEF_MMIO_IN(name, u##size, __stringify(insn)" %0,0,%1") | ||
111 | |||
112 | #define DEF_MMIO_OUT_BE(name, size, insn) \ | ||
113 | DEF_MMIO_OUT(name, u##size, __stringify(insn)"%U0%X0 %1,%0") | ||
114 | #define DEF_MMIO_OUT_LE(name, size, insn) \ | ||
115 | DEF_MMIO_OUT(name, u##size, __stringify(insn)" %1,0,%2") | ||
116 | |||
117 | DEF_MMIO_IN_BE(in_8, 8, lbz); | ||
118 | DEF_MMIO_IN_BE(in_be16, 16, lhz); | ||
119 | DEF_MMIO_IN_BE(in_be32, 32, lwz); | ||
120 | DEF_MMIO_IN_LE(in_le16, 16, lhbrx); | ||
121 | DEF_MMIO_IN_LE(in_le32, 32, lwbrx); | ||
122 | |||
123 | DEF_MMIO_OUT_BE(out_8, 8, stb); | ||
124 | DEF_MMIO_OUT_BE(out_be16, 16, sth); | ||
125 | DEF_MMIO_OUT_BE(out_be32, 32, stw); | ||
126 | DEF_MMIO_OUT_LE(out_le16, 16, sthbrx); | ||
127 | DEF_MMIO_OUT_LE(out_le32, 32, stwbrx); | ||
128 | |||
129 | #ifdef __powerpc64__ | ||
130 | DEF_MMIO_OUT_BE(out_be64, 64, std); | ||
131 | DEF_MMIO_IN_BE(in_be64, 64, ld); | ||
132 | |||
133 | /* There is no asm instructions for 64 bits reverse loads and stores */ | ||
134 | static inline u64 in_le64(const volatile u64 __iomem *addr) | ||
135 | { | ||
136 | return le64_to_cpu(in_be64(addr)); | ||
137 | } | ||
138 | |||
139 | static inline void out_le64(volatile u64 __iomem *addr, u64 val) | ||
140 | { | ||
141 | out_be64(addr, cpu_to_le64(val)); | ||
142 | } | ||
143 | #endif /* __powerpc64__ */ | ||
144 | |||
145 | /* | ||
146 | * Low level IO stream instructions are defined out of line for now | ||
147 | */ | ||
148 | extern void _insb(const volatile u8 __iomem *addr, void *buf, long count); | ||
149 | extern void _outsb(volatile u8 __iomem *addr,const void *buf,long count); | ||
150 | extern void _insw_ns(const volatile u16 __iomem *addr, void *buf, long count); | ||
151 | extern void _outsw_ns(volatile u16 __iomem *addr, const void *buf, long count); | ||
152 | extern void _insl_ns(const volatile u32 __iomem *addr, void *buf, long count); | ||
153 | extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count); | ||
154 | |||
155 | /* The _ns naming is historical and will be removed. For now, just #define | ||
156 | * the non _ns equivalent names | ||
157 | */ | ||
158 | #define _insw _insw_ns | ||
159 | #define _insl _insl_ns | ||
160 | #define _outsw _outsw_ns | ||
161 | #define _outsl _outsl_ns | ||
162 | |||
163 | |||
164 | /* | ||
165 | * memset_io, memcpy_toio, memcpy_fromio base implementations are out of line | ||
166 | */ | ||
167 | |||
168 | extern void _memset_io(volatile void __iomem *addr, int c, unsigned long n); | ||
169 | extern void _memcpy_fromio(void *dest, const volatile void __iomem *src, | ||
170 | unsigned long n); | ||
171 | extern void _memcpy_toio(volatile void __iomem *dest, const void *src, | ||
172 | unsigned long n); | ||
173 | |||
174 | /* | ||
175 | * | ||
176 | * PCI and standard ISA accessors | ||
177 | * | ||
178 | * Those are globally defined linux accessors for devices on PCI or ISA | ||
179 | * busses. They follow the Linux defined semantics. The current implementation | ||
180 | * for PowerPC is as close as possible to the x86 version of these, and thus | ||
181 | * provides fairly heavy weight barriers for the non-raw versions | ||
182 | * | ||
183 | * In addition, they support a hook mechanism when CONFIG_PPC_INDIRECT_IO | ||
184 | * allowing the platform to provide its own implementation of some or all | ||
185 | * of the accessors. | ||
186 | */ | ||
187 | |||
188 | /* | ||
189 | * Include the EEH definitions when EEH is enabled only so they don't get | ||
190 | * in the way when building for 32 bits | ||
191 | */ | ||
192 | #ifdef CONFIG_EEH | ||
193 | #include <asm/eeh.h> | ||
194 | #endif | ||
195 | |||
196 | /* Shortcut to the MMIO argument pointer */ | ||
197 | #define PCI_IO_ADDR volatile void __iomem * | ||
198 | |||
199 | /* Indirect IO address tokens: | ||
200 | * | ||
201 | * When CONFIG_PPC_INDIRECT_IO is set, the platform can provide hooks | ||
202 | * on all IOs. (Note that this is all 64 bits only for now) | ||
203 | * | ||
204 | * To help platforms who may need to differenciate MMIO addresses in | ||
205 | * their hooks, a bitfield is reserved for use by the platform near the | ||
206 | * top of MMIO addresses (not PIO, those have to cope the hard way). | ||
207 | * | ||
208 | * This bit field is 12 bits and is at the top of the IO virtual | ||
209 | * addresses PCI_IO_INDIRECT_TOKEN_MASK. | ||
210 | * | ||
211 | * The kernel virtual space is thus: | ||
212 | * | ||
213 | * 0xD000000000000000 : vmalloc | ||
214 | * 0xD000080000000000 : PCI PHB IO space | ||
215 | * 0xD000080080000000 : ioremap | ||
216 | * 0xD0000fffffffffff : end of ioremap region | ||
217 | * | ||
218 | * Since the top 4 bits are reserved as the region ID, we use thus | ||
219 | * the next 12 bits and keep 4 bits available for the future if the | ||
220 | * virtual address space is ever to be extended. | ||
221 | * | ||
222 | * The direct IO mapping operations will then mask off those bits | ||
223 | * before doing the actual access, though that only happen when | ||
224 | * CONFIG_PPC_INDIRECT_IO is set, thus be careful when you use that | ||
225 | * mechanism | ||
226 | */ | ||
227 | |||
228 | #ifdef CONFIG_PPC_INDIRECT_IO | ||
229 | #define PCI_IO_IND_TOKEN_MASK 0x0fff000000000000ul | ||
230 | #define PCI_IO_IND_TOKEN_SHIFT 48 | ||
231 | #define PCI_FIX_ADDR(addr) \ | ||
232 | ((PCI_IO_ADDR)(((unsigned long)(addr)) & ~PCI_IO_IND_TOKEN_MASK)) | ||
233 | #define PCI_GET_ADDR_TOKEN(addr) \ | ||
234 | (((unsigned long)(addr) & PCI_IO_IND_TOKEN_MASK) >> \ | ||
235 | PCI_IO_IND_TOKEN_SHIFT) | ||
236 | #define PCI_SET_ADDR_TOKEN(addr, token) \ | ||
237 | do { \ | ||
238 | unsigned long __a = (unsigned long)(addr); \ | ||
239 | __a &= ~PCI_IO_IND_TOKEN_MASK; \ | ||
240 | __a |= ((unsigned long)(token)) << PCI_IO_IND_TOKEN_SHIFT; \ | ||
241 | (addr) = (void __iomem *)__a; \ | ||
242 | } while(0) | ||
243 | #else | ||
244 | #define PCI_FIX_ADDR(addr) (addr) | ||
245 | #endif | ||
36 | 246 | ||
37 | #ifdef CONFIG_PPC_ISERIES | 247 | |
38 | 248 | /* | |
39 | extern int in_8(const volatile unsigned char __iomem *addr); | 249 | * Non ordered and non-swapping "raw" accessors |
40 | extern void out_8(volatile unsigned char __iomem *addr, int val); | 250 | */ |
41 | extern int in_le16(const volatile unsigned short __iomem *addr); | ||
42 | extern int in_be16(const volatile unsigned short __iomem *addr); | ||
43 | extern void out_le16(volatile unsigned short __iomem *addr, int val); | ||
44 | extern void out_be16(volatile unsigned short __iomem *addr, int val); | ||
45 | extern unsigned in_le32(const volatile unsigned __iomem *addr); | ||
46 | extern unsigned in_be32(const volatile unsigned __iomem *addr); | ||
47 | extern void out_le32(volatile unsigned __iomem *addr, int val); | ||
48 | extern void out_be32(volatile unsigned __iomem *addr, int val); | ||
49 | extern unsigned long in_le64(const volatile unsigned long __iomem *addr); | ||
50 | extern unsigned long in_be64(const volatile unsigned long __iomem *addr); | ||
51 | extern void out_le64(volatile unsigned long __iomem *addr, unsigned long val); | ||
52 | extern void out_be64(volatile unsigned long __iomem *addr, unsigned long val); | ||
53 | |||
54 | extern unsigned char __raw_readb(const volatile void __iomem *addr); | ||
55 | extern unsigned short __raw_readw(const volatile void __iomem *addr); | ||
56 | extern unsigned int __raw_readl(const volatile void __iomem *addr); | ||
57 | extern unsigned long __raw_readq(const volatile void __iomem *addr); | ||
58 | extern void __raw_writeb(unsigned char v, volatile void __iomem *addr); | ||
59 | extern void __raw_writew(unsigned short v, volatile void __iomem *addr); | ||
60 | extern void __raw_writel(unsigned int v, volatile void __iomem *addr); | ||
61 | extern void __raw_writeq(unsigned long v, volatile void __iomem *addr); | ||
62 | |||
63 | extern void memset_io(volatile void __iomem *addr, int c, unsigned long n); | ||
64 | extern void memcpy_fromio(void *dest, const volatile void __iomem *src, | ||
65 | unsigned long n); | ||
66 | extern void memcpy_toio(volatile void __iomem *dest, const void *src, | ||
67 | unsigned long n); | ||
68 | |||
69 | #else /* CONFIG_PPC_ISERIES */ | ||
70 | |||
71 | #define in_8(addr) __in_8((addr)) | ||
72 | #define out_8(addr, val) __out_8((addr), (val)) | ||
73 | #define in_le16(addr) __in_le16((addr)) | ||
74 | #define in_be16(addr) __in_be16((addr)) | ||
75 | #define out_le16(addr, val) __out_le16((addr), (val)) | ||
76 | #define out_be16(addr, val) __out_be16((addr), (val)) | ||
77 | #define in_le32(addr) __in_le32((addr)) | ||
78 | #define in_be32(addr) __in_be32((addr)) | ||
79 | #define out_le32(addr, val) __out_le32((addr), (val)) | ||
80 | #define out_be32(addr, val) __out_be32((addr), (val)) | ||
81 | #define in_le64(addr) __in_le64((addr)) | ||
82 | #define in_be64(addr) __in_be64((addr)) | ||
83 | #define out_le64(addr, val) __out_le64((addr), (val)) | ||
84 | #define out_be64(addr, val) __out_be64((addr), (val)) | ||
85 | 251 | ||
86 | static inline unsigned char __raw_readb(const volatile void __iomem *addr) | 252 | static inline unsigned char __raw_readb(const volatile void __iomem *addr) |
87 | { | 253 | { |
88 | return *(volatile unsigned char __force *)addr; | 254 | return *(volatile unsigned char __force *)PCI_FIX_ADDR(addr); |
89 | } | 255 | } |
90 | static inline unsigned short __raw_readw(const volatile void __iomem *addr) | 256 | static inline unsigned short __raw_readw(const volatile void __iomem *addr) |
91 | { | 257 | { |
92 | return *(volatile unsigned short __force *)addr; | 258 | return *(volatile unsigned short __force *)PCI_FIX_ADDR(addr); |
93 | } | 259 | } |
94 | static inline unsigned int __raw_readl(const volatile void __iomem *addr) | 260 | static inline unsigned int __raw_readl(const volatile void __iomem *addr) |
95 | { | 261 | { |
96 | return *(volatile unsigned int __force *)addr; | 262 | return *(volatile unsigned int __force *)PCI_FIX_ADDR(addr); |
97 | } | ||
98 | static inline unsigned long __raw_readq(const volatile void __iomem *addr) | ||
99 | { | ||
100 | return *(volatile unsigned long __force *)addr; | ||
101 | } | 263 | } |
102 | static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr) | 264 | static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr) |
103 | { | 265 | { |
104 | *(volatile unsigned char __force *)addr = v; | 266 | *(volatile unsigned char __force *)PCI_FIX_ADDR(addr) = v; |
105 | } | 267 | } |
106 | static inline void __raw_writew(unsigned short v, volatile void __iomem *addr) | 268 | static inline void __raw_writew(unsigned short v, volatile void __iomem *addr) |
107 | { | 269 | { |
108 | *(volatile unsigned short __force *)addr = v; | 270 | *(volatile unsigned short __force *)PCI_FIX_ADDR(addr) = v; |
109 | } | 271 | } |
110 | static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) | 272 | static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) |
111 | { | 273 | { |
112 | *(volatile unsigned int __force *)addr = v; | 274 | *(volatile unsigned int __force *)PCI_FIX_ADDR(addr) = v; |
275 | } | ||
276 | |||
277 | #ifdef __powerpc64__ | ||
278 | static inline unsigned long __raw_readq(const volatile void __iomem *addr) | ||
279 | { | ||
280 | return *(volatile unsigned long __force *)PCI_FIX_ADDR(addr); | ||
113 | } | 281 | } |
114 | static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) | 282 | static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) |
115 | { | 283 | { |
116 | *(volatile unsigned long __force *)addr = v; | 284 | *(volatile unsigned long __force *)PCI_FIX_ADDR(addr) = v; |
285 | } | ||
286 | #endif /* __powerpc64__ */ | ||
287 | |||
288 | /* | ||
289 | * | ||
290 | * PCI PIO and MMIO accessors. | ||
291 | * | ||
292 | * | ||
293 | * On 32 bits, PIO operations have a recovery mechanism in case they trigger | ||
294 | * machine checks (which they occasionally do when probing non existing | ||
295 | * IO ports on some platforms, like PowerMac and 8xx). | ||
296 | * I always found it to be of dubious reliability and I am tempted to get | ||
297 | * rid of it one of these days. So if you think it's important to keep it, | ||
298 | * please voice up asap. We never had it for 64 bits and I do not intend | ||
299 | * to port it over | ||
300 | */ | ||
301 | |||
302 | #ifdef CONFIG_PPC32 | ||
303 | |||
304 | #define __do_in_asm(name, op) \ | ||
305 | static inline unsigned int name(unsigned int port) \ | ||
306 | { \ | ||
307 | unsigned int x; \ | ||
308 | __asm__ __volatile__( \ | ||
309 | "sync\n" \ | ||
310 | "0:" op " %0,0,%1\n" \ | ||
311 | "1: twi 0,%0,0\n" \ | ||
312 | "2: isync\n" \ | ||
313 | "3: nop\n" \ | ||
314 | "4:\n" \ | ||
315 | ".section .fixup,\"ax\"\n" \ | ||
316 | "5: li %0,-1\n" \ | ||
317 | " b 4b\n" \ | ||
318 | ".previous\n" \ | ||
319 | ".section __ex_table,\"a\"\n" \ | ||
320 | " .align 2\n" \ | ||
321 | " .long 0b,5b\n" \ | ||
322 | " .long 1b,5b\n" \ | ||
323 | " .long 2b,5b\n" \ | ||
324 | " .long 3b,5b\n" \ | ||
325 | ".previous" \ | ||
326 | : "=&r" (x) \ | ||
327 | : "r" (port + _IO_BASE)); \ | ||
328 | return x; \ | ||
329 | } | ||
330 | |||
331 | #define __do_out_asm(name, op) \ | ||
332 | static inline void name(unsigned int val, unsigned int port) \ | ||
333 | { \ | ||
334 | __asm__ __volatile__( \ | ||
335 | "sync\n" \ | ||
336 | "0:" op " %0,0,%1\n" \ | ||
337 | "1: sync\n" \ | ||
338 | "2:\n" \ | ||
339 | ".section __ex_table,\"a\"\n" \ | ||
340 | " .align 2\n" \ | ||
341 | " .long 0b,2b\n" \ | ||
342 | " .long 1b,2b\n" \ | ||
343 | ".previous" \ | ||
344 | : : "r" (val), "r" (port + _IO_BASE)); \ | ||
345 | } | ||
346 | |||
347 | __do_in_asm(_rec_inb, "lbzx") | ||
348 | __do_in_asm(_rec_inw, "lhbrx") | ||
349 | __do_in_asm(_rec_inl, "lwbrx") | ||
350 | __do_out_asm(_rec_outb, "stbx") | ||
351 | __do_out_asm(_rec_outw, "sthbrx") | ||
352 | __do_out_asm(_rec_outl, "stwbrx") | ||
353 | |||
354 | #endif /* CONFIG_PPC32 */ | ||
355 | |||
356 | /* The "__do_*" operations below provide the actual "base" implementation | ||
357 | * for each of the defined acccessor. Some of them use the out_* functions | ||
358 | * directly, some of them still use EEH, though we might change that in the | ||
359 | * future. Those macros below provide the necessary argument swapping and | ||
360 | * handling of the IO base for PIO. | ||
361 | * | ||
362 | * They are themselves used by the macros that define the actual accessors | ||
363 | * and can be used by the hooks if any. | ||
364 | * | ||
365 | * Note that PIO operations are always defined in terms of their corresonding | ||
366 | * MMIO operations. That allows platforms like iSeries who want to modify the | ||
367 | * behaviour of both to only hook on the MMIO version and get both. It's also | ||
368 | * possible to hook directly at the toplevel PIO operation if they have to | ||
369 | * be handled differently | ||
370 | */ | ||
371 | #define __do_writeb(val, addr) out_8(PCI_FIX_ADDR(addr), val) | ||
372 | #define __do_writew(val, addr) out_le16(PCI_FIX_ADDR(addr), val) | ||
373 | #define __do_writel(val, addr) out_le32(PCI_FIX_ADDR(addr), val) | ||
374 | #define __do_writeq(val, addr) out_le64(PCI_FIX_ADDR(addr), val) | ||
375 | #define __do_writew_be(val, addr) out_be16(PCI_FIX_ADDR(addr), val) | ||
376 | #define __do_writel_be(val, addr) out_be32(PCI_FIX_ADDR(addr), val) | ||
377 | #define __do_writeq_be(val, addr) out_be64(PCI_FIX_ADDR(addr), val) | ||
378 | |||
379 | #ifdef CONFIG_EEH | ||
380 | #define __do_readb(addr) eeh_readb(PCI_FIX_ADDR(addr)) | ||
381 | #define __do_readw(addr) eeh_readw(PCI_FIX_ADDR(addr)) | ||
382 | #define __do_readl(addr) eeh_readl(PCI_FIX_ADDR(addr)) | ||
383 | #define __do_readq(addr) eeh_readq(PCI_FIX_ADDR(addr)) | ||
384 | #define __do_readw_be(addr) eeh_readw_be(PCI_FIX_ADDR(addr)) | ||
385 | #define __do_readl_be(addr) eeh_readl_be(PCI_FIX_ADDR(addr)) | ||
386 | #define __do_readq_be(addr) eeh_readq_be(PCI_FIX_ADDR(addr)) | ||
387 | #else /* CONFIG_EEH */ | ||
388 | #define __do_readb(addr) in_8(PCI_FIX_ADDR(addr)) | ||
389 | #define __do_readw(addr) in_le16(PCI_FIX_ADDR(addr)) | ||
390 | #define __do_readl(addr) in_le32(PCI_FIX_ADDR(addr)) | ||
391 | #define __do_readq(addr) in_le64(PCI_FIX_ADDR(addr)) | ||
392 | #define __do_readw_be(addr) in_be16(PCI_FIX_ADDR(addr)) | ||
393 | #define __do_readl_be(addr) in_be32(PCI_FIX_ADDR(addr)) | ||
394 | #define __do_readq_be(addr) in_be64(PCI_FIX_ADDR(addr)) | ||
395 | #endif /* !defined(CONFIG_EEH) */ | ||
396 | |||
397 | #ifdef CONFIG_PPC32 | ||
398 | #define __do_outb(val, port) _rec_outb(val, port) | ||
399 | #define __do_outw(val, port) _rec_outw(val, port) | ||
400 | #define __do_outl(val, port) _rec_outl(val, port) | ||
401 | #define __do_inb(port) _rec_inb(port) | ||
402 | #define __do_inw(port) _rec_inw(port) | ||
403 | #define __do_inl(port) _rec_inl(port) | ||
404 | #else /* CONFIG_PPC32 */ | ||
405 | #define __do_outb(val, port) writeb(val,(PCI_IO_ADDR)_IO_BASE+port); | ||
406 | #define __do_outw(val, port) writew(val,(PCI_IO_ADDR)_IO_BASE+port); | ||
407 | #define __do_outl(val, port) writel(val,(PCI_IO_ADDR)_IO_BASE+port); | ||
408 | #define __do_inb(port) readb((PCI_IO_ADDR)_IO_BASE + port); | ||
409 | #define __do_inw(port) readw((PCI_IO_ADDR)_IO_BASE + port); | ||
410 | #define __do_inl(port) readl((PCI_IO_ADDR)_IO_BASE + port); | ||
411 | #endif /* !CONFIG_PPC32 */ | ||
412 | |||
413 | #ifdef CONFIG_EEH | ||
414 | #define __do_readsb(a, b, n) eeh_readsb(PCI_FIX_ADDR(a), (b), (n)) | ||
415 | #define __do_readsw(a, b, n) eeh_readsw(PCI_FIX_ADDR(a), (b), (n)) | ||
416 | #define __do_readsl(a, b, n) eeh_readsl(PCI_FIX_ADDR(a), (b), (n)) | ||
417 | #else /* CONFIG_EEH */ | ||
418 | #define __do_readsb(a, b, n) _insb(PCI_FIX_ADDR(a), (b), (n)) | ||
419 | #define __do_readsw(a, b, n) _insw(PCI_FIX_ADDR(a), (b), (n)) | ||
420 | #define __do_readsl(a, b, n) _insl(PCI_FIX_ADDR(a), (b), (n)) | ||
421 | #endif /* !CONFIG_EEH */ | ||
422 | #define __do_writesb(a, b, n) _outsb(PCI_FIX_ADDR(a),(b),(n)) | ||
423 | #define __do_writesw(a, b, n) _outsw(PCI_FIX_ADDR(a),(b),(n)) | ||
424 | #define __do_writesl(a, b, n) _outsl(PCI_FIX_ADDR(a),(b),(n)) | ||
425 | |||
426 | #define __do_insb(p, b, n) readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n)) | ||
427 | #define __do_insw(p, b, n) readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n)) | ||
428 | #define __do_insl(p, b, n) readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n)) | ||
429 | #define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n)) | ||
430 | #define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n)) | ||
431 | #define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n)) | ||
432 | |||
433 | #define __do_memset_io(addr, c, n) \ | ||
434 | _memset_io(PCI_FIX_ADDR(addr), c, n) | ||
435 | #define __do_memcpy_toio(dst, src, n) \ | ||
436 | _memcpy_toio(PCI_FIX_ADDR(dst), src, n) | ||
437 | |||
438 | #ifdef CONFIG_EEH | ||
439 | #define __do_memcpy_fromio(dst, src, n) \ | ||
440 | eeh_memcpy_fromio(dst, PCI_FIX_ADDR(src), n) | ||
441 | #else /* CONFIG_EEH */ | ||
442 | #define __do_memcpy_fromio(dst, src, n) \ | ||
443 | _memcpy_fromio(dst,PCI_FIX_ADDR(src),n) | ||
444 | #endif /* !CONFIG_EEH */ | ||
445 | |||
446 | #ifdef CONFIG_PPC_INDIRECT_IO | ||
447 | #define DEF_PCI_HOOK(x) x | ||
448 | #else | ||
449 | #define DEF_PCI_HOOK(x) NULL | ||
450 | #endif | ||
451 | |||
452 | /* Structure containing all the hooks */ | ||
453 | extern struct ppc_pci_io { | ||
454 | |||
455 | #define DEF_PCI_AC_RET(name, ret, at, al) ret (*name) at; | ||
456 | #define DEF_PCI_AC_NORET(name, at, al) void (*name) at; | ||
457 | |||
458 | #include <asm/io-defs.h> | ||
459 | |||
460 | #undef DEF_PCI_AC_RET | ||
461 | #undef DEF_PCI_AC_NORET | ||
462 | |||
463 | } ppc_pci_io; | ||
464 | |||
465 | /* The inline wrappers */ | ||
466 | #define DEF_PCI_AC_RET(name, ret, at, al) \ | ||
467 | static inline ret name at \ | ||
468 | { \ | ||
469 | if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \ | ||
470 | return ppc_pci_io.name al; \ | ||
471 | return __do_##name al; \ | ||
472 | } | ||
473 | |||
474 | #define DEF_PCI_AC_NORET(name, at, al) \ | ||
475 | static inline void name at \ | ||
476 | { \ | ||
477 | if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \ | ||
478 | ppc_pci_io.name al; \ | ||
479 | else \ | ||
480 | __do_##name al; \ | ||
117 | } | 481 | } |
118 | #define memset_io(a,b,c) eeh_memset_io((a),(b),(c)) | ||
119 | #define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(b),(c)) | ||
120 | #define memcpy_toio(a,b,c) eeh_memcpy_toio((a),(b),(c)) | ||
121 | 482 | ||
122 | #endif /* CONFIG_PPC_ISERIES */ | 483 | #include <asm/io-defs.h> |
484 | |||
485 | #undef DEF_PCI_AC_RET | ||
486 | #undef DEF_PCI_AC_NORET | ||
487 | |||
488 | /* Some drivers check for the presence of readq & writeq with | ||
489 | * a #ifdef, so we make them happy here. | ||
490 | */ | ||
491 | #ifdef __powerpc64__ | ||
492 | #define readq readq | ||
493 | #define writeq writeq | ||
494 | #endif | ||
495 | |||
496 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
497 | |||
498 | #define dma_cache_inv(_start,_size) \ | ||
499 | invalidate_dcache_range(_start, (_start + _size)) | ||
500 | #define dma_cache_wback(_start,_size) \ | ||
501 | clean_dcache_range(_start, (_start + _size)) | ||
502 | #define dma_cache_wback_inv(_start,_size) \ | ||
503 | flush_dcache_range(_start, (_start + _size)) | ||
504 | |||
505 | #else /* CONFIG_NOT_COHERENT_CACHE */ | ||
506 | |||
507 | #define dma_cache_inv(_start,_size) do { } while (0) | ||
508 | #define dma_cache_wback(_start,_size) do { } while (0) | ||
509 | #define dma_cache_wback_inv(_start,_size) do { } while (0) | ||
510 | |||
511 | #endif /* !CONFIG_NOT_COHERENT_CACHE */ | ||
123 | 512 | ||
124 | /* | 513 | /* |
125 | * The insw/outsw/insl/outsl macros don't do byte-swapping. | 514 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem |
126 | * They are only used in practice for transferring buffers which | 515 | * access |
127 | * are arrays of bytes, and byte-swapping is not appropriate in | 516 | */ |
128 | * that case. - paulus */ | 517 | #define xlate_dev_mem_ptr(p) __va(p) |
129 | #define insb(port, buf, ns) eeh_insb((port), (buf), (ns)) | 518 | |
130 | #define insw(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) | 519 | /* |
131 | #define insl(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) | 520 | * Convert a virtual cached pointer to an uncached pointer |
132 | 521 | */ | |
133 | #define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns)) | 522 | #define xlate_dev_kmem_ptr(p) p |
134 | #define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) | ||
135 | #define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) | ||
136 | |||
137 | #define readb(addr) eeh_readb(addr) | ||
138 | #define readw(addr) eeh_readw(addr) | ||
139 | #define readl(addr) eeh_readl(addr) | ||
140 | #define readq(addr) eeh_readq(addr) | ||
141 | #define writeb(data, addr) eeh_writeb((data), (addr)) | ||
142 | #define writew(data, addr) eeh_writew((data), (addr)) | ||
143 | #define writel(data, addr) eeh_writel((data), (addr)) | ||
144 | #define writeq(data, addr) eeh_writeq((data), (addr)) | ||
145 | #define inb(port) eeh_inb((unsigned long)port) | ||
146 | #define outb(val, port) eeh_outb(val, (unsigned long)port) | ||
147 | #define inw(port) eeh_inw((unsigned long)port) | ||
148 | #define outw(val, port) eeh_outw(val, (unsigned long)port) | ||
149 | #define inl(port) eeh_inl((unsigned long)port) | ||
150 | #define outl(val, port) eeh_outl(val, (unsigned long)port) | ||
151 | 523 | ||
524 | /* | ||
525 | * We don't do relaxed operations yet, at least not with this semantic | ||
526 | */ | ||
152 | #define readb_relaxed(addr) readb(addr) | 527 | #define readb_relaxed(addr) readb(addr) |
153 | #define readw_relaxed(addr) readw(addr) | 528 | #define readw_relaxed(addr) readw(addr) |
154 | #define readl_relaxed(addr) readl(addr) | 529 | #define readl_relaxed(addr) readl(addr) |
155 | #define readq_relaxed(addr) readq(addr) | 530 | #define readq_relaxed(addr) readq(addr) |
156 | 531 | ||
157 | extern void _insb(volatile u8 __iomem *port, void *buf, long count); | 532 | #ifdef CONFIG_PPC32 |
158 | extern void _outsb(volatile u8 __iomem *port, const void *buf, long count); | 533 | #define mmiowb() |
159 | extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count); | 534 | #else |
160 | extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count); | 535 | /* |
161 | extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count); | 536 | * Enforce synchronisation of stores vs. spin_unlock |
162 | extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count); | 537 | * (this does it explicitely, though our implementation of spin_unlock |
163 | 538 | * does it implicitely too) | |
539 | */ | ||
164 | static inline void mmiowb(void) | 540 | static inline void mmiowb(void) |
165 | { | 541 | { |
166 | unsigned long tmp; | 542 | unsigned long tmp; |
@@ -169,6 +545,24 @@ static inline void mmiowb(void) | |||
169 | : "=&r" (tmp) : "i" (offsetof(struct paca_struct, io_sync)) | 545 | : "=&r" (tmp) : "i" (offsetof(struct paca_struct, io_sync)) |
170 | : "memory"); | 546 | : "memory"); |
171 | } | 547 | } |
548 | #endif /* !CONFIG_PPC32 */ | ||
549 | |||
550 | static inline void iosync(void) | ||
551 | { | ||
552 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
553 | } | ||
554 | |||
555 | /* Enforce in-order execution of data I/O. | ||
556 | * No distinction between read/write on PPC; use eieio for all three. | ||
557 | * Those are fairly week though. They don't provide a barrier between | ||
558 | * MMIO and cacheable storage nor do they provide a barrier vs. locks, | ||
559 | * they only provide barriers between 2 __raw MMIO operations and | ||
560 | * possibly break write combining. | ||
561 | */ | ||
562 | #define iobarrier_rw() eieio() | ||
563 | #define iobarrier_r() eieio() | ||
564 | #define iobarrier_w() eieio() | ||
565 | |||
172 | 566 | ||
173 | /* | 567 | /* |
174 | * output pause versions need a delay at least for the | 568 | * output pause versions need a delay at least for the |
@@ -185,11 +579,6 @@ static inline void mmiowb(void) | |||
185 | #define IO_SPACE_LIMIT ~(0UL) | 579 | #define IO_SPACE_LIMIT ~(0UL) |
186 | 580 | ||
187 | 581 | ||
188 | extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr, | ||
189 | unsigned long size, unsigned long flags); | ||
190 | extern void __iomem *__ioremap(unsigned long address, unsigned long size, | ||
191 | unsigned long flags); | ||
192 | |||
193 | /** | 582 | /** |
194 | * ioremap - map bus memory into CPU space | 583 | * ioremap - map bus memory into CPU space |
195 | * @address: bus address of the memory | 584 | * @address: bus address of the memory |
@@ -200,14 +589,77 @@ extern void __iomem *__ioremap(unsigned long address, unsigned long size, | |||
200 | * writew/writel functions and the other mmio helpers. The returned | 589 | * writew/writel functions and the other mmio helpers. The returned |
201 | * address is not guaranteed to be usable directly as a virtual | 590 | * address is not guaranteed to be usable directly as a virtual |
202 | * address. | 591 | * address. |
592 | * | ||
593 | * We provide a few variations of it: | ||
594 | * | ||
595 | * * ioremap is the standard one and provides non-cacheable guarded mappings | ||
596 | * and can be hooked by the platform via ppc_md | ||
597 | * | ||
598 | * * ioremap_flags allows to specify the page flags as an argument and can | ||
599 | * also be hooked by the platform via ppc_md | ||
600 | * | ||
601 | * * ioremap_nocache is identical to ioremap | ||
602 | * | ||
603 | * * iounmap undoes such a mapping and can be hooked | ||
604 | * | ||
605 | * * __ioremap_explicit (and the pending __iounmap_explicit) are low level | ||
606 | * functions to create hand-made mappings for use only by the PCI code | ||
607 | * and cannot currently be hooked. | ||
608 | * | ||
609 | * * __ioremap is the low level implementation used by ioremap and | ||
610 | * ioremap_flags and cannot be hooked (but can be used by a hook on one | ||
611 | * of the previous ones) | ||
612 | * | ||
613 | * * __iounmap, is the low level implementation used by iounmap and cannot | ||
614 | * be hooked (but can be used by a hook on iounmap) | ||
615 | * | ||
203 | */ | 616 | */ |
204 | extern void __iomem *ioremap(unsigned long address, unsigned long size); | 617 | extern void __iomem *ioremap(phys_addr_t address, unsigned long size); |
205 | 618 | extern void __iomem *ioremap_flags(phys_addr_t address, unsigned long size, | |
619 | unsigned long flags); | ||
206 | #define ioremap_nocache(addr, size) ioremap((addr), (size)) | 620 | #define ioremap_nocache(addr, size) ioremap((addr), (size)) |
207 | extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size); | ||
208 | extern void iounmap(volatile void __iomem *addr); | 621 | extern void iounmap(volatile void __iomem *addr); |
622 | |||
623 | extern void __iomem *__ioremap(phys_addr_t, unsigned long size, | ||
624 | unsigned long flags); | ||
625 | extern void __iounmap(volatile void __iomem *addr); | ||
626 | |||
627 | extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr, | ||
628 | unsigned long size, unsigned long flags); | ||
629 | extern int __iounmap_explicit(volatile void __iomem *start, | ||
630 | unsigned long size); | ||
631 | |||
209 | extern void __iomem * reserve_phb_iospace(unsigned long size); | 632 | extern void __iomem * reserve_phb_iospace(unsigned long size); |
210 | 633 | ||
634 | /* Those are more 32 bits only functions */ | ||
635 | extern unsigned long iopa(unsigned long addr); | ||
636 | extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; | ||
637 | extern void io_block_mapping(unsigned long virt, phys_addr_t phys, | ||
638 | unsigned int size, int flags); | ||
639 | |||
640 | |||
641 | /* | ||
642 | * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation | ||
643 | * which needs some additional definitions here. They basically allow PIO | ||
644 | * space overall to be 1GB. This will work as long as we never try to use | ||
645 | * iomap to map MMIO below 1GB which should be fine on ppc64 | ||
646 | */ | ||
647 | #define HAVE_ARCH_PIO_SIZE 1 | ||
648 | #define PIO_OFFSET 0x00000000UL | ||
649 | #define PIO_MASK 0x3fffffffUL | ||
650 | #define PIO_RESERVED 0x40000000UL | ||
651 | |||
652 | #define mmio_read16be(addr) readw_be(addr) | ||
653 | #define mmio_read32be(addr) readl_be(addr) | ||
654 | #define mmio_write16be(val, addr) writew_be(val, addr) | ||
655 | #define mmio_write32be(val, addr) writel_be(val, addr) | ||
656 | #define mmio_insb(addr, dst, count) readsb(addr, dst, count) | ||
657 | #define mmio_insw(addr, dst, count) readsw(addr, dst, count) | ||
658 | #define mmio_insl(addr, dst, count) readsl(addr, dst, count) | ||
659 | #define mmio_outsb(addr, src, count) writesb(addr, src, count) | ||
660 | #define mmio_outsw(addr, src, count) writesw(addr, src, count) | ||
661 | #define mmio_outsl(addr, src, count) writesl(addr, src, count) | ||
662 | |||
211 | /** | 663 | /** |
212 | * virt_to_phys - map virtual addresses to physical | 664 | * virt_to_phys - map virtual addresses to physical |
213 | * @address: address to remap | 665 | * @address: address to remap |
@@ -254,178 +706,33 @@ static inline void * phys_to_virt(unsigned long address) | |||
254 | */ | 706 | */ |
255 | #define BIO_VMERGE_BOUNDARY 0 | 707 | #define BIO_VMERGE_BOUNDARY 0 |
256 | 708 | ||
257 | static inline void iosync(void) | ||
258 | { | ||
259 | __asm__ __volatile__ ("sync" : : : "memory"); | ||
260 | } | ||
261 | |||
262 | /* Enforce in-order execution of data I/O. | ||
263 | * No distinction between read/write on PPC; use eieio for all three. | ||
264 | */ | ||
265 | #define iobarrier_rw() eieio() | ||
266 | #define iobarrier_r() eieio() | ||
267 | #define iobarrier_w() eieio() | ||
268 | |||
269 | /* | 709 | /* |
270 | * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. | 710 | * 32 bits still uses virt_to_bus() for it's implementation of DMA |
271 | * These routines do not perform EEH-related I/O address translation, | 711 | * mappings se we have to keep it defined here. We also have some old |
272 | * and should not be used directly by device drivers. Use inb/readb | 712 | * drivers (shame shame shame) that use bus_to_virt() and haven't been |
273 | * instead. | 713 | * fixed yet so I need to define it here. |
274 | */ | 714 | */ |
275 | static inline int __in_8(const volatile unsigned char __iomem *addr) | 715 | #ifdef CONFIG_PPC32 |
276 | { | ||
277 | int ret; | ||
278 | 716 | ||
279 | __asm__ __volatile__("sync; lbz%U1%X1 %0,%1; twi 0,%0,0; isync" | 717 | static inline unsigned long virt_to_bus(volatile void * address) |
280 | : "=r" (ret) : "m" (*addr)); | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static inline void __out_8(volatile unsigned char __iomem *addr, int val) | ||
285 | { | ||
286 | __asm__ __volatile__("sync; stb%U0%X0 %1,%0" | ||
287 | : "=m" (*addr) : "r" (val)); | ||
288 | get_paca()->io_sync = 1; | ||
289 | } | ||
290 | |||
291 | static inline int __in_le16(const volatile unsigned short __iomem *addr) | ||
292 | { | 718 | { |
293 | int ret; | 719 | if (address == NULL) |
294 | 720 | return 0; | |
295 | __asm__ __volatile__("sync; lhbrx %0,0,%1; twi 0,%0,0; isync" | 721 | return __pa(address) + PCI_DRAM_OFFSET; |
296 | : "=r" (ret) : "r" (addr), "m" (*addr)); | ||
297 | return ret; | ||
298 | } | 722 | } |
299 | 723 | ||
300 | static inline int __in_be16(const volatile unsigned short __iomem *addr) | 724 | static inline void * bus_to_virt(unsigned long address) |
301 | { | 725 | { |
302 | int ret; | 726 | if (address == 0) |
303 | 727 | return NULL; | |
304 | __asm__ __volatile__("sync; lhz%U1%X1 %0,%1; twi 0,%0,0; isync" | 728 | return __va(address - PCI_DRAM_OFFSET); |
305 | : "=r" (ret) : "m" (*addr)); | ||
306 | return ret; | ||
307 | } | 729 | } |
308 | 730 | ||
309 | static inline void __out_le16(volatile unsigned short __iomem *addr, int val) | 731 | #define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET) |
310 | { | ||
311 | __asm__ __volatile__("sync; sthbrx %1,0,%2" | ||
312 | : "=m" (*addr) : "r" (val), "r" (addr)); | ||
313 | get_paca()->io_sync = 1; | ||
314 | } | ||
315 | |||
316 | static inline void __out_be16(volatile unsigned short __iomem *addr, int val) | ||
317 | { | ||
318 | __asm__ __volatile__("sync; sth%U0%X0 %1,%0" | ||
319 | : "=m" (*addr) : "r" (val)); | ||
320 | get_paca()->io_sync = 1; | ||
321 | } | ||
322 | |||
323 | static inline unsigned __in_le32(const volatile unsigned __iomem *addr) | ||
324 | { | ||
325 | unsigned ret; | ||
326 | |||
327 | __asm__ __volatile__("sync; lwbrx %0,0,%1; twi 0,%0,0; isync" | ||
328 | : "=r" (ret) : "r" (addr), "m" (*addr)); | ||
329 | return ret; | ||
330 | } | ||
331 | 732 | ||
332 | static inline unsigned __in_be32(const volatile unsigned __iomem *addr) | 733 | #endif /* CONFIG_PPC32 */ |
333 | { | ||
334 | unsigned ret; | ||
335 | |||
336 | __asm__ __volatile__("sync; lwz%U1%X1 %0,%1; twi 0,%0,0; isync" | ||
337 | : "=r" (ret) : "m" (*addr)); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static inline void __out_le32(volatile unsigned __iomem *addr, int val) | ||
342 | { | ||
343 | __asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) | ||
344 | : "r" (val), "r" (addr)); | ||
345 | get_paca()->io_sync = 1; | ||
346 | } | ||
347 | |||
348 | static inline void __out_be32(volatile unsigned __iomem *addr, int val) | ||
349 | { | ||
350 | __asm__ __volatile__("sync; stw%U0%X0 %1,%0" | ||
351 | : "=m" (*addr) : "r" (val)); | ||
352 | get_paca()->io_sync = 1; | ||
353 | } | ||
354 | |||
355 | static inline unsigned long __in_le64(const volatile unsigned long __iomem *addr) | ||
356 | { | ||
357 | unsigned long tmp, ret; | ||
358 | |||
359 | __asm__ __volatile__( | ||
360 | "sync\n" | ||
361 | "ld %1,0(%2)\n" | ||
362 | "twi 0,%1,0\n" | ||
363 | "isync\n" | ||
364 | "rldimi %0,%1,5*8,1*8\n" | ||
365 | "rldimi %0,%1,3*8,2*8\n" | ||
366 | "rldimi %0,%1,1*8,3*8\n" | ||
367 | "rldimi %0,%1,7*8,4*8\n" | ||
368 | "rldicl %1,%1,32,0\n" | ||
369 | "rlwimi %0,%1,8,8,31\n" | ||
370 | "rlwimi %0,%1,24,16,23\n" | ||
371 | : "=r" (ret) , "=r" (tmp) : "b" (addr) , "m" (*addr)); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static inline unsigned long __in_be64(const volatile unsigned long __iomem *addr) | ||
376 | { | ||
377 | unsigned long ret; | ||
378 | 734 | ||
379 | __asm__ __volatile__("sync; ld%U1%X1 %0,%1; twi 0,%0,0; isync" | ||
380 | : "=r" (ret) : "m" (*addr)); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static inline void __out_le64(volatile unsigned long __iomem *addr, unsigned long val) | ||
385 | { | ||
386 | unsigned long tmp; | ||
387 | |||
388 | __asm__ __volatile__( | ||
389 | "rldimi %0,%1,5*8,1*8\n" | ||
390 | "rldimi %0,%1,3*8,2*8\n" | ||
391 | "rldimi %0,%1,1*8,3*8\n" | ||
392 | "rldimi %0,%1,7*8,4*8\n" | ||
393 | "rldicl %1,%1,32,0\n" | ||
394 | "rlwimi %0,%1,8,8,31\n" | ||
395 | "rlwimi %0,%1,24,16,23\n" | ||
396 | "sync\n" | ||
397 | "std %0,0(%3)" | ||
398 | : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr)); | ||
399 | get_paca()->io_sync = 1; | ||
400 | } | ||
401 | |||
402 | static inline void __out_be64(volatile unsigned long __iomem *addr, unsigned long val) | ||
403 | { | ||
404 | __asm__ __volatile__("sync; std%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); | ||
405 | get_paca()->io_sync = 1; | ||
406 | } | ||
407 | |||
408 | #include <asm/eeh.h> | ||
409 | |||
410 | /* Nothing to do */ | ||
411 | |||
412 | #define dma_cache_inv(_start,_size) do { } while (0) | ||
413 | #define dma_cache_wback(_start,_size) do { } while (0) | ||
414 | #define dma_cache_wback_inv(_start,_size) do { } while (0) | ||
415 | |||
416 | |||
417 | /* | ||
418 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | ||
419 | * access | ||
420 | */ | ||
421 | #define xlate_dev_mem_ptr(p) __va(p) | ||
422 | |||
423 | /* | ||
424 | * Convert a virtual cached pointer to an uncached pointer | ||
425 | */ | ||
426 | #define xlate_dev_kmem_ptr(p) p | ||
427 | 735 | ||
428 | #endif /* __KERNEL__ */ | 736 | #endif /* __KERNEL__ */ |
429 | 737 | ||
430 | #endif /* CONFIG_PPC64 */ | ||
431 | #endif /* _ASM_POWERPC_IO_H */ | 738 | #endif /* _ASM_POWERPC_IO_H */ |
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 39fad685ffa..f85dbd30555 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h | |||
@@ -34,7 +34,9 @@ | |||
34 | #define IOMMU_PAGE_MASK (~((1 << IOMMU_PAGE_SHIFT) - 1)) | 34 | #define IOMMU_PAGE_MASK (~((1 << IOMMU_PAGE_SHIFT) - 1)) |
35 | #define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE) | 35 | #define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE) |
36 | 36 | ||
37 | #ifndef __ASSEMBLY__ | 37 | /* Boot time flags */ |
38 | extern int iommu_is_off; | ||
39 | extern int iommu_force_on; | ||
38 | 40 | ||
39 | /* Pure 2^n version of get_order */ | 41 | /* Pure 2^n version of get_order */ |
40 | static __inline__ __attribute_const__ int get_iommu_order(unsigned long size) | 42 | static __inline__ __attribute_const__ int get_iommu_order(unsigned long size) |
@@ -42,8 +44,6 @@ static __inline__ __attribute_const__ int get_iommu_order(unsigned long size) | |||
42 | return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1; | 44 | return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1; |
43 | } | 45 | } |
44 | 46 | ||
45 | #endif /* __ASSEMBLY__ */ | ||
46 | |||
47 | 47 | ||
48 | /* | 48 | /* |
49 | * IOMAP_MAX_ORDER defines the largest contiguous block | 49 | * IOMAP_MAX_ORDER defines the largest contiguous block |
@@ -70,39 +70,31 @@ struct iommu_table { | |||
70 | struct scatterlist; | 70 | struct scatterlist; |
71 | struct device_node; | 71 | struct device_node; |
72 | 72 | ||
73 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
74 | |||
75 | /* Walks all buses and creates iommu tables */ | ||
76 | extern void iommu_setup_pSeries(void); | ||
77 | extern void iommu_setup_dart(void); | ||
78 | |||
79 | /* Frees table for an individual device node */ | 73 | /* Frees table for an individual device node */ |
80 | extern void iommu_free_table(struct device_node *dn); | 74 | extern void iommu_free_table(struct device_node *dn); |
81 | 75 | ||
82 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
83 | |||
84 | /* Initializes an iommu_table based in values set in the passed-in | 76 | /* Initializes an iommu_table based in values set in the passed-in |
85 | * structure | 77 | * structure |
86 | */ | 78 | */ |
87 | extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, | 79 | extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, |
88 | int nid); | 80 | int nid); |
89 | 81 | ||
90 | extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | 82 | extern int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, |
91 | struct scatterlist *sglist, int nelems, unsigned long mask, | 83 | int nelems, unsigned long mask, |
92 | enum dma_data_direction direction); | 84 | enum dma_data_direction direction); |
93 | extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, | 85 | extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, |
94 | int nelems, enum dma_data_direction direction); | 86 | int nelems, enum dma_data_direction direction); |
95 | 87 | ||
96 | extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | 88 | extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, |
97 | dma_addr_t *dma_handle, unsigned long mask, | 89 | dma_addr_t *dma_handle, unsigned long mask, |
98 | gfp_t flag, int node); | 90 | gfp_t flag, int node); |
99 | extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, | 91 | extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, |
100 | void *vaddr, dma_addr_t dma_handle); | 92 | void *vaddr, dma_addr_t dma_handle); |
101 | extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, | 93 | extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, |
102 | size_t size, unsigned long mask, | 94 | size_t size, unsigned long mask, |
103 | enum dma_data_direction direction); | 95 | enum dma_data_direction direction); |
104 | extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, | 96 | extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, |
105 | size_t size, enum dma_data_direction direction); | 97 | size_t size, enum dma_data_direction direction); |
106 | 98 | ||
107 | extern void iommu_init_early_pSeries(void); | 99 | extern void iommu_init_early_pSeries(void); |
108 | extern void iommu_init_early_iSeries(void); | 100 | extern void iommu_init_early_iSeries(void); |
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index f960f5346f4..46476e9a494 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h | |||
@@ -135,6 +135,10 @@ struct irq_map_entry { | |||
135 | 135 | ||
136 | extern struct irq_map_entry irq_map[NR_IRQS]; | 136 | extern struct irq_map_entry irq_map[NR_IRQS]; |
137 | 137 | ||
138 | static inline irq_hw_number_t virq_to_hw(unsigned int virq) | ||
139 | { | ||
140 | return irq_map[virq].hwirq; | ||
141 | } | ||
138 | 142 | ||
139 | /** | 143 | /** |
140 | * irq_alloc_host - Allocate a new irq_host data structure | 144 | * irq_alloc_host - Allocate a new irq_host data structure |
diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h index 0edbfe10cb3..6e323a13ac3 100644 --- a/include/asm-powerpc/iseries/iommu.h +++ b/include/asm-powerpc/iseries/iommu.h | |||
@@ -21,11 +21,13 @@ | |||
21 | * Boston, MA 02111-1307 USA | 21 | * Boston, MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | struct pci_dev; | ||
24 | struct device_node; | 25 | struct device_node; |
25 | struct iommu_table; | 26 | struct iommu_table; |
26 | 27 | ||
27 | /* Creates table for an individual device node */ | 28 | /* Creates table for an individual device node */ |
28 | extern void iommu_devnode_init_iSeries(struct device_node *dn); | 29 | extern void iommu_devnode_init_iSeries(struct pci_dev *pdev, |
30 | struct device_node *dn); | ||
29 | 31 | ||
30 | /* Get table parameters from HV */ | 32 | /* Get table parameters from HV */ |
31 | extern void iommu_table_getparms_iSeries(unsigned long busno, | 33 | extern void iommu_table_getparms_iSeries(unsigned long busno, |
diff --git a/include/asm-powerpc/lv1call.h b/include/asm-powerpc/lv1call.h new file mode 100644 index 00000000000..f733beeea63 --- /dev/null +++ b/include/asm-powerpc/lv1call.h | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * PS3 hvcall interface. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * Copyright 2003, 2004 (c) MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #if !defined(_ASM_POWERPC_LV1CALL_H) | ||
23 | #define _ASM_POWERPC_LV1CALL_H | ||
24 | |||
25 | #if !defined(__ASSEMBLY__) | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | |||
29 | /* lv1 call declaration macros */ | ||
30 | |||
31 | #define LV1_1_IN_ARG_DECL u64 in_1 | ||
32 | #define LV1_2_IN_ARG_DECL LV1_1_IN_ARG_DECL, u64 in_2 | ||
33 | #define LV1_3_IN_ARG_DECL LV1_2_IN_ARG_DECL, u64 in_3 | ||
34 | #define LV1_4_IN_ARG_DECL LV1_3_IN_ARG_DECL, u64 in_4 | ||
35 | #define LV1_5_IN_ARG_DECL LV1_4_IN_ARG_DECL, u64 in_5 | ||
36 | #define LV1_6_IN_ARG_DECL LV1_5_IN_ARG_DECL, u64 in_6 | ||
37 | #define LV1_7_IN_ARG_DECL LV1_6_IN_ARG_DECL, u64 in_7 | ||
38 | #define LV1_8_IN_ARG_DECL LV1_7_IN_ARG_DECL, u64 in_8 | ||
39 | #define LV1_1_OUT_ARG_DECL u64 *out_1 | ||
40 | #define LV1_2_OUT_ARG_DECL LV1_1_OUT_ARG_DECL, u64 *out_2 | ||
41 | #define LV1_3_OUT_ARG_DECL LV1_2_OUT_ARG_DECL, u64 *out_3 | ||
42 | #define LV1_4_OUT_ARG_DECL LV1_3_OUT_ARG_DECL, u64 *out_4 | ||
43 | #define LV1_5_OUT_ARG_DECL LV1_4_OUT_ARG_DECL, u64 *out_5 | ||
44 | #define LV1_6_OUT_ARG_DECL LV1_5_OUT_ARG_DECL, u64 *out_6 | ||
45 | #define LV1_7_OUT_ARG_DECL LV1_6_OUT_ARG_DECL, u64 *out_7 | ||
46 | |||
47 | #define LV1_0_IN_0_OUT_ARG_DECL void | ||
48 | #define LV1_1_IN_0_OUT_ARG_DECL LV1_1_IN_ARG_DECL | ||
49 | #define LV1_2_IN_0_OUT_ARG_DECL LV1_2_IN_ARG_DECL | ||
50 | #define LV1_3_IN_0_OUT_ARG_DECL LV1_3_IN_ARG_DECL | ||
51 | #define LV1_4_IN_0_OUT_ARG_DECL LV1_4_IN_ARG_DECL | ||
52 | #define LV1_5_IN_0_OUT_ARG_DECL LV1_5_IN_ARG_DECL | ||
53 | #define LV1_6_IN_0_OUT_ARG_DECL LV1_6_IN_ARG_DECL | ||
54 | #define LV1_7_IN_0_OUT_ARG_DECL LV1_7_IN_ARG_DECL | ||
55 | |||
56 | #define LV1_0_IN_1_OUT_ARG_DECL LV1_1_OUT_ARG_DECL | ||
57 | #define LV1_1_IN_1_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
58 | #define LV1_2_IN_1_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
59 | #define LV1_3_IN_1_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
60 | #define LV1_4_IN_1_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
61 | #define LV1_5_IN_1_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
62 | #define LV1_6_IN_1_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
63 | #define LV1_7_IN_1_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
64 | #define LV1_8_IN_1_OUT_ARG_DECL LV1_8_IN_ARG_DECL, LV1_1_OUT_ARG_DECL | ||
65 | |||
66 | #define LV1_0_IN_2_OUT_ARG_DECL LV1_2_OUT_ARG_DECL | ||
67 | #define LV1_1_IN_2_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_2_OUT_ARG_DECL | ||
68 | #define LV1_2_IN_2_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_2_OUT_ARG_DECL | ||
69 | #define LV1_3_IN_2_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_2_OUT_ARG_DECL | ||
70 | #define LV1_4_IN_2_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_2_OUT_ARG_DECL | ||
71 | #define LV1_5_IN_2_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_2_OUT_ARG_DECL | ||
72 | #define LV1_6_IN_2_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_2_OUT_ARG_DECL | ||
73 | #define LV1_7_IN_2_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_2_OUT_ARG_DECL | ||
74 | |||
75 | #define LV1_0_IN_3_OUT_ARG_DECL LV1_3_OUT_ARG_DECL | ||
76 | #define LV1_1_IN_3_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_3_OUT_ARG_DECL | ||
77 | #define LV1_2_IN_3_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_3_OUT_ARG_DECL | ||
78 | #define LV1_3_IN_3_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_3_OUT_ARG_DECL | ||
79 | #define LV1_4_IN_3_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_3_OUT_ARG_DECL | ||
80 | #define LV1_5_IN_3_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_3_OUT_ARG_DECL | ||
81 | #define LV1_6_IN_3_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_3_OUT_ARG_DECL | ||
82 | #define LV1_7_IN_3_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_3_OUT_ARG_DECL | ||
83 | |||
84 | #define LV1_0_IN_4_OUT_ARG_DECL LV1_4_OUT_ARG_DECL | ||
85 | #define LV1_1_IN_4_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_4_OUT_ARG_DECL | ||
86 | #define LV1_2_IN_4_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_4_OUT_ARG_DECL | ||
87 | #define LV1_3_IN_4_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_4_OUT_ARG_DECL | ||
88 | #define LV1_4_IN_4_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_4_OUT_ARG_DECL | ||
89 | #define LV1_5_IN_4_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_4_OUT_ARG_DECL | ||
90 | #define LV1_6_IN_4_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_4_OUT_ARG_DECL | ||
91 | #define LV1_7_IN_4_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_4_OUT_ARG_DECL | ||
92 | |||
93 | #define LV1_0_IN_5_OUT_ARG_DECL LV1_5_OUT_ARG_DECL | ||
94 | #define LV1_1_IN_5_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_5_OUT_ARG_DECL | ||
95 | #define LV1_2_IN_5_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_5_OUT_ARG_DECL | ||
96 | #define LV1_3_IN_5_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_5_OUT_ARG_DECL | ||
97 | #define LV1_4_IN_5_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_5_OUT_ARG_DECL | ||
98 | #define LV1_5_IN_5_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_5_OUT_ARG_DECL | ||
99 | #define LV1_6_IN_5_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_5_OUT_ARG_DECL | ||
100 | #define LV1_7_IN_5_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_5_OUT_ARG_DECL | ||
101 | |||
102 | #define LV1_0_IN_6_OUT_ARG_DECL LV1_6_OUT_ARG_DECL | ||
103 | #define LV1_1_IN_6_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_6_OUT_ARG_DECL | ||
104 | #define LV1_2_IN_6_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_6_OUT_ARG_DECL | ||
105 | #define LV1_3_IN_6_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_6_OUT_ARG_DECL | ||
106 | #define LV1_4_IN_6_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_6_OUT_ARG_DECL | ||
107 | #define LV1_5_IN_6_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_6_OUT_ARG_DECL | ||
108 | #define LV1_6_IN_6_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_6_OUT_ARG_DECL | ||
109 | #define LV1_7_IN_6_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_6_OUT_ARG_DECL | ||
110 | |||
111 | #define LV1_0_IN_7_OUT_ARG_DECL LV1_7_OUT_ARG_DECL | ||
112 | #define LV1_1_IN_7_OUT_ARG_DECL LV1_1_IN_ARG_DECL, LV1_7_OUT_ARG_DECL | ||
113 | #define LV1_2_IN_7_OUT_ARG_DECL LV1_2_IN_ARG_DECL, LV1_7_OUT_ARG_DECL | ||
114 | #define LV1_3_IN_7_OUT_ARG_DECL LV1_3_IN_ARG_DECL, LV1_7_OUT_ARG_DECL | ||
115 | #define LV1_4_IN_7_OUT_ARG_DECL LV1_4_IN_ARG_DECL, LV1_7_OUT_ARG_DECL | ||
116 | #define LV1_5_IN_7_OUT_ARG_DECL LV1_5_IN_ARG_DECL, LV1_7_OUT_ARG_DECL | ||
117 | #define LV1_6_IN_7_OUT_ARG_DECL LV1_6_IN_ARG_DECL, LV1_7_OUT_ARG_DECL | ||
118 | #define LV1_7_IN_7_OUT_ARG_DECL LV1_7_IN_ARG_DECL, LV1_7_OUT_ARG_DECL | ||
119 | |||
120 | #define LV1_1_IN_ARGS in_1 | ||
121 | #define LV1_2_IN_ARGS LV1_1_IN_ARGS, in_2 | ||
122 | #define LV1_3_IN_ARGS LV1_2_IN_ARGS, in_3 | ||
123 | #define LV1_4_IN_ARGS LV1_3_IN_ARGS, in_4 | ||
124 | #define LV1_5_IN_ARGS LV1_4_IN_ARGS, in_5 | ||
125 | #define LV1_6_IN_ARGS LV1_5_IN_ARGS, in_6 | ||
126 | #define LV1_7_IN_ARGS LV1_6_IN_ARGS, in_7 | ||
127 | #define LV1_8_IN_ARGS LV1_7_IN_ARGS, in_8 | ||
128 | |||
129 | #define LV1_1_OUT_ARGS out_1 | ||
130 | #define LV1_2_OUT_ARGS LV1_1_OUT_ARGS, out_2 | ||
131 | #define LV1_3_OUT_ARGS LV1_2_OUT_ARGS, out_3 | ||
132 | #define LV1_4_OUT_ARGS LV1_3_OUT_ARGS, out_4 | ||
133 | #define LV1_5_OUT_ARGS LV1_4_OUT_ARGS, out_5 | ||
134 | #define LV1_6_OUT_ARGS LV1_5_OUT_ARGS, out_6 | ||
135 | #define LV1_7_OUT_ARGS LV1_6_OUT_ARGS, out_7 | ||
136 | |||
137 | #define LV1_0_IN_0_OUT_ARGS | ||
138 | #define LV1_1_IN_0_OUT_ARGS LV1_1_IN_ARGS | ||
139 | #define LV1_2_IN_0_OUT_ARGS LV1_2_IN_ARGS | ||
140 | #define LV1_3_IN_0_OUT_ARGS LV1_3_IN_ARGS | ||
141 | #define LV1_4_IN_0_OUT_ARGS LV1_4_IN_ARGS | ||
142 | #define LV1_5_IN_0_OUT_ARGS LV1_5_IN_ARGS | ||
143 | #define LV1_6_IN_0_OUT_ARGS LV1_6_IN_ARGS | ||
144 | #define LV1_7_IN_0_OUT_ARGS LV1_7_IN_ARGS | ||
145 | |||
146 | #define LV1_0_IN_1_OUT_ARGS LV1_1_OUT_ARGS | ||
147 | #define LV1_1_IN_1_OUT_ARGS LV1_1_IN_ARGS, LV1_1_OUT_ARGS | ||
148 | #define LV1_2_IN_1_OUT_ARGS LV1_2_IN_ARGS, LV1_1_OUT_ARGS | ||
149 | #define LV1_3_IN_1_OUT_ARGS LV1_3_IN_ARGS, LV1_1_OUT_ARGS | ||
150 | #define LV1_4_IN_1_OUT_ARGS LV1_4_IN_ARGS, LV1_1_OUT_ARGS | ||
151 | #define LV1_5_IN_1_OUT_ARGS LV1_5_IN_ARGS, LV1_1_OUT_ARGS | ||
152 | #define LV1_6_IN_1_OUT_ARGS LV1_6_IN_ARGS, LV1_1_OUT_ARGS | ||
153 | #define LV1_7_IN_1_OUT_ARGS LV1_7_IN_ARGS, LV1_1_OUT_ARGS | ||
154 | #define LV1_8_IN_1_OUT_ARGS LV1_8_IN_ARGS, LV1_1_OUT_ARGS | ||
155 | |||
156 | #define LV1_0_IN_2_OUT_ARGS LV1_2_OUT_ARGS | ||
157 | #define LV1_1_IN_2_OUT_ARGS LV1_1_IN_ARGS, LV1_2_OUT_ARGS | ||
158 | #define LV1_2_IN_2_OUT_ARGS LV1_2_IN_ARGS, LV1_2_OUT_ARGS | ||
159 | #define LV1_3_IN_2_OUT_ARGS LV1_3_IN_ARGS, LV1_2_OUT_ARGS | ||
160 | #define LV1_4_IN_2_OUT_ARGS LV1_4_IN_ARGS, LV1_2_OUT_ARGS | ||
161 | #define LV1_5_IN_2_OUT_ARGS LV1_5_IN_ARGS, LV1_2_OUT_ARGS | ||
162 | #define LV1_6_IN_2_OUT_ARGS LV1_6_IN_ARGS, LV1_2_OUT_ARGS | ||
163 | #define LV1_7_IN_2_OUT_ARGS LV1_7_IN_ARGS, LV1_2_OUT_ARGS | ||
164 | |||
165 | #define LV1_0_IN_3_OUT_ARGS LV1_3_OUT_ARGS | ||
166 | #define LV1_1_IN_3_OUT_ARGS LV1_1_IN_ARGS, LV1_3_OUT_ARGS | ||
167 | #define LV1_2_IN_3_OUT_ARGS LV1_2_IN_ARGS, LV1_3_OUT_ARGS | ||
168 | #define LV1_3_IN_3_OUT_ARGS LV1_3_IN_ARGS, LV1_3_OUT_ARGS | ||
169 | #define LV1_4_IN_3_OUT_ARGS LV1_4_IN_ARGS, LV1_3_OUT_ARGS | ||
170 | #define LV1_5_IN_3_OUT_ARGS LV1_5_IN_ARGS, LV1_3_OUT_ARGS | ||
171 | #define LV1_6_IN_3_OUT_ARGS LV1_6_IN_ARGS, LV1_3_OUT_ARGS | ||
172 | #define LV1_7_IN_3_OUT_ARGS LV1_7_IN_ARGS, LV1_3_OUT_ARGS | ||
173 | |||
174 | #define LV1_0_IN_4_OUT_ARGS LV1_4_OUT_ARGS | ||
175 | #define LV1_1_IN_4_OUT_ARGS LV1_1_IN_ARGS, LV1_4_OUT_ARGS | ||
176 | #define LV1_2_IN_4_OUT_ARGS LV1_2_IN_ARGS, LV1_4_OUT_ARGS | ||
177 | #define LV1_3_IN_4_OUT_ARGS LV1_3_IN_ARGS, LV1_4_OUT_ARGS | ||
178 | #define LV1_4_IN_4_OUT_ARGS LV1_4_IN_ARGS, LV1_4_OUT_ARGS | ||
179 | #define LV1_5_IN_4_OUT_ARGS LV1_5_IN_ARGS, LV1_4_OUT_ARGS | ||
180 | #define LV1_6_IN_4_OUT_ARGS LV1_6_IN_ARGS, LV1_4_OUT_ARGS | ||
181 | #define LV1_7_IN_4_OUT_ARGS LV1_7_IN_ARGS, LV1_4_OUT_ARGS | ||
182 | |||
183 | #define LV1_0_IN_5_OUT_ARGS LV1_5_OUT_ARGS | ||
184 | #define LV1_1_IN_5_OUT_ARGS LV1_1_IN_ARGS, LV1_5_OUT_ARGS | ||
185 | #define LV1_2_IN_5_OUT_ARGS LV1_2_IN_ARGS, LV1_5_OUT_ARGS | ||
186 | #define LV1_3_IN_5_OUT_ARGS LV1_3_IN_ARGS, LV1_5_OUT_ARGS | ||
187 | #define LV1_4_IN_5_OUT_ARGS LV1_4_IN_ARGS, LV1_5_OUT_ARGS | ||
188 | #define LV1_5_IN_5_OUT_ARGS LV1_5_IN_ARGS, LV1_5_OUT_ARGS | ||
189 | #define LV1_6_IN_5_OUT_ARGS LV1_6_IN_ARGS, LV1_5_OUT_ARGS | ||
190 | #define LV1_7_IN_5_OUT_ARGS LV1_7_IN_ARGS, LV1_5_OUT_ARGS | ||
191 | |||
192 | #define LV1_0_IN_6_OUT_ARGS LV1_6_OUT_ARGS | ||
193 | #define LV1_1_IN_6_OUT_ARGS LV1_1_IN_ARGS, LV1_6_OUT_ARGS | ||
194 | #define LV1_2_IN_6_OUT_ARGS LV1_2_IN_ARGS, LV1_6_OUT_ARGS | ||
195 | #define LV1_3_IN_6_OUT_ARGS LV1_3_IN_ARGS, LV1_6_OUT_ARGS | ||
196 | #define LV1_4_IN_6_OUT_ARGS LV1_4_IN_ARGS, LV1_6_OUT_ARGS | ||
197 | #define LV1_5_IN_6_OUT_ARGS LV1_5_IN_ARGS, LV1_6_OUT_ARGS | ||
198 | #define LV1_6_IN_6_OUT_ARGS LV1_6_IN_ARGS, LV1_6_OUT_ARGS | ||
199 | #define LV1_7_IN_6_OUT_ARGS LV1_7_IN_ARGS, LV1_6_OUT_ARGS | ||
200 | |||
201 | #define LV1_0_IN_7_OUT_ARGS LV1_7_OUT_ARGS | ||
202 | #define LV1_1_IN_7_OUT_ARGS LV1_1_IN_ARGS, LV1_7_OUT_ARGS | ||
203 | #define LV1_2_IN_7_OUT_ARGS LV1_2_IN_ARGS, LV1_7_OUT_ARGS | ||
204 | #define LV1_3_IN_7_OUT_ARGS LV1_3_IN_ARGS, LV1_7_OUT_ARGS | ||
205 | #define LV1_4_IN_7_OUT_ARGS LV1_4_IN_ARGS, LV1_7_OUT_ARGS | ||
206 | #define LV1_5_IN_7_OUT_ARGS LV1_5_IN_ARGS, LV1_7_OUT_ARGS | ||
207 | #define LV1_6_IN_7_OUT_ARGS LV1_6_IN_ARGS, LV1_7_OUT_ARGS | ||
208 | #define LV1_7_IN_7_OUT_ARGS LV1_7_IN_ARGS, LV1_7_OUT_ARGS | ||
209 | |||
210 | /* | ||
211 | * This LV1_CALL() macro is for use by callers. It expands into an | ||
212 | * inline call wrapper and an underscored HV call declaration. The | ||
213 | * wrapper can be used to instrument the lv1 call interface. The | ||
214 | * file lv1call.S defines its own LV1_CALL() macro to expand into | ||
215 | * the actual underscored call definition. | ||
216 | */ | ||
217 | |||
218 | #if !defined(LV1_CALL) | ||
219 | #define LV1_CALL(name, in, out, num) \ | ||
220 | extern s64 _lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL); \ | ||
221 | static inline int lv1_##name(LV1_##in##_IN_##out##_OUT_ARG_DECL) \ | ||
222 | {return _lv1_##name(LV1_##in##_IN_##out##_OUT_ARGS);} | ||
223 | #endif | ||
224 | |||
225 | #endif /* !defined(__ASSEMBLY__) */ | ||
226 | |||
227 | /* lv1 call table */ | ||
228 | |||
229 | LV1_CALL(allocate_memory, 4, 2, 0 ) | ||
230 | LV1_CALL(write_htab_entry, 4, 0, 1 ) | ||
231 | LV1_CALL(construct_virtual_address_space, 3, 2, 2 ) | ||
232 | LV1_CALL(invalidate_htab_entries, 5, 0, 3 ) | ||
233 | LV1_CALL(get_virtual_address_space_id_of_ppe, 1, 1, 4 ) | ||
234 | LV1_CALL(query_logical_partition_address_region_info, 1, 5, 6 ) | ||
235 | LV1_CALL(select_virtual_address_space, 1, 0, 7 ) | ||
236 | LV1_CALL(pause, 1, 0, 9 ) | ||
237 | LV1_CALL(destruct_virtual_address_space, 1, 0, 10 ) | ||
238 | LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 ) | ||
239 | LV1_CALL(connect_irq_plug_ext, 5, 0, 12 ) | ||
240 | LV1_CALL(release_memory, 1, 0, 13 ) | ||
241 | LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 ) | ||
242 | LV1_CALL(construct_event_receive_port, 0, 1, 18 ) | ||
243 | LV1_CALL(destruct_event_receive_port, 1, 0, 19 ) | ||
244 | LV1_CALL(send_event_locally, 1, 0, 24 ) | ||
245 | LV1_CALL(end_of_interrupt, 1, 0, 27 ) | ||
246 | LV1_CALL(connect_irq_plug, 2, 0, 28 ) | ||
247 | LV1_CALL(disconnect_irq_plug, 1, 0, 29 ) | ||
248 | LV1_CALL(end_of_interrupt_ext, 3, 0, 30 ) | ||
249 | LV1_CALL(did_update_interrupt_mask, 2, 0, 31 ) | ||
250 | LV1_CALL(shutdown_logical_partition, 1, 0, 44 ) | ||
251 | LV1_CALL(destruct_logical_spe, 1, 0, 54 ) | ||
252 | LV1_CALL(construct_logical_spe, 7, 6, 57 ) | ||
253 | LV1_CALL(set_spe_interrupt_mask, 3, 0, 61 ) | ||
254 | LV1_CALL(set_spe_transition_notifier, 3, 0, 64 ) | ||
255 | LV1_CALL(disable_logical_spe, 2, 0, 65 ) | ||
256 | LV1_CALL(clear_spe_interrupt_status, 4, 0, 66 ) | ||
257 | LV1_CALL(get_spe_interrupt_status, 2, 1, 67 ) | ||
258 | LV1_CALL(get_logical_ppe_id, 0, 1, 69 ) | ||
259 | LV1_CALL(set_interrupt_mask, 5, 0, 73 ) | ||
260 | LV1_CALL(get_logical_partition_id, 0, 1, 74 ) | ||
261 | LV1_CALL(configure_execution_time_variable, 1, 0, 77 ) | ||
262 | LV1_CALL(get_spe_irq_outlet, 2, 1, 78 ) | ||
263 | LV1_CALL(set_spe_privilege_state_area_1_register, 3, 0, 79 ) | ||
264 | LV1_CALL(create_repository_node, 6, 0, 90 ) | ||
265 | LV1_CALL(get_repository_node_value, 5, 2, 91 ) | ||
266 | LV1_CALL(modify_repository_node_value, 6, 0, 92 ) | ||
267 | LV1_CALL(remove_repository_node, 4, 0, 93 ) | ||
268 | LV1_CALL(read_htab_entries, 2, 5, 95 ) | ||
269 | LV1_CALL(set_dabr, 2, 0, 96 ) | ||
270 | LV1_CALL(get_total_execution_time, 2, 1, 103 ) | ||
271 | LV1_CALL(construct_io_irq_outlet, 1, 1, 120 ) | ||
272 | LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 ) | ||
273 | LV1_CALL(map_htab, 1, 1, 122 ) | ||
274 | LV1_CALL(unmap_htab, 1, 0, 123 ) | ||
275 | LV1_CALL(get_version_info, 0, 1, 127 ) | ||
276 | LV1_CALL(insert_htab_entry, 6, 3, 158 ) | ||
277 | LV1_CALL(read_virtual_uart, 3, 1, 162 ) | ||
278 | LV1_CALL(write_virtual_uart, 3, 1, 163 ) | ||
279 | LV1_CALL(set_virtual_uart_param, 3, 0, 164 ) | ||
280 | LV1_CALL(get_virtual_uart_param, 2, 1, 165 ) | ||
281 | LV1_CALL(configure_virtual_uart_irq, 1, 1, 166 ) | ||
282 | LV1_CALL(open_device, 3, 0, 170 ) | ||
283 | LV1_CALL(close_device, 2, 0, 171 ) | ||
284 | LV1_CALL(map_device_mmio_region, 5, 1, 172 ) | ||
285 | LV1_CALL(unmap_device_mmio_region, 3, 0, 173 ) | ||
286 | LV1_CALL(allocate_device_dma_region, 5, 1, 174 ) | ||
287 | LV1_CALL(free_device_dma_region, 3, 0, 175 ) | ||
288 | LV1_CALL(map_device_dma_region, 6, 0, 176 ) | ||
289 | LV1_CALL(unmap_device_dma_region, 4, 0, 177 ) | ||
290 | LV1_CALL(net_add_multicast_address, 4, 0, 185 ) | ||
291 | LV1_CALL(net_remove_multicast_address, 4, 0, 186 ) | ||
292 | LV1_CALL(net_start_tx_dma, 4, 0, 187 ) | ||
293 | LV1_CALL(net_stop_tx_dma, 3, 0, 188 ) | ||
294 | LV1_CALL(net_start_rx_dma, 4, 0, 189 ) | ||
295 | LV1_CALL(net_stop_rx_dma, 3, 0, 190 ) | ||
296 | LV1_CALL(net_set_interrupt_status_indicator, 4, 0, 191 ) | ||
297 | LV1_CALL(net_set_interrupt_mask, 4, 0, 193 ) | ||
298 | LV1_CALL(net_control, 6, 2, 194 ) | ||
299 | LV1_CALL(connect_interrupt_event_receive_port, 4, 0, 197 ) | ||
300 | LV1_CALL(disconnect_interrupt_event_receive_port, 4, 0, 198 ) | ||
301 | LV1_CALL(get_spe_all_interrupt_statuses, 1, 1, 199 ) | ||
302 | LV1_CALL(deconfigure_virtual_uart_irq, 0, 0, 202 ) | ||
303 | LV1_CALL(enable_logical_spe, 2, 0, 207 ) | ||
304 | LV1_CALL(gpu_open, 1, 0, 210 ) | ||
305 | LV1_CALL(gpu_close, 0, 0, 211 ) | ||
306 | LV1_CALL(gpu_device_map, 1, 2, 212 ) | ||
307 | LV1_CALL(gpu_device_unmap, 1, 0, 213 ) | ||
308 | LV1_CALL(gpu_memory_allocate, 5, 2, 214 ) | ||
309 | LV1_CALL(gpu_memory_free, 1, 0, 216 ) | ||
310 | LV1_CALL(gpu_context_allocate, 2, 5, 217 ) | ||
311 | LV1_CALL(gpu_context_free, 1, 0, 218 ) | ||
312 | LV1_CALL(gpu_context_iomap, 5, 0, 221 ) | ||
313 | LV1_CALL(gpu_context_attribute, 6, 0, 225 ) | ||
314 | LV1_CALL(gpu_context_intr, 1, 1, 227 ) | ||
315 | LV1_CALL(gpu_attribute, 5, 0, 228 ) | ||
316 | LV1_CALL(get_rtc, 0, 2, 232 ) | ||
317 | LV1_CALL(set_ppe_periodic_tracer_frequency, 1, 0, 240 ) | ||
318 | LV1_CALL(start_ppe_periodic_tracer, 5, 0, 241 ) | ||
319 | LV1_CALL(stop_ppe_periodic_tracer, 1, 1, 242 ) | ||
320 | LV1_CALL(storage_read, 6, 1, 245 ) | ||
321 | LV1_CALL(storage_write, 6, 1, 246 ) | ||
322 | LV1_CALL(storage_send_device_command, 6, 1, 248 ) | ||
323 | LV1_CALL(storage_get_async_status, 1, 2, 249 ) | ||
324 | LV1_CALL(storage_check_async_status, 2, 1, 254 ) | ||
325 | LV1_CALL(panic, 1, 0, 255 ) | ||
326 | LV1_CALL(construct_lpm, 6, 3, 140 ) | ||
327 | LV1_CALL(destruct_lpm, 1, 0, 141 ) | ||
328 | LV1_CALL(start_lpm, 1, 0, 142 ) | ||
329 | LV1_CALL(stop_lpm, 1, 1, 143 ) | ||
330 | LV1_CALL(copy_lpm_trace_buffer, 3, 1, 144 ) | ||
331 | LV1_CALL(add_lpm_event_bookmark, 5, 0, 145 ) | ||
332 | LV1_CALL(delete_lpm_event_bookmark, 3, 0, 146 ) | ||
333 | LV1_CALL(set_lpm_interrupt_mask, 3, 1, 147 ) | ||
334 | LV1_CALL(get_lpm_interrupt_status, 1, 1, 148 ) | ||
335 | LV1_CALL(set_lpm_general_control, 5, 2, 149 ) | ||
336 | LV1_CALL(set_lpm_interval, 3, 1, 150 ) | ||
337 | LV1_CALL(set_lpm_trigger_control, 3, 1, 151 ) | ||
338 | LV1_CALL(set_lpm_counter_control, 4, 1, 152 ) | ||
339 | LV1_CALL(set_lpm_group_control, 3, 1, 153 ) | ||
340 | LV1_CALL(set_lpm_debug_bus_control, 3, 1, 154 ) | ||
341 | LV1_CALL(set_lpm_counter, 5, 2, 155 ) | ||
342 | LV1_CALL(set_lpm_signal, 7, 0, 156 ) | ||
343 | LV1_CALL(set_lpm_spr_trigger, 2, 0, 157 ) | ||
344 | |||
345 | #endif | ||
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index dac90dc341c..1b04e572354 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
@@ -26,6 +26,7 @@ struct device_node; | |||
26 | struct iommu_table; | 26 | struct iommu_table; |
27 | struct rtc_time; | 27 | struct rtc_time; |
28 | struct file; | 28 | struct file; |
29 | struct pci_controller; | ||
29 | #ifdef CONFIG_KEXEC | 30 | #ifdef CONFIG_KEXEC |
30 | struct kimage; | 31 | struct kimage; |
31 | #endif | 32 | #endif |
@@ -84,9 +85,12 @@ struct machdep_calls { | |||
84 | unsigned long (*tce_get)(struct iommu_table *tbl, | 85 | unsigned long (*tce_get)(struct iommu_table *tbl, |
85 | long index); | 86 | long index); |
86 | void (*tce_flush)(struct iommu_table *tbl); | 87 | void (*tce_flush)(struct iommu_table *tbl); |
87 | void (*iommu_dev_setup)(struct pci_dev *dev); | 88 | void (*pci_dma_dev_setup)(struct pci_dev *dev); |
88 | void (*iommu_bus_setup)(struct pci_bus *bus); | 89 | void (*pci_dma_bus_setup)(struct pci_bus *bus); |
89 | void (*irq_bus_setup)(struct pci_bus *bus); | 90 | |
91 | void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, | ||
92 | unsigned long flags); | ||
93 | void (*iounmap)(volatile void __iomem *token); | ||
90 | #endif /* CONFIG_PPC64 */ | 94 | #endif /* CONFIG_PPC64 */ |
91 | 95 | ||
92 | int (*probe)(void); | 96 | int (*probe)(void); |
@@ -106,6 +110,10 @@ struct machdep_calls { | |||
106 | /* Called after scanning the bus, before allocating resources */ | 110 | /* Called after scanning the bus, before allocating resources */ |
107 | void (*pcibios_fixup)(void); | 111 | void (*pcibios_fixup)(void); |
108 | int (*pci_probe_mode)(struct pci_bus *); | 112 | int (*pci_probe_mode)(struct pci_bus *); |
113 | void (*pci_irq_fixup)(struct pci_dev *dev); | ||
114 | |||
115 | /* To setup PHBs when using automatic OF platform driver for PCI */ | ||
116 | int (*pci_setup_phb)(struct pci_controller *host); | ||
109 | 117 | ||
110 | void (*restart)(char *cmd); | 118 | void (*restart)(char *cmd); |
111 | void (*power_off)(void); | 119 | void (*power_off)(void); |
@@ -199,10 +207,6 @@ struct machdep_calls { | |||
199 | * Returns 0 to allow assignment/enabling of the device. */ | 207 | * Returns 0 to allow assignment/enabling of the device. */ |
200 | int (*pcibios_enable_device_hook)(struct pci_dev *, int initial); | 208 | int (*pcibios_enable_device_hook)(struct pci_dev *, int initial); |
201 | 209 | ||
202 | /* For interrupt routing */ | ||
203 | unsigned char (*pci_swizzle)(struct pci_dev *, unsigned char *); | ||
204 | int (*pci_map_irq)(struct pci_dev *, unsigned char, unsigned char); | ||
205 | |||
206 | /* Called in indirect_* to avoid touching devices */ | 210 | /* Called in indirect_* to avoid touching devices */ |
207 | int (*pci_exclude_device)(unsigned char, unsigned char); | 211 | int (*pci_exclude_device)(unsigned char, unsigned char); |
208 | 212 | ||
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index c3fc7a28e3c..41c8c9c5a25 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h | |||
@@ -248,21 +248,6 @@ extern void hpte_init_native(void); | |||
248 | extern void hpte_init_lpar(void); | 248 | extern void hpte_init_lpar(void); |
249 | extern void hpte_init_iSeries(void); | 249 | extern void hpte_init_iSeries(void); |
250 | 250 | ||
251 | extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, | ||
252 | unsigned long va, unsigned long prpn, | ||
253 | unsigned long rflags, | ||
254 | unsigned long vflags, int psize); | ||
255 | |||
256 | extern long native_hpte_insert(unsigned long hpte_group, | ||
257 | unsigned long va, unsigned long prpn, | ||
258 | unsigned long rflags, | ||
259 | unsigned long vflags, int psize); | ||
260 | |||
261 | extern long iSeries_hpte_insert(unsigned long hpte_group, | ||
262 | unsigned long va, unsigned long prpn, | ||
263 | unsigned long rflags, | ||
264 | unsigned long vflags, int psize); | ||
265 | |||
266 | extern void stabs_alloc(void); | 251 | extern void stabs_alloc(void); |
267 | extern void slb_initialize(void); | 252 | extern void slb_initialize(void); |
268 | extern void slb_flush_and_rebolt(void); | 253 | extern void slb_flush_and_rebolt(void); |
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h new file mode 100644 index 00000000000..4a28a850998 --- /dev/null +++ b/include/asm-powerpc/mpc52xx.h | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips | ||
3 | * May need to be cleaned as the port goes on ... | ||
4 | * | ||
5 | * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com> | ||
6 | * Copyright (C) 2003 MontaVista, Software, Inc. | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public License | ||
9 | * version 2. This program is licensed "as is" without any warranty of any | ||
10 | * kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_POWERPC_MPC52xx_H__ | ||
14 | #define __ASM_POWERPC_MPC52xx_H__ | ||
15 | |||
16 | #ifndef __ASSEMBLY__ | ||
17 | #include <asm/types.h> | ||
18 | #include <asm/prom.h> | ||
19 | #endif /* __ASSEMBLY__ */ | ||
20 | |||
21 | |||
22 | /* ======================================================================== */ | ||
23 | /* Structures mapping of some unit register set */ | ||
24 | /* ======================================================================== */ | ||
25 | |||
26 | #ifndef __ASSEMBLY__ | ||
27 | |||
28 | /* Memory Mapping Control */ | ||
29 | struct mpc52xx_mmap_ctl { | ||
30 | u32 mbar; /* MMAP_CTRL + 0x00 */ | ||
31 | |||
32 | u32 cs0_start; /* MMAP_CTRL + 0x04 */ | ||
33 | u32 cs0_stop; /* MMAP_CTRL + 0x08 */ | ||
34 | u32 cs1_start; /* MMAP_CTRL + 0x0c */ | ||
35 | u32 cs1_stop; /* MMAP_CTRL + 0x10 */ | ||
36 | u32 cs2_start; /* MMAP_CTRL + 0x14 */ | ||
37 | u32 cs2_stop; /* MMAP_CTRL + 0x18 */ | ||
38 | u32 cs3_start; /* MMAP_CTRL + 0x1c */ | ||
39 | u32 cs3_stop; /* MMAP_CTRL + 0x20 */ | ||
40 | u32 cs4_start; /* MMAP_CTRL + 0x24 */ | ||
41 | u32 cs4_stop; /* MMAP_CTRL + 0x28 */ | ||
42 | u32 cs5_start; /* MMAP_CTRL + 0x2c */ | ||
43 | u32 cs5_stop; /* MMAP_CTRL + 0x30 */ | ||
44 | |||
45 | u32 sdram0; /* MMAP_CTRL + 0x34 */ | ||
46 | u32 sdram1; /* MMAP_CTRL + 0X38 */ | ||
47 | |||
48 | u32 reserved[4]; /* MMAP_CTRL + 0x3c .. 0x48 */ | ||
49 | |||
50 | u32 boot_start; /* MMAP_CTRL + 0x4c */ | ||
51 | u32 boot_stop; /* MMAP_CTRL + 0x50 */ | ||
52 | |||
53 | u32 ipbi_ws_ctrl; /* MMAP_CTRL + 0x54 */ | ||
54 | |||
55 | u32 cs6_start; /* MMAP_CTRL + 0x58 */ | ||
56 | u32 cs6_stop; /* MMAP_CTRL + 0x5c */ | ||
57 | u32 cs7_start; /* MMAP_CTRL + 0x60 */ | ||
58 | u32 cs7_stop; /* MMAP_CTRL + 0x64 */ | ||
59 | }; | ||
60 | |||
61 | /* SDRAM control */ | ||
62 | struct mpc52xx_sdram { | ||
63 | u32 mode; /* SDRAM + 0x00 */ | ||
64 | u32 ctrl; /* SDRAM + 0x04 */ | ||
65 | u32 config1; /* SDRAM + 0x08 */ | ||
66 | u32 config2; /* SDRAM + 0x0c */ | ||
67 | }; | ||
68 | |||
69 | /* SDMA */ | ||
70 | struct mpc52xx_sdma { | ||
71 | u32 taskBar; /* SDMA + 0x00 */ | ||
72 | u32 currentPointer; /* SDMA + 0x04 */ | ||
73 | u32 endPointer; /* SDMA + 0x08 */ | ||
74 | u32 variablePointer; /* SDMA + 0x0c */ | ||
75 | |||
76 | u8 IntVect1; /* SDMA + 0x10 */ | ||
77 | u8 IntVect2; /* SDMA + 0x11 */ | ||
78 | u16 PtdCntrl; /* SDMA + 0x12 */ | ||
79 | |||
80 | u32 IntPend; /* SDMA + 0x14 */ | ||
81 | u32 IntMask; /* SDMA + 0x18 */ | ||
82 | |||
83 | u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */ | ||
84 | |||
85 | u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */ | ||
86 | |||
87 | u32 cReqSelect; /* SDMA + 0x5c */ | ||
88 | u32 task_size0; /* SDMA + 0x60 */ | ||
89 | u32 task_size1; /* SDMA + 0x64 */ | ||
90 | u32 MDEDebug; /* SDMA + 0x68 */ | ||
91 | u32 ADSDebug; /* SDMA + 0x6c */ | ||
92 | u32 Value1; /* SDMA + 0x70 */ | ||
93 | u32 Value2; /* SDMA + 0x74 */ | ||
94 | u32 Control; /* SDMA + 0x78 */ | ||
95 | u32 Status; /* SDMA + 0x7c */ | ||
96 | u32 PTDDebug; /* SDMA + 0x80 */ | ||
97 | }; | ||
98 | |||
99 | /* GPT */ | ||
100 | struct mpc52xx_gpt { | ||
101 | u32 mode; /* GPTx + 0x00 */ | ||
102 | u32 count; /* GPTx + 0x04 */ | ||
103 | u32 pwm; /* GPTx + 0x08 */ | ||
104 | u32 status; /* GPTx + 0X0c */ | ||
105 | }; | ||
106 | |||
107 | /* GPIO */ | ||
108 | struct mpc52xx_gpio { | ||
109 | u32 port_config; /* GPIO + 0x00 */ | ||
110 | u32 simple_gpioe; /* GPIO + 0x04 */ | ||
111 | u32 simple_ode; /* GPIO + 0x08 */ | ||
112 | u32 simple_ddr; /* GPIO + 0x0c */ | ||
113 | u32 simple_dvo; /* GPIO + 0x10 */ | ||
114 | u32 simple_ival; /* GPIO + 0x14 */ | ||
115 | u8 outo_gpioe; /* GPIO + 0x18 */ | ||
116 | u8 reserved1[3]; /* GPIO + 0x19 */ | ||
117 | u8 outo_dvo; /* GPIO + 0x1c */ | ||
118 | u8 reserved2[3]; /* GPIO + 0x1d */ | ||
119 | u8 sint_gpioe; /* GPIO + 0x20 */ | ||
120 | u8 reserved3[3]; /* GPIO + 0x21 */ | ||
121 | u8 sint_ode; /* GPIO + 0x24 */ | ||
122 | u8 reserved4[3]; /* GPIO + 0x25 */ | ||
123 | u8 sint_ddr; /* GPIO + 0x28 */ | ||
124 | u8 reserved5[3]; /* GPIO + 0x29 */ | ||
125 | u8 sint_dvo; /* GPIO + 0x2c */ | ||
126 | u8 reserved6[3]; /* GPIO + 0x2d */ | ||
127 | u8 sint_inten; /* GPIO + 0x30 */ | ||
128 | u8 reserved7[3]; /* GPIO + 0x31 */ | ||
129 | u16 sint_itype; /* GPIO + 0x34 */ | ||
130 | u16 reserved8; /* GPIO + 0x36 */ | ||
131 | u8 gpio_control; /* GPIO + 0x38 */ | ||
132 | u8 reserved9[3]; /* GPIO + 0x39 */ | ||
133 | u8 sint_istat; /* GPIO + 0x3c */ | ||
134 | u8 sint_ival; /* GPIO + 0x3d */ | ||
135 | u8 bus_errs; /* GPIO + 0x3e */ | ||
136 | u8 reserved10; /* GPIO + 0x3f */ | ||
137 | }; | ||
138 | |||
139 | #define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD 4 | ||
140 | #define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD 5 | ||
141 | #define MPC52xx_GPIO_PCI_DIS (1<<15) | ||
142 | |||
143 | /* GPIO with WakeUp*/ | ||
144 | struct mpc52xx_gpio_wkup { | ||
145 | u8 wkup_gpioe; /* GPIO_WKUP + 0x00 */ | ||
146 | u8 reserved1[3]; /* GPIO_WKUP + 0x03 */ | ||
147 | u8 wkup_ode; /* GPIO_WKUP + 0x04 */ | ||
148 | u8 reserved2[3]; /* GPIO_WKUP + 0x05 */ | ||
149 | u8 wkup_ddr; /* GPIO_WKUP + 0x08 */ | ||
150 | u8 reserved3[3]; /* GPIO_WKUP + 0x09 */ | ||
151 | u8 wkup_dvo; /* GPIO_WKUP + 0x0C */ | ||
152 | u8 reserved4[3]; /* GPIO_WKUP + 0x0D */ | ||
153 | u8 wkup_inten; /* GPIO_WKUP + 0x10 */ | ||
154 | u8 reserved5[3]; /* GPIO_WKUP + 0x11 */ | ||
155 | u8 wkup_iinten; /* GPIO_WKUP + 0x14 */ | ||
156 | u8 reserved6[3]; /* GPIO_WKUP + 0x15 */ | ||
157 | u16 wkup_itype; /* GPIO_WKUP + 0x18 */ | ||
158 | u8 reserved7[2]; /* GPIO_WKUP + 0x1A */ | ||
159 | u8 wkup_maste; /* GPIO_WKUP + 0x1C */ | ||
160 | u8 reserved8[3]; /* GPIO_WKUP + 0x1D */ | ||
161 | u8 wkup_ival; /* GPIO_WKUP + 0x20 */ | ||
162 | u8 reserved9[3]; /* GPIO_WKUP + 0x21 */ | ||
163 | u8 wkup_istat; /* GPIO_WKUP + 0x24 */ | ||
164 | u8 reserved10[3]; /* GPIO_WKUP + 0x25 */ | ||
165 | }; | ||
166 | |||
167 | /* XLB Bus control */ | ||
168 | struct mpc52xx_xlb { | ||
169 | u8 reserved[0x40]; | ||
170 | u32 config; /* XLB + 0x40 */ | ||
171 | u32 version; /* XLB + 0x44 */ | ||
172 | u32 status; /* XLB + 0x48 */ | ||
173 | u32 int_enable; /* XLB + 0x4c */ | ||
174 | u32 addr_capture; /* XLB + 0x50 */ | ||
175 | u32 bus_sig_capture; /* XLB + 0x54 */ | ||
176 | u32 addr_timeout; /* XLB + 0x58 */ | ||
177 | u32 data_timeout; /* XLB + 0x5c */ | ||
178 | u32 bus_act_timeout; /* XLB + 0x60 */ | ||
179 | u32 master_pri_enable; /* XLB + 0x64 */ | ||
180 | u32 master_priority; /* XLB + 0x68 */ | ||
181 | u32 base_address; /* XLB + 0x6c */ | ||
182 | u32 snoop_window; /* XLB + 0x70 */ | ||
183 | }; | ||
184 | |||
185 | #define MPC52xx_XLB_CFG_PLDIS (1 << 31) | ||
186 | #define MPC52xx_XLB_CFG_SNOOP (1 << 15) | ||
187 | |||
188 | /* Clock Distribution control */ | ||
189 | struct mpc52xx_cdm { | ||
190 | u32 jtag_id; /* CDM + 0x00 reg0 read only */ | ||
191 | u32 rstcfg; /* CDM + 0x04 reg1 read only */ | ||
192 | u32 breadcrumb; /* CDM + 0x08 reg2 */ | ||
193 | |||
194 | u8 mem_clk_sel; /* CDM + 0x0c reg3 byte0 */ | ||
195 | u8 xlb_clk_sel; /* CDM + 0x0d reg3 byte1 read only */ | ||
196 | u8 ipb_clk_sel; /* CDM + 0x0e reg3 byte2 */ | ||
197 | u8 pci_clk_sel; /* CDM + 0x0f reg3 byte3 */ | ||
198 | |||
199 | u8 ext_48mhz_en; /* CDM + 0x10 reg4 byte0 */ | ||
200 | u8 fd_enable; /* CDM + 0x11 reg4 byte1 */ | ||
201 | u16 fd_counters; /* CDM + 0x12 reg4 byte2,3 */ | ||
202 | |||
203 | u32 clk_enables; /* CDM + 0x14 reg5 */ | ||
204 | |||
205 | u8 osc_disable; /* CDM + 0x18 reg6 byte0 */ | ||
206 | u8 reserved0[3]; /* CDM + 0x19 reg6 byte1,2,3 */ | ||
207 | |||
208 | u8 ccs_sleep_enable; /* CDM + 0x1c reg7 byte0 */ | ||
209 | u8 osc_sleep_enable; /* CDM + 0x1d reg7 byte1 */ | ||
210 | u8 reserved1; /* CDM + 0x1e reg7 byte2 */ | ||
211 | u8 ccs_qreq_test; /* CDM + 0x1f reg7 byte3 */ | ||
212 | |||
213 | u8 soft_reset; /* CDM + 0x20 u8 byte0 */ | ||
214 | u8 no_ckstp; /* CDM + 0x21 u8 byte0 */ | ||
215 | u8 reserved2[2]; /* CDM + 0x22 u8 byte1,2,3 */ | ||
216 | |||
217 | u8 pll_lock; /* CDM + 0x24 reg9 byte0 */ | ||
218 | u8 pll_looselock; /* CDM + 0x25 reg9 byte1 */ | ||
219 | u8 pll_sm_lockwin; /* CDM + 0x26 reg9 byte2 */ | ||
220 | u8 reserved3; /* CDM + 0x27 reg9 byte3 */ | ||
221 | |||
222 | u16 reserved4; /* CDM + 0x28 reg10 byte0,1 */ | ||
223 | u16 mclken_div_psc1; /* CDM + 0x2a reg10 byte2,3 */ | ||
224 | |||
225 | u16 reserved5; /* CDM + 0x2c reg11 byte0,1 */ | ||
226 | u16 mclken_div_psc2; /* CDM + 0x2e reg11 byte2,3 */ | ||
227 | |||
228 | u16 reserved6; /* CDM + 0x30 reg12 byte0,1 */ | ||
229 | u16 mclken_div_psc3; /* CDM + 0x32 reg12 byte2,3 */ | ||
230 | |||
231 | u16 reserved7; /* CDM + 0x34 reg13 byte0,1 */ | ||
232 | u16 mclken_div_psc6; /* CDM + 0x36 reg13 byte2,3 */ | ||
233 | }; | ||
234 | |||
235 | #endif /* __ASSEMBLY__ */ | ||
236 | |||
237 | |||
238 | /* ========================================================================= */ | ||
239 | /* Prototypes for MPC52xx sysdev */ | ||
240 | /* ========================================================================= */ | ||
241 | |||
242 | #ifndef __ASSEMBLY__ | ||
243 | |||
244 | extern void __iomem * mpc52xx_find_and_map(const char *); | ||
245 | extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node); | ||
246 | extern void mpc52xx_setup_cpu(void); | ||
247 | |||
248 | extern void mpc52xx_init_irq(void); | ||
249 | extern unsigned int mpc52xx_get_irq(void); | ||
250 | |||
251 | #endif /* __ASSEMBLY__ */ | ||
252 | |||
253 | #endif /* __ASM_POWERPC_MPC52xx_H__ */ | ||
254 | |||
diff --git a/include/asm-powerpc/mpc85xx.h b/include/asm-powerpc/mpc85xx.h index ccdb8a21138..54142997a58 100644 --- a/include/asm-powerpc/mpc85xx.h +++ b/include/asm-powerpc/mpc85xx.h | |||
@@ -31,14 +31,6 @@ | |||
31 | #include <platforms/85xx/mpc85xx_cds.h> | 31 | #include <platforms/85xx/mpc85xx_cds.h> |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | #define _IO_BASE isa_io_base | ||
35 | #define _ISA_MEM_BASE isa_mem_base | ||
36 | #ifdef CONFIG_PCI | ||
37 | #define PCI_DRAM_OFFSET pci_dram_offset | ||
38 | #else | ||
39 | #define PCI_DRAM_OFFSET 0 | ||
40 | #endif | ||
41 | |||
42 | /* Let modules/drivers get at CCSRBAR */ | 34 | /* Let modules/drivers get at CCSRBAR */ |
43 | extern phys_addr_t get_ccsrbar(void); | 35 | extern phys_addr_t get_ccsrbar(void); |
44 | 36 | ||
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index ef0a5458d2b..b71e7b32a55 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h | |||
@@ -3,6 +3,7 @@ | |||
3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
4 | 4 | ||
5 | #include <linux/irq.h> | 5 | #include <linux/irq.h> |
6 | #include <asm/dcr.h> | ||
6 | 7 | ||
7 | /* | 8 | /* |
8 | * Global registers | 9 | * Global registers |
@@ -225,6 +226,23 @@ struct mpic_irq_fixup | |||
225 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | 226 | #endif /* CONFIG_MPIC_BROKEN_U3 */ |
226 | 227 | ||
227 | 228 | ||
229 | enum mpic_reg_type { | ||
230 | mpic_access_mmio_le, | ||
231 | mpic_access_mmio_be, | ||
232 | #ifdef CONFIG_PPC_DCR | ||
233 | mpic_access_dcr | ||
234 | #endif | ||
235 | }; | ||
236 | |||
237 | struct mpic_reg_bank { | ||
238 | u32 __iomem *base; | ||
239 | #ifdef CONFIG_PPC_DCR | ||
240 | dcr_host_t dhost; | ||
241 | unsigned int dbase; | ||
242 | unsigned int doff; | ||
243 | #endif /* CONFIG_PPC_DCR */ | ||
244 | }; | ||
245 | |||
228 | /* The instance data of a given MPIC */ | 246 | /* The instance data of a given MPIC */ |
229 | struct mpic | 247 | struct mpic |
230 | { | 248 | { |
@@ -264,11 +282,18 @@ struct mpic | |||
264 | spinlock_t fixup_lock; | 282 | spinlock_t fixup_lock; |
265 | #endif | 283 | #endif |
266 | 284 | ||
285 | /* Register access method */ | ||
286 | enum mpic_reg_type reg_type; | ||
287 | |||
267 | /* The various ioremap'ed bases */ | 288 | /* The various ioremap'ed bases */ |
268 | volatile u32 __iomem *gregs; | 289 | struct mpic_reg_bank gregs; |
269 | volatile u32 __iomem *tmregs; | 290 | struct mpic_reg_bank tmregs; |
270 | volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS]; | 291 | struct mpic_reg_bank cpuregs[MPIC_MAX_CPUS]; |
271 | volatile u32 __iomem *isus[MPIC_MAX_ISU]; | 292 | struct mpic_reg_bank isus[MPIC_MAX_ISU]; |
293 | |||
294 | #ifdef CONFIG_PPC_DCR | ||
295 | unsigned int dcr_base; | ||
296 | #endif | ||
272 | 297 | ||
273 | #ifdef CONFIG_MPIC_WEIRD | 298 | #ifdef CONFIG_MPIC_WEIRD |
274 | /* Pointer to HW info array */ | 299 | /* Pointer to HW info array */ |
@@ -305,6 +330,8 @@ struct mpic | |||
305 | #define MPIC_SPV_EOI 0x00000020 | 330 | #define MPIC_SPV_EOI 0x00000020 |
306 | /* No passthrough disable */ | 331 | /* No passthrough disable */ |
307 | #define MPIC_NO_PTHROU_DIS 0x00000040 | 332 | #define MPIC_NO_PTHROU_DIS 0x00000040 |
333 | /* DCR based MPIC */ | ||
334 | #define MPIC_USES_DCR 0x00000080 | ||
308 | 335 | ||
309 | /* MPIC HW modification ID */ | 336 | /* MPIC HW modification ID */ |
310 | #define MPIC_REGSET_MASK 0xf0000000 | 337 | #define MPIC_REGSET_MASK 0xf0000000 |
@@ -337,7 +364,7 @@ struct mpic | |||
337 | * that is senses[0] correspond to linux irq "irq_offset". | 364 | * that is senses[0] correspond to linux irq "irq_offset". |
338 | */ | 365 | */ |
339 | extern struct mpic *mpic_alloc(struct device_node *node, | 366 | extern struct mpic *mpic_alloc(struct device_node *node, |
340 | unsigned long phys_addr, | 367 | phys_addr_t phys_addr, |
341 | unsigned int flags, | 368 | unsigned int flags, |
342 | unsigned int isu_size, | 369 | unsigned int isu_size, |
343 | unsigned int irq_count, | 370 | unsigned int irq_count, |
@@ -350,7 +377,7 @@ extern struct mpic *mpic_alloc(struct device_node *node, | |||
350 | * @phys_addr: physical address of the ISU | 377 | * @phys_addr: physical address of the ISU |
351 | */ | 378 | */ |
352 | extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | 379 | extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, |
353 | unsigned long phys_addr); | 380 | phys_addr_t phys_addr); |
354 | 381 | ||
355 | /* Set default sense codes | 382 | /* Set default sense codes |
356 | * | 383 | * |
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index c5c0b0b3cd5..a889b2005bf 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h | |||
@@ -6,12 +6,6 @@ | |||
6 | #include <linux/mod_devicetable.h> | 6 | #include <linux/mod_devicetable.h> |
7 | #include <asm/prom.h> | 7 | #include <asm/prom.h> |
8 | 8 | ||
9 | /* | ||
10 | * The of_platform_bus_type is a bus type used by drivers that do not | ||
11 | * attach to a macio or similar bus but still use OF probing | ||
12 | * mechanism | ||
13 | */ | ||
14 | extern struct bus_type of_platform_bus_type; | ||
15 | 9 | ||
16 | /* | 10 | /* |
17 | * The of_device is a kind of "base class" that is a superset of | 11 | * The of_device is a kind of "base class" that is a superset of |
@@ -20,46 +14,22 @@ extern struct bus_type of_platform_bus_type; | |||
20 | */ | 14 | */ |
21 | struct of_device | 15 | struct of_device |
22 | { | 16 | { |
23 | struct device_node *node; /* OF device node */ | 17 | struct device_node *node; /* to be obsoleted */ |
24 | u64 dma_mask; /* DMA mask */ | 18 | u64 dma_mask; /* DMA mask */ |
25 | struct device dev; /* Generic device interface */ | 19 | struct device dev; /* Generic device interface */ |
26 | }; | 20 | }; |
27 | #define to_of_device(d) container_of(d, struct of_device, dev) | 21 | #define to_of_device(d) container_of(d, struct of_device, dev) |
28 | 22 | ||
23 | extern const struct of_device_id *of_match_node( | ||
24 | const struct of_device_id *matches, const struct device_node *node); | ||
29 | extern const struct of_device_id *of_match_device( | 25 | extern const struct of_device_id *of_match_device( |
30 | const struct of_device_id *matches, const struct of_device *dev); | 26 | const struct of_device_id *matches, const struct of_device *dev); |
31 | 27 | ||
32 | extern struct of_device *of_dev_get(struct of_device *dev); | 28 | extern struct of_device *of_dev_get(struct of_device *dev); |
33 | extern void of_dev_put(struct of_device *dev); | 29 | extern void of_dev_put(struct of_device *dev); |
34 | 30 | ||
35 | /* | ||
36 | * An of_platform_driver driver is attached to a basic of_device on | ||
37 | * the "platform bus" (of_platform_bus_type) | ||
38 | */ | ||
39 | struct of_platform_driver | ||
40 | { | ||
41 | char *name; | ||
42 | struct of_device_id *match_table; | ||
43 | struct module *owner; | ||
44 | |||
45 | int (*probe)(struct of_device* dev, const struct of_device_id *match); | ||
46 | int (*remove)(struct of_device* dev); | ||
47 | |||
48 | int (*suspend)(struct of_device* dev, pm_message_t state); | ||
49 | int (*resume)(struct of_device* dev); | ||
50 | int (*shutdown)(struct of_device* dev); | ||
51 | |||
52 | struct device_driver driver; | ||
53 | }; | ||
54 | #define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) | ||
55 | |||
56 | extern int of_register_driver(struct of_platform_driver *drv); | ||
57 | extern void of_unregister_driver(struct of_platform_driver *drv); | ||
58 | extern int of_device_register(struct of_device *ofdev); | 31 | extern int of_device_register(struct of_device *ofdev); |
59 | extern void of_device_unregister(struct of_device *ofdev); | 32 | extern void of_device_unregister(struct of_device *ofdev); |
60 | extern struct of_device *of_platform_device_create(struct device_node *np, | ||
61 | const char *bus_id, | ||
62 | struct device *parent); | ||
63 | extern void of_release_dev(struct device *dev); | 33 | extern void of_release_dev(struct device *dev); |
64 | 34 | ||
65 | #endif /* __KERNEL__ */ | 35 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/of_platform.h b/include/asm-powerpc/of_platform.h new file mode 100644 index 00000000000..217eafb167e --- /dev/null +++ b/include/asm-powerpc/of_platform.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. | ||
3 | * <benh@kernel.crashing.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <asm/of_device.h> | ||
13 | |||
14 | /* | ||
15 | * The of_platform_bus_type is a bus type used by drivers that do not | ||
16 | * attach to a macio or similar bus but still use OF probing | ||
17 | * mechanism | ||
18 | */ | ||
19 | extern struct bus_type of_platform_bus_type; | ||
20 | |||
21 | /* | ||
22 | * An of_platform_driver driver is attached to a basic of_device on | ||
23 | * the "platform bus" (of_platform_bus_type) | ||
24 | */ | ||
25 | struct of_platform_driver | ||
26 | { | ||
27 | char *name; | ||
28 | struct of_device_id *match_table; | ||
29 | struct module *owner; | ||
30 | |||
31 | int (*probe)(struct of_device* dev, | ||
32 | const struct of_device_id *match); | ||
33 | int (*remove)(struct of_device* dev); | ||
34 | |||
35 | int (*suspend)(struct of_device* dev, pm_message_t state); | ||
36 | int (*resume)(struct of_device* dev); | ||
37 | int (*shutdown)(struct of_device* dev); | ||
38 | |||
39 | struct device_driver driver; | ||
40 | }; | ||
41 | #define to_of_platform_driver(drv) \ | ||
42 | container_of(drv,struct of_platform_driver, driver) | ||
43 | |||
44 | /* Platform drivers register/unregister */ | ||
45 | extern int of_register_platform_driver(struct of_platform_driver *drv); | ||
46 | extern void of_unregister_platform_driver(struct of_platform_driver *drv); | ||
47 | |||
48 | /* Platform devices and busses creation */ | ||
49 | extern struct of_device *of_platform_device_create(struct device_node *np, | ||
50 | const char *bus_id, | ||
51 | struct device *parent); | ||
52 | /* pseudo "matches" value to not do deep probe */ | ||
53 | #define OF_NO_DEEP_PROBE ((struct of_device_id *)-1) | ||
54 | |||
55 | extern int of_platform_bus_probe(struct device_node *root, | ||
56 | struct of_device_id *matches, | ||
57 | struct device *parent); | ||
58 | |||
59 | extern struct of_device *of_find_device_by_node(struct device_node *np); | ||
60 | extern struct of_device *of_find_device_by_phandle(phandle ph); | ||
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h index 07a10e590c1..71043bf3641 100644 --- a/include/asm-powerpc/oprofile_impl.h +++ b/include/asm-powerpc/oprofile_impl.h | |||
@@ -44,7 +44,9 @@ struct op_powerpc_model { | |||
44 | int num_counters); | 44 | int num_counters); |
45 | void (*cpu_setup) (struct op_counter_config *); | 45 | void (*cpu_setup) (struct op_counter_config *); |
46 | void (*start) (struct op_counter_config *); | 46 | void (*start) (struct op_counter_config *); |
47 | void (*global_start) (struct op_counter_config *); | ||
47 | void (*stop) (void); | 48 | void (*stop) (void); |
49 | void (*global_stop) (void); | ||
48 | void (*handle_interrupt) (struct pt_regs *, | 50 | void (*handle_interrupt) (struct pt_regs *, |
49 | struct op_counter_config *); | 51 | struct op_counter_config *); |
50 | int num_counters; | 52 | int num_counters; |
@@ -54,6 +56,7 @@ extern struct op_powerpc_model op_model_fsl_booke; | |||
54 | extern struct op_powerpc_model op_model_rs64; | 56 | extern struct op_powerpc_model op_model_rs64; |
55 | extern struct op_powerpc_model op_model_power4; | 57 | extern struct op_powerpc_model op_model_power4; |
56 | extern struct op_powerpc_model op_model_7450; | 58 | extern struct op_powerpc_model op_model_7450; |
59 | extern struct op_powerpc_model op_model_cell; | ||
57 | 60 | ||
58 | #ifndef CONFIG_FSL_BOOKE | 61 | #ifndef CONFIG_FSL_BOOKE |
59 | 62 | ||
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 0a4e5c93e8e..0d3adc09c84 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h | |||
@@ -93,7 +93,8 @@ struct paca_struct { | |||
93 | u64 stab_rr; /* stab/slb round-robin counter */ | 93 | u64 stab_rr; /* stab/slb round-robin counter */ |
94 | u64 saved_r1; /* r1 save for RTAS calls */ | 94 | u64 saved_r1; /* r1 save for RTAS calls */ |
95 | u64 saved_msr; /* MSR saved here by enter_rtas */ | 95 | u64 saved_msr; /* MSR saved here by enter_rtas */ |
96 | u8 proc_enabled; /* irq soft-enable flag */ | 96 | u8 soft_enabled; /* irq soft-enable flag */ |
97 | u8 hard_enabled; /* set if irqs are enabled in MSR */ | ||
97 | u8 io_sync; /* writel() needs spin_unlock sync */ | 98 | u8 io_sync; /* writel() needs spin_unlock sync */ |
98 | 99 | ||
99 | /* Stuff for accurate time accounting */ | 100 | /* Stuff for accurate time accounting */ |
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index 86ee46b09b8..7bb7f900980 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h | |||
@@ -25,6 +25,7 @@ struct pci_controller { | |||
25 | int node; | 25 | int node; |
26 | void *arch_data; | 26 | void *arch_data; |
27 | struct list_head list_node; | 27 | struct list_head list_node; |
28 | struct device *parent; | ||
28 | 29 | ||
29 | int first_busno; | 30 | int first_busno; |
30 | int last_busno; | 31 | int last_busno; |
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index 721c97f09b2..16f13319c76 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h | |||
@@ -70,15 +70,15 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) | |||
70 | */ | 70 | */ |
71 | #define PCI_DISABLE_MWI | 71 | #define PCI_DISABLE_MWI |
72 | 72 | ||
73 | extern struct dma_mapping_ops pci_dma_ops; | 73 | extern struct dma_mapping_ops *pci_dma_ops; |
74 | 74 | ||
75 | /* For DAC DMA, we currently don't support it by default, but | 75 | /* For DAC DMA, we currently don't support it by default, but |
76 | * we let 64-bit platforms override this. | 76 | * we let 64-bit platforms override this. |
77 | */ | 77 | */ |
78 | static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) | 78 | static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) |
79 | { | 79 | { |
80 | if (pci_dma_ops.dac_dma_supported) | 80 | if (pci_dma_ops && pci_dma_ops->dac_dma_supported) |
81 | return pci_dma_ops.dac_dma_supported(&hwdev->dev, mask); | 81 | return pci_dma_ops->dac_dma_supported(&hwdev->dev, mask); |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
@@ -210,6 +210,8 @@ extern int remap_bus_range(struct pci_bus *bus); | |||
210 | extern void pcibios_fixup_device_resources(struct pci_dev *dev, | 210 | extern void pcibios_fixup_device_resources(struct pci_dev *dev, |
211 | struct pci_bus *bus); | 211 | struct pci_bus *bus); |
212 | 212 | ||
213 | extern void pcibios_setup_new_device(struct pci_dev *dev); | ||
214 | |||
213 | extern void pcibios_claim_one_bus(struct pci_bus *b); | 215 | extern void pcibios_claim_one_bus(struct pci_bus *b); |
214 | 216 | ||
215 | extern struct pci_controller *init_phb_dynamic(struct device_node *dn); | 217 | extern struct pci_controller *init_phb_dynamic(struct device_node *dn); |
@@ -232,12 +234,10 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file, | |||
232 | unsigned long size, | 234 | unsigned long size, |
233 | pgprot_t prot); | 235 | pgprot_t prot); |
234 | 236 | ||
235 | #if defined(CONFIG_PPC_MULTIPLATFORM) || defined(CONFIG_PPC32) | ||
236 | #define HAVE_ARCH_PCI_RESOURCE_TO_USER | 237 | #define HAVE_ARCH_PCI_RESOURCE_TO_USER |
237 | extern void pci_resource_to_user(const struct pci_dev *dev, int bar, | 238 | extern void pci_resource_to_user(const struct pci_dev *dev, int bar, |
238 | const struct resource *rsrc, | 239 | const struct resource *rsrc, |
239 | resource_size_t *start, resource_size_t *end); | 240 | resource_size_t *start, resource_size_t *end); |
240 | #endif /* CONFIG_PPC_MULTIPLATFORM || CONFIG_PPC32 */ | ||
241 | 241 | ||
242 | #endif /* __KERNEL__ */ | 242 | #endif /* __KERNEL__ */ |
243 | #endif /* __ASM_POWERPC_PCI_H */ | 243 | #endif /* __ASM_POWERPC_PCI_H */ |
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 1115756c79f..ab6eddb518c 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h | |||
@@ -36,18 +36,17 @@ typedef void *(*traverse_func)(struct device_node *me, void *data); | |||
36 | void *traverse_pci_devices(struct device_node *start, traverse_func pre, | 36 | void *traverse_pci_devices(struct device_node *start, traverse_func pre, |
37 | void *data); | 37 | void *data); |
38 | 38 | ||
39 | void pci_devs_phb_init(void); | 39 | extern void pci_devs_phb_init(void); |
40 | void pci_devs_phb_init_dynamic(struct pci_controller *phb); | 40 | extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); |
41 | int setup_phb(struct device_node *dev, struct pci_controller *phb); | 41 | extern void scan_phb(struct pci_controller *hose); |
42 | void __devinit scan_phb(struct pci_controller *hose); | ||
43 | 42 | ||
44 | /* From rtas_pci.h */ | 43 | /* From rtas_pci.h */ |
45 | void init_pci_config_tokens (void); | 44 | extern void init_pci_config_tokens (void); |
46 | unsigned long get_phb_buid (struct device_node *); | 45 | extern unsigned long get_phb_buid (struct device_node *); |
46 | extern int rtas_setup_phb(struct pci_controller *phb); | ||
47 | 47 | ||
48 | /* From pSeries_pci.h */ | 48 | /* From pSeries_pci.h */ |
49 | extern void pSeries_final_fixup(void); | 49 | extern void pSeries_final_fixup(void); |
50 | extern void pSeries_irq_bus_setup(struct pci_bus *bus); | ||
51 | 50 | ||
52 | extern unsigned long pci_probe_only; | 51 | extern unsigned long pci_probe_only; |
53 | 52 | ||
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index 6cb6fb19e57..a26c32ee552 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h | |||
@@ -53,10 +53,6 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin; | |||
53 | 53 | ||
54 | #endif /* CONFIG_PPC_PREP */ | 54 | #endif /* CONFIG_PPC_PREP */ |
55 | 55 | ||
56 | #ifndef CONFIG_PPC_MULTIPLATFORM | ||
57 | #define _machine 0 | ||
58 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
59 | |||
60 | #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ | 56 | #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ |
61 | 57 | ||
62 | /* | 58 | /* |
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index ec11d44eaeb..0afee17f33b 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
20 | #include <linux/platform_device.h> | ||
20 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
21 | 22 | ||
22 | /* Definitions used by the flattened device tree */ | 23 | /* Definitions used by the flattened device tree */ |
@@ -333,6 +334,20 @@ extern int of_irq_map_one(struct device_node *device, int index, | |||
333 | struct pci_dev; | 334 | struct pci_dev; |
334 | extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); | 335 | extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); |
335 | 336 | ||
337 | static inline int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) | ||
338 | { | ||
339 | int irq = irq_of_parse_and_map(dev, index); | ||
340 | |||
341 | /* Only dereference the resource if both the | ||
342 | * resource and the irq are valid. */ | ||
343 | if (r && irq != NO_IRQ) { | ||
344 | r->start = r->end = irq; | ||
345 | r->flags = IORESOURCE_IRQ; | ||
346 | } | ||
347 | |||
348 | return irq; | ||
349 | } | ||
350 | |||
336 | 351 | ||
337 | #endif /* __KERNEL__ */ | 352 | #endif /* __KERNEL__ */ |
338 | #endif /* _POWERPC_PROM_H */ | 353 | #endif /* _POWERPC_PROM_H */ |
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h new file mode 100644 index 00000000000..52a69ed0d90 --- /dev/null +++ b/include/asm-powerpc/ps3.h | |||
@@ -0,0 +1,462 @@ | |||
1 | /* | ||
2 | * PS3 platform declarations. | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #if !defined(_ASM_POWERPC_PS3_H) | ||
22 | #define _ASM_POWERPC_PS3_H | ||
23 | |||
24 | #include <linux/compiler.h> /* for __deprecated */ | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/device.h> | ||
28 | |||
29 | /** | ||
30 | * struct ps3_device_id - HV bus device identifier from the system repository | ||
31 | * @bus_id: HV bus id, {1..} (zero invalid) | ||
32 | * @dev_id: HV device id, {0..} | ||
33 | */ | ||
34 | |||
35 | struct ps3_device_id { | ||
36 | unsigned int bus_id; | ||
37 | unsigned int dev_id; | ||
38 | }; | ||
39 | |||
40 | |||
41 | /* dma routines */ | ||
42 | |||
43 | enum ps3_dma_page_size { | ||
44 | PS3_DMA_4K = 12U, | ||
45 | PS3_DMA_64K = 16U, | ||
46 | PS3_DMA_1M = 20U, | ||
47 | PS3_DMA_16M = 24U, | ||
48 | }; | ||
49 | |||
50 | enum ps3_dma_region_type { | ||
51 | PS3_DMA_OTHER = 0, | ||
52 | PS3_DMA_INTERNAL = 2, | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * struct ps3_dma_region - A per device dma state variables structure | ||
57 | * @did: The HV device id. | ||
58 | * @page_size: The ioc pagesize. | ||
59 | * @region_type: The HV region type. | ||
60 | * @bus_addr: The 'translated' bus address of the region. | ||
61 | * @len: The length in bytes of the region. | ||
62 | * @chunk_list: Opaque variable used by the ioc page manager. | ||
63 | */ | ||
64 | |||
65 | struct ps3_dma_region { | ||
66 | struct ps3_device_id did; | ||
67 | enum ps3_dma_page_size page_size; | ||
68 | enum ps3_dma_region_type region_type; | ||
69 | unsigned long bus_addr; | ||
70 | unsigned long len; | ||
71 | struct { | ||
72 | spinlock_t lock; | ||
73 | struct list_head head; | ||
74 | } chunk_list; | ||
75 | }; | ||
76 | |||
77 | /** | ||
78 | * struct ps3_dma_region_init - Helper to initialize structure variables | ||
79 | * | ||
80 | * Helper to properly initialize variables prior to calling | ||
81 | * ps3_system_bus_device_register. | ||
82 | */ | ||
83 | |||
84 | static inline void ps3_dma_region_init(struct ps3_dma_region *r, | ||
85 | const struct ps3_device_id* did, enum ps3_dma_page_size page_size, | ||
86 | enum ps3_dma_region_type region_type) | ||
87 | { | ||
88 | r->did = *did; | ||
89 | r->page_size = page_size; | ||
90 | r->region_type = region_type; | ||
91 | } | ||
92 | int ps3_dma_region_create(struct ps3_dma_region *r); | ||
93 | int ps3_dma_region_free(struct ps3_dma_region *r); | ||
94 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, | ||
95 | unsigned long len, unsigned long *bus_addr); | ||
96 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, | ||
97 | unsigned long len); | ||
98 | |||
99 | /* mmio routines */ | ||
100 | |||
101 | enum ps3_mmio_page_size { | ||
102 | PS3_MMIO_4K = 12U, | ||
103 | PS3_MMIO_64K = 16U | ||
104 | }; | ||
105 | |||
106 | /** | ||
107 | * struct ps3_mmio_region - a per device mmio state variables structure | ||
108 | * | ||
109 | * Current systems can be supported with a single region per device. | ||
110 | */ | ||
111 | |||
112 | struct ps3_mmio_region { | ||
113 | struct ps3_device_id did; | ||
114 | unsigned long bus_addr; | ||
115 | unsigned long len; | ||
116 | enum ps3_mmio_page_size page_size; | ||
117 | unsigned long lpar_addr; | ||
118 | }; | ||
119 | |||
120 | /** | ||
121 | * struct ps3_mmio_region_init - Helper to initialize structure variables | ||
122 | * | ||
123 | * Helper to properly initialize variables prior to calling | ||
124 | * ps3_system_bus_device_register. | ||
125 | */ | ||
126 | |||
127 | static inline void ps3_mmio_region_init(struct ps3_mmio_region *r, | ||
128 | const struct ps3_device_id* did, unsigned long bus_addr, | ||
129 | unsigned long len, enum ps3_mmio_page_size page_size) | ||
130 | { | ||
131 | r->did = *did; | ||
132 | r->bus_addr = bus_addr; | ||
133 | r->len = len; | ||
134 | r->page_size = page_size; | ||
135 | } | ||
136 | int ps3_mmio_region_create(struct ps3_mmio_region *r); | ||
137 | int ps3_free_mmio_region(struct ps3_mmio_region *r); | ||
138 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); | ||
139 | |||
140 | /* inrerrupt routines */ | ||
141 | |||
142 | int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq); | ||
143 | int ps3_free_io_irq(unsigned int virq); | ||
144 | int ps3_alloc_event_irq(unsigned int *virq); | ||
145 | int ps3_free_event_irq(unsigned int virq); | ||
146 | int ps3_send_event_locally(unsigned int virq); | ||
147 | int ps3_connect_event_irq(const struct ps3_device_id *did, | ||
148 | unsigned int interrupt_id, unsigned int *virq); | ||
149 | int ps3_disconnect_event_irq(const struct ps3_device_id *did, | ||
150 | unsigned int interrupt_id, unsigned int virq); | ||
151 | int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq); | ||
152 | int ps3_free_vuart_irq(unsigned int virq); | ||
153 | int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class, | ||
154 | unsigned int *virq); | ||
155 | int ps3_free_spe_irq(unsigned int virq); | ||
156 | |||
157 | /* lv1 result codes */ | ||
158 | |||
159 | enum lv1_result { | ||
160 | LV1_SUCCESS = 0, | ||
161 | /* not used -1 */ | ||
162 | LV1_RESOURCE_SHORTAGE = -2, | ||
163 | LV1_NO_PRIVILEGE = -3, | ||
164 | LV1_DENIED_BY_POLICY = -4, | ||
165 | LV1_ACCESS_VIOLATION = -5, | ||
166 | LV1_NO_ENTRY = -6, | ||
167 | LV1_DUPLICATE_ENTRY = -7, | ||
168 | LV1_TYPE_MISMATCH = -8, | ||
169 | LV1_BUSY = -9, | ||
170 | LV1_EMPTY = -10, | ||
171 | LV1_WRONG_STATE = -11, | ||
172 | /* not used -12 */ | ||
173 | LV1_NO_MATCH = -13, | ||
174 | LV1_ALREADY_CONNECTED = -14, | ||
175 | LV1_UNSUPPORTED_PARAMETER_VALUE = -15, | ||
176 | LV1_CONDITION_NOT_SATISFIED = -16, | ||
177 | LV1_ILLEGAL_PARAMETER_VALUE = -17, | ||
178 | LV1_BAD_OPTION = -18, | ||
179 | LV1_IMPLEMENTATION_LIMITATION = -19, | ||
180 | LV1_NOT_IMPLEMENTED = -20, | ||
181 | LV1_INVALID_CLASS_ID = -21, | ||
182 | LV1_CONSTRAINT_NOT_SATISFIED = -22, | ||
183 | LV1_ALIGNMENT_ERROR = -23, | ||
184 | LV1_INTERNAL_ERROR = -32768, | ||
185 | }; | ||
186 | |||
187 | static inline const char* ps3_result(int result) | ||
188 | { | ||
189 | #if defined(DEBUG) | ||
190 | switch (result) { | ||
191 | case LV1_SUCCESS: | ||
192 | return "LV1_SUCCESS (0)"; | ||
193 | case -1: | ||
194 | return "** unknown result ** (-1)"; | ||
195 | case LV1_RESOURCE_SHORTAGE: | ||
196 | return "LV1_RESOURCE_SHORTAGE (-2)"; | ||
197 | case LV1_NO_PRIVILEGE: | ||
198 | return "LV1_NO_PRIVILEGE (-3)"; | ||
199 | case LV1_DENIED_BY_POLICY: | ||
200 | return "LV1_DENIED_BY_POLICY (-4)"; | ||
201 | case LV1_ACCESS_VIOLATION: | ||
202 | return "LV1_ACCESS_VIOLATION (-5)"; | ||
203 | case LV1_NO_ENTRY: | ||
204 | return "LV1_NO_ENTRY (-6)"; | ||
205 | case LV1_DUPLICATE_ENTRY: | ||
206 | return "LV1_DUPLICATE_ENTRY (-7)"; | ||
207 | case LV1_TYPE_MISMATCH: | ||
208 | return "LV1_TYPE_MISMATCH (-8)"; | ||
209 | case LV1_BUSY: | ||
210 | return "LV1_BUSY (-9)"; | ||
211 | case LV1_EMPTY: | ||
212 | return "LV1_EMPTY (-10)"; | ||
213 | case LV1_WRONG_STATE: | ||
214 | return "LV1_WRONG_STATE (-11)"; | ||
215 | case -12: | ||
216 | return "** unknown result ** (-12)"; | ||
217 | case LV1_NO_MATCH: | ||
218 | return "LV1_NO_MATCH (-13)"; | ||
219 | case LV1_ALREADY_CONNECTED: | ||
220 | return "LV1_ALREADY_CONNECTED (-14)"; | ||
221 | case LV1_UNSUPPORTED_PARAMETER_VALUE: | ||
222 | return "LV1_UNSUPPORTED_PARAMETER_VALUE (-15)"; | ||
223 | case LV1_CONDITION_NOT_SATISFIED: | ||
224 | return "LV1_CONDITION_NOT_SATISFIED (-16)"; | ||
225 | case LV1_ILLEGAL_PARAMETER_VALUE: | ||
226 | return "LV1_ILLEGAL_PARAMETER_VALUE (-17)"; | ||
227 | case LV1_BAD_OPTION: | ||
228 | return "LV1_BAD_OPTION (-18)"; | ||
229 | case LV1_IMPLEMENTATION_LIMITATION: | ||
230 | return "LV1_IMPLEMENTATION_LIMITATION (-19)"; | ||
231 | case LV1_NOT_IMPLEMENTED: | ||
232 | return "LV1_NOT_IMPLEMENTED (-20)"; | ||
233 | case LV1_INVALID_CLASS_ID: | ||
234 | return "LV1_INVALID_CLASS_ID (-21)"; | ||
235 | case LV1_CONSTRAINT_NOT_SATISFIED: | ||
236 | return "LV1_CONSTRAINT_NOT_SATISFIED (-22)"; | ||
237 | case LV1_ALIGNMENT_ERROR: | ||
238 | return "LV1_ALIGNMENT_ERROR (-23)"; | ||
239 | case LV1_INTERNAL_ERROR: | ||
240 | return "LV1_INTERNAL_ERROR (-32768)"; | ||
241 | default: | ||
242 | BUG(); | ||
243 | return "** unknown result **"; | ||
244 | }; | ||
245 | #else | ||
246 | return ""; | ||
247 | #endif | ||
248 | } | ||
249 | |||
250 | /* repository bus info */ | ||
251 | |||
252 | enum ps3_bus_type { | ||
253 | PS3_BUS_TYPE_SB = 4, | ||
254 | PS3_BUS_TYPE_STORAGE = 5, | ||
255 | }; | ||
256 | |||
257 | enum ps3_dev_type { | ||
258 | PS3_DEV_TYPE_SB_GELIC = 3, | ||
259 | PS3_DEV_TYPE_SB_USB = 4, | ||
260 | PS3_DEV_TYPE_SB_GPIO = 6, | ||
261 | }; | ||
262 | |||
263 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | ||
264 | u64 *value); | ||
265 | int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id); | ||
266 | int ps3_repository_read_bus_type(unsigned int bus_index, | ||
267 | enum ps3_bus_type *bus_type); | ||
268 | int ps3_repository_read_bus_num_dev(unsigned int bus_index, | ||
269 | unsigned int *num_dev); | ||
270 | |||
271 | /* repository bus device info */ | ||
272 | |||
273 | enum ps3_interrupt_type { | ||
274 | PS3_INTERRUPT_TYPE_EVENT_PORT = 2, | ||
275 | PS3_INTERRUPT_TYPE_SB_OHCI = 3, | ||
276 | PS3_INTERRUPT_TYPE_SB_EHCI = 4, | ||
277 | PS3_INTERRUPT_TYPE_OTHER = 5, | ||
278 | }; | ||
279 | |||
280 | enum ps3_region_type { | ||
281 | PS3_REGION_TYPE_SB_OHCI = 3, | ||
282 | PS3_REGION_TYPE_SB_EHCI = 4, | ||
283 | PS3_REGION_TYPE_SB_GPIO = 5, | ||
284 | }; | ||
285 | |||
286 | int ps3_repository_read_dev_str(unsigned int bus_index, | ||
287 | unsigned int dev_index, const char *dev_str, u64 *value); | ||
288 | int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, | ||
289 | unsigned int *dev_id); | ||
290 | int ps3_repository_read_dev_type(unsigned int bus_index, | ||
291 | unsigned int dev_index, enum ps3_dev_type *dev_type); | ||
292 | int ps3_repository_read_dev_intr(unsigned int bus_index, | ||
293 | unsigned int dev_index, unsigned int intr_index, | ||
294 | enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id); | ||
295 | int ps3_repository_read_dev_reg_type(unsigned int bus_index, | ||
296 | unsigned int dev_index, unsigned int reg_index, | ||
297 | enum ps3_region_type *reg_type); | ||
298 | int ps3_repository_read_dev_reg_addr(unsigned int bus_index, | ||
299 | unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, | ||
300 | u64 *len); | ||
301 | int ps3_repository_read_dev_reg(unsigned int bus_index, | ||
302 | unsigned int dev_index, unsigned int reg_index, | ||
303 | enum ps3_region_type *reg_type, u64 *bus_addr, u64 *len); | ||
304 | |||
305 | /* repository bus enumerators */ | ||
306 | |||
307 | struct ps3_repository_device { | ||
308 | unsigned int bus_index; | ||
309 | unsigned int dev_index; | ||
310 | struct ps3_device_id did; | ||
311 | }; | ||
312 | |||
313 | int ps3_repository_find_device(enum ps3_bus_type bus_type, | ||
314 | enum ps3_dev_type dev_type, | ||
315 | const struct ps3_repository_device *start_dev, | ||
316 | struct ps3_repository_device *dev); | ||
317 | static inline int ps3_repository_find_first_device( | ||
318 | enum ps3_bus_type bus_type, enum ps3_dev_type dev_type, | ||
319 | struct ps3_repository_device *dev) | ||
320 | { | ||
321 | return ps3_repository_find_device(bus_type, dev_type, NULL, dev); | ||
322 | } | ||
323 | int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | ||
324 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id); | ||
325 | int ps3_repository_find_region(const struct ps3_repository_device *dev, | ||
326 | enum ps3_region_type reg_type, u64 *bus_addr, u64 *len); | ||
327 | |||
328 | /* repository block device info */ | ||
329 | |||
330 | int ps3_repository_read_dev_port(unsigned int bus_index, | ||
331 | unsigned int dev_index, u64 *port); | ||
332 | int ps3_repository_read_dev_blk_size(unsigned int bus_index, | ||
333 | unsigned int dev_index, u64 *blk_size); | ||
334 | int ps3_repository_read_dev_num_blocks(unsigned int bus_index, | ||
335 | unsigned int dev_index, u64 *num_blocks); | ||
336 | int ps3_repository_read_dev_num_regions(unsigned int bus_index, | ||
337 | unsigned int dev_index, unsigned int *num_regions); | ||
338 | int ps3_repository_read_dev_region_id(unsigned int bus_index, | ||
339 | unsigned int dev_index, unsigned int region_index, | ||
340 | unsigned int *region_id); | ||
341 | int ps3_repository_read_dev_region_size(unsigned int bus_index, | ||
342 | unsigned int dev_index, unsigned int region_index, u64 *region_size); | ||
343 | int ps3_repository_read_dev_region_start(unsigned int bus_index, | ||
344 | unsigned int dev_index, unsigned int region_index, u64 *region_start); | ||
345 | |||
346 | /* repository pu and memory info */ | ||
347 | |||
348 | int ps3_repository_read_num_pu(unsigned int *num_pu); | ||
349 | int ps3_repository_read_ppe_id(unsigned int *pu_index, unsigned int *ppe_id); | ||
350 | int ps3_repository_read_rm_base(unsigned int ppe_id, u64 *rm_base); | ||
351 | int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size); | ||
352 | int ps3_repository_read_region_total(u64 *region_total); | ||
353 | int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, | ||
354 | u64 *region_total); | ||
355 | |||
356 | /* repository pme info */ | ||
357 | |||
358 | int ps3_repository_read_num_be(unsigned int *num_be); | ||
359 | int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id); | ||
360 | int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq); | ||
361 | int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq); | ||
362 | |||
363 | /* repository 'Other OS' area */ | ||
364 | |||
365 | int ps3_repository_read_boot_dat_addr(u64 *lpar_addr); | ||
366 | int ps3_repository_read_boot_dat_size(unsigned int *size); | ||
367 | int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size); | ||
368 | |||
369 | /* repository spu info */ | ||
370 | |||
371 | /** | ||
372 | * enum spu_resource_type - Type of spu resource. | ||
373 | * @spu_resource_type_shared: Logical spu is shared with other partions. | ||
374 | * @spu_resource_type_exclusive: Logical spu is not shared with other partions. | ||
375 | * | ||
376 | * Returned by ps3_repository_read_spu_resource_id(). | ||
377 | */ | ||
378 | |||
379 | enum ps3_spu_resource_type { | ||
380 | PS3_SPU_RESOURCE_TYPE_SHARED = 0, | ||
381 | PS3_SPU_RESOURCE_TYPE_EXCLUSIVE = 0x8000000000000000UL, | ||
382 | }; | ||
383 | |||
384 | int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved); | ||
385 | int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id); | ||
386 | int ps3_repository_read_spu_resource_id(unsigned int res_index, | ||
387 | enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); | ||
388 | |||
389 | |||
390 | /* system bus routines */ | ||
391 | |||
392 | enum ps3_match_id { | ||
393 | PS3_MATCH_ID_EHCI = 1, | ||
394 | PS3_MATCH_ID_OHCI, | ||
395 | PS3_MATCH_ID_GELIC, | ||
396 | PS3_MATCH_ID_AV_SETTINGS, | ||
397 | PS3_MATCH_ID_SYSTEM_MANAGER, | ||
398 | }; | ||
399 | |||
400 | /** | ||
401 | * struct ps3_system_bus_device - a device on the system bus | ||
402 | */ | ||
403 | |||
404 | struct ps3_system_bus_device { | ||
405 | enum ps3_match_id match_id; | ||
406 | struct ps3_device_id did; | ||
407 | unsigned int interrupt_id; | ||
408 | /* struct iommu_table *iommu_table; -- waiting for Ben's cleanups */ | ||
409 | struct ps3_dma_region *d_region; | ||
410 | struct ps3_mmio_region *m_region; | ||
411 | struct device core; | ||
412 | }; | ||
413 | |||
414 | /** | ||
415 | * struct ps3_system_bus_driver - a driver for a device on the system bus | ||
416 | */ | ||
417 | |||
418 | struct ps3_system_bus_driver { | ||
419 | enum ps3_match_id match_id; | ||
420 | struct device_driver core; | ||
421 | int (*probe)(struct ps3_system_bus_device *); | ||
422 | int (*remove)(struct ps3_system_bus_device *); | ||
423 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ | ||
424 | /* int (*resume)(struct ps3_system_bus_device *); */ | ||
425 | }; | ||
426 | |||
427 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); | ||
428 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); | ||
429 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); | ||
430 | static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver( | ||
431 | struct device_driver *_drv) | ||
432 | { | ||
433 | return container_of(_drv, struct ps3_system_bus_driver, core); | ||
434 | } | ||
435 | static inline struct ps3_system_bus_device *to_ps3_system_bus_device( | ||
436 | struct device *_dev) | ||
437 | { | ||
438 | return container_of(_dev, struct ps3_system_bus_device, core); | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * ps3_system_bus_set_drvdata - | ||
443 | * @dev: device structure | ||
444 | * @data: Data to set | ||
445 | */ | ||
446 | |||
447 | static inline void ps3_system_bus_set_driver_data( | ||
448 | struct ps3_system_bus_device *dev, void *data) | ||
449 | { | ||
450 | dev->core.driver_data = data; | ||
451 | } | ||
452 | static inline void *ps3_system_bus_get_driver_data( | ||
453 | struct ps3_system_bus_device *dev) | ||
454 | { | ||
455 | return dev->core.driver_data; | ||
456 | } | ||
457 | |||
458 | /* These two need global scope for get_dma_ops(). */ | ||
459 | |||
460 | extern struct bus_type ps3_system_bus_type; | ||
461 | |||
462 | #endif | ||
diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index d34f9e1f242..5a0c136c041 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h | |||
@@ -54,8 +54,6 @@ struct rtas_args { | |||
54 | rtas_arg_t *rets; /* Pointer to return values in args[]. */ | 54 | rtas_arg_t *rets; /* Pointer to return values in args[]. */ |
55 | }; | 55 | }; |
56 | 56 | ||
57 | extern struct rtas_args rtas_stop_self_args; | ||
58 | |||
59 | struct rtas_t { | 57 | struct rtas_t { |
60 | unsigned long entry; /* physical address pointer */ | 58 | unsigned long entry; /* physical address pointer */ |
61 | unsigned long base; /* physical address pointer */ | 59 | unsigned long base; /* physical address pointer */ |
diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h index 38b1ea3b58f..48ad807a0b8 100644 --- a/include/asm-powerpc/sparsemem.h +++ b/include/asm-powerpc/sparsemem.h | |||
@@ -9,8 +9,14 @@ | |||
9 | * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space | 9 | * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space |
10 | */ | 10 | */ |
11 | #define SECTION_SIZE_BITS 24 | 11 | #define SECTION_SIZE_BITS 24 |
12 | |||
13 | #if defined(CONFIG_PS3_USE_LPAR_ADDR) | ||
14 | #define MAX_PHYSADDR_BITS 47 | ||
15 | #define MAX_PHYSMEM_BITS 47 | ||
16 | #else | ||
12 | #define MAX_PHYSADDR_BITS 44 | 17 | #define MAX_PHYSADDR_BITS 44 |
13 | #define MAX_PHYSMEM_BITS 44 | 18 | #define MAX_PHYSMEM_BITS 44 |
19 | #endif | ||
14 | 20 | ||
15 | #ifdef CONFIG_MEMORY_HOTPLUG | 21 | #ifdef CONFIG_MEMORY_HOTPLUG |
16 | extern void create_section_mapping(unsigned long start, unsigned long end); | 22 | extern void create_section_mapping(unsigned long start, unsigned long end); |
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index e73ea00efd8..fdad4267b44 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h | |||
@@ -111,14 +111,12 @@ struct spu { | |||
111 | u8 *local_store; | 111 | u8 *local_store; |
112 | unsigned long problem_phys; | 112 | unsigned long problem_phys; |
113 | struct spu_problem __iomem *problem; | 113 | struct spu_problem __iomem *problem; |
114 | struct spu_priv1 __iomem *priv1; | ||
115 | struct spu_priv2 __iomem *priv2; | 114 | struct spu_priv2 __iomem *priv2; |
116 | struct list_head list; | 115 | struct list_head list; |
117 | struct list_head sched_list; | 116 | struct list_head sched_list; |
117 | struct list_head full_list; | ||
118 | int number; | 118 | int number; |
119 | int nid; | ||
120 | unsigned int irqs[3]; | 119 | unsigned int irqs[3]; |
121 | u32 isrc; | ||
122 | u32 node; | 120 | u32 node; |
123 | u64 flags; | 121 | u64 flags; |
124 | u64 dar; | 122 | u64 dar; |
@@ -144,6 +142,7 @@ struct spu { | |||
144 | char irq_c1[8]; | 142 | char irq_c1[8]; |
145 | char irq_c2[8]; | 143 | char irq_c2[8]; |
146 | 144 | ||
145 | void* pdata; /* platform private data */ | ||
147 | struct sys_device sysdev; | 146 | struct sys_device sysdev; |
148 | }; | 147 | }; |
149 | 148 | ||
@@ -170,6 +169,13 @@ extern struct spufs_calls { | |||
170 | struct module *owner; | 169 | struct module *owner; |
171 | } spufs_calls; | 170 | } spufs_calls; |
172 | 171 | ||
172 | /* coredump calls implemented in spufs */ | ||
173 | struct spu_coredump_calls { | ||
174 | asmlinkage int (*arch_notes_size)(void); | ||
175 | asmlinkage void (*arch_write_notes)(struct file *file); | ||
176 | struct module *owner; | ||
177 | }; | ||
178 | |||
173 | /* return status from spu_run, same as in libspe */ | 179 | /* return status from spu_run, same as in libspe */ |
174 | #define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */ | 180 | #define SPE_EVENT_DMA_ALIGNMENT 0x0008 /*A DMA alignment error */ |
175 | #define SPE_EVENT_SPE_ERROR 0x0010 /*An illegal instruction error*/ | 181 | #define SPE_EVENT_SPE_ERROR 0x0010 /*An illegal instruction error*/ |
@@ -182,8 +188,10 @@ extern struct spufs_calls { | |||
182 | */ | 188 | */ |
183 | #define SPU_CREATE_EVENTS_ENABLED 0x0001 | 189 | #define SPU_CREATE_EVENTS_ENABLED 0x0001 |
184 | #define SPU_CREATE_GANG 0x0002 | 190 | #define SPU_CREATE_GANG 0x0002 |
191 | #define SPU_CREATE_NOSCHED 0x0004 | ||
192 | #define SPU_CREATE_ISOLATE 0x0008 | ||
185 | 193 | ||
186 | #define SPU_CREATE_FLAG_ALL 0x0003 /* mask of all valid flags */ | 194 | #define SPU_CREATE_FLAG_ALL 0x000f /* mask of all valid flags */ |
187 | 195 | ||
188 | 196 | ||
189 | #ifdef CONFIG_SPU_FS_MODULE | 197 | #ifdef CONFIG_SPU_FS_MODULE |
@@ -199,6 +207,15 @@ static inline void unregister_spu_syscalls(struct spufs_calls *calls) | |||
199 | } | 207 | } |
200 | #endif /* MODULE */ | 208 | #endif /* MODULE */ |
201 | 209 | ||
210 | int register_arch_coredump_calls(struct spu_coredump_calls *calls); | ||
211 | void unregister_arch_coredump_calls(struct spu_coredump_calls *calls); | ||
212 | |||
213 | int spu_add_sysdev_attr(struct sysdev_attribute *attr); | ||
214 | void spu_remove_sysdev_attr(struct sysdev_attribute *attr); | ||
215 | |||
216 | int spu_add_sysdev_attr_group(struct attribute_group *attrs); | ||
217 | void spu_remove_sysdev_attr_group(struct attribute_group *attrs); | ||
218 | |||
202 | 219 | ||
203 | /* | 220 | /* |
204 | * Notifier blocks: | 221 | * Notifier blocks: |
@@ -277,6 +294,7 @@ struct spu_problem { | |||
277 | u32 spu_runcntl_RW; /* 0x401c */ | 294 | u32 spu_runcntl_RW; /* 0x401c */ |
278 | #define SPU_RUNCNTL_STOP 0L | 295 | #define SPU_RUNCNTL_STOP 0L |
279 | #define SPU_RUNCNTL_RUNNABLE 1L | 296 | #define SPU_RUNCNTL_RUNNABLE 1L |
297 | #define SPU_RUNCNTL_ISOLATE 2L | ||
280 | u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */ | 298 | u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */ |
281 | u32 spu_status_R; /* 0x4024 */ | 299 | u32 spu_status_R; /* 0x4024 */ |
282 | #define SPU_STOP_STATUS_SHIFT 16 | 300 | #define SPU_STOP_STATUS_SHIFT 16 |
@@ -289,8 +307,8 @@ struct spu_problem { | |||
289 | #define SPU_STATUS_INVALID_INSTR 0x20 | 307 | #define SPU_STATUS_INVALID_INSTR 0x20 |
290 | #define SPU_STATUS_INVALID_CH 0x40 | 308 | #define SPU_STATUS_INVALID_CH 0x40 |
291 | #define SPU_STATUS_ISOLATED_STATE 0x80 | 309 | #define SPU_STATUS_ISOLATED_STATE 0x80 |
292 | #define SPU_STATUS_ISOLATED_LOAD_STAUTUS 0x200 | 310 | #define SPU_STATUS_ISOLATED_LOAD_STATUS 0x200 |
293 | #define SPU_STATUS_ISOLATED_EXIT_STAUTUS 0x400 | 311 | #define SPU_STATUS_ISOLATED_EXIT_STATUS 0x400 |
294 | u8 pad_0x4028_0x402c[0x4]; /* 0x4028 */ | 312 | u8 pad_0x4028_0x402c[0x4]; /* 0x4028 */ |
295 | u32 spu_spe_R; /* 0x402c */ | 313 | u32 spu_spe_R; /* 0x402c */ |
296 | u8 pad_0x4030_0x4034[0x4]; /* 0x4030 */ | 314 | u8 pad_0x4030_0x4034[0x4]; /* 0x4030 */ |
diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h index 964c2d38ccb..bdbf906a767 100644 --- a/include/asm-powerpc/spu_csa.h +++ b/include/asm-powerpc/spu_csa.h | |||
@@ -151,7 +151,6 @@ struct spu_priv1_collapsed { | |||
151 | u64 mfc_fir_chkstp_enable_RW; | 151 | u64 mfc_fir_chkstp_enable_RW; |
152 | u64 smf_sbi_signal_sel; | 152 | u64 smf_sbi_signal_sel; |
153 | u64 smf_ato_signal_sel; | 153 | u64 smf_ato_signal_sel; |
154 | u64 mfc_sdr_RW; | ||
155 | u64 tlb_index_hint_RO; | 154 | u64 tlb_index_hint_RO; |
156 | u64 tlb_index_W; | 155 | u64 tlb_index_W; |
157 | u64 tlb_vpn_RW; | 156 | u64 tlb_vpn_RW; |
diff --git a/include/asm-powerpc/spu_info.h b/include/asm-powerpc/spu_info.h new file mode 100644 index 00000000000..3545efbf989 --- /dev/null +++ b/include/asm-powerpc/spu_info.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * SPU info structures | ||
3 | * | ||
4 | * (C) Copyright 2006 IBM Corp. | ||
5 | * | ||
6 | * Author: Dwayne Grant McConnell <decimal@us.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef _SPU_INFO_H | ||
24 | #define _SPU_INFO_H | ||
25 | |||
26 | #ifdef __KERNEL__ | ||
27 | #include <asm/spu.h> | ||
28 | #include <linux/types.h> | ||
29 | #else | ||
30 | struct mfc_cq_sr { | ||
31 | __u64 mfc_cq_data0_RW; | ||
32 | __u64 mfc_cq_data1_RW; | ||
33 | __u64 mfc_cq_data2_RW; | ||
34 | __u64 mfc_cq_data3_RW; | ||
35 | }; | ||
36 | #endif /* __KERNEL__ */ | ||
37 | |||
38 | struct spu_dma_info { | ||
39 | __u64 dma_info_type; | ||
40 | __u64 dma_info_mask; | ||
41 | __u64 dma_info_status; | ||
42 | __u64 dma_info_stall_and_notify; | ||
43 | __u64 dma_info_atomic_command_status; | ||
44 | struct mfc_cq_sr dma_info_command_data[16]; | ||
45 | }; | ||
46 | |||
47 | struct spu_proxydma_info { | ||
48 | __u64 proxydma_info_type; | ||
49 | __u64 proxydma_info_mask; | ||
50 | __u64 proxydma_info_status; | ||
51 | struct mfc_cq_sr proxydma_info_command_data[8]; | ||
52 | }; | ||
53 | |||
54 | #endif | ||
diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h index 300c458b6d0..69dcb0c5388 100644 --- a/include/asm-powerpc/spu_priv1.h +++ b/include/asm-powerpc/spu_priv1.h | |||
@@ -21,12 +21,13 @@ | |||
21 | #define _SPU_PRIV1_H | 21 | #define _SPU_PRIV1_H |
22 | #if defined(__KERNEL__) | 22 | #if defined(__KERNEL__) |
23 | 23 | ||
24 | #include <linux/types.h> | ||
25 | |||
24 | struct spu; | 26 | struct spu; |
25 | 27 | ||
26 | /* access to priv1 registers */ | 28 | /* access to priv1 registers */ |
27 | 29 | ||
28 | struct spu_priv1_ops | 30 | struct spu_priv1_ops { |
29 | { | ||
30 | void (*int_mask_and) (struct spu *spu, int class, u64 mask); | 31 | void (*int_mask_and) (struct spu *spu, int class, u64 mask); |
31 | void (*int_mask_or) (struct spu *spu, int class, u64 mask); | 32 | void (*int_mask_or) (struct spu *spu, int class, u64 mask); |
32 | void (*int_mask_set) (struct spu *spu, int class, u64 mask); | 33 | void (*int_mask_set) (struct spu *spu, int class, u64 mask); |
@@ -37,7 +38,7 @@ struct spu_priv1_ops | |||
37 | u64 (*mfc_dar_get) (struct spu *spu); | 38 | u64 (*mfc_dar_get) (struct spu *spu); |
38 | u64 (*mfc_dsisr_get) (struct spu *spu); | 39 | u64 (*mfc_dsisr_get) (struct spu *spu); |
39 | void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); | 40 | void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); |
40 | void (*mfc_sdr_set) (struct spu *spu, u64 sdr); | 41 | void (*mfc_sdr_setup) (struct spu *spu); |
41 | void (*mfc_sr1_set) (struct spu *spu, u64 sr1); | 42 | void (*mfc_sr1_set) (struct spu *spu, u64 sr1); |
42 | u64 (*mfc_sr1_get) (struct spu *spu); | 43 | u64 (*mfc_sr1_get) (struct spu *spu); |
43 | void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id); | 44 | void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id); |
@@ -112,9 +113,9 @@ spu_mfc_dsisr_set (struct spu *spu, u64 dsisr) | |||
112 | } | 113 | } |
113 | 114 | ||
114 | static inline void | 115 | static inline void |
115 | spu_mfc_sdr_set (struct spu *spu, u64 sdr) | 116 | spu_mfc_sdr_setup (struct spu *spu) |
116 | { | 117 | { |
117 | spu_priv1_ops->mfc_sdr_set(spu, sdr); | 118 | spu_priv1_ops->mfc_sdr_setup(spu); |
118 | } | 119 | } |
119 | 120 | ||
120 | static inline void | 121 | static inline void |
@@ -171,12 +172,41 @@ spu_resource_allocation_enable_get (struct spu *spu) | |||
171 | return spu_priv1_ops->resource_allocation_enable_get(spu); | 172 | return spu_priv1_ops->resource_allocation_enable_get(spu); |
172 | } | 173 | } |
173 | 174 | ||
174 | /* The declarations folowing are put here for convenience | 175 | /* spu management abstraction */ |
175 | * and only intended to be used by the platform setup code | 176 | |
176 | * for initializing spu_priv1_ops. | 177 | struct spu_management_ops { |
178 | int (*enumerate_spus)(int (*fn)(void *data)); | ||
179 | int (*create_spu)(struct spu *spu, void *data); | ||
180 | int (*destroy_spu)(struct spu *spu); | ||
181 | }; | ||
182 | |||
183 | extern const struct spu_management_ops* spu_management_ops; | ||
184 | |||
185 | static inline int | ||
186 | spu_enumerate_spus (int (*fn)(void *data)) | ||
187 | { | ||
188 | return spu_management_ops->enumerate_spus(fn); | ||
189 | } | ||
190 | |||
191 | static inline int | ||
192 | spu_create_spu (struct spu *spu, void *data) | ||
193 | { | ||
194 | return spu_management_ops->create_spu(spu, data); | ||
195 | } | ||
196 | |||
197 | static inline int | ||
198 | spu_destroy_spu (struct spu *spu) | ||
199 | { | ||
200 | return spu_management_ops->destroy_spu(spu); | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * The declarations folowing are put here for convenience | ||
205 | * and only intended to be used by the platform setup code. | ||
177 | */ | 206 | */ |
178 | 207 | ||
179 | extern const struct spu_priv1_ops spu_priv1_mmio_ops; | 208 | extern const struct spu_priv1_ops spu_priv1_mmio_ops; |
209 | extern const struct spu_management_ops spu_management_of_ops; | ||
180 | 210 | ||
181 | #endif /* __KERNEL__ */ | 211 | #endif /* __KERNEL__ */ |
182 | #endif | 212 | #endif |
diff --git a/include/asm-powerpc/todc.h b/include/asm-powerpc/todc.h deleted file mode 100644 index 60a8c39b8c1..00000000000 --- a/include/asm-powerpc/todc.h +++ /dev/null | |||
@@ -1,487 +0,0 @@ | |||
1 | /* | ||
2 | * Definitions for the M48Txx and mc146818 series of Time of day/Real Time | ||
3 | * Clock chips. | ||
4 | * | ||
5 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
6 | * | ||
7 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
8 | * the terms of the GNU General Public License version 2. This program | ||
9 | * is licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips. | ||
15 | * Purpose is to make one generic file that handles all of these chips instead | ||
16 | * of every platform implementing the same code over & over again. | ||
17 | */ | ||
18 | |||
19 | #ifndef __PPC_KERNEL_TODC_H | ||
20 | #define __PPC_KERNEL_TODC_H | ||
21 | |||
22 | typedef struct { | ||
23 | uint rtc_type; /* your particular chip */ | ||
24 | |||
25 | /* | ||
26 | * Following are the addresses of the AS0, AS1, and DATA registers | ||
27 | * of these chips. Note that these are board-specific. | ||
28 | */ | ||
29 | unsigned int nvram_as0; | ||
30 | unsigned int nvram_as1; | ||
31 | unsigned int nvram_data; | ||
32 | |||
33 | /* | ||
34 | * Define bits to stop external set of regs from changing so | ||
35 | * the chip can be read/written reliably. | ||
36 | */ | ||
37 | unsigned char enable_read; | ||
38 | unsigned char enable_write; | ||
39 | |||
40 | /* | ||
41 | * Following is the number of AS0 address bits. This is normally | ||
42 | * 8 but some bad hardware routes address lines incorrectly. | ||
43 | */ | ||
44 | int as0_bits; | ||
45 | |||
46 | int nvram_size; /* Size of NVRAM on chip */ | ||
47 | int sw_flags; /* Software control flags */ | ||
48 | |||
49 | /* Following are the register offsets for the particular chip */ | ||
50 | int year; | ||
51 | int month; | ||
52 | int day_of_month; | ||
53 | int day_of_week; | ||
54 | int hours; | ||
55 | int minutes; | ||
56 | int seconds; | ||
57 | int control_b; | ||
58 | int control_a; | ||
59 | int watchdog; | ||
60 | int interrupts; | ||
61 | int alarm_date; | ||
62 | int alarm_hour; | ||
63 | int alarm_minutes; | ||
64 | int alarm_seconds; | ||
65 | int century; | ||
66 | int flags; | ||
67 | |||
68 | /* | ||
69 | * Some RTC chips have their NVRAM buried behind a addr/data pair of | ||
70 | * regs on the first level/clock registers. The following fields | ||
71 | * are the addresses for those addr/data regs. | ||
72 | */ | ||
73 | int nvram_addr_reg; | ||
74 | int nvram_data_reg; | ||
75 | } todc_info_t; | ||
76 | |||
77 | /* | ||
78 | * Define the types of TODC/RTC variants that are supported in | ||
79 | * arch/ppc/kernel/todc_time.c | ||
80 | * Make a new one of these for any chip somehow differs from what's already | ||
81 | * defined. That way, if you ever need to put in code to touch those | ||
82 | * bits/registers in todc_time.c, you can put it inside an | ||
83 | * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break | ||
84 | * anyone else. | ||
85 | */ | ||
86 | #define TODC_TYPE_MK48T35 1 | ||
87 | #define TODC_TYPE_MK48T37 2 | ||
88 | #define TODC_TYPE_MK48T59 3 | ||
89 | #define TODC_TYPE_DS1693 4 /* Dallas DS1693 RTC */ | ||
90 | #define TODC_TYPE_DS1743 5 /* Dallas DS1743 RTC */ | ||
91 | #define TODC_TYPE_DS1746 6 /* Dallas DS1746 RTC */ | ||
92 | #define TODC_TYPE_DS1747 7 /* Dallas DS1747 RTC */ | ||
93 | #define TODC_TYPE_DS1501 8 /* Dallas DS1501 RTC */ | ||
94 | #define TODC_TYPE_DS1643 9 /* Dallas DS1643 RTC */ | ||
95 | #define TODC_TYPE_PC97307 10 /* PC97307 internal RTC */ | ||
96 | #define TODC_TYPE_DS1557 11 /* Dallas DS1557 RTC */ | ||
97 | #define TODC_TYPE_DS17285 12 /* Dallas DS17285 RTC */ | ||
98 | #define TODC_TYPE_DS1553 13 /* Dallas DS1553 RTC */ | ||
99 | #define TODC_TYPE_MC146818 100 /* Leave room for m48txx's */ | ||
100 | |||
101 | /* | ||
102 | * Bit to clear/set to enable reads/writes to the chip | ||
103 | */ | ||
104 | #define TODC_MK48TXX_CNTL_A_R 0x40 | ||
105 | #define TODC_MK48TXX_CNTL_A_W 0x80 | ||
106 | #define TODC_MK48TXX_DAY_CB 0x80 | ||
107 | |||
108 | #define TODC_DS1501_CNTL_B_TE 0x80 | ||
109 | |||
110 | /* | ||
111 | * Define flag bits used by todc routines. | ||
112 | */ | ||
113 | #define TODC_FLAG_2_LEVEL_NVRAM 0x00000001 | ||
114 | |||
115 | /* | ||
116 | * Define the values for the various RTC's that should to into the todc_info | ||
117 | * table. | ||
118 | * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only | ||
119 | * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set. | ||
120 | */ | ||
121 | #define TODC_TYPE_MK48T35_NVRAM_SIZE 0x7ff8 | ||
122 | #define TODC_TYPE_MK48T35_SW_FLAGS 0 | ||
123 | #define TODC_TYPE_MK48T35_YEAR 0x7fff | ||
124 | #define TODC_TYPE_MK48T35_MONTH 0x7ffe | ||
125 | #define TODC_TYPE_MK48T35_DOM 0x7ffd /* Day of Month */ | ||
126 | #define TODC_TYPE_MK48T35_DOW 0x7ffc /* Day of Week */ | ||
127 | #define TODC_TYPE_MK48T35_HOURS 0x7ffb | ||
128 | #define TODC_TYPE_MK48T35_MINUTES 0x7ffa | ||
129 | #define TODC_TYPE_MK48T35_SECONDS 0x7ff9 | ||
130 | #define TODC_TYPE_MK48T35_CNTL_B 0x7ff9 | ||
131 | #define TODC_TYPE_MK48T35_CNTL_A 0x7ff8 | ||
132 | #define TODC_TYPE_MK48T35_WATCHDOG 0x0000 | ||
133 | #define TODC_TYPE_MK48T35_INTERRUPTS 0x0000 | ||
134 | #define TODC_TYPE_MK48T35_ALARM_DATE 0x0000 | ||
135 | #define TODC_TYPE_MK48T35_ALARM_HOUR 0x0000 | ||
136 | #define TODC_TYPE_MK48T35_ALARM_MINUTES 0x0000 | ||
137 | #define TODC_TYPE_MK48T35_ALARM_SECONDS 0x0000 | ||
138 | #define TODC_TYPE_MK48T35_CENTURY 0x0000 | ||
139 | #define TODC_TYPE_MK48T35_FLAGS 0x0000 | ||
140 | #define TODC_TYPE_MK48T35_NVRAM_ADDR_REG 0 | ||
141 | #define TODC_TYPE_MK48T35_NVRAM_DATA_REG 0 | ||
142 | |||
143 | #define TODC_TYPE_MK48T37_NVRAM_SIZE 0x7ff0 | ||
144 | #define TODC_TYPE_MK48T37_SW_FLAGS 0 | ||
145 | #define TODC_TYPE_MK48T37_YEAR 0x7fff | ||
146 | #define TODC_TYPE_MK48T37_MONTH 0x7ffe | ||
147 | #define TODC_TYPE_MK48T37_DOM 0x7ffd /* Day of Month */ | ||
148 | #define TODC_TYPE_MK48T37_DOW 0x7ffc /* Day of Week */ | ||
149 | #define TODC_TYPE_MK48T37_HOURS 0x7ffb | ||
150 | #define TODC_TYPE_MK48T37_MINUTES 0x7ffa | ||
151 | #define TODC_TYPE_MK48T37_SECONDS 0x7ff9 | ||
152 | #define TODC_TYPE_MK48T37_CNTL_B 0x7ff9 | ||
153 | #define TODC_TYPE_MK48T37_CNTL_A 0x7ff8 | ||
154 | #define TODC_TYPE_MK48T37_WATCHDOG 0x7ff7 | ||
155 | #define TODC_TYPE_MK48T37_INTERRUPTS 0x7ff6 | ||
156 | #define TODC_TYPE_MK48T37_ALARM_DATE 0x7ff5 | ||
157 | #define TODC_TYPE_MK48T37_ALARM_HOUR 0x7ff4 | ||
158 | #define TODC_TYPE_MK48T37_ALARM_MINUTES 0x7ff3 | ||
159 | #define TODC_TYPE_MK48T37_ALARM_SECONDS 0x7ff2 | ||
160 | #define TODC_TYPE_MK48T37_CENTURY 0x7ff1 | ||
161 | #define TODC_TYPE_MK48T37_FLAGS 0x7ff0 | ||
162 | #define TODC_TYPE_MK48T37_NVRAM_ADDR_REG 0 | ||
163 | #define TODC_TYPE_MK48T37_NVRAM_DATA_REG 0 | ||
164 | |||
165 | #define TODC_TYPE_MK48T59_NVRAM_SIZE 0x1ff0 | ||
166 | #define TODC_TYPE_MK48T59_SW_FLAGS 0 | ||
167 | #define TODC_TYPE_MK48T59_YEAR 0x1fff | ||
168 | #define TODC_TYPE_MK48T59_MONTH 0x1ffe | ||
169 | #define TODC_TYPE_MK48T59_DOM 0x1ffd /* Day of Month */ | ||
170 | #define TODC_TYPE_MK48T59_DOW 0x1ffc /* Day of Week */ | ||
171 | #define TODC_TYPE_MK48T59_HOURS 0x1ffb | ||
172 | #define TODC_TYPE_MK48T59_MINUTES 0x1ffa | ||
173 | #define TODC_TYPE_MK48T59_SECONDS 0x1ff9 | ||
174 | #define TODC_TYPE_MK48T59_CNTL_B 0x1ff9 | ||
175 | #define TODC_TYPE_MK48T59_CNTL_A 0x1ff8 | ||
176 | #define TODC_TYPE_MK48T59_WATCHDOG 0x1fff | ||
177 | #define TODC_TYPE_MK48T59_INTERRUPTS 0x1fff | ||
178 | #define TODC_TYPE_MK48T59_ALARM_DATE 0x1fff | ||
179 | #define TODC_TYPE_MK48T59_ALARM_HOUR 0x1fff | ||
180 | #define TODC_TYPE_MK48T59_ALARM_MINUTES 0x1fff | ||
181 | #define TODC_TYPE_MK48T59_ALARM_SECONDS 0x1fff | ||
182 | #define TODC_TYPE_MK48T59_CENTURY 0x1fff | ||
183 | #define TODC_TYPE_MK48T59_FLAGS 0x1fff | ||
184 | #define TODC_TYPE_MK48T59_NVRAM_ADDR_REG 0 | ||
185 | #define TODC_TYPE_MK48T59_NVRAM_DATA_REG 0 | ||
186 | |||
187 | #define TODC_TYPE_DS1501_NVRAM_SIZE 0x100 | ||
188 | #define TODC_TYPE_DS1501_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM | ||
189 | #define TODC_TYPE_DS1501_YEAR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06) | ||
190 | #define TODC_TYPE_DS1501_MONTH (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05) | ||
191 | #define TODC_TYPE_DS1501_DOM (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04) | ||
192 | #define TODC_TYPE_DS1501_DOW (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03) | ||
193 | #define TODC_TYPE_DS1501_HOURS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02) | ||
194 | #define TODC_TYPE_DS1501_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01) | ||
195 | #define TODC_TYPE_DS1501_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00) | ||
196 | #define TODC_TYPE_DS1501_CNTL_B (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) | ||
197 | #define TODC_TYPE_DS1501_CNTL_A (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) | ||
198 | #define TODC_TYPE_DS1501_WATCHDOG (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) | ||
199 | #define TODC_TYPE_DS1501_INTERRUPTS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) | ||
200 | #define TODC_TYPE_DS1501_ALARM_DATE (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b) | ||
201 | #define TODC_TYPE_DS1501_ALARM_HOUR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a) | ||
202 | #define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09) | ||
203 | #define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08) | ||
204 | #define TODC_TYPE_DS1501_CENTURY (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07) | ||
205 | #define TODC_TYPE_DS1501_FLAGS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) | ||
206 | #define TODC_TYPE_DS1501_NVRAM_ADDR_REG 0x10 | ||
207 | #define TODC_TYPE_DS1501_NVRAM_DATA_REG 0x13 | ||
208 | |||
209 | #define TODC_TYPE_DS1553_NVRAM_SIZE 0x1ff0 | ||
210 | #define TODC_TYPE_DS1553_SW_FLAGS 0 | ||
211 | #define TODC_TYPE_DS1553_YEAR 0x1fff | ||
212 | #define TODC_TYPE_DS1553_MONTH 0x1ffe | ||
213 | #define TODC_TYPE_DS1553_DOM 0x1ffd /* Day of Month */ | ||
214 | #define TODC_TYPE_DS1553_DOW 0x1ffc /* Day of Week */ | ||
215 | #define TODC_TYPE_DS1553_HOURS 0x1ffb | ||
216 | #define TODC_TYPE_DS1553_MINUTES 0x1ffa | ||
217 | #define TODC_TYPE_DS1553_SECONDS 0x1ff9 | ||
218 | #define TODC_TYPE_DS1553_CNTL_B 0x1ff9 | ||
219 | #define TODC_TYPE_DS1553_CNTL_A 0x1ff8 /* control_a R/W regs */ | ||
220 | #define TODC_TYPE_DS1553_WATCHDOG 0x1ff7 | ||
221 | #define TODC_TYPE_DS1553_INTERRUPTS 0x1ff6 | ||
222 | #define TODC_TYPE_DS1553_ALARM_DATE 0x1ff5 | ||
223 | #define TODC_TYPE_DS1553_ALARM_HOUR 0x1ff4 | ||
224 | #define TODC_TYPE_DS1553_ALARM_MINUTES 0x1ff3 | ||
225 | #define TODC_TYPE_DS1553_ALARM_SECONDS 0x1ff2 | ||
226 | #define TODC_TYPE_DS1553_CENTURY 0x1ff8 | ||
227 | #define TODC_TYPE_DS1553_FLAGS 0x1ff0 | ||
228 | #define TODC_TYPE_DS1553_NVRAM_ADDR_REG 0 | ||
229 | #define TODC_TYPE_DS1553_NVRAM_DATA_REG 0 | ||
230 | |||
231 | #define TODC_TYPE_DS1557_NVRAM_SIZE 0x7fff0 | ||
232 | #define TODC_TYPE_DS1557_SW_FLAGS 0 | ||
233 | #define TODC_TYPE_DS1557_YEAR 0x7ffff | ||
234 | #define TODC_TYPE_DS1557_MONTH 0x7fffe | ||
235 | #define TODC_TYPE_DS1557_DOM 0x7fffd /* Day of Month */ | ||
236 | #define TODC_TYPE_DS1557_DOW 0x7fffc /* Day of Week */ | ||
237 | #define TODC_TYPE_DS1557_HOURS 0x7fffb | ||
238 | #define TODC_TYPE_DS1557_MINUTES 0x7fffa | ||
239 | #define TODC_TYPE_DS1557_SECONDS 0x7fff9 | ||
240 | #define TODC_TYPE_DS1557_CNTL_B 0x7fff9 | ||
241 | #define TODC_TYPE_DS1557_CNTL_A 0x7fff8 /* control_a R/W regs */ | ||
242 | #define TODC_TYPE_DS1557_WATCHDOG 0x7fff7 | ||
243 | #define TODC_TYPE_DS1557_INTERRUPTS 0x7fff6 | ||
244 | #define TODC_TYPE_DS1557_ALARM_DATE 0x7fff5 | ||
245 | #define TODC_TYPE_DS1557_ALARM_HOUR 0x7fff4 | ||
246 | #define TODC_TYPE_DS1557_ALARM_MINUTES 0x7fff3 | ||
247 | #define TODC_TYPE_DS1557_ALARM_SECONDS 0x7fff2 | ||
248 | #define TODC_TYPE_DS1557_CENTURY 0x7fff8 | ||
249 | #define TODC_TYPE_DS1557_FLAGS 0x7fff0 | ||
250 | #define TODC_TYPE_DS1557_NVRAM_ADDR_REG 0 | ||
251 | #define TODC_TYPE_DS1557_NVRAM_DATA_REG 0 | ||
252 | |||
253 | #define TODC_TYPE_DS1643_NVRAM_SIZE 0x1ff8 | ||
254 | #define TODC_TYPE_DS1643_SW_FLAGS 0 | ||
255 | #define TODC_TYPE_DS1643_YEAR 0x1fff | ||
256 | #define TODC_TYPE_DS1643_MONTH 0x1ffe | ||
257 | #define TODC_TYPE_DS1643_DOM 0x1ffd /* Day of Month */ | ||
258 | #define TODC_TYPE_DS1643_DOW 0x1ffc /* Day of Week */ | ||
259 | #define TODC_TYPE_DS1643_HOURS 0x1ffb | ||
260 | #define TODC_TYPE_DS1643_MINUTES 0x1ffa | ||
261 | #define TODC_TYPE_DS1643_SECONDS 0x1ff9 | ||
262 | #define TODC_TYPE_DS1643_CNTL_B 0x1ff9 | ||
263 | #define TODC_TYPE_DS1643_CNTL_A 0x1ff8 /* control_a R/W regs */ | ||
264 | #define TODC_TYPE_DS1643_WATCHDOG 0x1fff | ||
265 | #define TODC_TYPE_DS1643_INTERRUPTS 0x1fff | ||
266 | #define TODC_TYPE_DS1643_ALARM_DATE 0x1fff | ||
267 | #define TODC_TYPE_DS1643_ALARM_HOUR 0x1fff | ||
268 | #define TODC_TYPE_DS1643_ALARM_MINUTES 0x1fff | ||
269 | #define TODC_TYPE_DS1643_ALARM_SECONDS 0x1fff | ||
270 | #define TODC_TYPE_DS1643_CENTURY 0x1ff8 | ||
271 | #define TODC_TYPE_DS1643_FLAGS 0x1fff | ||
272 | #define TODC_TYPE_DS1643_NVRAM_ADDR_REG 0 | ||
273 | #define TODC_TYPE_DS1643_NVRAM_DATA_REG 0 | ||
274 | |||
275 | #define TODC_TYPE_DS1693_NVRAM_SIZE 0 /* Not handled yet */ | ||
276 | #define TODC_TYPE_DS1693_SW_FLAGS 0 | ||
277 | #define TODC_TYPE_DS1693_YEAR 0x09 | ||
278 | #define TODC_TYPE_DS1693_MONTH 0x08 | ||
279 | #define TODC_TYPE_DS1693_DOM 0x07 /* Day of Month */ | ||
280 | #define TODC_TYPE_DS1693_DOW 0x06 /* Day of Week */ | ||
281 | #define TODC_TYPE_DS1693_HOURS 0x04 | ||
282 | #define TODC_TYPE_DS1693_MINUTES 0x02 | ||
283 | #define TODC_TYPE_DS1693_SECONDS 0x00 | ||
284 | #define TODC_TYPE_DS1693_CNTL_B 0x0b | ||
285 | #define TODC_TYPE_DS1693_CNTL_A 0x0a | ||
286 | #define TODC_TYPE_DS1693_WATCHDOG 0xff | ||
287 | #define TODC_TYPE_DS1693_INTERRUPTS 0xff | ||
288 | #define TODC_TYPE_DS1693_ALARM_DATE 0x49 | ||
289 | #define TODC_TYPE_DS1693_ALARM_HOUR 0x05 | ||
290 | #define TODC_TYPE_DS1693_ALARM_MINUTES 0x03 | ||
291 | #define TODC_TYPE_DS1693_ALARM_SECONDS 0x01 | ||
292 | #define TODC_TYPE_DS1693_CENTURY 0x48 | ||
293 | #define TODC_TYPE_DS1693_FLAGS 0xff | ||
294 | #define TODC_TYPE_DS1693_NVRAM_ADDR_REG 0 | ||
295 | #define TODC_TYPE_DS1693_NVRAM_DATA_REG 0 | ||
296 | |||
297 | #define TODC_TYPE_DS1743_NVRAM_SIZE 0x1ff8 | ||
298 | #define TODC_TYPE_DS1743_SW_FLAGS 0 | ||
299 | #define TODC_TYPE_DS1743_YEAR 0x1fff | ||
300 | #define TODC_TYPE_DS1743_MONTH 0x1ffe | ||
301 | #define TODC_TYPE_DS1743_DOM 0x1ffd /* Day of Month */ | ||
302 | #define TODC_TYPE_DS1743_DOW 0x1ffc /* Day of Week */ | ||
303 | #define TODC_TYPE_DS1743_HOURS 0x1ffb | ||
304 | #define TODC_TYPE_DS1743_MINUTES 0x1ffa | ||
305 | #define TODC_TYPE_DS1743_SECONDS 0x1ff9 | ||
306 | #define TODC_TYPE_DS1743_CNTL_B 0x1ff9 | ||
307 | #define TODC_TYPE_DS1743_CNTL_A 0x1ff8 /* control_a R/W regs */ | ||
308 | #define TODC_TYPE_DS1743_WATCHDOG 0x1fff | ||
309 | #define TODC_TYPE_DS1743_INTERRUPTS 0x1fff | ||
310 | #define TODC_TYPE_DS1743_ALARM_DATE 0x1fff | ||
311 | #define TODC_TYPE_DS1743_ALARM_HOUR 0x1fff | ||
312 | #define TODC_TYPE_DS1743_ALARM_MINUTES 0x1fff | ||
313 | #define TODC_TYPE_DS1743_ALARM_SECONDS 0x1fff | ||
314 | #define TODC_TYPE_DS1743_CENTURY 0x1ff8 | ||
315 | #define TODC_TYPE_DS1743_FLAGS 0x1fff | ||
316 | #define TODC_TYPE_DS1743_NVRAM_ADDR_REG 0 | ||
317 | #define TODC_TYPE_DS1743_NVRAM_DATA_REG 0 | ||
318 | |||
319 | #define TODC_TYPE_DS1746_NVRAM_SIZE 0x1fff8 | ||
320 | #define TODC_TYPE_DS1746_SW_FLAGS 0 | ||
321 | #define TODC_TYPE_DS1746_YEAR 0x1ffff | ||
322 | #define TODC_TYPE_DS1746_MONTH 0x1fffe | ||
323 | #define TODC_TYPE_DS1746_DOM 0x1fffd /* Day of Month */ | ||
324 | #define TODC_TYPE_DS1746_DOW 0x1fffc /* Day of Week */ | ||
325 | #define TODC_TYPE_DS1746_HOURS 0x1fffb | ||
326 | #define TODC_TYPE_DS1746_MINUTES 0x1fffa | ||
327 | #define TODC_TYPE_DS1746_SECONDS 0x1fff9 | ||
328 | #define TODC_TYPE_DS1746_CNTL_B 0x1fff9 | ||
329 | #define TODC_TYPE_DS1746_CNTL_A 0x1fff8 /* control_a R/W regs */ | ||
330 | #define TODC_TYPE_DS1746_WATCHDOG 0x00000 | ||
331 | #define TODC_TYPE_DS1746_INTERRUPTS 0x00000 | ||
332 | #define TODC_TYPE_DS1746_ALARM_DATE 0x00000 | ||
333 | #define TODC_TYPE_DS1746_ALARM_HOUR 0x00000 | ||
334 | #define TODC_TYPE_DS1746_ALARM_MINUTES 0x00000 | ||
335 | #define TODC_TYPE_DS1746_ALARM_SECONDS 0x00000 | ||
336 | #define TODC_TYPE_DS1746_CENTURY 0x00000 | ||
337 | #define TODC_TYPE_DS1746_FLAGS 0x00000 | ||
338 | #define TODC_TYPE_DS1746_NVRAM_ADDR_REG 0 | ||
339 | #define TODC_TYPE_DS1746_NVRAM_DATA_REG 0 | ||
340 | |||
341 | #define TODC_TYPE_DS1747_NVRAM_SIZE 0x7fff8 | ||
342 | #define TODC_TYPE_DS1747_SW_FLAGS 0 | ||
343 | #define TODC_TYPE_DS1747_YEAR 0x7ffff | ||
344 | #define TODC_TYPE_DS1747_MONTH 0x7fffe | ||
345 | #define TODC_TYPE_DS1747_DOM 0x7fffd /* Day of Month */ | ||
346 | #define TODC_TYPE_DS1747_DOW 0x7fffc /* Day of Week */ | ||
347 | #define TODC_TYPE_DS1747_HOURS 0x7fffb | ||
348 | #define TODC_TYPE_DS1747_MINUTES 0x7fffa | ||
349 | #define TODC_TYPE_DS1747_SECONDS 0x7fff9 | ||
350 | #define TODC_TYPE_DS1747_CNTL_B 0x7fff9 | ||
351 | #define TODC_TYPE_DS1747_CNTL_A 0x7fff8 /* control_a R/W regs */ | ||
352 | #define TODC_TYPE_DS1747_WATCHDOG 0x00000 | ||
353 | #define TODC_TYPE_DS1747_INTERRUPTS 0x00000 | ||
354 | #define TODC_TYPE_DS1747_ALARM_DATE 0x00000 | ||
355 | #define TODC_TYPE_DS1747_ALARM_HOUR 0x00000 | ||
356 | #define TODC_TYPE_DS1747_ALARM_MINUTES 0x00000 | ||
357 | #define TODC_TYPE_DS1747_ALARM_SECONDS 0x00000 | ||
358 | #define TODC_TYPE_DS1747_CENTURY 0x00000 | ||
359 | #define TODC_TYPE_DS1747_FLAGS 0x00000 | ||
360 | #define TODC_TYPE_DS1747_NVRAM_ADDR_REG 0 | ||
361 | #define TODC_TYPE_DS1747_NVRAM_DATA_REG 0 | ||
362 | |||
363 | #define TODC_TYPE_DS17285_NVRAM_SIZE (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */ | ||
364 | #define TODC_TYPE_DS17285_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM | ||
365 | #define TODC_TYPE_DS17285_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00) | ||
366 | #define TODC_TYPE_DS17285_ALARM_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01) | ||
367 | #define TODC_TYPE_DS17285_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02) | ||
368 | #define TODC_TYPE_DS17285_ALARM_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03) | ||
369 | #define TODC_TYPE_DS17285_HOURS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04) | ||
370 | #define TODC_TYPE_DS17285_ALARM_HOUR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05) | ||
371 | #define TODC_TYPE_DS17285_DOW (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06) | ||
372 | #define TODC_TYPE_DS17285_DOM (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07) | ||
373 | #define TODC_TYPE_DS17285_MONTH (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08) | ||
374 | #define TODC_TYPE_DS17285_YEAR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09) | ||
375 | #define TODC_TYPE_DS17285_CNTL_A (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A) | ||
376 | #define TODC_TYPE_DS17285_CNTL_B (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B) | ||
377 | #define TODC_TYPE_DS17285_CNTL_C (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C) | ||
378 | #define TODC_TYPE_DS17285_CNTL_D (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D) | ||
379 | #define TODC_TYPE_DS17285_WATCHDOG 0 | ||
380 | #define TODC_TYPE_DS17285_INTERRUPTS 0 | ||
381 | #define TODC_TYPE_DS17285_ALARM_DATE 0 | ||
382 | #define TODC_TYPE_DS17285_CENTURY 0 | ||
383 | #define TODC_TYPE_DS17285_FLAGS 0 | ||
384 | #define TODC_TYPE_DS17285_NVRAM_ADDR_REG 0x50 | ||
385 | #define TODC_TYPE_DS17285_NVRAM_DATA_REG 0x53 | ||
386 | |||
387 | #define TODC_TYPE_MC146818_NVRAM_SIZE 0 /* XXXX */ | ||
388 | #define TODC_TYPE_MC146818_SW_FLAGS 0 | ||
389 | #define TODC_TYPE_MC146818_YEAR 0x09 | ||
390 | #define TODC_TYPE_MC146818_MONTH 0x08 | ||
391 | #define TODC_TYPE_MC146818_DOM 0x07 /* Day of Month */ | ||
392 | #define TODC_TYPE_MC146818_DOW 0x06 /* Day of Week */ | ||
393 | #define TODC_TYPE_MC146818_HOURS 0x04 | ||
394 | #define TODC_TYPE_MC146818_MINUTES 0x02 | ||
395 | #define TODC_TYPE_MC146818_SECONDS 0x00 | ||
396 | #define TODC_TYPE_MC146818_CNTL_B 0x0a | ||
397 | #define TODC_TYPE_MC146818_CNTL_A 0x0b /* control_a R/W regs */ | ||
398 | #define TODC_TYPE_MC146818_WATCHDOG 0 | ||
399 | #define TODC_TYPE_MC146818_INTERRUPTS 0x0c | ||
400 | #define TODC_TYPE_MC146818_ALARM_DATE 0xff | ||
401 | #define TODC_TYPE_MC146818_ALARM_HOUR 0x05 | ||
402 | #define TODC_TYPE_MC146818_ALARM_MINUTES 0x03 | ||
403 | #define TODC_TYPE_MC146818_ALARM_SECONDS 0x01 | ||
404 | #define TODC_TYPE_MC146818_CENTURY 0xff | ||
405 | #define TODC_TYPE_MC146818_FLAGS 0xff | ||
406 | #define TODC_TYPE_MC146818_NVRAM_ADDR_REG 0 | ||
407 | #define TODC_TYPE_MC146818_NVRAM_DATA_REG 0 | ||
408 | |||
409 | #define TODC_TYPE_PC97307_NVRAM_SIZE 0 /* No NVRAM? */ | ||
410 | #define TODC_TYPE_PC97307_SW_FLAGS 0 | ||
411 | #define TODC_TYPE_PC97307_YEAR 0x09 | ||
412 | #define TODC_TYPE_PC97307_MONTH 0x08 | ||
413 | #define TODC_TYPE_PC97307_DOM 0x07 /* Day of Month */ | ||
414 | #define TODC_TYPE_PC97307_DOW 0x06 /* Day of Week */ | ||
415 | #define TODC_TYPE_PC97307_HOURS 0x04 | ||
416 | #define TODC_TYPE_PC97307_MINUTES 0x02 | ||
417 | #define TODC_TYPE_PC97307_SECONDS 0x00 | ||
418 | #define TODC_TYPE_PC97307_CNTL_B 0x0a | ||
419 | #define TODC_TYPE_PC97307_CNTL_A 0x0b /* control_a R/W regs */ | ||
420 | #define TODC_TYPE_PC97307_WATCHDOG 0x0c | ||
421 | #define TODC_TYPE_PC97307_INTERRUPTS 0x0d | ||
422 | #define TODC_TYPE_PC97307_ALARM_DATE 0xff | ||
423 | #define TODC_TYPE_PC97307_ALARM_HOUR 0x05 | ||
424 | #define TODC_TYPE_PC97307_ALARM_MINUTES 0x03 | ||
425 | #define TODC_TYPE_PC97307_ALARM_SECONDS 0x01 | ||
426 | #define TODC_TYPE_PC97307_CENTURY 0xff | ||
427 | #define TODC_TYPE_PC97307_FLAGS 0xff | ||
428 | #define TODC_TYPE_PC97307_NVRAM_ADDR_REG 0 | ||
429 | #define TODC_TYPE_PC97307_NVRAM_DATA_REG 0 | ||
430 | |||
431 | /* | ||
432 | * Define macros to allocate and init the todc_info_t table that will | ||
433 | * be used by the todc_time.c routines. | ||
434 | */ | ||
435 | #define TODC_ALLOC() \ | ||
436 | static todc_info_t todc_info_alloc; \ | ||
437 | todc_info_t *todc_info = &todc_info_alloc; | ||
438 | |||
439 | #define TODC_INIT(clock_type, as0, as1, data, bits) { \ | ||
440 | todc_info->rtc_type = clock_type; \ | ||
441 | \ | ||
442 | todc_info->nvram_as0 = (unsigned int)(as0); \ | ||
443 | todc_info->nvram_as1 = (unsigned int)(as1); \ | ||
444 | todc_info->nvram_data = (unsigned int)(data); \ | ||
445 | \ | ||
446 | todc_info->as0_bits = (bits); \ | ||
447 | \ | ||
448 | todc_info->nvram_size = clock_type ##_NVRAM_SIZE; \ | ||
449 | todc_info->sw_flags = clock_type ##_SW_FLAGS; \ | ||
450 | \ | ||
451 | todc_info->year = clock_type ##_YEAR; \ | ||
452 | todc_info->month = clock_type ##_MONTH; \ | ||
453 | todc_info->day_of_month = clock_type ##_DOM; \ | ||
454 | todc_info->day_of_week = clock_type ##_DOW; \ | ||
455 | todc_info->hours = clock_type ##_HOURS; \ | ||
456 | todc_info->minutes = clock_type ##_MINUTES; \ | ||
457 | todc_info->seconds = clock_type ##_SECONDS; \ | ||
458 | todc_info->control_b = clock_type ##_CNTL_B; \ | ||
459 | todc_info->control_a = clock_type ##_CNTL_A; \ | ||
460 | todc_info->watchdog = clock_type ##_WATCHDOG; \ | ||
461 | todc_info->interrupts = clock_type ##_INTERRUPTS; \ | ||
462 | todc_info->alarm_date = clock_type ##_ALARM_DATE; \ | ||
463 | todc_info->alarm_hour = clock_type ##_ALARM_HOUR; \ | ||
464 | todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES; \ | ||
465 | todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS; \ | ||
466 | todc_info->century = clock_type ##_CENTURY; \ | ||
467 | todc_info->flags = clock_type ##_FLAGS; \ | ||
468 | \ | ||
469 | todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG; \ | ||
470 | todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG; \ | ||
471 | } | ||
472 | |||
473 | extern todc_info_t *todc_info; | ||
474 | |||
475 | unsigned char todc_direct_read_val(int addr); | ||
476 | void todc_direct_write_val(int addr, unsigned char val); | ||
477 | unsigned char todc_m48txx_read_val(int addr); | ||
478 | void todc_m48txx_write_val(int addr, unsigned char val); | ||
479 | unsigned char todc_mc146818_read_val(int addr); | ||
480 | void todc_mc146818_write_val(int addr, unsigned char val); | ||
481 | |||
482 | long todc_time_init(void); | ||
483 | void todc_get_rtc_time(struct rtc_time *); | ||
484 | int todc_set_rtc_time(struct rtc_time *); | ||
485 | void todc_calibrate_decr(void); | ||
486 | |||
487 | #endif /* __PPC_KERNEL_TODC_H */ | ||
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h index 9fe7894ee03..50c014007de 100644 --- a/include/asm-powerpc/topology.h +++ b/include/asm-powerpc/topology.h | |||
@@ -32,7 +32,14 @@ static inline int node_to_first_cpu(int node) | |||
32 | int of_node_to_nid(struct device_node *device); | 32 | int of_node_to_nid(struct device_node *device); |
33 | 33 | ||
34 | struct pci_bus; | 34 | struct pci_bus; |
35 | #ifdef CONFIG_PCI | ||
35 | extern int pcibus_to_node(struct pci_bus *bus); | 36 | extern int pcibus_to_node(struct pci_bus *bus); |
37 | #else | ||
38 | static inline int pcibus_to_node(struct pci_bus *bus) | ||
39 | { | ||
40 | return -1; | ||
41 | } | ||
42 | #endif | ||
36 | 43 | ||
37 | #define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \ | 44 | #define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \ |
38 | CPU_MASK_ALL : \ | 45 | CPU_MASK_ALL : \ |
diff --git a/include/asm-powerpc/tsi108.h b/include/asm-powerpc/tsi108.h index 2c702d35a7c..4e95d153be8 100644 --- a/include/asm-powerpc/tsi108.h +++ b/include/asm-powerpc/tsi108.h | |||
@@ -98,12 +98,12 @@ typedef struct { | |||
98 | extern u32 get_vir_csrbase(void); | 98 | extern u32 get_vir_csrbase(void); |
99 | extern u32 tsi108_csr_vir_base; | 99 | extern u32 tsi108_csr_vir_base; |
100 | 100 | ||
101 | extern inline u32 tsi108_read_reg(u32 reg_offset) | 101 | static inline u32 tsi108_read_reg(u32 reg_offset) |
102 | { | 102 | { |
103 | return in_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset)); | 103 | return in_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset)); |
104 | } | 104 | } |
105 | 105 | ||
106 | extern inline void tsi108_write_reg(u32 reg_offset, u32 val) | 106 | static inline void tsi108_write_reg(u32 reg_offset, u32 val) |
107 | { | 107 | { |
108 | out_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset), val); | 108 | out_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset), val); |
109 | } | 109 | } |
diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index d83fc29c2bb..adbf16b8cfb 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h | |||
@@ -304,7 +304,7 @@ extern unsigned long __copy_tofrom_user(void __user *to, | |||
304 | 304 | ||
305 | #ifndef __powerpc64__ | 305 | #ifndef __powerpc64__ |
306 | 306 | ||
307 | extern inline unsigned long copy_from_user(void *to, | 307 | static inline unsigned long copy_from_user(void *to, |
308 | const void __user *from, unsigned long n) | 308 | const void __user *from, unsigned long n) |
309 | { | 309 | { |
310 | unsigned long over; | 310 | unsigned long over; |
@@ -319,7 +319,7 @@ extern inline unsigned long copy_from_user(void *to, | |||
319 | return n; | 319 | return n; |
320 | } | 320 | } |
321 | 321 | ||
322 | extern inline unsigned long copy_to_user(void __user *to, | 322 | static inline unsigned long copy_to_user(void __user *to, |
323 | const void *from, unsigned long n) | 323 | const void *from, unsigned long n) |
324 | { | 324 | { |
325 | unsigned long over; | 325 | unsigned long over; |
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 0e4ea37f646..04b6c17cc59 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h | |||
@@ -446,7 +446,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 | |||
446 | #include <linux/types.h> | 446 | #include <linux/types.h> |
447 | #include <linux/compiler.h> | 447 | #include <linux/compiler.h> |
448 | #include <linux/linkage.h> | 448 | #include <linux/linkage.h> |
449 | #include <asm/syscalls.h> | ||
450 | 449 | ||
451 | #define __ARCH_WANT_IPC_PARSE_VERSION | 450 | #define __ARCH_WANT_IPC_PARSE_VERSION |
452 | #define __ARCH_WANT_OLD_READDIR | 451 | #define __ARCH_WANT_OLD_READDIR |
@@ -481,16 +480,9 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 | |||
481 | 480 | ||
482 | /* | 481 | /* |
483 | * "Conditional" syscalls | 482 | * "Conditional" syscalls |
484 | * | ||
485 | * What we want is __attribute__((weak,alias("sys_ni_syscall"))), | ||
486 | * but it doesn't work on all toolchains, so we just do it by hand | ||
487 | */ | 483 | */ |
488 | #ifdef CONFIG_PPC32 | 484 | #define cond_syscall(x) \ |
489 | #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") | 485 | asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall"))) |
490 | #else | ||
491 | #define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall") | ||
492 | #endif | ||
493 | |||
494 | 486 | ||
495 | #endif /* __ASSEMBLY__ */ | 487 | #endif /* __ASSEMBLY__ */ |
496 | #endif /* __KERNEL__ */ | 488 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 4b51d42e141..0117b544ecb 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h | |||
@@ -45,7 +45,6 @@ struct iommu_table; | |||
45 | * The vio_dev structure is used to describe virtual I/O devices. | 45 | * The vio_dev structure is used to describe virtual I/O devices. |
46 | */ | 46 | */ |
47 | struct vio_dev { | 47 | struct vio_dev { |
48 | struct iommu_table *iommu_table; /* vio_map_* uses this */ | ||
49 | const char *name; | 48 | const char *name; |
50 | const char *type; | 49 | const char *type; |
51 | uint32_t unit_address; | 50 | uint32_t unit_address; |
diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index f1d337ed68d..88320a05f0a 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h | |||
@@ -14,8 +14,10 @@ | |||
14 | 14 | ||
15 | #ifdef CONFIG_XMON | 15 | #ifdef CONFIG_XMON |
16 | extern void xmon_setup(void); | 16 | extern void xmon_setup(void); |
17 | extern void xmon_register_spus(struct list_head *list); | ||
17 | #else | 18 | #else |
18 | static inline void xmon_setup(void) { }; | 19 | static inline void xmon_setup(void) { }; |
20 | static inline void xmon_register_spus(struct list_head *list) { }; | ||
19 | #endif | 21 | #endif |
20 | 22 | ||
21 | #endif /* __KERNEL __ */ | 23 | #endif /* __KERNEL __ */ |
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index a4c411b753e..ccf1a9bb2e4 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h | |||
@@ -26,17 +26,11 @@ | |||
26 | 26 | ||
27 | #if defined(CONFIG_4xx) | 27 | #if defined(CONFIG_4xx) |
28 | #include <asm/ibm4xx.h> | 28 | #include <asm/ibm4xx.h> |
29 | #elif defined(CONFIG_PPC_MPC52xx) | ||
30 | #include <asm/mpc52xx.h> | ||
31 | #elif defined(CONFIG_8xx) | 29 | #elif defined(CONFIG_8xx) |
32 | #include <asm/mpc8xx.h> | 30 | #include <asm/mpc8xx.h> |
33 | #elif defined(CONFIG_8260) | 31 | #elif defined(CONFIG_8260) |
34 | #include <asm/mpc8260.h> | 32 | #include <asm/mpc8260.h> |
35 | #elif defined(CONFIG_83xx) | 33 | #elif defined(CONFIG_APUS) || !defined(CONFIG_PCI) |
36 | #include <asm/mpc83xx.h> | ||
37 | #elif defined(CONFIG_85xx) | ||
38 | #include <asm/mpc85xx.h> | ||
39 | #elif defined(CONFIG_APUS) | ||
40 | #define _IO_BASE 0 | 34 | #define _IO_BASE 0 |
41 | #define _ISA_MEM_BASE 0 | 35 | #define _ISA_MEM_BASE 0 |
42 | #define PCI_DRAM_OFFSET 0 | 36 | #define PCI_DRAM_OFFSET 0 |
@@ -237,6 +231,14 @@ static inline void __raw_writel(__u32 b, volatile void __iomem *addr) | |||
237 | #define insl(port, buf, nl) _insl_ns((port)+___IO_BASE, (buf), (nl)) | 231 | #define insl(port, buf, nl) _insl_ns((port)+___IO_BASE, (buf), (nl)) |
238 | #define outsl(port, buf, nl) _outsl_ns((port)+___IO_BASE, (buf), (nl)) | 232 | #define outsl(port, buf, nl) _outsl_ns((port)+___IO_BASE, (buf), (nl)) |
239 | 233 | ||
234 | #define readsb(a, b, n) _insb((a), (b), (n)) | ||
235 | #define readsw(a, b, n) _insw_ns((a), (b), (n)) | ||
236 | #define readsl(a, b, n) _insl_ns((a), (b), (n)) | ||
237 | #define writesb(a, b, n) _outsb((a),(b),(n)) | ||
238 | #define writesw(a, b, n) _outsw_ns((a),(b),(n)) | ||
239 | #define writesl(a, b, n) _outsl_ns((a),(b),(n)) | ||
240 | |||
241 | |||
240 | /* | 242 | /* |
241 | * On powermacs and 8xx we will get a machine check exception | 243 | * On powermacs and 8xx we will get a machine check exception |
242 | * if we try to read data from a non-existent I/O port. Because | 244 | * if we try to read data from a non-existent I/O port. Because |
@@ -327,12 +329,12 @@ __do_out_asm(outl, "stwbrx") | |||
327 | #define inl_p(port) inl((port)) | 329 | #define inl_p(port) inl((port)) |
328 | #define outl_p(val, port) outl((val), (port)) | 330 | #define outl_p(val, port) outl((val), (port)) |
329 | 331 | ||
330 | extern void _insb(volatile u8 __iomem *port, void *buf, long count); | 332 | extern void _insb(const volatile u8 __iomem *addr, void *buf, long count); |
331 | extern void _outsb(volatile u8 __iomem *port, const void *buf, long count); | 333 | extern void _outsb(volatile u8 __iomem *addr,const void *buf,long count); |
332 | extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count); | 334 | extern void _insw_ns(const volatile u16 __iomem *addr, void *buf, long count); |
333 | extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count); | 335 | extern void _outsw_ns(volatile u16 __iomem *addr, const void *buf, long count); |
334 | extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count); | 336 | extern void _insl_ns(const volatile u32 __iomem *addr, void *buf, long count); |
335 | extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count); | 337 | extern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count); |
336 | 338 | ||
337 | 339 | ||
338 | #define IO_SPACE_LIMIT ~0 | 340 | #define IO_SPACE_LIMIT ~0 |
diff --git a/include/asm-ppc/m48t35.h b/include/asm-ppc/m48t35.h index f3c5e5dfa98..a5277ea4b19 100644 --- a/include/asm-ppc/m48t35.h +++ b/include/asm-ppc/m48t35.h | |||
@@ -39,7 +39,7 @@ | |||
39 | #define M48T35_RTC_WATCHDOG_RB 0x03 | 39 | #define M48T35_RTC_WATCHDOG_RB 0x03 |
40 | #define M48T35_RTC_WATCHDOG_BMB 0x7c | 40 | #define M48T35_RTC_WATCHDOG_BMB 0x7c |
41 | #define M48T35_RTC_WATCHDOG_WDS 0x80 | 41 | #define M48T35_RTC_WATCHDOG_WDS 0x80 |
42 | #define M48T35_RTC_WATCHDOG_ALL (M48T35_RTC_WATCHDOG_RB|M48T35_RTC_WATCHDOG_BMB|M48T35_RTC_W | 42 | #define M48T35_RTC_WATCHDOG_ALL (M48T35_RTC_WATCHDOG_RB|M48T35_RTC_WATCHDOG_BMB|M48T35_RTC_W) |
43 | 43 | ||
44 | #define M48T35_RTC_CONTROL_WRITE 0x80 | 44 | #define M48T35_RTC_CONTROL_WRITE 0x80 |
45 | #define M48T35_RTC_CONTROL_READ 0x40 | 45 | #define M48T35_RTC_CONTROL_READ 0x40 |
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h index 64c8874618d..d9d21aa68ba 100644 --- a/include/asm-ppc/mpc52xx.h +++ b/include/asm-ppc/mpc52xx.h | |||
@@ -29,17 +29,6 @@ struct pt_regs; | |||
29 | #endif /* __ASSEMBLY__ */ | 29 | #endif /* __ASSEMBLY__ */ |
30 | 30 | ||
31 | 31 | ||
32 | #ifdef CONFIG_PCI | ||
33 | #define _IO_BASE isa_io_base | ||
34 | #define _ISA_MEM_BASE isa_mem_base | ||
35 | #define PCI_DRAM_OFFSET pci_dram_offset | ||
36 | #else | ||
37 | #define _IO_BASE 0 | ||
38 | #define _ISA_MEM_BASE 0 | ||
39 | #define PCI_DRAM_OFFSET 0 | ||
40 | #endif | ||
41 | |||
42 | |||
43 | /* ======================================================================== */ | 32 | /* ======================================================================== */ |
44 | /* PPC Sys devices definition */ | 33 | /* PPC Sys devices definition */ |
45 | /* ======================================================================== */ | 34 | /* ======================================================================== */ |
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h index 02ed2c32571..c3061972309 100644 --- a/include/asm-ppc/mpc83xx.h +++ b/include/asm-ppc/mpc83xx.h | |||
@@ -25,14 +25,6 @@ | |||
25 | #include <platforms/83xx/mpc834x_sys.h> | 25 | #include <platforms/83xx/mpc834x_sys.h> |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #define _IO_BASE isa_io_base | ||
29 | #define _ISA_MEM_BASE isa_mem_base | ||
30 | #ifdef CONFIG_PCI | ||
31 | #define PCI_DRAM_OFFSET pci_dram_offset | ||
32 | #else | ||
33 | #define PCI_DRAM_OFFSET 0 | ||
34 | #endif | ||
35 | |||
36 | /* | 28 | /* |
37 | * The "residual" board information structure the boot loader passes | 29 | * The "residual" board information structure the boot loader passes |
38 | * into the kernel. | 30 | * into the kernel. |
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h index 9b4851199c7..d7e4a79d77f 100644 --- a/include/asm-ppc/mpc85xx.h +++ b/include/asm-ppc/mpc85xx.h | |||
@@ -44,14 +44,6 @@ | |||
44 | #include <platforms/85xx/tqm85xx.h> | 44 | #include <platforms/85xx/tqm85xx.h> |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #define _IO_BASE isa_io_base | ||
48 | #define _ISA_MEM_BASE isa_mem_base | ||
49 | #ifdef CONFIG_PCI | ||
50 | #define PCI_DRAM_OFFSET pci_dram_offset | ||
51 | #else | ||
52 | #define PCI_DRAM_OFFSET 0 | ||
53 | #endif | ||
54 | |||
55 | /* | 47 | /* |
56 | * The "residual" board information structure the boot loader passes | 48 | * The "residual" board information structure the boot loader passes |
57 | * into the kernel. | 49 | * into the kernel. |
diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h index 9d5230689b3..6c955d0c1ef 100644 --- a/include/asm-ppc/pci-bridge.h +++ b/include/asm-ppc/pci-bridge.h | |||
@@ -43,6 +43,7 @@ struct pci_controller { | |||
43 | struct pci_controller *next; | 43 | struct pci_controller *next; |
44 | struct pci_bus *bus; | 44 | struct pci_bus *bus; |
45 | void *arch_data; | 45 | void *arch_data; |
46 | struct device *parent; | ||
46 | 47 | ||
47 | int first_busno; | 48 | int first_busno; |
48 | int last_busno; | 49 | int last_busno; |
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 3fef7d67aed..f02d71bf689 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -33,6 +33,14 @@ struct cpu { | |||
33 | 33 | ||
34 | extern int register_cpu(struct cpu *cpu, int num); | 34 | extern int register_cpu(struct cpu *cpu, int num); |
35 | extern struct sys_device *get_cpu_sysdev(unsigned cpu); | 35 | extern struct sys_device *get_cpu_sysdev(unsigned cpu); |
36 | |||
37 | extern int cpu_add_sysdev_attr(struct sysdev_attribute *attr); | ||
38 | extern void cpu_remove_sysdev_attr(struct sysdev_attribute *attr); | ||
39 | |||
40 | extern int cpu_add_sysdev_attr_group(struct attribute_group *attrs); | ||
41 | extern void cpu_remove_sysdev_attr_group(struct attribute_group *attrs); | ||
42 | |||
43 | |||
36 | #ifdef CONFIG_HOTPLUG_CPU | 44 | #ifdef CONFIG_HOTPLUG_CPU |
37 | extern void unregister_cpu(struct cpu *cpu); | 45 | extern void unregister_cpu(struct cpu *cpu); |
38 | #endif | 46 | #endif |
diff --git a/include/linux/elf.h b/include/linux/elf.h index b70d1d2c8d2..743d5c8e6d3 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h | |||
@@ -368,5 +368,12 @@ extern Elf64_Dyn _DYNAMIC []; | |||
368 | 368 | ||
369 | #endif | 369 | #endif |
370 | 370 | ||
371 | #ifndef ARCH_HAVE_EXTRA_ELF_NOTES | ||
372 | static inline int arch_notes_size(void) { return 0; } | ||
373 | static inline void arch_write_notes(struct file *file) { } | ||
374 | |||
375 | #define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size() | ||
376 | #define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file) | ||
377 | #endif /* ARCH_HAVE_EXTRA_ELF_NOTES */ | ||
371 | 378 | ||
372 | #endif /* _LINUX_ELF_H */ | 379 | #endif /* _LINUX_ELF_H */ |
diff --git a/lib/iomap.c b/lib/iomap.c index 55689c5d337..d6ccdd85df5 100644 --- a/lib/iomap.c +++ b/lib/iomap.c | |||
@@ -50,6 +50,16 @@ | |||
50 | } \ | 50 | } \ |
51 | } while (0) | 51 | } while (0) |
52 | 52 | ||
53 | #ifndef pio_read16be | ||
54 | #define pio_read16be(port) swab16(inw(port)) | ||
55 | #define pio_read32be(port) swab32(inl(port)) | ||
56 | #endif | ||
57 | |||
58 | #ifndef mmio_read16be | ||
59 | #define mmio_read16be(addr) be16_to_cpu(__raw_readw(addr)) | ||
60 | #define mmio_read32be(addr) be32_to_cpu(__raw_readl(addr)) | ||
61 | #endif | ||
62 | |||
53 | unsigned int fastcall ioread8(void __iomem *addr) | 63 | unsigned int fastcall ioread8(void __iomem *addr) |
54 | { | 64 | { |
55 | IO_COND(addr, return inb(port), return readb(addr)); | 65 | IO_COND(addr, return inb(port), return readb(addr)); |
@@ -60,7 +70,7 @@ unsigned int fastcall ioread16(void __iomem *addr) | |||
60 | } | 70 | } |
61 | unsigned int fastcall ioread16be(void __iomem *addr) | 71 | unsigned int fastcall ioread16be(void __iomem *addr) |
62 | { | 72 | { |
63 | IO_COND(addr, return inw(port), return be16_to_cpu(__raw_readw(addr))); | 73 | IO_COND(addr, return pio_read16be(port), return mmio_read16be(addr)); |
64 | } | 74 | } |
65 | unsigned int fastcall ioread32(void __iomem *addr) | 75 | unsigned int fastcall ioread32(void __iomem *addr) |
66 | { | 76 | { |
@@ -68,7 +78,7 @@ unsigned int fastcall ioread32(void __iomem *addr) | |||
68 | } | 78 | } |
69 | unsigned int fastcall ioread32be(void __iomem *addr) | 79 | unsigned int fastcall ioread32be(void __iomem *addr) |
70 | { | 80 | { |
71 | IO_COND(addr, return inl(port), return be32_to_cpu(__raw_readl(addr))); | 81 | IO_COND(addr, return pio_read32be(port), return mmio_read32be(addr)); |
72 | } | 82 | } |
73 | EXPORT_SYMBOL(ioread8); | 83 | EXPORT_SYMBOL(ioread8); |
74 | EXPORT_SYMBOL(ioread16); | 84 | EXPORT_SYMBOL(ioread16); |
@@ -76,6 +86,16 @@ EXPORT_SYMBOL(ioread16be); | |||
76 | EXPORT_SYMBOL(ioread32); | 86 | EXPORT_SYMBOL(ioread32); |
77 | EXPORT_SYMBOL(ioread32be); | 87 | EXPORT_SYMBOL(ioread32be); |
78 | 88 | ||
89 | #ifndef pio_write16be | ||
90 | #define pio_write16be(val,port) outw(swab16(val),port) | ||
91 | #define pio_write32be(val,port) outl(swab32(val),port) | ||
92 | #endif | ||
93 | |||
94 | #ifndef mmio_write16be | ||
95 | #define mmio_write16be(val,port) __raw_writew(be16_to_cpu(val),port) | ||
96 | #define mmio_write32be(val,port) __raw_writel(be32_to_cpu(val),port) | ||
97 | #endif | ||
98 | |||
79 | void fastcall iowrite8(u8 val, void __iomem *addr) | 99 | void fastcall iowrite8(u8 val, void __iomem *addr) |
80 | { | 100 | { |
81 | IO_COND(addr, outb(val,port), writeb(val, addr)); | 101 | IO_COND(addr, outb(val,port), writeb(val, addr)); |
@@ -86,7 +106,7 @@ void fastcall iowrite16(u16 val, void __iomem *addr) | |||
86 | } | 106 | } |
87 | void fastcall iowrite16be(u16 val, void __iomem *addr) | 107 | void fastcall iowrite16be(u16 val, void __iomem *addr) |
88 | { | 108 | { |
89 | IO_COND(addr, outw(val,port), __raw_writew(cpu_to_be16(val), addr)); | 109 | IO_COND(addr, pio_write16be(val,port), mmio_write16be(val, addr)); |
90 | } | 110 | } |
91 | void fastcall iowrite32(u32 val, void __iomem *addr) | 111 | void fastcall iowrite32(u32 val, void __iomem *addr) |
92 | { | 112 | { |
@@ -94,7 +114,7 @@ void fastcall iowrite32(u32 val, void __iomem *addr) | |||
94 | } | 114 | } |
95 | void fastcall iowrite32be(u32 val, void __iomem *addr) | 115 | void fastcall iowrite32be(u32 val, void __iomem *addr) |
96 | { | 116 | { |
97 | IO_COND(addr, outl(val,port), __raw_writel(cpu_to_be32(val), addr)); | 117 | IO_COND(addr, pio_write32be(val,port), mmio_write32be(val, addr)); |
98 | } | 118 | } |
99 | EXPORT_SYMBOL(iowrite8); | 119 | EXPORT_SYMBOL(iowrite8); |
100 | EXPORT_SYMBOL(iowrite16); | 120 | EXPORT_SYMBOL(iowrite16); |
@@ -108,6 +128,7 @@ EXPORT_SYMBOL(iowrite32be); | |||
108 | * convert to CPU byte order. We write in "IO byte | 128 | * convert to CPU byte order. We write in "IO byte |
109 | * order" (we also don't have IO barriers). | 129 | * order" (we also don't have IO barriers). |
110 | */ | 130 | */ |
131 | #ifndef mmio_insb | ||
111 | static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) | 132 | static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) |
112 | { | 133 | { |
113 | while (--count >= 0) { | 134 | while (--count >= 0) { |
@@ -132,7 +153,9 @@ static inline void mmio_insl(void __iomem *addr, u32 *dst, int count) | |||
132 | dst++; | 153 | dst++; |
133 | } | 154 | } |
134 | } | 155 | } |
156 | #endif | ||
135 | 157 | ||
158 | #ifndef mmio_outsb | ||
136 | static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) | 159 | static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) |
137 | { | 160 | { |
138 | while (--count >= 0) { | 161 | while (--count >= 0) { |
@@ -154,6 +177,7 @@ static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count) | |||
154 | src++; | 177 | src++; |
155 | } | 178 | } |
156 | } | 179 | } |
180 | #endif | ||
157 | 181 | ||
158 | void fastcall ioread8_rep(void __iomem *addr, void *dst, unsigned long count) | 182 | void fastcall ioread8_rep(void __iomem *addr, void *dst, unsigned long count) |
159 | { | 183 | { |