diff options
102 files changed, 4173 insertions, 969 deletions
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index b5e46efeba84..7b4e8a70882c 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
@@ -57,6 +57,7 @@ Table of Contents | |||
57 | n) 4xx/Axon EMAC ethernet nodes | 57 | n) 4xx/Axon EMAC ethernet nodes |
58 | o) Xilinx IP cores | 58 | o) Xilinx IP cores |
59 | p) Freescale Synchronous Serial Interface | 59 | p) Freescale Synchronous Serial Interface |
60 | q) USB EHCI controllers | ||
60 | 61 | ||
61 | VII - Specifying interrupt information for devices | 62 | VII - Specifying interrupt information for devices |
62 | 1) interrupts property | 63 | 1) interrupts property |
@@ -2577,6 +2578,20 @@ platforms are moved over to use the flattened-device-tree model. | |||
2577 | Requred properties: | 2578 | Requred properties: |
2578 | - current-speed : Baud rate of uartlite | 2579 | - current-speed : Baud rate of uartlite |
2579 | 2580 | ||
2581 | v) Xilinx hwicap | ||
2582 | |||
2583 | Xilinx hwicap devices provide access to the configuration logic | ||
2584 | of the FPGA through the Internal Configuration Access Port | ||
2585 | (ICAP). The ICAP enables partial reconfiguration of the FPGA, | ||
2586 | readback of the configuration information, and some control over | ||
2587 | 'warm boots' of the FPGA fabric. | ||
2588 | |||
2589 | Required properties: | ||
2590 | - xlnx,family : The family of the FPGA, necessary since the | ||
2591 | capabilities of the underlying ICAP hardware | ||
2592 | differ between different families. May be | ||
2593 | 'virtex2p', 'virtex4', or 'virtex5'. | ||
2594 | |||
2580 | p) Freescale Synchronous Serial Interface | 2595 | p) Freescale Synchronous Serial Interface |
2581 | 2596 | ||
2582 | The SSI is a serial device that communicates with audio codecs. It can | 2597 | The SSI is a serial device that communicates with audio codecs. It can |
@@ -2775,6 +2790,33 @@ platforms are moved over to use the flattened-device-tree model. | |||
2775 | interrupt-parent = < &ipic >; | 2790 | interrupt-parent = < &ipic >; |
2776 | }; | 2791 | }; |
2777 | 2792 | ||
2793 | q) USB EHCI controllers | ||
2794 | |||
2795 | Required properties: | ||
2796 | - compatible : should be "usb-ehci". | ||
2797 | - reg : should contain at least address and length of the standard EHCI | ||
2798 | register set for the device. Optional platform-dependent registers | ||
2799 | (debug-port or other) can be also specified here, but only after | ||
2800 | definition of standard EHCI registers. | ||
2801 | - interrupts : one EHCI interrupt should be described here. | ||
2802 | If device registers are implemented in big endian mode, the device | ||
2803 | node should have "big-endian-regs" property. | ||
2804 | If controller implementation operates with big endian descriptors, | ||
2805 | "big-endian-desc" property should be specified. | ||
2806 | If both big endian registers and descriptors are used by the controller | ||
2807 | implementation, "big-endian" property can be specified instead of having | ||
2808 | both "big-endian-regs" and "big-endian-desc". | ||
2809 | |||
2810 | Example (Sequoia 440EPx): | ||
2811 | ehci@e0000300 { | ||
2812 | compatible = "ibm,usb-ehci-440epx", "usb-ehci"; | ||
2813 | interrupt-parent = <&UIC0>; | ||
2814 | interrupts = <1a 4>; | ||
2815 | reg = <0 e0000300 90 0 e0000390 70>; | ||
2816 | big-endian; | ||
2817 | }; | ||
2818 | |||
2819 | |||
2778 | More devices will be defined as this spec matures. | 2820 | More devices will be defined as this spec matures. |
2779 | 2821 | ||
2780 | VII - Specifying interrupt information for devices | 2822 | VII - Specifying interrupt information for devices |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index cf030b004415..8dcac0b22d68 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -97,6 +97,7 @@ config EARLY_PRINTK | |||
97 | config COMPAT | 97 | config COMPAT |
98 | bool | 98 | bool |
99 | default y if PPC64 | 99 | default y if PPC64 |
100 | select COMPAT_BINFMT_ELF | ||
100 | 101 | ||
101 | config SYSVIPC_COMPAT | 102 | config SYSVIPC_COMPAT |
102 | bool | 103 | bool |
@@ -438,25 +439,6 @@ config WANT_DEVICE_TREE | |||
438 | bool | 439 | bool |
439 | default n | 440 | default n |
440 | 441 | ||
441 | config DEVICE_TREE | ||
442 | string "Static device tree source file" | ||
443 | depends on WANT_DEVICE_TREE | ||
444 | help | ||
445 | This specifies the device tree source (.dts) file to be | ||
446 | compiled and included when building the bootwrapper. If a | ||
447 | relative filename is given, then it will be relative to | ||
448 | arch/powerpc/boot/dts. If you are not using the bootwrapper, | ||
449 | or do not need to build a dts into the bootwrapper, this | ||
450 | field is ignored. | ||
451 | |||
452 | For example, this is required when building a cuImage target | ||
453 | for an older U-Boot, which cannot pass a device tree itself. | ||
454 | Such a kernel will not work with a newer U-Boot that tries to | ||
455 | pass a device tree (unless you tell it not to). If your U-Boot | ||
456 | does not mention a device tree in "help bootm", then use the | ||
457 | cuImage target and specify a device tree here. Otherwise, use | ||
458 | the uImage target and leave this field blank. | ||
459 | |||
460 | endmenu | 442 | endmenu |
461 | 443 | ||
462 | config ISA_DMA_API | 444 | config ISA_DMA_API |
@@ -512,7 +494,7 @@ config PCI | |||
512 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ | 494 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ |
513 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ | 495 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ |
514 | || PPC_PS3 || 44x | 496 | || PPC_PS3 || 44x |
515 | default y if !40x && !CPM2 && !8xx && !PPC_83xx \ | 497 | default y if !40x && !CPM2 && !8xx && !PPC_MPC512x && !PPC_83xx \ |
516 | && !PPC_85xx && !PPC_86xx | 498 | && !PPC_85xx && !PPC_86xx |
517 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx | 499 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx |
518 | default PCI_QSPAN if !4xx && !CPM2 && 8xx | 500 | default PCI_QSPAN if !4xx && !CPM2 && 8xx |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index f70df9b64f8f..6845482f0093 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -151,14 +151,11 @@ core-$(CONFIG_XMON) += arch/powerpc/xmon/ | |||
151 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ | 151 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ |
152 | 152 | ||
153 | # Default to zImage, override when needed | 153 | # Default to zImage, override when needed |
154 | defaultimage-y := zImage | 154 | all: zImage |
155 | defaultimage-$(CONFIG_DEFAULT_UIMAGE) := uImage | ||
156 | KBUILD_IMAGE := $(defaultimage-y) | ||
157 | all: $(KBUILD_IMAGE) | ||
158 | 155 | ||
159 | CPPFLAGS_vmlinux.lds := -Upowerpc | 156 | CPPFLAGS_vmlinux.lds := -Upowerpc |
160 | 157 | ||
161 | BOOT_TARGETS = zImage zImage.initrd uImage | 158 | BOOT_TARGETS = zImage zImage.initrd uImage treeImage.% cuImage.% |
162 | 159 | ||
163 | PHONY += $(BOOT_TARGETS) | 160 | PHONY += $(BOOT_TARGETS) |
164 | 161 | ||
@@ -180,7 +177,7 @@ define archhelp | |||
180 | endef | 177 | endef |
181 | 178 | ||
182 | install: vdso_install | 179 | install: vdso_install |
183 | $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install | 180 | $(Q)$(MAKE) $(build)=$(boot) install |
184 | 181 | ||
185 | vdso_install: | 182 | vdso_install: |
186 | ifeq ($(CONFIG_PPC64),y) | 183 | ifeq ($(CONFIG_PPC64),y) |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 122a27078998..49797a45416c 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -60,8 +60,9 @@ src-wlib := string.S crt0.S stdio.c main.c \ | |||
60 | src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \ | 60 | src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \ |
61 | cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ | 61 | cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ |
62 | ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ | 62 | ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \ |
63 | cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c \ | 63 | cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c \ |
64 | fixed-head.S ep88xc.c cuboot-hpc2.c ep405.c cuboot-taishan.c \ | 64 | cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \ |
65 | fixed-head.S ep88xc.c ep405.c \ | ||
65 | cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \ | 66 | cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \ |
66 | cuboot-warp.c cuboot-85xx-cpm2.c | 67 | cuboot-warp.c cuboot-85xx-cpm2.c |
67 | src-boot := $(src-wlib) $(src-plat) empty.c | 68 | src-boot := $(src-wlib) $(src-plat) empty.c |
@@ -123,6 +124,8 @@ targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) | |||
123 | extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ | 124 | extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ |
124 | $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds | 125 | $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds |
125 | 126 | ||
127 | dtstree := $(srctree)/$(src)/dts | ||
128 | |||
126 | wrapper :=$(srctree)/$(src)/wrapper | 129 | wrapper :=$(srctree)/$(src)/wrapper |
127 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \ | 130 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \ |
128 | $(wrapper) FORCE | 131 | $(wrapper) FORCE |
@@ -181,7 +184,7 @@ quiet_cmd_wrap = WRAP $@ | |||
181 | image-$(CONFIG_PPC_PSERIES) += zImage.pseries | 184 | image-$(CONFIG_PPC_PSERIES) += zImage.pseries |
182 | image-$(CONFIG_PPC_MAPLE) += zImage.pseries | 185 | image-$(CONFIG_PPC_MAPLE) += zImage.pseries |
183 | image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries | 186 | image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries |
184 | image-$(CONFIG_PPC_PS3) += zImage.ps3 | 187 | image-$(CONFIG_PPC_PS3) += zImage-dtb.ps3 |
185 | image-$(CONFIG_PPC_CELLEB) += zImage.pseries | 188 | image-$(CONFIG_PPC_CELLEB) += zImage.pseries |
186 | image-$(CONFIG_PPC_CHRP) += zImage.chrp | 189 | image-$(CONFIG_PPC_CHRP) += zImage.chrp |
187 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp | 190 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp |
@@ -191,33 +194,69 @@ image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 | |||
191 | image-$(CONFIG_PPC_ISERIES) += zImage.iseries | 194 | image-$(CONFIG_PPC_ISERIES) += zImage.iseries |
192 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage | 195 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage |
193 | 196 | ||
194 | ifneq ($(CONFIG_DEVICE_TREE),"") | 197 | # |
195 | image-$(CONFIG_PPC_8xx) += cuImage.8xx | 198 | # Targets which embed a device tree blob |
196 | image-$(CONFIG_PPC_EP88XC) += zImage.ep88xc | 199 | # |
197 | image-$(CONFIG_EP405) += zImage.ep405 | 200 | # Theses are default targets to build images which embed device tree blobs. |
198 | image-$(CONFIG_8260) += cuImage.pq2 | 201 | # They are only required on boards which do not have FDT support in firmware. |
199 | image-$(CONFIG_EP8248E) += zImage.ep8248e | 202 | # Boards with newish u-boot firmare can use the uImage target above |
200 | image-$(CONFIG_PPC_MPC52xx) += cuImage.52xx | 203 | # |
201 | image-$(CONFIG_STORCENTER) += cuImage.824x | 204 | |
202 | image-$(CONFIG_PPC_83xx) += cuImage.83xx | 205 | # Board ports in arch/powerpc/platform/40x/Kconfig |
203 | image-$(CONFIG_PPC_85xx) += cuImage.85xx | 206 | image-$(CONFIG_EP405) += zImage-dtb.ep405 |
204 | ifeq ($(CONFIG_CPM2),y) | 207 | image-$(CONFIG_WALNUT) += treeImage.walnut |
205 | image-$(CONFIG_PPC_85xx) += cuImage.85xx-cpm2 | 208 | |
206 | endif | 209 | # Board ports in arch/powerpc/platform/44x/Kconfig |
207 | image-$(CONFIG_MPC7448HPC2) += cuImage.hpc2 | ||
208 | image-$(CONFIG_EBONY) += treeImage.ebony cuImage.ebony | 210 | image-$(CONFIG_EBONY) += treeImage.ebony cuImage.ebony |
209 | image-$(CONFIG_BAMBOO) += treeImage.bamboo cuImage.bamboo | 211 | image-$(CONFIG_BAMBOO) += treeImage.bamboo cuImage.bamboo |
210 | image-$(CONFIG_SEQUOIA) += cuImage.sequoia | 212 | image-$(CONFIG_SEQUOIA) += cuImage.sequoia |
211 | image-$(CONFIG_RAINIER) += cuImage.rainier | 213 | image-$(CONFIG_RAINIER) += cuImage.rainier |
212 | image-$(CONFIG_WALNUT) += treeImage.walnut | ||
213 | image-$(CONFIG_TAISHAN) += cuImage.taishan | 214 | image-$(CONFIG_TAISHAN) += cuImage.taishan |
214 | image-$(CONFIG_KATMAI) += cuImage.katmai | 215 | image-$(CONFIG_KATMAI) += cuImage.katmai |
215 | image-$(CONFIG_WARP) += cuImage.warp | 216 | image-$(CONFIG_WARP) += cuImage.warp |
216 | endif | ||
217 | 217 | ||
218 | ifneq ($(CONFIG_REDBOOT),"") | 218 | # Board ports in arch/powerpc/platform/8xx/Kconfig |
219 | image-$(CONFIG_PPC_8xx) += zImage.redboot-8xx | 219 | image-$(CONFIG_PPC_MPC86XADS) += cuImage.mpc866ads |
220 | endif | 220 | image-$(CONFIG_PPC_MPC885ADS) += cuImage.mpc885ads |
221 | image-$(CONFIG_PPC_EP88XC) += zImage-dtb.ep88xc | ||
222 | image-$(CONFIG_PPC_ADDER875) += cuImage.adder875-uboot \ | ||
223 | zImage-dtb.adder875-redboot | ||
224 | |||
225 | # Board ports in arch/powerpc/platform/52xx/Kconfig | ||
226 | image-$(CONFIG_PPC_LITE5200) += cuImage.lite5200 cuImage.lite5200b | ||
227 | |||
228 | # Board ports in arch/powerpc/platform/82xx/Kconfig | ||
229 | image-$(CONFIG_MPC8272_ADS) += cuImage.mpc8272ads | ||
230 | image-$(CONFIG_PQ2FADS) += cuImage.pq2fads | ||
231 | image-$(CONFIG_EP8248E) += zImage-dtb.ep8248e | ||
232 | |||
233 | # Board ports in arch/powerpc/platform/83xx/Kconfig | ||
234 | image-$(CONFIG_MPC832x_MDS) += cuImage.mpc832x_mds | ||
235 | image-$(CONFIG_MPC832x_RDB) += cuImage.mpc832x_rdb | ||
236 | image-$(CONFIG_MPC834x_ITX) += cuImage.mpc8349emitx \ | ||
237 | cuImage.mpc8349emitxgp | ||
238 | image-$(CONFIG_MPC834x_MDS) += cuImage.mpc834x_mds | ||
239 | image-$(CONFIG_MPC836x_MDS) += cuImage.mpc836x_mds | ||
240 | |||
241 | # Board ports in arch/powerpc/platform/85xx/Kconfig | ||
242 | image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads | ||
243 | image-$(CONFIG_MPC8560_ADS) += cuImage.mpc8560ads | ||
244 | image-$(CONFIG_MPC85xx_CDS) += cuImage.mpc8541cds \ | ||
245 | cuImage.mpc8548cds \ | ||
246 | cuImage.mpc8555cds | ||
247 | image-$(CONFIG_MPC85xx_MDS) += cuImage.mpc8568mds | ||
248 | image-$(CONFIG_MPC85xx_DS) += cuImage.mpc8544ds \ | ||
249 | cuImage.mpc8572ds | ||
250 | image-$(CONFIG_TQM8540) += cuImage.tqm8540 | ||
251 | image-$(CONFIG_TQM8541) += cuImage.tqm8541 | ||
252 | image-$(CONFIG_TQM8555) += cuImage.tqm8555 | ||
253 | image-$(CONFIG_TQM8560) += cuImage.tqm8560 | ||
254 | image-$(CONFIG_SBC8548) += cuImage.tqm8548 | ||
255 | image-$(CONFIG_SBC8560) += cuImage.tqm8560 | ||
256 | |||
257 | # Board ports in arch/powerpc/platform/embedded6xx/Kconfig | ||
258 | image-$(CONFIG_STORCENTER) += cuImage.storcenter | ||
259 | image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2 | ||
221 | 260 | ||
222 | # For 32-bit powermacs, build the COFF and miboot images | 261 | # For 32-bit powermacs, build the COFF and miboot images |
223 | # as well as the ELF images. | 262 | # as well as the ELF images. |
@@ -233,24 +272,20 @@ targets += $(image-y) $(initrd-y) | |||
233 | 272 | ||
234 | $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz | 273 | $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz |
235 | 274 | ||
236 | # If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an | ||
237 | # empty string, define 'dts' to be path to the dts | ||
238 | # CONFIG_DEVICE_TREE will have "" around it, make sure to strip them | ||
239 | ifeq ($(CONFIG_WANT_DEVICE_TREE),y) | ||
240 | ifneq ($(CONFIG_DEVICE_TREE),"") | ||
241 | dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ | ||
242 | ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) | ||
243 | endif | ||
244 | endif | ||
245 | |||
246 | # Don't put the ramdisk on the pattern rule; when its missing make will try | 275 | # Don't put the ramdisk on the pattern rule; when its missing make will try |
247 | # the pattern rule with less dependencies that also matches (even with the | 276 | # the pattern rule with less dependencies that also matches (even with the |
248 | # hard dependency listed). | 277 | # hard dependency listed). |
249 | $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts) | 278 | $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) |
250 | $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) | 279 | $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) |
251 | 280 | ||
252 | $(obj)/zImage.%: vmlinux $(wrapperbits) $(dts) | 281 | $(obj)/zImage.%: vmlinux $(wrapperbits) |
253 | $(call if_changed,wrap,$*,$(dts)) | 282 | $(call if_changed,wrap,$*) |
283 | |||
284 | $(obj)/zImage-dtb.initrd.%: vmlinux $(wrapperbits) $(dtstree)/%.dts | ||
285 | $(call if_changed,wrap,$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz) | ||
286 | |||
287 | $(obj)/zImage-dtb.%: vmlinux $(wrapperbits) $(dtstree)/%.dts | ||
288 | $(call if_changed,wrap,$*,$(dtstree)/$*.dts) | ||
254 | 289 | ||
255 | # This cannot be in the root of $(src) as the zImage rule always adds a $(obj) | 290 | # This cannot be in the root of $(src) as the zImage rule always adds a $(obj) |
256 | # prefix | 291 | # prefix |
@@ -260,24 +295,17 @@ $(obj)/vmlinux.strip: vmlinux | |||
260 | $(obj)/zImage.iseries: vmlinux | 295 | $(obj)/zImage.iseries: vmlinux |
261 | $(STRIP) -s -R .comment $< -o $@ | 296 | $(STRIP) -s -R .comment $< -o $@ |
262 | 297 | ||
263 | $(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts | ||
264 | $(STRIP) -s -R .comment $< -o vmlinux.strip | ||
265 | $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,) | ||
266 | |||
267 | $(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz | ||
268 | $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz) | ||
269 | |||
270 | $(obj)/uImage: vmlinux $(wrapperbits) | 298 | $(obj)/uImage: vmlinux $(wrapperbits) |
271 | $(call if_changed,wrap,uboot) | 299 | $(call if_changed,wrap,uboot) |
272 | 300 | ||
273 | $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits) | 301 | $(obj)/cuImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits) |
274 | $(call if_changed,wrap,cuboot-$*,$(dts)) | 302 | $(call if_changed,wrap,cuboot-$*,$(dtstree)/$*.dts) |
275 | 303 | ||
276 | $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits) | 304 | $(obj)/treeImage.initrd.%: vmlinux $(dtstree)/%.dts $(wrapperbits) |
277 | $(call if_changed,wrap,treeboot-$*,$(dts),,$(obj)/ramdisk.image.gz) | 305 | $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz) |
278 | 306 | ||
279 | $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits) | 307 | $(obj)/treeImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits) |
280 | $(call if_changed,wrap,treeboot-$*,$(dts)) | 308 | $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts) |
281 | 309 | ||
282 | # If there isn't a platform selected then just strip the vmlinux. | 310 | # If there isn't a platform selected then just strip the vmlinux. |
283 | ifeq (,$(image-y)) | 311 | ifeq (,$(image-y)) |
diff --git a/arch/powerpc/boot/cuboot-hpc2.c b/arch/powerpc/boot/cuboot-mpc7448hpc2.c index 1b8953259d75..1b8953259d75 100644 --- a/arch/powerpc/boot/cuboot-hpc2.c +++ b/arch/powerpc/boot/cuboot-mpc7448hpc2.c | |||
diff --git a/arch/powerpc/boot/dts/adder875-redboot.dts b/arch/powerpc/boot/dts/adder875-redboot.dts index 930bfb3894eb..28e9cd3d7a21 100644 --- a/arch/powerpc/boot/dts/adder875-redboot.dts +++ b/arch/powerpc/boot/dts/adder875-redboot.dts | |||
@@ -151,6 +151,7 @@ | |||
151 | compatible = "fsl,mpc875-brg", | 151 | compatible = "fsl,mpc875-brg", |
152 | "fsl,cpm1-brg", | 152 | "fsl,cpm1-brg", |
153 | "fsl,cpm-brg"; | 153 | "fsl,cpm-brg"; |
154 | clock-frequency = <50000000>; | ||
154 | reg = <0x9f0 0x10>; | 155 | reg = <0x9f0 0x10>; |
155 | }; | 156 | }; |
156 | 157 | ||
diff --git a/arch/powerpc/boot/dts/adder875-uboot.dts b/arch/powerpc/boot/dts/adder875-uboot.dts index 0197242dacfb..54fb60ec03e5 100644 --- a/arch/powerpc/boot/dts/adder875-uboot.dts +++ b/arch/powerpc/boot/dts/adder875-uboot.dts | |||
@@ -150,6 +150,7 @@ | |||
150 | compatible = "fsl,mpc875-brg", | 150 | compatible = "fsl,mpc875-brg", |
151 | "fsl,cpm1-brg", | 151 | "fsl,cpm1-brg", |
152 | "fsl,cpm-brg"; | 152 | "fsl,cpm-brg"; |
153 | clock-frequency = <50000000>; | ||
153 | reg = <0x9f0 0x10>; | 154 | reg = <0x9f0 0x10>; |
154 | }; | 155 | }; |
155 | 156 | ||
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts new file mode 100644 index 000000000000..94ad7b2b241e --- /dev/null +++ b/arch/powerpc/boot/dts/mpc5121ads.dts | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * MPC5121E MDS Device Tree Source | ||
3 | * | ||
4 | * Copyright 2007 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | /dts-v1/; | ||
13 | |||
14 | / { | ||
15 | model = "mpc5121ads"; | ||
16 | compatible = "fsl,mpc5121ads"; | ||
17 | #address-cells = <1>; | ||
18 | #size-cells = <1>; | ||
19 | |||
20 | cpus { | ||
21 | #address-cells = <1>; | ||
22 | #size-cells = <0>; | ||
23 | |||
24 | PowerPC,5121@0 { | ||
25 | device_type = "cpu"; | ||
26 | reg = <0>; | ||
27 | d-cache-line-size = <0x20>; // 32 bytes | ||
28 | i-cache-line-size = <0x20>; // 32 bytes | ||
29 | d-cache-size = <0x8000>; // L1, 32K | ||
30 | i-cache-size = <0x8000>; // L1, 32K | ||
31 | timebase-frequency = <49500000>;// 49.5 MHz (csb/4) | ||
32 | bus-frequency = <198000000>; // 198 MHz csb bus | ||
33 | clock-frequency = <396000000>; // 396 MHz ppc core | ||
34 | }; | ||
35 | }; | ||
36 | |||
37 | memory { | ||
38 | device_type = "memory"; | ||
39 | reg = <0x00000000 0x10000000>; // 256MB at 0 | ||
40 | }; | ||
41 | |||
42 | localbus@80000020 { | ||
43 | compatible = "fsl,mpc5121ads-localbus"; | ||
44 | #address-cells = <2>; | ||
45 | #size-cells = <1>; | ||
46 | reg = <0x80000020 0x40>; | ||
47 | |||
48 | ranges = <0x0 0x0 0xfc000000 0x04000000 | ||
49 | 0x2 0x0 0x82000000 0x00008000>; | ||
50 | |||
51 | flash@0,0 { | ||
52 | compatible = "cfi-flash"; | ||
53 | reg = <0 0x0 0x4000000>; | ||
54 | bank-width = <4>; | ||
55 | device-width = <1>; | ||
56 | }; | ||
57 | |||
58 | board-control@2,0 { | ||
59 | compatible = "fsl,mpc5121ads-cpld"; | ||
60 | reg = <0x2 0x0 0x8000>; | ||
61 | }; | ||
62 | }; | ||
63 | |||
64 | soc@80000000 { | ||
65 | compatible = "fsl,mpc5121-immr"; | ||
66 | #address-cells = <1>; | ||
67 | #size-cells = <1>; | ||
68 | #interrupt-cells = <2>; | ||
69 | ranges = <0x0 0x80000000 0x400000>; | ||
70 | reg = <0x80000000 0x400000>; | ||
71 | bus-frequency = <66000000>; // 66 MHz ips bus | ||
72 | |||
73 | |||
74 | // IPIC | ||
75 | // interrupts cell = <intr #, sense> | ||
76 | // sense values match linux IORESOURCE_IRQ_* defines: | ||
77 | // sense == 8: Level, low assertion | ||
78 | // sense == 2: Edge, high-to-low change | ||
79 | // | ||
80 | ipic: interrupt-controller@c00 { | ||
81 | compatible = "fsl,mpc5121-ipic", "fsl,ipic"; | ||
82 | interrupt-controller; | ||
83 | #address-cells = <0>; | ||
84 | #interrupt-cells = <2>; | ||
85 | reg = <0xc00 0x100>; | ||
86 | }; | ||
87 | |||
88 | // 512x PSCs are not 52xx PSCs compatible | ||
89 | // PSC3 serial port A aka ttyPSC0 | ||
90 | serial@11300 { | ||
91 | device_type = "serial"; | ||
92 | compatible = "fsl,mpc5121-psc-uart"; | ||
93 | // Logical port assignment needed until driver | ||
94 | // learns to use aliases | ||
95 | port-number = <0>; | ||
96 | cell-index = <3>; | ||
97 | reg = <0x11300 0x100>; | ||
98 | interrupts = <0x28 0x8>; // actually the fifo irq | ||
99 | interrupt-parent = < &ipic >; | ||
100 | }; | ||
101 | |||
102 | // PSC4 serial port B aka ttyPSC1 | ||
103 | serial@11400 { | ||
104 | device_type = "serial"; | ||
105 | compatible = "fsl,mpc5121-psc-uart"; | ||
106 | // Logical port assignment needed until driver | ||
107 | // learns to use aliases | ||
108 | port-number = <1>; | ||
109 | cell-index = <4>; | ||
110 | reg = <0x11400 0x100>; | ||
111 | interrupts = <0x28 0x8>; // actually the fifo irq | ||
112 | interrupt-parent = < &ipic >; | ||
113 | }; | ||
114 | |||
115 | pscsfifo@11f00 { | ||
116 | compatible = "fsl,mpc5121-psc-fifo"; | ||
117 | reg = <0x11f00 0x100>; | ||
118 | interrupts = <0x28 0x8>; | ||
119 | interrupt-parent = < &ipic >; | ||
120 | }; | ||
121 | }; | ||
122 | }; | ||
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts index 2d6653fe72ff..e1f0dca8ac39 100644 --- a/arch/powerpc/boot/dts/mpc8313erdb.dts +++ b/arch/powerpc/boot/dts/mpc8313erdb.dts | |||
@@ -118,6 +118,10 @@ | |||
118 | interrupts = <14 0x8>; | 118 | interrupts = <14 0x8>; |
119 | interrupt-parent = <&ipic>; | 119 | interrupt-parent = <&ipic>; |
120 | dfsrr; | 120 | dfsrr; |
121 | rtc@68 { | ||
122 | compatible = "dallas,ds1339"; | ||
123 | reg = <0x68>; | ||
124 | }; | ||
121 | }; | 125 | }; |
122 | 126 | ||
123 | i2c@3100 { | 127 | i2c@3100 { |
diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts index b582032ba3d6..d7a1ececa30f 100644 --- a/arch/powerpc/boot/dts/mpc8315erdb.dts +++ b/arch/powerpc/boot/dts/mpc8315erdb.dts | |||
@@ -96,7 +96,7 @@ | |||
96 | #address-cells = <1>; | 96 | #address-cells = <1>; |
97 | #size-cells = <1>; | 97 | #size-cells = <1>; |
98 | device_type = "soc"; | 98 | device_type = "soc"; |
99 | compatible = "simple-bus"; | 99 | compatible = "fsl,mpc8315-immr", "simple-bus"; |
100 | ranges = <0 0xe0000000 0x00100000>; | 100 | ranges = <0 0xe0000000 0x00100000>; |
101 | reg = <0xe0000000 0x00000200>; | 101 | reg = <0xe0000000 0x00000200>; |
102 | bus-frequency = <0>; | 102 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index 7480edae85ed..0199c5c548d8 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts | |||
@@ -332,7 +332,7 @@ | |||
332 | 0xc000 0x0 0x0 0x3 &ipic 23 0x8 | 332 | 0xc000 0x0 0x0 0x3 &ipic 23 0x8 |
333 | 0xc000 0x0 0x0 0x4 &ipic 20 0x8>; | 333 | 0xc000 0x0 0x0 0x4 &ipic 20 0x8>; |
334 | interrupt-parent = <&ipic>; | 334 | interrupt-parent = <&ipic>; |
335 | interrupts = <66 0x8>; | 335 | interrupts = <67 0x8>; |
336 | bus-range = <0 0>; | 336 | bus-range = <0 0>; |
337 | ranges = <0x02000000 0x0 0xb0000000 0xb0000000 0x0 0x10000000 | 337 | ranges = <0x02000000 0x0 0xb0000000 0xb0000000 0x0 0x10000000 |
338 | 0x42000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 | 338 | 0x42000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000 |
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts index 813c259abbe5..db37214aee37 100644 --- a/arch/powerpc/boot/dts/mpc8572ds.dts +++ b/arch/powerpc/boot/dts/mpc8572ds.dts | |||
@@ -42,6 +42,18 @@ | |||
42 | bus-frequency = <0>; | 42 | bus-frequency = <0>; |
43 | clock-frequency = <0>; | 43 | clock-frequency = <0>; |
44 | }; | 44 | }; |
45 | |||
46 | PowerPC,8572@1 { | ||
47 | device_type = "cpu"; | ||
48 | reg = <1>; | ||
49 | d-cache-line-size = <20>; // 32 bytes | ||
50 | i-cache-line-size = <20>; // 32 bytes | ||
51 | d-cache-size = <8000>; // L1, 32K | ||
52 | i-cache-size = <8000>; // L1, 32K | ||
53 | timebase-frequency = <0>; | ||
54 | bus-frequency = <0>; | ||
55 | clock-frequency = <0>; | ||
56 | }; | ||
45 | }; | 57 | }; |
46 | 58 | ||
47 | memory { | 59 | memory { |
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts index 8848e637293e..d84a012c2aaf 100644 --- a/arch/powerpc/boot/dts/mpc885ads.dts +++ b/arch/powerpc/boot/dts/mpc885ads.dts | |||
@@ -166,6 +166,7 @@ | |||
166 | compatible = "fsl,mpc885-brg", | 166 | compatible = "fsl,mpc885-brg", |
167 | "fsl,cpm1-brg", | 167 | "fsl,cpm1-brg", |
168 | "fsl,cpm-brg"; | 168 | "fsl,cpm-brg"; |
169 | clock-frequency = <0>; | ||
169 | reg = <9f0 10>; | 170 | reg = <9f0 10>; |
170 | }; | 171 | }; |
171 | 172 | ||
diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts index d9046c1adcbe..5c13d46f441d 100644 --- a/arch/powerpc/boot/dts/sequoia.dts +++ b/arch/powerpc/boot/dts/sequoia.dts | |||
@@ -138,6 +138,14 @@ | |||
138 | interrupts = <15 8>; | 138 | interrupts = <15 8>; |
139 | }; | 139 | }; |
140 | 140 | ||
141 | USB0: ehci@e0000300 { | ||
142 | compatible = "ibm,usb-ehci-440epx", "usb-ehci"; | ||
143 | interrupt-parent = <&UIC0>; | ||
144 | interrupts = <1a 4>; | ||
145 | reg = <0 e0000300 90 0 e0000390 70>; | ||
146 | big-endian; | ||
147 | }; | ||
148 | |||
141 | POB0: opb { | 149 | POB0: opb { |
142 | compatible = "ibm,opb-440epx", "ibm,opb"; | 150 | compatible = "ibm,opb-440epx", "ibm,opb"; |
143 | #address-cells = <1>; | 151 | #address-cells = <1>; |
diff --git a/arch/powerpc/boot/dts/storcenter.dts b/arch/powerpc/boot/dts/storcenter.dts index 2204874ac5f3..5893816c0bce 100644 --- a/arch/powerpc/boot/dts/storcenter.dts +++ b/arch/powerpc/boot/dts/storcenter.dts | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | / { | 16 | / { |
17 | model = "StorCenter"; | 17 | model = "StorCenter"; |
18 | compatible = "storcenter"; | 18 | compatible = "iomega,storcenter"; |
19 | #address-cells = <1>; | 19 | #address-cells = <1>; |
20 | #size-cells = <1>; | 20 | #size-cells = <1>; |
21 | 21 | ||
@@ -62,12 +62,12 @@ | |||
62 | #size-cells = <0>; | 62 | #size-cells = <0>; |
63 | compatible = "fsl-i2c"; | 63 | compatible = "fsl-i2c"; |
64 | reg = <0x3000 0x100>; | 64 | reg = <0x3000 0x100>; |
65 | interrupts = <5 2>; | 65 | interrupts = <17 2>; |
66 | interrupt-parent = <&mpic>; | 66 | interrupt-parent = <&mpic>; |
67 | 67 | ||
68 | rtc@68 { | 68 | rtc@68 { |
69 | compatible = "dallas,ds1337"; | 69 | compatible = "dallas,ds1337"; |
70 | reg = <68>; | 70 | reg = <0x68>; |
71 | }; | 71 | }; |
72 | }; | 72 | }; |
73 | 73 | ||
@@ -78,7 +78,7 @@ | |||
78 | reg = <0x4500 0x20>; | 78 | reg = <0x4500 0x20>; |
79 | clock-frequency = <97553800>; /* Hz */ | 79 | clock-frequency = <97553800>; /* Hz */ |
80 | current-speed = <115200>; | 80 | current-speed = <115200>; |
81 | interrupts = <9 2>; | 81 | interrupts = <25 2>; |
82 | interrupt-parent = <&mpic>; | 82 | interrupt-parent = <&mpic>; |
83 | }; | 83 | }; |
84 | 84 | ||
@@ -89,7 +89,7 @@ | |||
89 | reg = <0x4600 0x20>; | 89 | reg = <0x4600 0x20>; |
90 | clock-frequency = <97553800>; /* Hz */ | 90 | clock-frequency = <97553800>; /* Hz */ |
91 | current-speed = <9600>; | 91 | current-speed = <9600>; |
92 | interrupts = <10 2>; | 92 | interrupts = <26 2>; |
93 | interrupt-parent = <&mpic>; | 93 | interrupt-parent = <&mpic>; |
94 | }; | 94 | }; |
95 | 95 | ||
@@ -136,6 +136,6 @@ | |||
136 | }; | 136 | }; |
137 | 137 | ||
138 | chosen { | 138 | chosen { |
139 | linux,stdout-path = "/soc/serial@4500"; | 139 | linux,stdout-path = &serial0; |
140 | }; | 140 | }; |
141 | }; | 141 | }; |
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 763a0c46f441..c3178155311b 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper | |||
@@ -158,6 +158,29 @@ miboot|uboot) | |||
158 | cuboot*) | 158 | cuboot*) |
159 | binary=y | 159 | binary=y |
160 | gzip= | 160 | gzip= |
161 | case "$platform" in | ||
162 | *-mpc885ads|*-adder875*|*-ep88xc) | ||
163 | platformo=$object/cuboot-8xx.o | ||
164 | ;; | ||
165 | *5200*|*-motionpro) | ||
166 | platformo=$object/cuboot-52xx.o | ||
167 | ;; | ||
168 | *-pq2fads|*-ep8248e|*-mpc8272*|*-storcenter) | ||
169 | platformo=$object/cuboot-pq2.o | ||
170 | ;; | ||
171 | *-mpc824*) | ||
172 | platformo=$object/cuboot-824x.o | ||
173 | ;; | ||
174 | *-mpc83*) | ||
175 | platformo=$object/cuboot-83xx.o | ||
176 | ;; | ||
177 | *-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555*) | ||
178 | platformo=$object/cuboot-85xx-cpm2.o | ||
179 | ;; | ||
180 | *-mpc85*) | ||
181 | platformo=$object/cuboot-85xx.o | ||
182 | ;; | ||
183 | esac | ||
161 | ;; | 184 | ;; |
162 | ps3) | 185 | ps3) |
163 | platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o" | 186 | platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o" |
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig index 31bdbf3f7566..a9807f083bc4 100644 --- a/arch/powerpc/configs/mpc83xx_defconfig +++ b/arch/powerpc/configs/mpc83xx_defconfig | |||
@@ -186,7 +186,7 @@ CONFIG_PREEMPT_NONE=y | |||
186 | # CONFIG_PREEMPT is not set | 186 | # CONFIG_PREEMPT is not set |
187 | CONFIG_BINFMT_ELF=y | 187 | CONFIG_BINFMT_ELF=y |
188 | # CONFIG_BINFMT_MISC is not set | 188 | # CONFIG_BINFMT_MISC is not set |
189 | # CONFIG_MATH_EMULATION is not set | 189 | CONFIG_MATH_EMULATION=y |
190 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y | 190 | CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y |
191 | CONFIG_ARCH_FLATMEM_ENABLE=y | 191 | CONFIG_ARCH_FLATMEM_ENABLE=y |
192 | CONFIG_ARCH_POPULATES_NODE_MAP=y | 192 | CONFIG_ARCH_POPULATES_NODE_MAP=y |
@@ -416,14 +416,14 @@ CONFIG_PHYLIB=y | |||
416 | # MII PHY device drivers | 416 | # MII PHY device drivers |
417 | # | 417 | # |
418 | CONFIG_MARVELL_PHY=y | 418 | CONFIG_MARVELL_PHY=y |
419 | # CONFIG_DAVICOM_PHY is not set | 419 | CONFIG_DAVICOM_PHY=y |
420 | # CONFIG_QSEMI_PHY is not set | 420 | # CONFIG_QSEMI_PHY is not set |
421 | # CONFIG_LXT_PHY is not set | 421 | # CONFIG_LXT_PHY is not set |
422 | # CONFIG_CICADA_PHY is not set | 422 | # CONFIG_CICADA_PHY is not set |
423 | # CONFIG_VITESSE_PHY is not set | 423 | CONFIG_VITESSE_PHY=y |
424 | # CONFIG_SMSC_PHY is not set | 424 | # CONFIG_SMSC_PHY is not set |
425 | # CONFIG_BROADCOM_PHY is not set | 425 | # CONFIG_BROADCOM_PHY is not set |
426 | # CONFIG_ICPLUS_PHY is not set | 426 | CONFIG_ICPLUS_PHY=y |
427 | # CONFIG_FIXED_PHY is not set | 427 | # CONFIG_FIXED_PHY is not set |
428 | # CONFIG_MDIO_BITBANG is not set | 428 | # CONFIG_MDIO_BITBANG is not set |
429 | CONFIG_NET_ETHERNET=y | 429 | CONFIG_NET_ETHERNET=y |
@@ -436,7 +436,7 @@ CONFIG_MII=y | |||
436 | CONFIG_NETDEV_1000=y | 436 | CONFIG_NETDEV_1000=y |
437 | CONFIG_GIANFAR=y | 437 | CONFIG_GIANFAR=y |
438 | # CONFIG_GFAR_NAPI is not set | 438 | # CONFIG_GFAR_NAPI is not set |
439 | # CONFIG_UCC_GETH is not set | 439 | CONFIG_UCC_GETH=y |
440 | CONFIG_NETDEV_10000=y | 440 | CONFIG_NETDEV_10000=y |
441 | 441 | ||
442 | # | 442 | # |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 58dbfeff9b4d..0662ae46f724 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' | ||
6 | |||
5 | ifeq ($(CONFIG_PPC64),y) | 7 | ifeq ($(CONFIG_PPC64),y) |
6 | CFLAGS_prom_init.o += -mno-minimal-toc | 8 | CFLAGS_prom_init.o += -mno-minimal-toc |
7 | endif | 9 | endif |
@@ -15,7 +17,7 @@ obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ | |||
15 | init_task.o process.o systbl.o idle.o \ | 17 | init_task.o process.o systbl.o idle.o \ |
16 | signal.o | 18 | signal.o |
17 | obj-y += vdso32/ | 19 | obj-y += vdso32/ |
18 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 20 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ |
19 | signal_64.o ptrace32.o \ | 21 | signal_64.o ptrace32.o \ |
20 | paca.o cpu_setup_ppc970.o \ | 22 | paca.o cpu_setup_ppc970.o \ |
21 | cpu_setup_pa6t.o \ | 23 | cpu_setup_pa6t.o \ |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index ed083feaf6f9..e6e49289f788 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mman.h> | 22 | #include <linux/mman.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/suspend.h> | 24 | #include <linux/suspend.h> |
25 | #include <linux/hrtimer.h> | ||
25 | #ifdef CONFIG_PPC64 | 26 | #ifdef CONFIG_PPC64 |
26 | #include <linux/time.h> | 27 | #include <linux/time.h> |
27 | #include <linux/hardirq.h> | 28 | #include <linux/hardirq.h> |
@@ -312,7 +313,7 @@ int main(void) | |||
312 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); | 313 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); |
313 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); | 314 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); |
314 | DEFINE(NSEC_PER_SEC, NSEC_PER_SEC); | 315 | DEFINE(NSEC_PER_SEC, NSEC_PER_SEC); |
315 | DEFINE(CLOCK_REALTIME_RES, TICK_NSEC); | 316 | DEFINE(CLOCK_REALTIME_RES, (KTIME_MONOTONIC_RES).tv64); |
316 | 317 | ||
317 | #ifdef CONFIG_BUG | 318 | #ifdef CONFIG_BUG |
318 | DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry)); | 319 | DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry)); |
diff --git a/arch/powerpc/kernel/binfmt_elf32.c b/arch/powerpc/kernel/binfmt_elf32.c deleted file mode 100644 index 1d45d7782d4e..000000000000 --- a/arch/powerpc/kernel/binfmt_elf32.c +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | * binfmt_elf32.c: Support 32-bit PPC ELF binaries on Power3 and followons. | ||
3 | * based on the SPARC64 version. | ||
4 | * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) | ||
5 | * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) | ||
6 | * | ||
7 | * Copyright (C) 2000,2001 Ken Aaker (kdaaker@rchland.vnet.ibm.com), IBM Corp | ||
8 | * Copyright (C) 2001 Anton Blanchard (anton@au.ibm.com), IBM | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <asm/processor.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/compat.h> | ||
19 | #include <linux/elfcore-compat.h> | ||
20 | |||
21 | #undef ELF_ARCH | ||
22 | #undef ELF_CLASS | ||
23 | #define ELF_CLASS ELFCLASS32 | ||
24 | #define ELF_ARCH EM_PPC | ||
25 | |||
26 | #undef elfhdr | ||
27 | #undef elf_phdr | ||
28 | #undef elf_note | ||
29 | #undef elf_addr_t | ||
30 | #define elfhdr elf32_hdr | ||
31 | #define elf_phdr elf32_phdr | ||
32 | #define elf_note elf32_note | ||
33 | #define elf_addr_t Elf32_Off | ||
34 | |||
35 | #define elf_prstatus compat_elf_prstatus | ||
36 | #define elf_prpsinfo compat_elf_prpsinfo | ||
37 | |||
38 | #define elf_core_copy_regs compat_elf_core_copy_regs | ||
39 | static inline void compat_elf_core_copy_regs(compat_elf_gregset_t *elf_regs, | ||
40 | struct pt_regs *regs) | ||
41 | { | ||
42 | PPC_ELF_CORE_COPY_REGS((*elf_regs), regs); | ||
43 | } | ||
44 | |||
45 | #define elf_core_copy_task_regs compat_elf_core_copy_task_regs | ||
46 | static int compat_elf_core_copy_task_regs(struct task_struct *tsk, | ||
47 | compat_elf_gregset_t *elf_regs) | ||
48 | { | ||
49 | struct pt_regs *regs = tsk->thread.regs; | ||
50 | if (regs) | ||
51 | compat_elf_core_copy_regs(elf_regs, regs); | ||
52 | return 1; | ||
53 | } | ||
54 | |||
55 | #include <linux/time.h> | ||
56 | |||
57 | #undef cputime_to_timeval | ||
58 | #define cputime_to_timeval cputime_to_compat_timeval | ||
59 | static __inline__ void | ||
60 | cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) | ||
61 | { | ||
62 | unsigned long jiffies = cputime_to_jiffies(cputime); | ||
63 | value->tv_usec = (jiffies % HZ) * (1000000L / HZ); | ||
64 | value->tv_sec = jiffies / HZ; | ||
65 | } | ||
66 | |||
67 | #define init_elf_binfmt init_elf32_binfmt | ||
68 | |||
69 | #include "../../../fs/binfmt_elf.c" | ||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index a4c2771b5e62..2a8f5cc5184f 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -959,6 +959,9 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
959 | .icache_bsize = 32, | 959 | .icache_bsize = 32, |
960 | .dcache_bsize = 32, | 960 | .dcache_bsize = 32, |
961 | .cpu_setup = __setup_cpu_603, | 961 | .cpu_setup = __setup_cpu_603, |
962 | .num_pmcs = 4, | ||
963 | .oprofile_cpu_type = "ppc/e300", | ||
964 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | ||
962 | .platform = "ppc603", | 965 | .platform = "ppc603", |
963 | }, | 966 | }, |
964 | { /* e300c4 (e300c1, plus one IU) */ | 967 | { /* e300c4 (e300c1, plus one IU) */ |
@@ -971,6 +974,9 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
971 | .dcache_bsize = 32, | 974 | .dcache_bsize = 32, |
972 | .cpu_setup = __setup_cpu_603, | 975 | .cpu_setup = __setup_cpu_603, |
973 | .machine_check = machine_check_generic, | 976 | .machine_check = machine_check_generic, |
977 | .num_pmcs = 4, | ||
978 | .oprofile_cpu_type = "ppc/e300", | ||
979 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | ||
974 | .platform = "ppc603", | 980 | .platform = "ppc603", |
975 | }, | 981 | }, |
976 | { /* default match, we assume split I/D cache & TB (non-601)... */ | 982 | { /* default match, we assume split I/D cache & TB (non-601)... */ |
@@ -1435,7 +1441,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1435 | .dcache_bsize = 32, | 1441 | .dcache_bsize = 32, |
1436 | .num_pmcs = 4, | 1442 | .num_pmcs = 4, |
1437 | .oprofile_cpu_type = "ppc/e500", | 1443 | .oprofile_cpu_type = "ppc/e500", |
1438 | .oprofile_type = PPC_OPROFILE_BOOKE, | 1444 | .oprofile_type = PPC_OPROFILE_FSL_EMB, |
1439 | .machine_check = machine_check_e500, | 1445 | .machine_check = machine_check_e500, |
1440 | .platform = "ppc8540", | 1446 | .platform = "ppc8540", |
1441 | }, | 1447 | }, |
@@ -1453,7 +1459,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1453 | .dcache_bsize = 32, | 1459 | .dcache_bsize = 32, |
1454 | .num_pmcs = 4, | 1460 | .num_pmcs = 4, |
1455 | .oprofile_cpu_type = "ppc/e500", | 1461 | .oprofile_cpu_type = "ppc/e500", |
1456 | .oprofile_type = PPC_OPROFILE_BOOKE, | 1462 | .oprofile_type = PPC_OPROFILE_FSL_EMB, |
1457 | .machine_check = machine_check_e500, | 1463 | .machine_check = machine_check_e500, |
1458 | .platform = "ppc8548", | 1464 | .platform = "ppc8548", |
1459 | }, | 1465 | }, |
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 76b862bd1fe9..61dd17449ddc 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c | |||
@@ -36,7 +36,8 @@ static struct legacy_serial_info { | |||
36 | static struct __initdata of_device_id parents[] = { | 36 | static struct __initdata of_device_id parents[] = { |
37 | {.type = "soc",}, | 37 | {.type = "soc",}, |
38 | {.type = "tsi-bridge",}, | 38 | {.type = "tsi-bridge",}, |
39 | {.type = "opb", .compatible = "ibm,opb",}, | 39 | {.type = "opb", }, |
40 | {.compatible = "ibm,opb",}, | ||
40 | {.compatible = "simple-bus",}, | 41 | {.compatible = "simple-bus",}, |
41 | {.compatible = "wrs,epld-localbus",}, | 42 | {.compatible = "wrs,epld-localbus",}, |
42 | }; | 43 | }; |
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c index ea04e0ab3f2f..0516e2d3e02e 100644 --- a/arch/powerpc/kernel/pmc.c +++ b/arch/powerpc/kernel/pmc.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | static void dummy_perf(struct pt_regs *regs) | 27 | static void dummy_perf(struct pt_regs *regs) |
28 | { | 28 | { |
29 | #if defined(CONFIG_FSL_BOOKE) && !defined(CONFIG_E200) | 29 | #if defined(CONFIG_FSL_EMB_PERFMON) |
30 | mtpmr(PMRN_PMGC0, mfpmr(PMRN_PMGC0) & ~PMGC0_PMIE); | 30 | mtpmr(PMRN_PMGC0, mfpmr(PMRN_PMGC0) & ~PMGC0_PMIE); |
31 | #elif defined(CONFIG_PPC64) || defined(CONFIG_6xx) | 31 | #elif defined(CONFIG_PPC64) || defined(CONFIG_6xx) |
32 | if (cur_cpu_spec->pmc_type == PPC_PMC_IBM) | 32 | if (cur_cpu_spec->pmc_type == PPC_PMC_IBM) |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 8b056d2295cc..7673e9865733 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
24 | #include <linux/regset.h> | ||
25 | #include <linux/elf.h> | ||
24 | #include <linux/user.h> | 26 | #include <linux/user.h> |
25 | #include <linux/security.h> | 27 | #include <linux/security.h> |
26 | #include <linux/signal.h> | 28 | #include <linux/signal.h> |
@@ -58,20 +60,38 @@ | |||
58 | #define PT_MAX_PUT_REG PT_CCR | 60 | #define PT_MAX_PUT_REG PT_CCR |
59 | #endif | 61 | #endif |
60 | 62 | ||
63 | static unsigned long get_user_msr(struct task_struct *task) | ||
64 | { | ||
65 | return task->thread.regs->msr | task->thread.fpexc_mode; | ||
66 | } | ||
67 | |||
68 | static int set_user_msr(struct task_struct *task, unsigned long msr) | ||
69 | { | ||
70 | task->thread.regs->msr &= ~MSR_DEBUGCHANGE; | ||
71 | task->thread.regs->msr |= msr & MSR_DEBUGCHANGE; | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * We prevent mucking around with the reserved area of trap | ||
77 | * which are used internally by the kernel. | ||
78 | */ | ||
79 | static int set_user_trap(struct task_struct *task, unsigned long trap) | ||
80 | { | ||
81 | task->thread.regs->trap = trap & 0xfff0; | ||
82 | return 0; | ||
83 | } | ||
84 | |||
61 | /* | 85 | /* |
62 | * Get contents of register REGNO in task TASK. | 86 | * Get contents of register REGNO in task TASK. |
63 | */ | 87 | */ |
64 | unsigned long ptrace_get_reg(struct task_struct *task, int regno) | 88 | unsigned long ptrace_get_reg(struct task_struct *task, int regno) |
65 | { | 89 | { |
66 | unsigned long tmp = 0; | ||
67 | |||
68 | if (task->thread.regs == NULL) | 90 | if (task->thread.regs == NULL) |
69 | return -EIO; | 91 | return -EIO; |
70 | 92 | ||
71 | if (regno == PT_MSR) { | 93 | if (regno == PT_MSR) |
72 | tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | 94 | return get_user_msr(task); |
73 | return tmp | task->thread.fpexc_mode; | ||
74 | } | ||
75 | 95 | ||
76 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) | 96 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) |
77 | return ((unsigned long *)task->thread.regs)[regno]; | 97 | return ((unsigned long *)task->thread.regs)[regno]; |
@@ -87,40 +107,134 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) | |||
87 | if (task->thread.regs == NULL) | 107 | if (task->thread.regs == NULL) |
88 | return -EIO; | 108 | return -EIO; |
89 | 109 | ||
90 | if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) { | 110 | if (regno == PT_MSR) |
91 | if (regno == PT_MSR) | 111 | return set_user_msr(task, data); |
92 | data = (data & MSR_DEBUGCHANGE) | 112 | if (regno == PT_TRAP) |
93 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | 113 | return set_user_trap(task, data); |
94 | /* We prevent mucking around with the reserved area of trap | 114 | |
95 | * which are used internally by the kernel | 115 | if (regno <= PT_MAX_PUT_REG) { |
96 | */ | ||
97 | if (regno == PT_TRAP) | ||
98 | data &= 0xfff0; | ||
99 | ((unsigned long *)task->thread.regs)[regno] = data; | 116 | ((unsigned long *)task->thread.regs)[regno] = data; |
100 | return 0; | 117 | return 0; |
101 | } | 118 | } |
102 | return -EIO; | 119 | return -EIO; |
103 | } | 120 | } |
104 | 121 | ||
122 | static int gpr_get(struct task_struct *target, const struct user_regset *regset, | ||
123 | unsigned int pos, unsigned int count, | ||
124 | void *kbuf, void __user *ubuf) | ||
125 | { | ||
126 | int ret; | ||
127 | |||
128 | if (target->thread.regs == NULL) | ||
129 | return -EIO; | ||
130 | |||
131 | CHECK_FULL_REGS(target->thread.regs); | ||
132 | |||
133 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
134 | target->thread.regs, | ||
135 | 0, offsetof(struct pt_regs, msr)); | ||
136 | if (!ret) { | ||
137 | unsigned long msr = get_user_msr(target); | ||
138 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr, | ||
139 | offsetof(struct pt_regs, msr), | ||
140 | offsetof(struct pt_regs, msr) + | ||
141 | sizeof(msr)); | ||
142 | } | ||
143 | |||
144 | BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != | ||
145 | offsetof(struct pt_regs, msr) + sizeof(long)); | ||
146 | |||
147 | if (!ret) | ||
148 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
149 | &target->thread.regs->orig_gpr3, | ||
150 | offsetof(struct pt_regs, orig_gpr3), | ||
151 | sizeof(struct pt_regs)); | ||
152 | if (!ret) | ||
153 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
154 | sizeof(struct pt_regs), -1); | ||
155 | |||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | static int gpr_set(struct task_struct *target, const struct user_regset *regset, | ||
160 | unsigned int pos, unsigned int count, | ||
161 | const void *kbuf, const void __user *ubuf) | ||
162 | { | ||
163 | unsigned long reg; | ||
164 | int ret; | ||
165 | |||
166 | if (target->thread.regs == NULL) | ||
167 | return -EIO; | ||
168 | |||
169 | CHECK_FULL_REGS(target->thread.regs); | ||
170 | |||
171 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
172 | target->thread.regs, | ||
173 | 0, PT_MSR * sizeof(reg)); | ||
105 | 174 | ||
106 | static int get_fpregs(void __user *data, struct task_struct *task, | 175 | if (!ret && count > 0) { |
107 | int has_fpscr) | 176 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, |
177 | PT_MSR * sizeof(reg), | ||
178 | (PT_MSR + 1) * sizeof(reg)); | ||
179 | if (!ret) | ||
180 | ret = set_user_msr(target, reg); | ||
181 | } | ||
182 | |||
183 | BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != | ||
184 | offsetof(struct pt_regs, msr) + sizeof(long)); | ||
185 | |||
186 | if (!ret) | ||
187 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
188 | &target->thread.regs->orig_gpr3, | ||
189 | PT_ORIG_R3 * sizeof(reg), | ||
190 | (PT_MAX_PUT_REG + 1) * sizeof(reg)); | ||
191 | |||
192 | if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret) | ||
193 | ret = user_regset_copyin_ignore( | ||
194 | &pos, &count, &kbuf, &ubuf, | ||
195 | (PT_MAX_PUT_REG + 1) * sizeof(reg), | ||
196 | PT_TRAP * sizeof(reg)); | ||
197 | |||
198 | if (!ret && count > 0) { | ||
199 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, | ||
200 | PT_TRAP * sizeof(reg), | ||
201 | (PT_TRAP + 1) * sizeof(reg)); | ||
202 | if (!ret) | ||
203 | ret = set_user_trap(target, reg); | ||
204 | } | ||
205 | |||
206 | if (!ret) | ||
207 | ret = user_regset_copyin_ignore( | ||
208 | &pos, &count, &kbuf, &ubuf, | ||
209 | (PT_TRAP + 1) * sizeof(reg), -1); | ||
210 | |||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | static int fpr_get(struct task_struct *target, const struct user_regset *regset, | ||
215 | unsigned int pos, unsigned int count, | ||
216 | void *kbuf, void __user *ubuf) | ||
108 | { | 217 | { |
109 | unsigned int count = has_fpscr ? 33 : 32; | 218 | flush_fp_to_thread(target); |
110 | 219 | ||
111 | if (copy_to_user(data, task->thread.fpr, count * sizeof(double))) | 220 | BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) != |
112 | return -EFAULT; | 221 | offsetof(struct thread_struct, fpr[32])); |
113 | return 0; | 222 | |
223 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
224 | &target->thread.fpr, 0, -1); | ||
114 | } | 225 | } |
115 | 226 | ||
116 | static int set_fpregs(void __user *data, struct task_struct *task, | 227 | static int fpr_set(struct task_struct *target, const struct user_regset *regset, |
117 | int has_fpscr) | 228 | unsigned int pos, unsigned int count, |
229 | const void *kbuf, const void __user *ubuf) | ||
118 | { | 230 | { |
119 | unsigned int count = has_fpscr ? 33 : 32; | 231 | flush_fp_to_thread(target); |
120 | 232 | ||
121 | if (copy_from_user(task->thread.fpr, data, count * sizeof(double))) | 233 | BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) != |
122 | return -EFAULT; | 234 | offsetof(struct thread_struct, fpr[32])); |
123 | return 0; | 235 | |
236 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
237 | &target->thread.fpr, 0, -1); | ||
124 | } | 238 | } |
125 | 239 | ||
126 | 240 | ||
@@ -138,56 +252,74 @@ static int set_fpregs(void __user *data, struct task_struct *task, | |||
138 | * (combined (32- and 64-bit) gdb. | 252 | * (combined (32- and 64-bit) gdb. |
139 | */ | 253 | */ |
140 | 254 | ||
141 | /* | 255 | static int vr_active(struct task_struct *target, |
142 | * Get contents of AltiVec register state in task TASK | 256 | const struct user_regset *regset) |
143 | */ | ||
144 | static int get_vrregs(unsigned long __user *data, struct task_struct *task) | ||
145 | { | 257 | { |
146 | unsigned long regsize; | 258 | flush_altivec_to_thread(target); |
259 | return target->thread.used_vr ? regset->n : 0; | ||
260 | } | ||
147 | 261 | ||
148 | /* copy AltiVec registers VR[0] .. VR[31] */ | 262 | static int vr_get(struct task_struct *target, const struct user_regset *regset, |
149 | regsize = 32 * sizeof(vector128); | 263 | unsigned int pos, unsigned int count, |
150 | if (copy_to_user(data, task->thread.vr, regsize)) | 264 | void *kbuf, void __user *ubuf) |
151 | return -EFAULT; | 265 | { |
152 | data += (regsize / sizeof(unsigned long)); | 266 | int ret; |
153 | 267 | ||
154 | /* copy VSCR */ | 268 | flush_altivec_to_thread(target); |
155 | regsize = 1 * sizeof(vector128); | ||
156 | if (copy_to_user(data, &task->thread.vscr, regsize)) | ||
157 | return -EFAULT; | ||
158 | data += (regsize / sizeof(unsigned long)); | ||
159 | 269 | ||
160 | /* copy VRSAVE */ | 270 | BUILD_BUG_ON(offsetof(struct thread_struct, vscr) != |
161 | if (put_user(task->thread.vrsave, (u32 __user *)data)) | 271 | offsetof(struct thread_struct, vr[32])); |
162 | return -EFAULT; | ||
163 | 272 | ||
164 | return 0; | 273 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
274 | &target->thread.vr, 0, | ||
275 | 33 * sizeof(vector128)); | ||
276 | if (!ret) { | ||
277 | /* | ||
278 | * Copy out only the low-order word of vrsave. | ||
279 | */ | ||
280 | union { | ||
281 | elf_vrreg_t reg; | ||
282 | u32 word; | ||
283 | } vrsave; | ||
284 | memset(&vrsave, 0, sizeof(vrsave)); | ||
285 | vrsave.word = target->thread.vrsave; | ||
286 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave, | ||
287 | 33 * sizeof(vector128), -1); | ||
288 | } | ||
289 | |||
290 | return ret; | ||
165 | } | 291 | } |
166 | 292 | ||
167 | /* | 293 | static int vr_set(struct task_struct *target, const struct user_regset *regset, |
168 | * Write contents of AltiVec register state into task TASK. | 294 | unsigned int pos, unsigned int count, |
169 | */ | 295 | const void *kbuf, const void __user *ubuf) |
170 | static int set_vrregs(struct task_struct *task, unsigned long __user *data) | ||
171 | { | 296 | { |
172 | unsigned long regsize; | 297 | int ret; |
173 | 298 | ||
174 | /* copy AltiVec registers VR[0] .. VR[31] */ | 299 | flush_altivec_to_thread(target); |
175 | regsize = 32 * sizeof(vector128); | ||
176 | if (copy_from_user(task->thread.vr, data, regsize)) | ||
177 | return -EFAULT; | ||
178 | data += (regsize / sizeof(unsigned long)); | ||
179 | 300 | ||
180 | /* copy VSCR */ | 301 | BUILD_BUG_ON(offsetof(struct thread_struct, vscr) != |
181 | regsize = 1 * sizeof(vector128); | 302 | offsetof(struct thread_struct, vr[32])); |
182 | if (copy_from_user(&task->thread.vscr, data, regsize)) | ||
183 | return -EFAULT; | ||
184 | data += (regsize / sizeof(unsigned long)); | ||
185 | 303 | ||
186 | /* copy VRSAVE */ | 304 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
187 | if (get_user(task->thread.vrsave, (u32 __user *)data)) | 305 | &target->thread.vr, 0, 33 * sizeof(vector128)); |
188 | return -EFAULT; | 306 | if (!ret && count > 0) { |
307 | /* | ||
308 | * We use only the first word of vrsave. | ||
309 | */ | ||
310 | union { | ||
311 | elf_vrreg_t reg; | ||
312 | u32 word; | ||
313 | } vrsave; | ||
314 | memset(&vrsave, 0, sizeof(vrsave)); | ||
315 | vrsave.word = target->thread.vrsave; | ||
316 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave, | ||
317 | 33 * sizeof(vector128), -1); | ||
318 | if (!ret) | ||
319 | target->thread.vrsave = vrsave.word; | ||
320 | } | ||
189 | 321 | ||
190 | return 0; | 322 | return ret; |
191 | } | 323 | } |
192 | #endif /* CONFIG_ALTIVEC */ | 324 | #endif /* CONFIG_ALTIVEC */ |
193 | 325 | ||
@@ -203,57 +335,273 @@ static int set_vrregs(struct task_struct *task, unsigned long __user *data) | |||
203 | * } | 335 | * } |
204 | */ | 336 | */ |
205 | 337 | ||
206 | /* | 338 | static int evr_active(struct task_struct *target, |
207 | * Get contents of SPE register state in task TASK. | 339 | const struct user_regset *regset) |
208 | */ | ||
209 | static int get_evrregs(unsigned long *data, struct task_struct *task) | ||
210 | { | 340 | { |
211 | int i; | 341 | flush_spe_to_thread(target); |
342 | return target->thread.used_spe ? regset->n : 0; | ||
343 | } | ||
212 | 344 | ||
213 | if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long))) | 345 | static int evr_get(struct task_struct *target, const struct user_regset *regset, |
214 | return -EFAULT; | 346 | unsigned int pos, unsigned int count, |
347 | void *kbuf, void __user *ubuf) | ||
348 | { | ||
349 | int ret; | ||
215 | 350 | ||
216 | /* copy SPEFSCR */ | 351 | flush_spe_to_thread(target); |
217 | if (__put_user(task->thread.spefscr, &data[34])) | ||
218 | return -EFAULT; | ||
219 | 352 | ||
220 | /* copy SPE registers EVR[0] .. EVR[31] */ | 353 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
221 | for (i = 0; i < 32; i++, data++) | 354 | &target->thread.evr, |
222 | if (__put_user(task->thread.evr[i], data)) | 355 | 0, sizeof(target->thread.evr)); |
223 | return -EFAULT; | ||
224 | 356 | ||
225 | /* copy ACC */ | 357 | BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) != |
226 | if (__put_user64(task->thread.acc, (unsigned long long *)data)) | 358 | offsetof(struct thread_struct, spefscr)); |
227 | return -EFAULT; | ||
228 | 359 | ||
229 | return 0; | 360 | if (!ret) |
361 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
362 | &target->thread.acc, | ||
363 | sizeof(target->thread.evr), -1); | ||
364 | |||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | static int evr_set(struct task_struct *target, const struct user_regset *regset, | ||
369 | unsigned int pos, unsigned int count, | ||
370 | const void *kbuf, const void __user *ubuf) | ||
371 | { | ||
372 | int ret; | ||
373 | |||
374 | flush_spe_to_thread(target); | ||
375 | |||
376 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
377 | &target->thread.evr, | ||
378 | 0, sizeof(target->thread.evr)); | ||
379 | |||
380 | BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) != | ||
381 | offsetof(struct thread_struct, spefscr)); | ||
382 | |||
383 | if (!ret) | ||
384 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
385 | &target->thread.acc, | ||
386 | sizeof(target->thread.evr), -1); | ||
387 | |||
388 | return ret; | ||
230 | } | 389 | } |
390 | #endif /* CONFIG_SPE */ | ||
391 | |||
231 | 392 | ||
232 | /* | 393 | /* |
233 | * Write contents of SPE register state into task TASK. | 394 | * These are our native regset flavors. |
234 | */ | 395 | */ |
235 | static int set_evrregs(struct task_struct *task, unsigned long *data) | 396 | enum powerpc_regset { |
397 | REGSET_GPR, | ||
398 | REGSET_FPR, | ||
399 | #ifdef CONFIG_ALTIVEC | ||
400 | REGSET_VMX, | ||
401 | #endif | ||
402 | #ifdef CONFIG_SPE | ||
403 | REGSET_SPE, | ||
404 | #endif | ||
405 | }; | ||
406 | |||
407 | static const struct user_regset native_regsets[] = { | ||
408 | [REGSET_GPR] = { | ||
409 | .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, | ||
410 | .size = sizeof(long), .align = sizeof(long), | ||
411 | .get = gpr_get, .set = gpr_set | ||
412 | }, | ||
413 | [REGSET_FPR] = { | ||
414 | .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, | ||
415 | .size = sizeof(double), .align = sizeof(double), | ||
416 | .get = fpr_get, .set = fpr_set | ||
417 | }, | ||
418 | #ifdef CONFIG_ALTIVEC | ||
419 | [REGSET_VMX] = { | ||
420 | .core_note_type = NT_PPC_VMX, .n = 34, | ||
421 | .size = sizeof(vector128), .align = sizeof(vector128), | ||
422 | .active = vr_active, .get = vr_get, .set = vr_set | ||
423 | }, | ||
424 | #endif | ||
425 | #ifdef CONFIG_SPE | ||
426 | [REGSET_SPE] = { | ||
427 | .n = 35, | ||
428 | .size = sizeof(u32), .align = sizeof(u32), | ||
429 | .active = evr_active, .get = evr_get, .set = evr_set | ||
430 | }, | ||
431 | #endif | ||
432 | }; | ||
433 | |||
434 | static const struct user_regset_view user_ppc_native_view = { | ||
435 | .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, | ||
436 | .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets) | ||
437 | }; | ||
438 | |||
439 | #ifdef CONFIG_PPC64 | ||
440 | #include <linux/compat.h> | ||
441 | |||
442 | static int gpr32_get(struct task_struct *target, | ||
443 | const struct user_regset *regset, | ||
444 | unsigned int pos, unsigned int count, | ||
445 | void *kbuf, void __user *ubuf) | ||
236 | { | 446 | { |
237 | int i; | 447 | const unsigned long *regs = &target->thread.regs->gpr[0]; |
448 | compat_ulong_t *k = kbuf; | ||
449 | compat_ulong_t __user *u = ubuf; | ||
450 | compat_ulong_t reg; | ||
451 | |||
452 | if (target->thread.regs == NULL) | ||
453 | return -EIO; | ||
454 | |||
455 | CHECK_FULL_REGS(target->thread.regs); | ||
238 | 456 | ||
239 | if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long))) | 457 | pos /= sizeof(reg); |
240 | return -EFAULT; | 458 | count /= sizeof(reg); |
241 | 459 | ||
242 | /* copy SPEFSCR */ | 460 | if (kbuf) |
243 | if (__get_user(task->thread.spefscr, &data[34])) | 461 | for (; count > 0 && pos < PT_MSR; --count) |
244 | return -EFAULT; | 462 | *k++ = regs[pos++]; |
463 | else | ||
464 | for (; count > 0 && pos < PT_MSR; --count) | ||
465 | if (__put_user((compat_ulong_t) regs[pos++], u++)) | ||
466 | return -EFAULT; | ||
245 | 467 | ||
246 | /* copy SPE registers EVR[0] .. EVR[31] */ | 468 | if (count > 0 && pos == PT_MSR) { |
247 | for (i = 0; i < 32; i++, data++) | 469 | reg = get_user_msr(target); |
248 | if (__get_user(task->thread.evr[i], data)) | 470 | if (kbuf) |
471 | *k++ = reg; | ||
472 | else if (__put_user(reg, u++)) | ||
249 | return -EFAULT; | 473 | return -EFAULT; |
250 | /* copy ACC */ | 474 | ++pos; |
251 | if (__get_user64(task->thread.acc, (unsigned long long*)data)) | 475 | --count; |
252 | return -EFAULT; | 476 | } |
253 | 477 | ||
254 | return 0; | 478 | if (kbuf) |
479 | for (; count > 0 && pos < PT_REGS_COUNT; --count) | ||
480 | *k++ = regs[pos++]; | ||
481 | else | ||
482 | for (; count > 0 && pos < PT_REGS_COUNT; --count) | ||
483 | if (__put_user((compat_ulong_t) regs[pos++], u++)) | ||
484 | return -EFAULT; | ||
485 | |||
486 | kbuf = k; | ||
487 | ubuf = u; | ||
488 | pos *= sizeof(reg); | ||
489 | count *= sizeof(reg); | ||
490 | return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
491 | PT_REGS_COUNT * sizeof(reg), -1); | ||
492 | } | ||
493 | |||
494 | static int gpr32_set(struct task_struct *target, | ||
495 | const struct user_regset *regset, | ||
496 | unsigned int pos, unsigned int count, | ||
497 | const void *kbuf, const void __user *ubuf) | ||
498 | { | ||
499 | unsigned long *regs = &target->thread.regs->gpr[0]; | ||
500 | const compat_ulong_t *k = kbuf; | ||
501 | const compat_ulong_t __user *u = ubuf; | ||
502 | compat_ulong_t reg; | ||
503 | |||
504 | if (target->thread.regs == NULL) | ||
505 | return -EIO; | ||
506 | |||
507 | CHECK_FULL_REGS(target->thread.regs); | ||
508 | |||
509 | pos /= sizeof(reg); | ||
510 | count /= sizeof(reg); | ||
511 | |||
512 | if (kbuf) | ||
513 | for (; count > 0 && pos < PT_MSR; --count) | ||
514 | regs[pos++] = *k++; | ||
515 | else | ||
516 | for (; count > 0 && pos < PT_MSR; --count) { | ||
517 | if (__get_user(reg, u++)) | ||
518 | return -EFAULT; | ||
519 | regs[pos++] = reg; | ||
520 | } | ||
521 | |||
522 | |||
523 | if (count > 0 && pos == PT_MSR) { | ||
524 | if (kbuf) | ||
525 | reg = *k++; | ||
526 | else if (__get_user(reg, u++)) | ||
527 | return -EFAULT; | ||
528 | set_user_msr(target, reg); | ||
529 | ++pos; | ||
530 | --count; | ||
531 | } | ||
532 | |||
533 | if (kbuf) | ||
534 | for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) | ||
535 | regs[pos++] = *k++; | ||
536 | else | ||
537 | for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) { | ||
538 | if (__get_user(reg, u++)) | ||
539 | return -EFAULT; | ||
540 | regs[pos++] = reg; | ||
541 | } | ||
542 | |||
543 | if (count > 0 && pos == PT_TRAP) { | ||
544 | if (kbuf) | ||
545 | reg = *k++; | ||
546 | else if (__get_user(reg, u++)) | ||
547 | return -EFAULT; | ||
548 | set_user_trap(target, reg); | ||
549 | ++pos; | ||
550 | --count; | ||
551 | } | ||
552 | |||
553 | kbuf = k; | ||
554 | ubuf = u; | ||
555 | pos *= sizeof(reg); | ||
556 | count *= sizeof(reg); | ||
557 | return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, | ||
558 | (PT_TRAP + 1) * sizeof(reg), -1); | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * These are the regset flavors matching the CONFIG_PPC32 native set. | ||
563 | */ | ||
564 | static const struct user_regset compat_regsets[] = { | ||
565 | [REGSET_GPR] = { | ||
566 | .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, | ||
567 | .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), | ||
568 | .get = gpr32_get, .set = gpr32_set | ||
569 | }, | ||
570 | [REGSET_FPR] = { | ||
571 | .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, | ||
572 | .size = sizeof(double), .align = sizeof(double), | ||
573 | .get = fpr_get, .set = fpr_set | ||
574 | }, | ||
575 | #ifdef CONFIG_ALTIVEC | ||
576 | [REGSET_VMX] = { | ||
577 | .core_note_type = NT_PPC_VMX, .n = 34, | ||
578 | .size = sizeof(vector128), .align = sizeof(vector128), | ||
579 | .active = vr_active, .get = vr_get, .set = vr_set | ||
580 | }, | ||
581 | #endif | ||
582 | #ifdef CONFIG_SPE | ||
583 | [REGSET_SPE] = { | ||
584 | .core_note_type = NT_PPC_SPE, .n = 35, | ||
585 | .size = sizeof(u32), .align = sizeof(u32), | ||
586 | .active = evr_active, .get = evr_get, .set = evr_set | ||
587 | }, | ||
588 | #endif | ||
589 | }; | ||
590 | |||
591 | static const struct user_regset_view user_ppc_compat_view = { | ||
592 | .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI, | ||
593 | .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets) | ||
594 | }; | ||
595 | #endif /* CONFIG_PPC64 */ | ||
596 | |||
597 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | ||
598 | { | ||
599 | #ifdef CONFIG_PPC64 | ||
600 | if (test_tsk_thread_flag(task, TIF_32BIT)) | ||
601 | return &user_ppc_compat_view; | ||
602 | #endif | ||
603 | return &user_ppc_native_view; | ||
255 | } | 604 | } |
256 | #endif /* CONFIG_SPE */ | ||
257 | 605 | ||
258 | 606 | ||
259 | void user_enable_single_step(struct task_struct *task) | 607 | void user_enable_single_step(struct task_struct *task) |
@@ -323,55 +671,29 @@ void ptrace_disable(struct task_struct *child) | |||
323 | static long arch_ptrace_old(struct task_struct *child, long request, long addr, | 671 | static long arch_ptrace_old(struct task_struct *child, long request, long addr, |
324 | long data) | 672 | long data) |
325 | { | 673 | { |
326 | int ret = -EPERM; | 674 | switch (request) { |
327 | 675 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | |
328 | switch(request) { | 676 | return copy_regset_to_user(child, &user_ppc_native_view, |
329 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 677 | REGSET_GPR, 0, 32 * sizeof(long), |
330 | int i; | 678 | (void __user *) data); |
331 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 679 | |
332 | unsigned long __user *tmp = (unsigned long __user *)addr; | 680 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ |
333 | 681 | return copy_regset_from_user(child, &user_ppc_native_view, | |
334 | CHECK_FULL_REGS(child->thread.regs); | 682 | REGSET_GPR, 0, 32 * sizeof(long), |
335 | for (i = 0; i < 32; i++) { | 683 | (const void __user *) data); |
336 | ret = put_user(*reg, tmp); | 684 | |
337 | if (ret) | 685 | case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ |
338 | break; | 686 | return copy_regset_to_user(child, &user_ppc_native_view, |
339 | reg++; | 687 | REGSET_FPR, 0, 32 * sizeof(double), |
340 | tmp++; | 688 | (void __user *) data); |
341 | } | 689 | |
342 | break; | 690 | case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */ |
343 | } | 691 | return copy_regset_from_user(child, &user_ppc_native_view, |
344 | 692 | REGSET_FPR, 0, 32 * sizeof(double), | |
345 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | 693 | (const void __user *) data); |
346 | int i; | ||
347 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
348 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
349 | |||
350 | CHECK_FULL_REGS(child->thread.regs); | ||
351 | for (i = 0; i < 32; i++) { | ||
352 | ret = get_user(*reg, tmp); | ||
353 | if (ret) | ||
354 | break; | ||
355 | reg++; | ||
356 | tmp++; | ||
357 | } | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | ||
362 | flush_fp_to_thread(child); | ||
363 | ret = get_fpregs((void __user *)addr, child, 0); | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||
368 | flush_fp_to_thread(child); | ||
369 | ret = set_fpregs((void __user *)addr, child, 0); | ||
370 | break; | ||
371 | } | 694 | } |
372 | 695 | ||
373 | } | 696 | return -EPERM; |
374 | return ret; | ||
375 | } | 697 | } |
376 | 698 | ||
377 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 699 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
@@ -379,12 +701,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
379 | int ret = -EPERM; | 701 | int ret = -EPERM; |
380 | 702 | ||
381 | switch (request) { | 703 | switch (request) { |
382 | /* when I and D space are separate, these will need to be fixed. */ | ||
383 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
384 | case PTRACE_PEEKDATA: | ||
385 | ret = generic_ptrace_peekdata(child, addr, data); | ||
386 | break; | ||
387 | |||
388 | /* read the word at location addr in the USER area. */ | 704 | /* read the word at location addr in the USER area. */ |
389 | case PTRACE_PEEKUSR: { | 705 | case PTRACE_PEEKUSR: { |
390 | unsigned long index, tmp; | 706 | unsigned long index, tmp; |
@@ -412,12 +728,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
412 | break; | 728 | break; |
413 | } | 729 | } |
414 | 730 | ||
415 | /* If I and D space are separate, this will have to be fixed. */ | ||
416 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
417 | case PTRACE_POKEDATA: | ||
418 | ret = generic_ptrace_pokedata(child, addr, data); | ||
419 | break; | ||
420 | |||
421 | /* write the word at location addr in the USER area */ | 731 | /* write the word at location addr in the USER area */ |
422 | case PTRACE_POKEUSR: { | 732 | case PTRACE_POKEUSR: { |
423 | unsigned long index; | 733 | unsigned long index; |
@@ -462,85 +772,60 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
462 | #ifdef CONFIG_PPC64 | 772 | #ifdef CONFIG_PPC64 |
463 | case PTRACE_GETREGS64: | 773 | case PTRACE_GETREGS64: |
464 | #endif | 774 | #endif |
465 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ | 775 | case PTRACE_GETREGS: /* Get all pt_regs from the child. */ |
466 | int ui; | 776 | return copy_regset_to_user(child, &user_ppc_native_view, |
467 | if (!access_ok(VERIFY_WRITE, (void __user *)data, | 777 | REGSET_GPR, |
468 | sizeof(struct pt_regs))) { | 778 | 0, sizeof(struct pt_regs), |
469 | ret = -EIO; | 779 | (void __user *) data); |
470 | break; | ||
471 | } | ||
472 | CHECK_FULL_REGS(child->thread.regs); | ||
473 | ret = 0; | ||
474 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
475 | ret |= __put_user(ptrace_get_reg(child, ui), | ||
476 | (unsigned long __user *) data); | ||
477 | data += sizeof(long); | ||
478 | } | ||
479 | break; | ||
480 | } | ||
481 | 780 | ||
482 | #ifdef CONFIG_PPC64 | 781 | #ifdef CONFIG_PPC64 |
483 | case PTRACE_SETREGS64: | 782 | case PTRACE_SETREGS64: |
484 | #endif | 783 | #endif |
485 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | 784 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
486 | unsigned long tmp; | 785 | return copy_regset_from_user(child, &user_ppc_native_view, |
487 | int ui; | 786 | REGSET_GPR, |
488 | if (!access_ok(VERIFY_READ, (void __user *)data, | 787 | 0, sizeof(struct pt_regs), |
489 | sizeof(struct pt_regs))) { | 788 | (const void __user *) data); |
490 | ret = -EIO; | 789 | |
491 | break; | 790 | case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ |
492 | } | 791 | return copy_regset_to_user(child, &user_ppc_native_view, |
493 | CHECK_FULL_REGS(child->thread.regs); | 792 | REGSET_FPR, |
494 | ret = 0; | 793 | 0, sizeof(elf_fpregset_t), |
495 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | 794 | (void __user *) data); |
496 | ret = __get_user(tmp, (unsigned long __user *) data); | 795 | |
497 | if (ret) | 796 | case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */ |
498 | break; | 797 | return copy_regset_from_user(child, &user_ppc_native_view, |
499 | ptrace_put_reg(child, ui, tmp); | 798 | REGSET_FPR, |
500 | data += sizeof(long); | 799 | 0, sizeof(elf_fpregset_t), |
501 | } | 800 | (const void __user *) data); |
502 | break; | ||
503 | } | ||
504 | |||
505 | case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */ | ||
506 | flush_fp_to_thread(child); | ||
507 | ret = get_fpregs((void __user *)data, child, 1); | ||
508 | break; | ||
509 | } | ||
510 | |||
511 | case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */ | ||
512 | flush_fp_to_thread(child); | ||
513 | ret = set_fpregs((void __user *)data, child, 1); | ||
514 | break; | ||
515 | } | ||
516 | 801 | ||
517 | #ifdef CONFIG_ALTIVEC | 802 | #ifdef CONFIG_ALTIVEC |
518 | case PTRACE_GETVRREGS: | 803 | case PTRACE_GETVRREGS: |
519 | /* Get the child altivec register state. */ | 804 | return copy_regset_to_user(child, &user_ppc_native_view, |
520 | flush_altivec_to_thread(child); | 805 | REGSET_VMX, |
521 | ret = get_vrregs((unsigned long __user *)data, child); | 806 | 0, (33 * sizeof(vector128) + |
522 | break; | 807 | sizeof(u32)), |
808 | (void __user *) data); | ||
523 | 809 | ||
524 | case PTRACE_SETVRREGS: | 810 | case PTRACE_SETVRREGS: |
525 | /* Set the child altivec register state. */ | 811 | return copy_regset_from_user(child, &user_ppc_native_view, |
526 | flush_altivec_to_thread(child); | 812 | REGSET_VMX, |
527 | ret = set_vrregs(child, (unsigned long __user *)data); | 813 | 0, (33 * sizeof(vector128) + |
528 | break; | 814 | sizeof(u32)), |
815 | (const void __user *) data); | ||
529 | #endif | 816 | #endif |
530 | #ifdef CONFIG_SPE | 817 | #ifdef CONFIG_SPE |
531 | case PTRACE_GETEVRREGS: | 818 | case PTRACE_GETEVRREGS: |
532 | /* Get the child spe register state. */ | 819 | /* Get the child spe register state. */ |
533 | flush_spe_to_thread(child); | 820 | return copy_regset_to_user(child, &user_ppc_native_view, |
534 | ret = get_evrregs((unsigned long __user *)data, child); | 821 | REGSET_SPE, 0, 35 * sizeof(u32), |
535 | break; | 822 | (void __user *) data); |
536 | 823 | ||
537 | case PTRACE_SETEVRREGS: | 824 | case PTRACE_SETEVRREGS: |
538 | /* Set the child spe register state. */ | 825 | /* Set the child spe register state. */ |
539 | /* this is to clear the MSR_SPE bit to force a reload | 826 | return copy_regset_from_user(child, &user_ppc_native_view, |
540 | * of register state from memory */ | 827 | REGSET_SPE, 0, 35 * sizeof(u32), |
541 | flush_spe_to_thread(child); | 828 | (const void __user *) data); |
542 | ret = set_evrregs(child, (unsigned long __user *)data); | ||
543 | break; | ||
544 | #endif | 829 | #endif |
545 | 830 | ||
546 | /* Old reverse args ptrace callss */ | 831 | /* Old reverse args ptrace callss */ |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index fea6206ff90f..4c1de6af4c09 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -24,9 +24,11 @@ | |||
24 | #include <linux/smp_lock.h> | 24 | #include <linux/smp_lock.h> |
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
27 | #include <linux/regset.h> | ||
27 | #include <linux/user.h> | 28 | #include <linux/user.h> |
28 | #include <linux/security.h> | 29 | #include <linux/security.h> |
29 | #include <linux/signal.h> | 30 | #include <linux/signal.h> |
31 | #include <linux/compat.h> | ||
30 | 32 | ||
31 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
32 | #include <asm/page.h> | 34 | #include <asm/page.h> |
@@ -45,87 +47,31 @@ | |||
45 | static long compat_ptrace_old(struct task_struct *child, long request, | 47 | static long compat_ptrace_old(struct task_struct *child, long request, |
46 | long addr, long data) | 48 | long addr, long data) |
47 | { | 49 | { |
48 | int ret = -EPERM; | 50 | switch (request) { |
49 | 51 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | |
50 | switch(request) { | 52 | return copy_regset_to_user(child, |
51 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 53 | task_user_regset_view(current), 0, |
52 | int i; | 54 | 0, 32 * sizeof(compat_long_t), |
53 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 55 | compat_ptr(data)); |
54 | unsigned int __user *tmp = (unsigned int __user *)addr; | 56 | |
55 | 57 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ | |
56 | CHECK_FULL_REGS(child->thread.regs); | 58 | return copy_regset_from_user(child, |
57 | for (i = 0; i < 32; i++) { | 59 | task_user_regset_view(current), 0, |
58 | ret = put_user(*reg, tmp); | 60 | 0, 32 * sizeof(compat_long_t), |
59 | if (ret) | 61 | compat_ptr(data)); |
60 | break; | ||
61 | reg++; | ||
62 | tmp++; | ||
63 | } | ||
64 | break; | ||
65 | } | ||
66 | |||
67 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||
68 | int i; | ||
69 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
70 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
71 | |||
72 | CHECK_FULL_REGS(child->thread.regs); | ||
73 | for (i = 0; i < 32; i++) { | ||
74 | ret = get_user(*reg, tmp); | ||
75 | if (ret) | ||
76 | break; | ||
77 | reg++; | ||
78 | tmp++; | ||
79 | } | ||
80 | break; | ||
81 | } | 62 | } |
82 | 63 | ||
83 | } | 64 | return -EPERM; |
84 | return ret; | ||
85 | } | 65 | } |
86 | 66 | ||
87 | long compat_sys_ptrace(int request, int pid, unsigned long addr, | 67 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, |
88 | unsigned long data) | 68 | compat_ulong_t caddr, compat_ulong_t cdata) |
89 | { | 69 | { |
90 | struct task_struct *child; | 70 | unsigned long addr = caddr; |
71 | unsigned long data = cdata; | ||
91 | int ret; | 72 | int ret; |
92 | 73 | ||
93 | lock_kernel(); | ||
94 | if (request == PTRACE_TRACEME) { | ||
95 | ret = ptrace_traceme(); | ||
96 | goto out; | ||
97 | } | ||
98 | |||
99 | child = ptrace_get_task_struct(pid); | ||
100 | if (IS_ERR(child)) { | ||
101 | ret = PTR_ERR(child); | ||
102 | goto out; | ||
103 | } | ||
104 | |||
105 | if (request == PTRACE_ATTACH) { | ||
106 | ret = ptrace_attach(child); | ||
107 | goto out_tsk; | ||
108 | } | ||
109 | |||
110 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | ||
111 | if (ret < 0) | ||
112 | goto out_tsk; | ||
113 | |||
114 | switch (request) { | 74 | switch (request) { |
115 | /* when I and D space are separate, these will need to be fixed. */ | ||
116 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
117 | case PTRACE_PEEKDATA: { | ||
118 | unsigned int tmp; | ||
119 | int copied; | ||
120 | |||
121 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
122 | ret = -EIO; | ||
123 | if (copied != sizeof(tmp)) | ||
124 | break; | ||
125 | ret = put_user(tmp, (u32 __user *)data); | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | /* | 75 | /* |
130 | * Read 4 bytes of the other process' storage | 76 | * Read 4 bytes of the other process' storage |
131 | * data is a pointer specifying where the user wants the | 77 | * data is a pointer specifying where the user wants the |
@@ -225,19 +171,6 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
225 | break; | 171 | break; |
226 | } | 172 | } |
227 | 173 | ||
228 | /* If I and D space are separate, this will have to be fixed. */ | ||
229 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
230 | case PTRACE_POKEDATA: { | ||
231 | unsigned int tmp; | ||
232 | tmp = data; | ||
233 | ret = 0; | ||
234 | if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) | ||
235 | == sizeof(tmp)) | ||
236 | break; | ||
237 | ret = -EIO; | ||
238 | break; | ||
239 | } | ||
240 | |||
241 | /* | 174 | /* |
242 | * Write 4 bytes into the other process' storage | 175 | * Write 4 bytes into the other process' storage |
243 | * data is the 4 bytes that the user wants written | 176 | * data is the 4 bytes that the user wants written |
@@ -337,46 +270,17 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
337 | break; | 270 | break; |
338 | } | 271 | } |
339 | 272 | ||
340 | case PTRACE_GETEVENTMSG: | 273 | case PTRACE_GETREGS: /* Get all pt_regs from the child. */ |
341 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); | 274 | return copy_regset_to_user( |
342 | break; | 275 | child, task_user_regset_view(current), 0, |
276 | 0, PT_REGS_COUNT * sizeof(compat_long_t), | ||
277 | compat_ptr(data)); | ||
343 | 278 | ||
344 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ | 279 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
345 | int ui; | 280 | return copy_regset_from_user( |
346 | if (!access_ok(VERIFY_WRITE, (void __user *)data, | 281 | child, task_user_regset_view(current), 0, |
347 | PT_REGS_COUNT * sizeof(int))) { | 282 | 0, PT_REGS_COUNT * sizeof(compat_long_t), |
348 | ret = -EIO; | 283 | compat_ptr(data)); |
349 | break; | ||
350 | } | ||
351 | CHECK_FULL_REGS(child->thread.regs); | ||
352 | ret = 0; | ||
353 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
354 | ret |= __put_user(ptrace_get_reg(child, ui), | ||
355 | (unsigned int __user *) data); | ||
356 | data += sizeof(int); | ||
357 | } | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | ||
362 | unsigned long tmp; | ||
363 | int ui; | ||
364 | if (!access_ok(VERIFY_READ, (void __user *)data, | ||
365 | PT_REGS_COUNT * sizeof(int))) { | ||
366 | ret = -EIO; | ||
367 | break; | ||
368 | } | ||
369 | CHECK_FULL_REGS(child->thread.regs); | ||
370 | ret = 0; | ||
371 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
372 | ret = __get_user(tmp, (unsigned int __user *) data); | ||
373 | if (ret) | ||
374 | break; | ||
375 | ptrace_put_reg(child, ui, tmp); | ||
376 | data += sizeof(int); | ||
377 | } | ||
378 | break; | ||
379 | } | ||
380 | 284 | ||
381 | case PTRACE_GETFPREGS: | 285 | case PTRACE_GETFPREGS: |
382 | case PTRACE_SETFPREGS: | 286 | case PTRACE_SETFPREGS: |
@@ -402,12 +306,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
402 | break; | 306 | break; |
403 | 307 | ||
404 | default: | 308 | default: |
405 | ret = ptrace_request(child, request, addr, data); | 309 | ret = compat_ptrace_request(child, request, addr, data); |
406 | break; | 310 | break; |
407 | } | 311 | } |
408 | out_tsk: | 312 | |
409 | put_task_struct(child); | ||
410 | out: | ||
411 | unlock_kernel(); | ||
412 | return ret; | 313 | return ret; |
413 | } | 314 | } |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 848a20475db8..4b5b7ff4f78b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #endif | 54 | #endif |
55 | #include <asm/kexec.h> | 55 | #include <asm/kexec.h> |
56 | 56 | ||
57 | #ifdef CONFIG_DEBUGGER | 57 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
58 | int (*__debugger)(struct pt_regs *regs); | 58 | int (*__debugger)(struct pt_regs *regs); |
59 | int (*__debugger_ipi)(struct pt_regs *regs); | 59 | int (*__debugger_ipi)(struct pt_regs *regs); |
60 | int (*__debugger_bpt)(struct pt_regs *regs); | 60 | int (*__debugger_bpt)(struct pt_regs *regs); |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index f0bad7070fb5..f98867252ee2 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -176,7 +176,7 @@ static void __devinit vio_dev_release(struct device *dev) | |||
176 | * Returns a pointer to the created vio_dev or NULL if node has | 176 | * Returns a pointer to the created vio_dev or NULL if node has |
177 | * NULL device_type or compatible fields. | 177 | * NULL device_type or compatible fields. |
178 | */ | 178 | */ |
179 | struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) | 179 | struct vio_dev *vio_register_device_node(struct device_node *of_node) |
180 | { | 180 | { |
181 | struct vio_dev *viodev; | 181 | struct vio_dev *viodev; |
182 | const unsigned int *unit_address; | 182 | const unsigned int *unit_address; |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index ff5debf5eedd..93a5c53e3423 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -485,7 +485,12 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, | |||
485 | */ | 485 | */ |
486 | _tlbie(address, 0 /* 8xx doesn't care about PID */); | 486 | _tlbie(address, 0 /* 8xx doesn't care about PID */); |
487 | #endif | 487 | #endif |
488 | if (!PageReserved(page) | 488 | /* The _PAGE_USER test should really be _PAGE_EXEC, but |
489 | * older glibc versions execute some code from no-exec | ||
490 | * pages, which for now we are supporting. If exec-only | ||
491 | * pages are ever implemented, this will have to change. | ||
492 | */ | ||
493 | if (!PageReserved(page) && (pte_val(pte) & _PAGE_USER) | ||
489 | && !test_bit(PG_arch_1, &page->flags)) { | 494 | && !test_bit(PG_arch_1, &page->flags)) { |
490 | if (vma->vm_mm == current->active_mm) { | 495 | if (vma->vm_mm == current->active_mm) { |
491 | __flush_dcache_icache((void *) address); | 496 | __flush_dcache_icache((void *) address); |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index bc60322d2436..a300d254aac6 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | static int numa_enabled = 1; | 25 | static int numa_enabled = 1; |
26 | 26 | ||
27 | static char *cmdline __initdata; | ||
28 | |||
27 | static int numa_debug; | 29 | static int numa_debug; |
28 | #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); } | 30 | #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); } |
29 | 31 | ||
@@ -39,6 +41,53 @@ static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; | |||
39 | static int min_common_depth; | 41 | static int min_common_depth; |
40 | static int n_mem_addr_cells, n_mem_size_cells; | 42 | static int n_mem_addr_cells, n_mem_size_cells; |
41 | 43 | ||
44 | static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn, | ||
45 | unsigned int *nid) | ||
46 | { | ||
47 | unsigned long long mem; | ||
48 | char *p = cmdline; | ||
49 | static unsigned int fake_nid; | ||
50 | static unsigned long long curr_boundary; | ||
51 | |||
52 | /* | ||
53 | * Modify node id, iff we started creating NUMA nodes | ||
54 | * We want to continue from where we left of the last time | ||
55 | */ | ||
56 | if (fake_nid) | ||
57 | *nid = fake_nid; | ||
58 | /* | ||
59 | * In case there are no more arguments to parse, the | ||
60 | * node_id should be the same as the last fake node id | ||
61 | * (we've handled this above). | ||
62 | */ | ||
63 | if (!p) | ||
64 | return 0; | ||
65 | |||
66 | mem = memparse(p, &p); | ||
67 | if (!mem) | ||
68 | return 0; | ||
69 | |||
70 | if (mem < curr_boundary) | ||
71 | return 0; | ||
72 | |||
73 | curr_boundary = mem; | ||
74 | |||
75 | if ((end_pfn << PAGE_SHIFT) > mem) { | ||
76 | /* | ||
77 | * Skip commas and spaces | ||
78 | */ | ||
79 | while (*p == ',' || *p == ' ' || *p == '\t') | ||
80 | p++; | ||
81 | |||
82 | cmdline = p; | ||
83 | fake_nid++; | ||
84 | *nid = fake_nid; | ||
85 | dbg("created new fake_node with id %d\n", fake_nid); | ||
86 | return 1; | ||
87 | } | ||
88 | return 0; | ||
89 | } | ||
90 | |||
42 | static void __cpuinit map_cpu_to_node(int cpu, int node) | 91 | static void __cpuinit map_cpu_to_node(int cpu, int node) |
43 | { | 92 | { |
44 | numa_cpu_lookup_table[cpu] = node; | 93 | numa_cpu_lookup_table[cpu] = node; |
@@ -344,6 +393,9 @@ static void __init parse_drconf_memory(struct device_node *memory) | |||
344 | if (nid == 0xffff || nid >= MAX_NUMNODES) | 393 | if (nid == 0xffff || nid >= MAX_NUMNODES) |
345 | nid = default_nid; | 394 | nid = default_nid; |
346 | } | 395 | } |
396 | |||
397 | fake_numa_create_new_node(((start + lmb_size) >> PAGE_SHIFT), | ||
398 | &nid); | ||
347 | node_set_online(nid); | 399 | node_set_online(nid); |
348 | 400 | ||
349 | size = numa_enforce_memory_limit(start, lmb_size); | 401 | size = numa_enforce_memory_limit(start, lmb_size); |
@@ -429,6 +481,8 @@ new_range: | |||
429 | nid = of_node_to_nid_single(memory); | 481 | nid = of_node_to_nid_single(memory); |
430 | if (nid < 0) | 482 | if (nid < 0) |
431 | nid = default_nid; | 483 | nid = default_nid; |
484 | |||
485 | fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid); | ||
432 | node_set_online(nid); | 486 | node_set_online(nid); |
433 | 487 | ||
434 | if (!(size = numa_enforce_memory_limit(start, size))) { | 488 | if (!(size = numa_enforce_memory_limit(start, size))) { |
@@ -461,7 +515,7 @@ static void __init setup_nonnuma(void) | |||
461 | unsigned long top_of_ram = lmb_end_of_DRAM(); | 515 | unsigned long top_of_ram = lmb_end_of_DRAM(); |
462 | unsigned long total_ram = lmb_phys_mem_size(); | 516 | unsigned long total_ram = lmb_phys_mem_size(); |
463 | unsigned long start_pfn, end_pfn; | 517 | unsigned long start_pfn, end_pfn; |
464 | unsigned int i; | 518 | unsigned int i, nid = 0; |
465 | 519 | ||
466 | printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", | 520 | printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", |
467 | top_of_ram, total_ram); | 521 | top_of_ram, total_ram); |
@@ -471,9 +525,11 @@ static void __init setup_nonnuma(void) | |||
471 | for (i = 0; i < lmb.memory.cnt; ++i) { | 525 | for (i = 0; i < lmb.memory.cnt; ++i) { |
472 | start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; | 526 | start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; |
473 | end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); | 527 | end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); |
474 | add_active_range(0, start_pfn, end_pfn); | 528 | |
529 | fake_numa_create_new_node(end_pfn, &nid); | ||
530 | add_active_range(nid, start_pfn, end_pfn); | ||
531 | node_set_online(nid); | ||
475 | } | 532 | } |
476 | node_set_online(0); | ||
477 | } | 533 | } |
478 | 534 | ||
479 | void __init dump_numa_cpu_topology(void) | 535 | void __init dump_numa_cpu_topology(void) |
@@ -702,6 +758,10 @@ static int __init early_numa(char *p) | |||
702 | if (strstr(p, "debug")) | 758 | if (strstr(p, "debug")) |
703 | numa_debug = 1; | 759 | numa_debug = 1; |
704 | 760 | ||
761 | p = strstr(p, "fake="); | ||
762 | if (p) | ||
763 | cmdline = p + strlen("fake="); | ||
764 | |||
705 | return 0; | 765 | return 0; |
706 | } | 766 | } |
707 | early_param("numa", early_numa); | 767 | early_param("numa", early_numa); |
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index c5f64c3bd668..2ef6b0dddd8c 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
@@ -15,5 +15,5 @@ oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \ | |||
15 | cell/spu_profiler.o cell/vma_map.o \ | 15 | cell/spu_profiler.o cell/vma_map.o \ |
16 | cell/spu_task_sync.o | 16 | cell/spu_task_sync.o |
17 | oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o | 17 | oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o |
18 | oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o | 18 | oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o |
19 | oprofile-$(CONFIG_6xx) += op_model_7450.o | 19 | oprofile-$(CONFIG_6xx) += op_model_7450.o |
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index a28cce1d6c24..4908dc98f9ca 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
@@ -202,9 +202,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
202 | model = &op_model_7450; | 202 | model = &op_model_7450; |
203 | break; | 203 | break; |
204 | #endif | 204 | #endif |
205 | #ifdef CONFIG_FSL_BOOKE | 205 | #if defined(CONFIG_FSL_EMB_PERFMON) |
206 | case PPC_OPROFILE_BOOKE: | 206 | case PPC_OPROFILE_FSL_EMB: |
207 | model = &op_model_fsl_booke; | 207 | model = &op_model_fsl_emb; |
208 | break; | 208 | break; |
209 | #endif | 209 | #endif |
210 | default: | 210 | default: |
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_emb.c index 183a28bb1812..91596f6ba1f4 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_emb.c | |||
@@ -1,7 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/powerpc/oprofile/op_model_fsl_booke.c | 2 | * Freescale Embedded oprofile support, based on ppc64 oprofile support |
3 | * | ||
4 | * Freescale Book-E oprofile support, based on ppc64 oprofile support | ||
5 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM | 3 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM |
6 | * | 4 | * |
7 | * Copyright (c) 2004 Freescale Semiconductor, Inc | 5 | * Copyright (c) 2004 Freescale Semiconductor, Inc |
@@ -22,7 +20,7 @@ | |||
22 | #include <asm/system.h> | 20 | #include <asm/system.h> |
23 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
24 | #include <asm/cputable.h> | 22 | #include <asm/cputable.h> |
25 | #include <asm/reg_booke.h> | 23 | #include <asm/reg_fsl_emb.h> |
26 | #include <asm/page.h> | 24 | #include <asm/page.h> |
27 | #include <asm/pmc.h> | 25 | #include <asm/pmc.h> |
28 | #include <asm/oprofile_impl.h> | 26 | #include <asm/oprofile_impl.h> |
@@ -244,7 +242,7 @@ static void dump_pmcs(void) | |||
244 | mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); | 242 | mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); |
245 | } | 243 | } |
246 | 244 | ||
247 | static int fsl_booke_cpu_setup(struct op_counter_config *ctr) | 245 | static int fsl_emb_cpu_setup(struct op_counter_config *ctr) |
248 | { | 246 | { |
249 | int i; | 247 | int i; |
250 | 248 | ||
@@ -262,7 +260,7 @@ static int fsl_booke_cpu_setup(struct op_counter_config *ctr) | |||
262 | return 0; | 260 | return 0; |
263 | } | 261 | } |
264 | 262 | ||
265 | static int fsl_booke_reg_setup(struct op_counter_config *ctr, | 263 | static int fsl_emb_reg_setup(struct op_counter_config *ctr, |
266 | struct op_system_config *sys, | 264 | struct op_system_config *sys, |
267 | int num_ctrs) | 265 | int num_ctrs) |
268 | { | 266 | { |
@@ -281,7 +279,7 @@ static int fsl_booke_reg_setup(struct op_counter_config *ctr, | |||
281 | return 0; | 279 | return 0; |
282 | } | 280 | } |
283 | 281 | ||
284 | static int fsl_booke_start(struct op_counter_config *ctr) | 282 | static int fsl_emb_start(struct op_counter_config *ctr) |
285 | { | 283 | { |
286 | int i; | 284 | int i; |
287 | 285 | ||
@@ -315,7 +313,7 @@ static int fsl_booke_start(struct op_counter_config *ctr) | |||
315 | return 0; | 313 | return 0; |
316 | } | 314 | } |
317 | 315 | ||
318 | static void fsl_booke_stop(void) | 316 | static void fsl_emb_stop(void) |
319 | { | 317 | { |
320 | /* freeze counters */ | 318 | /* freeze counters */ |
321 | pmc_stop_ctrs(); | 319 | pmc_stop_ctrs(); |
@@ -329,7 +327,7 @@ static void fsl_booke_stop(void) | |||
329 | } | 327 | } |
330 | 328 | ||
331 | 329 | ||
332 | static void fsl_booke_handle_interrupt(struct pt_regs *regs, | 330 | static void fsl_emb_handle_interrupt(struct pt_regs *regs, |
333 | struct op_counter_config *ctr) | 331 | struct op_counter_config *ctr) |
334 | { | 332 | { |
335 | unsigned long pc; | 333 | unsigned long pc; |
@@ -362,10 +360,10 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs, | |||
362 | pmc_start_ctrs(1); | 360 | pmc_start_ctrs(1); |
363 | } | 361 | } |
364 | 362 | ||
365 | struct op_powerpc_model op_model_fsl_booke = { | 363 | struct op_powerpc_model op_model_fsl_emb = { |
366 | .reg_setup = fsl_booke_reg_setup, | 364 | .reg_setup = fsl_emb_reg_setup, |
367 | .cpu_setup = fsl_booke_cpu_setup, | 365 | .cpu_setup = fsl_emb_cpu_setup, |
368 | .start = fsl_booke_start, | 366 | .start = fsl_emb_start, |
369 | .stop = fsl_booke_stop, | 367 | .stop = fsl_emb_stop, |
370 | .handle_interrupt = fsl_booke_handle_interrupt, | 368 | .handle_interrupt = fsl_emb_handle_interrupt, |
371 | }; | 369 | }; |
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 74f31177e47a..a9260e21451e 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig | |||
@@ -72,6 +72,7 @@ config WALNUT | |||
72 | default y | 72 | default y |
73 | select 405GP | 73 | select 405GP |
74 | select PCI | 74 | select PCI |
75 | select OF_RTC | ||
75 | help | 76 | help |
76 | This option enables support for the IBM PPC405GP evaluation board. | 77 | This option enables support for the IBM PPC405GP evaluation board. |
77 | 78 | ||
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c index 88b66444dfb2..0422590040db 100644 --- a/arch/powerpc/platforms/40x/virtex.c +++ b/arch/powerpc/platforms/40x/virtex.c | |||
@@ -37,7 +37,7 @@ static int __init virtex_probe(void) | |||
37 | { | 37 | { |
38 | unsigned long root = of_get_flat_dt_root(); | 38 | unsigned long root = of_get_flat_dt_root(); |
39 | 39 | ||
40 | if (!of_flat_dt_is_compatible(root, "xilinx,virtex")) | 40 | if (!of_flat_dt_is_compatible(root, "xlnx,virtex")) |
41 | return 0; | 41 | return 0; |
42 | 42 | ||
43 | return 1; | 43 | return 1; |
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c index 5d9edd917f92..b8b257efeb77 100644 --- a/arch/powerpc/platforms/40x/walnut.c +++ b/arch/powerpc/platforms/40x/walnut.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
21 | #include <linux/rtc.h> | ||
21 | 22 | ||
22 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
23 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 8f01563dbd2a..da5b7b7599db 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c | |||
@@ -137,7 +137,7 @@ static int __init pika_dtm_start(void) | |||
137 | } | 137 | } |
138 | of_node_put(np); | 138 | of_node_put(np); |
139 | 139 | ||
140 | fpga = ioremap(res.start + 0x20, 4); | 140 | fpga = ioremap(res.start, 0x24); |
141 | if (fpga == NULL) | 141 | if (fpga == NULL) |
142 | return -ENOENT; | 142 | return -ENOENT; |
143 | 143 | ||
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig new file mode 100644 index 000000000000..c6fa49e23dc0 --- /dev/null +++ b/arch/powerpc/platforms/512x/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | config PPC_MPC512x | ||
2 | bool | ||
3 | select FSL_SOC | ||
4 | select IPIC | ||
5 | default n | ||
6 | |||
7 | config PPC_MPC5121 | ||
8 | bool | ||
9 | select PPC_MPC512x | ||
10 | default n | ||
11 | |||
12 | config MPC5121_ADS | ||
13 | bool "Freescale MPC5121E ADS" | ||
14 | depends on PPC_MULTIPLATFORM && PPC32 | ||
15 | select DEFAULT_UIMAGE | ||
16 | select WANT_DEVICE_TREE | ||
17 | select PPC_MPC5121 | ||
18 | help | ||
19 | This option enables support for the MPC5121E ADS board. | ||
20 | default n | ||
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile new file mode 100644 index 000000000000..232c89f2039a --- /dev/null +++ b/arch/powerpc/platforms/512x/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # | ||
2 | # Makefile for the Freescale PowerPC 512x linux kernel. | ||
3 | # | ||
4 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c new file mode 100644 index 000000000000..50bd3a319022 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007 | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121 ADS board setup | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * 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 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | |||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/ipic.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/time.h> | ||
25 | |||
26 | /** | ||
27 | * mpc512x_find_ips_freq - Find the IPS bus frequency for a device | ||
28 | * @node: device node | ||
29 | * | ||
30 | * Returns IPS bus frequency, or 0 if the bus frequency cannot be found. | ||
31 | */ | ||
32 | unsigned long | ||
33 | mpc512x_find_ips_freq(struct device_node *node) | ||
34 | { | ||
35 | struct device_node *np; | ||
36 | const unsigned int *p_ips_freq = NULL; | ||
37 | |||
38 | of_node_get(node); | ||
39 | while (node) { | ||
40 | p_ips_freq = of_get_property(node, "bus-frequency", NULL); | ||
41 | if (p_ips_freq) | ||
42 | break; | ||
43 | |||
44 | np = of_get_parent(node); | ||
45 | of_node_put(node); | ||
46 | node = np; | ||
47 | } | ||
48 | if (node) | ||
49 | of_node_put(node); | ||
50 | |||
51 | return p_ips_freq ? *p_ips_freq : 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(mpc512x_find_ips_freq); | ||
54 | |||
55 | static struct of_device_id __initdata of_bus_ids[] = { | ||
56 | { .name = "soc", }, | ||
57 | { .name = "localbus", }, | ||
58 | {}, | ||
59 | }; | ||
60 | |||
61 | static void __init mpc5121_ads_declare_of_platform_devices(void) | ||
62 | { | ||
63 | /* Find every child of the SOC node and add it to of_platform */ | ||
64 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | ||
65 | printk(KERN_ERR __FILE__ ": " | ||
66 | "Error while probing of_platform bus\n"); | ||
67 | } | ||
68 | |||
69 | static void __init mpc5121_ads_init_IRQ(void) | ||
70 | { | ||
71 | struct device_node *np; | ||
72 | |||
73 | np = of_find_compatible_node(NULL, NULL, "fsl,ipic"); | ||
74 | if (!np) | ||
75 | return; | ||
76 | |||
77 | ipic_init(np, 0); | ||
78 | of_node_put(np); | ||
79 | |||
80 | /* | ||
81 | * Initialize the default interrupt mapping priorities, | ||
82 | * in case the boot rom changed something on us. | ||
83 | */ | ||
84 | ipic_set_default_priority(); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Called very early, MMU is off, device-tree isn't unflattened | ||
89 | */ | ||
90 | static int __init mpc5121_ads_probe(void) | ||
91 | { | ||
92 | unsigned long root = of_get_flat_dt_root(); | ||
93 | |||
94 | return of_flat_dt_is_compatible(root, "fsl,mpc5121ads"); | ||
95 | } | ||
96 | |||
97 | define_machine(mpc5121_ads) { | ||
98 | .name = "MPC5121 ADS", | ||
99 | .probe = mpc5121_ads_probe, | ||
100 | .init = mpc5121_ads_declare_of_platform_devices, | ||
101 | .init_IRQ = mpc5121_ads_init_IRQ, | ||
102 | .get_irq = ipic_get_irq, | ||
103 | .calibrate_decr = generic_calibrate_decr, | ||
104 | }; | ||
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c index 3fce6b375dbc..7d3018751988 100644 --- a/arch/powerpc/platforms/82xx/mpc8272_ads.c +++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c | |||
@@ -134,13 +134,12 @@ static void __init mpc8272_ads_setup_arch(void) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | bcsr = of_iomap(np, 0); | 136 | bcsr = of_iomap(np, 0); |
137 | of_node_put(np); | ||
137 | if (!bcsr) { | 138 | if (!bcsr) { |
138 | printk(KERN_ERR "Cannot map BCSR registers\n"); | 139 | printk(KERN_ERR "Cannot map BCSR registers\n"); |
139 | return; | 140 | return; |
140 | } | 141 | } |
141 | 142 | ||
142 | of_node_put(np); | ||
143 | |||
144 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); | 143 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); |
145 | setbits32(&bcsr[1], BCSR1_FETH_RST); | 144 | setbits32(&bcsr[1], BCSR1_FETH_RST); |
146 | 145 | ||
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c index 68196e349994..e1dceeec4994 100644 --- a/arch/powerpc/platforms/82xx/pq2fads.c +++ b/arch/powerpc/platforms/82xx/pq2fads.c | |||
@@ -130,13 +130,12 @@ static void __init pq2fads_setup_arch(void) | |||
130 | } | 130 | } |
131 | 131 | ||
132 | bcsr = of_iomap(np, 0); | 132 | bcsr = of_iomap(np, 0); |
133 | of_node_put(np); | ||
133 | if (!bcsr) { | 134 | if (!bcsr) { |
134 | printk(KERN_ERR "Cannot map BCSR registers\n"); | 135 | printk(KERN_ERR "Cannot map BCSR registers\n"); |
135 | return; | 136 | return; |
136 | } | 137 | } |
137 | 138 | ||
138 | of_node_put(np); | ||
139 | |||
140 | /* Enable the serial and ethernet ports */ | 139 | /* Enable the serial and ethernet ports */ |
141 | 140 | ||
142 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); | 141 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 9f0fd88b2b1f..e7f706b624fe 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
@@ -101,7 +101,7 @@ static void __init mpc832x_rdb_setup_arch(void) | |||
101 | #ifdef CONFIG_QUICC_ENGINE | 101 | #ifdef CONFIG_QUICC_ENGINE |
102 | qe_reset(); | 102 | qe_reset(); |
103 | 103 | ||
104 | if ((np = of_find_node_by_name(np, "par_io")) != NULL) { | 104 | if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) { |
105 | par_io_init(np); | 105 | par_io_init(np); |
106 | of_node_put(np); | 106 | of_node_put(np); |
107 | 107 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 88bb748aff0d..68065e62fc3d 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -14,6 +14,8 @@ | |||
14 | #define MPC83XX_SCCR_USB_DRCM_11 0x00300000 | 14 | #define MPC83XX_SCCR_USB_DRCM_11 0x00300000 |
15 | #define MPC83XX_SCCR_USB_DRCM_01 0x00100000 | 15 | #define MPC83XX_SCCR_USB_DRCM_01 0x00100000 |
16 | #define MPC83XX_SCCR_USB_DRCM_10 0x00200000 | 16 | #define MPC83XX_SCCR_USB_DRCM_10 0x00200000 |
17 | #define MPC8315_SCCR_USB_MASK 0x00c00000 | ||
18 | #define MPC8315_SCCR_USB_DRCM_11 0x00c00000 | ||
17 | #define MPC837X_SCCR_USB_DRCM_11 0x00c00000 | 19 | #define MPC837X_SCCR_USB_DRCM_11 0x00c00000 |
18 | 20 | ||
19 | /* system i/o configuration register low */ | 21 | /* system i/o configuration register low */ |
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c index 681230a30acd..471fdd8f4108 100644 --- a/arch/powerpc/platforms/83xx/usb.c +++ b/arch/powerpc/platforms/83xx/usb.c | |||
@@ -104,6 +104,7 @@ int mpc831x_usb_cfg(void) | |||
104 | u32 temp; | 104 | u32 temp; |
105 | void __iomem *immap, *usb_regs; | 105 | void __iomem *immap, *usb_regs; |
106 | struct device_node *np = NULL; | 106 | struct device_node *np = NULL; |
107 | struct device_node *immr_node = NULL; | ||
107 | const void *prop; | 108 | const void *prop; |
108 | struct resource res; | 109 | struct resource res; |
109 | int ret = 0; | 110 | int ret = 0; |
@@ -124,10 +125,15 @@ int mpc831x_usb_cfg(void) | |||
124 | } | 125 | } |
125 | 126 | ||
126 | /* Configure clock */ | 127 | /* Configure clock */ |
127 | temp = in_be32(immap + MPC83XX_SCCR_OFFS); | 128 | immr_node = of_get_parent(np); |
128 | temp &= ~MPC83XX_SCCR_USB_MASK; | 129 | if (immr_node && of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) |
129 | temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | 130 | clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, |
130 | out_be32(immap + MPC83XX_SCCR_OFFS, temp); | 131 | MPC8315_SCCR_USB_MASK, |
132 | MPC8315_SCCR_USB_DRCM_11); | ||
133 | else | ||
134 | clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, | ||
135 | MPC83XX_SCCR_USB_MASK, | ||
136 | MPC83XX_SCCR_USB_DRCM_11); | ||
131 | 137 | ||
132 | /* Configure pin mux for ULPI. There is no pin mux for UTMI */ | 138 | /* Configure pin mux for ULPI. There is no pin mux for UTMI */ |
133 | if (prop && !strcmp(prop, "ulpi")) { | 139 | if (prop && !strcmp(prop, "ulpi")) { |
@@ -144,6 +150,9 @@ int mpc831x_usb_cfg(void) | |||
144 | 150 | ||
145 | iounmap(immap); | 151 | iounmap(immap); |
146 | 152 | ||
153 | if (immr_node) | ||
154 | of_node_put(immr_node); | ||
155 | |||
147 | /* Map USB SOC space */ | 156 | /* Map USB SOC space */ |
148 | ret = of_address_to_resource(np, 0, &res); | 157 | ret = of_address_to_resource(np, 0, &res); |
149 | if (ret) { | 158 | if (ret) { |
diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c index c6bc0783c3b0..82363e98f50e 100644 --- a/arch/powerpc/platforms/8xx/adder875.c +++ b/arch/powerpc/platforms/8xx/adder875.c | |||
@@ -15,12 +15,12 @@ | |||
15 | 15 | ||
16 | #include <asm/time.h> | 16 | #include <asm/time.h> |
17 | #include <asm/machdep.h> | 17 | #include <asm/machdep.h> |
18 | #include <asm/commproc.h> | 18 | #include <asm/cpm1.h> |
19 | #include <asm/fs_pd.h> | 19 | #include <asm/fs_pd.h> |
20 | #include <asm/udbg.h> | 20 | #include <asm/udbg.h> |
21 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
22 | 22 | ||
23 | #include <sysdev/commproc.h> | 23 | #include "mpc8xx.h" |
24 | 24 | ||
25 | struct cpm_pin { | 25 | struct cpm_pin { |
26 | int port, pin, flags; | 26 | int port, pin, flags; |
@@ -108,7 +108,7 @@ define_machine(adder875) { | |||
108 | .name = "Adder MPC875", | 108 | .name = "Adder MPC875", |
109 | .probe = adder875_probe, | 109 | .probe = adder875_probe, |
110 | .setup_arch = adder875_setup, | 110 | .setup_arch = adder875_setup, |
111 | .init_IRQ = m8xx_pic_init, | 111 | .init_IRQ = mpc8xx_pics_init, |
112 | .get_irq = mpc8xx_get_irq, | 112 | .get_irq = mpc8xx_get_irq, |
113 | .restart = mpc8xx_restart, | 113 | .restart = mpc8xx_restart, |
114 | .calibrate_decr = generic_calibrate_decr, | 114 | .calibrate_decr = generic_calibrate_decr, |
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c index a8dffa005775..7d9ac6040d63 100644 --- a/arch/powerpc/platforms/8xx/ep88xc.c +++ b/arch/powerpc/platforms/8xx/ep88xc.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <asm/machdep.h> | 15 | #include <asm/machdep.h> |
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <asm/udbg.h> | 17 | #include <asm/udbg.h> |
18 | #include <asm/commproc.h> | ||
19 | #include <asm/cpm1.h> | 18 | #include <asm/cpm1.h> |
20 | 19 | ||
21 | #include "mpc8xx.h" | 20 | #include "mpc8xx.h" |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index fdce10c4f074..fcedbec07f94 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -24,6 +24,7 @@ config PPC_83xx | |||
24 | select MPC83xx | 24 | select MPC83xx |
25 | select IPIC | 25 | select IPIC |
26 | select WANT_DEVICE_TREE | 26 | select WANT_DEVICE_TREE |
27 | select FSL_EMB_PERFMON | ||
27 | 28 | ||
28 | config PPC_86xx | 29 | config PPC_86xx |
29 | bool "Freescale 86xx" | 30 | bool "Freescale 86xx" |
@@ -41,6 +42,7 @@ config CLASSIC32 | |||
41 | source "arch/powerpc/platforms/pseries/Kconfig" | 42 | source "arch/powerpc/platforms/pseries/Kconfig" |
42 | source "arch/powerpc/platforms/iseries/Kconfig" | 43 | source "arch/powerpc/platforms/iseries/Kconfig" |
43 | source "arch/powerpc/platforms/chrp/Kconfig" | 44 | source "arch/powerpc/platforms/chrp/Kconfig" |
45 | source "arch/powerpc/platforms/512x/Kconfig" | ||
44 | source "arch/powerpc/platforms/52xx/Kconfig" | 46 | source "arch/powerpc/platforms/52xx/Kconfig" |
45 | source "arch/powerpc/platforms/powermac/Kconfig" | 47 | source "arch/powerpc/platforms/powermac/Kconfig" |
46 | source "arch/powerpc/platforms/prep/Kconfig" | 48 | source "arch/powerpc/platforms/prep/Kconfig" |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 7fc41104d53e..69941ba70975 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -14,7 +14,7 @@ choice | |||
14 | There are five families of 32 bit PowerPC chips supported. | 14 | There are five families of 32 bit PowerPC chips supported. |
15 | The most common ones are the desktop and server CPUs (601, 603, | 15 | The most common ones are the desktop and server CPUs (601, 603, |
16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their | 16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their |
17 | embedded 52xx/82xx/83xx/86xx counterparts. | 17 | embedded 512x/52xx/82xx/83xx/86xx counterparts. |
18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 | 18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 |
19 | (85xx) each form a family of their own that is not compatible | 19 | (85xx) each form a family of their own that is not compatible |
20 | with the others. | 20 | with the others. |
@@ -22,7 +22,7 @@ choice | |||
22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. | 22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. |
23 | 23 | ||
24 | config 6xx | 24 | config 6xx |
25 | bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx" | 25 | bool "512x/52xx/6xx/7xx/74xx/82xx/83xx/86xx" |
26 | select PPC_FPU | 26 | select PPC_FPU |
27 | 27 | ||
28 | config PPC_85xx | 28 | config PPC_85xx |
@@ -94,6 +94,7 @@ config 8xx | |||
94 | bool | 94 | bool |
95 | 95 | ||
96 | config E500 | 96 | config E500 |
97 | select FSL_EMB_PERFMON | ||
97 | bool | 98 | bool |
98 | 99 | ||
99 | config PPC_FPU | 100 | config PPC_FPU |
@@ -115,6 +116,9 @@ config FSL_BOOKE | |||
115 | depends on E200 || E500 | 116 | depends on E200 || E500 |
116 | default y | 117 | default y |
117 | 118 | ||
119 | config FSL_EMB_PERFMON | ||
120 | bool | ||
121 | |||
118 | config PTE_64BIT | 122 | config PTE_64BIT |
119 | bool | 123 | bool |
120 | depends on 44x || E500 | 124 | depends on 44x || E500 |
@@ -221,7 +225,7 @@ config NR_CPUS | |||
221 | 225 | ||
222 | config NOT_COHERENT_CACHE | 226 | config NOT_COHERENT_CACHE |
223 | bool | 227 | bool |
224 | depends on 4xx || 8xx || E200 | 228 | depends on 4xx || 8xx || E200 || PPC_MPC512x |
225 | default y | 229 | default y |
226 | 230 | ||
227 | config CHECK_CACHE_COHERENCY | 231 | config CHECK_CACHE_COHERENCY |
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 6d9079da5f5a..a984894466d9 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
@@ -11,6 +11,7 @@ endif | |||
11 | obj-$(CONFIG_PPC_CHRP) += chrp/ | 11 | obj-$(CONFIG_PPC_CHRP) += chrp/ |
12 | obj-$(CONFIG_40x) += 40x/ | 12 | obj-$(CONFIG_40x) += 40x/ |
13 | obj-$(CONFIG_44x) += 44x/ | 13 | obj-$(CONFIG_44x) += 44x/ |
14 | obj-$(CONFIG_PPC_MPC512x) += 512x/ | ||
14 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ | 15 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ |
15 | obj-$(CONFIG_PPC_8xx) += 8xx/ | 16 | obj-$(CONFIG_PPC_8xx) += 8xx/ |
16 | obj-$(CONFIG_PPC_82xx) += 82xx/ | 17 | obj-$(CONFIG_PPC_82xx) += 82xx/ |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 3a963b4a9be0..2f169991896d 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -54,6 +54,13 @@ config SPU_FS_64K_LS | |||
54 | uses 4K pages. This can improve performances of applications | 54 | uses 4K pages. This can improve performances of applications |
55 | using multiple SPEs by lowering the TLB pressure on them. | 55 | using multiple SPEs by lowering the TLB pressure on them. |
56 | 56 | ||
57 | config SPU_TRACE | ||
58 | tristate "SPU event tracing support" | ||
59 | depends on SPU_FS && MARKERS | ||
60 | help | ||
61 | This option allows reading a trace of spu-related events through | ||
62 | the sputrace file in procfs. | ||
63 | |||
57 | config SPU_BASE | 64 | config SPU_BASE |
58 | bool | 65 | bool |
59 | default n | 66 | default n |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 095988f13bf4..d95e71dee91f 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/msi.h> | 15 | #include <linux/msi.h> |
16 | #include <linux/reboot.h> | 16 | #include <linux/of_platform.h> |
17 | 17 | ||
18 | #include <asm/dcr.h> | 18 | #include <asm/dcr.h> |
19 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
@@ -65,14 +65,12 @@ | |||
65 | 65 | ||
66 | struct axon_msic { | 66 | struct axon_msic { |
67 | struct irq_host *irq_host; | 67 | struct irq_host *irq_host; |
68 | __le32 *fifo; | 68 | __le32 *fifo_virt; |
69 | dma_addr_t fifo_phys; | ||
69 | dcr_host_t dcr_host; | 70 | dcr_host_t dcr_host; |
70 | struct list_head list; | ||
71 | u32 read_offset; | 71 | u32 read_offset; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static LIST_HEAD(axon_msic_list); | ||
75 | |||
76 | static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) | 74 | static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) |
77 | { | 75 | { |
78 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); | 76 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); |
@@ -94,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
94 | 92 | ||
95 | while (msic->read_offset != write_offset) { | 93 | while (msic->read_offset != write_offset) { |
96 | idx = msic->read_offset / sizeof(__le32); | 94 | idx = msic->read_offset / sizeof(__le32); |
97 | msi = le32_to_cpu(msic->fifo[idx]); | 95 | msi = le32_to_cpu(msic->fifo_virt[idx]); |
98 | msi &= 0xFFFF; | 96 | msi &= 0xFFFF; |
99 | 97 | ||
100 | pr_debug("axon_msi: woff %x roff %x msi %x\n", | 98 | pr_debug("axon_msi: woff %x roff %x msi %x\n", |
@@ -139,6 +137,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev) | |||
139 | 137 | ||
140 | tmp = dn; | 138 | tmp = dn; |
141 | dn = of_find_node_by_phandle(*ph); | 139 | dn = of_find_node_by_phandle(*ph); |
140 | of_node_put(tmp); | ||
142 | if (!dn) { | 141 | if (!dn) { |
143 | dev_dbg(&dev->dev, | 142 | dev_dbg(&dev->dev, |
144 | "axon_msi: msi-translator doesn't point to a node\n"); | 143 | "axon_msi: msi-translator doesn't point to a node\n"); |
@@ -156,7 +155,6 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev) | |||
156 | 155 | ||
157 | out_error: | 156 | out_error: |
158 | of_node_put(dn); | 157 | of_node_put(dn); |
159 | of_node_put(tmp); | ||
160 | 158 | ||
161 | return msic; | 159 | return msic; |
162 | } | 160 | } |
@@ -292,30 +290,24 @@ static struct irq_host_ops msic_host_ops = { | |||
292 | .map = msic_host_map, | 290 | .map = msic_host_map, |
293 | }; | 291 | }; |
294 | 292 | ||
295 | static int axon_msi_notify_reboot(struct notifier_block *nb, | 293 | static int axon_msi_shutdown(struct of_device *device) |
296 | unsigned long code, void *data) | ||
297 | { | 294 | { |
298 | struct axon_msic *msic; | 295 | struct axon_msic *msic = device->dev.platform_data; |
299 | u32 tmp; | 296 | u32 tmp; |
300 | 297 | ||
301 | list_for_each_entry(msic, &axon_msic_list, list) { | 298 | pr_debug("axon_msi: disabling %s\n", |
302 | pr_debug("axon_msi: disabling %s\n", | 299 | msic->irq_host->of_node->full_name); |
303 | msic->irq_host->of_node->full_name); | 300 | tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); |
304 | tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); | 301 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; |
305 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; | 302 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); |
306 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); | ||
307 | } | ||
308 | 303 | ||
309 | return 0; | 304 | return 0; |
310 | } | 305 | } |
311 | 306 | ||
312 | static struct notifier_block axon_msi_reboot_notifier = { | 307 | static int axon_msi_probe(struct of_device *device, |
313 | .notifier_call = axon_msi_notify_reboot | 308 | const struct of_device_id *device_id) |
314 | }; | ||
315 | |||
316 | static int axon_msi_setup_one(struct device_node *dn) | ||
317 | { | 309 | { |
318 | struct page *page; | 310 | struct device_node *dn = device->node; |
319 | struct axon_msic *msic; | 311 | struct axon_msic *msic; |
320 | unsigned int virq; | 312 | unsigned int virq; |
321 | int dcr_base, dcr_len; | 313 | int dcr_base, dcr_len; |
@@ -346,16 +338,14 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
346 | goto out_free_msic; | 338 | goto out_free_msic; |
347 | } | 339 | } |
348 | 340 | ||
349 | page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL, | 341 | msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, |
350 | get_order(MSIC_FIFO_SIZE_BYTES)); | 342 | &msic->fifo_phys, GFP_KERNEL); |
351 | if (!page) { | 343 | if (!msic->fifo_virt) { |
352 | printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n", | 344 | printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n", |
353 | dn->full_name); | 345 | dn->full_name); |
354 | goto out_free_msic; | 346 | goto out_free_msic; |
355 | } | 347 | } |
356 | 348 | ||
357 | msic->fifo = page_address(page); | ||
358 | |||
359 | msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, | 349 | msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, |
360 | NR_IRQS, &msic_host_ops, 0); | 350 | NR_IRQS, &msic_host_ops, 0); |
361 | if (!msic->irq_host) { | 351 | if (!msic->irq_host) { |
@@ -378,14 +368,18 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
378 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); | 368 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); |
379 | 369 | ||
380 | /* Enable the MSIC hardware */ | 370 | /* Enable the MSIC hardware */ |
381 | msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32); | 371 | msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32); |
382 | msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG, | 372 | msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG, |
383 | (u64)msic->fifo & 0xFFFFFFFF); | 373 | msic->fifo_phys & 0xFFFFFFFF); |
384 | msic_dcr_write(msic, MSIC_CTRL_REG, | 374 | msic_dcr_write(msic, MSIC_CTRL_REG, |
385 | MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE | | 375 | MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE | |
386 | MSIC_CTRL_FIFO_SIZE); | 376 | MSIC_CTRL_FIFO_SIZE); |
387 | 377 | ||
388 | list_add(&msic->list, &axon_msic_list); | 378 | device->dev.platform_data = msic; |
379 | |||
380 | ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; | ||
381 | ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; | ||
382 | ppc_md.msi_check_device = axon_msi_check_device; | ||
389 | 383 | ||
390 | printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name); | 384 | printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name); |
391 | 385 | ||
@@ -394,7 +388,8 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
394 | out_free_host: | 388 | out_free_host: |
395 | kfree(msic->irq_host); | 389 | kfree(msic->irq_host); |
396 | out_free_fifo: | 390 | out_free_fifo: |
397 | __free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES)); | 391 | dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt, |
392 | msic->fifo_phys); | ||
398 | out_free_msic: | 393 | out_free_msic: |
399 | kfree(msic); | 394 | kfree(msic); |
400 | out: | 395 | out: |
@@ -402,28 +397,24 @@ out: | |||
402 | return -1; | 397 | return -1; |
403 | } | 398 | } |
404 | 399 | ||
405 | static int axon_msi_init(void) | 400 | static const struct of_device_id axon_msi_device_id[] = { |
406 | { | 401 | { |
407 | struct device_node *dn; | 402 | .compatible = "ibm,axon-msic" |
408 | int found = 0; | 403 | }, |
409 | 404 | {} | |
410 | pr_debug("axon_msi: initialising ...\n"); | 405 | }; |
411 | |||
412 | for_each_compatible_node(dn, NULL, "ibm,axon-msic") { | ||
413 | if (axon_msi_setup_one(dn) == 0) | ||
414 | found++; | ||
415 | } | ||
416 | |||
417 | if (found) { | ||
418 | ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; | ||
419 | ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; | ||
420 | ppc_md.msi_check_device = axon_msi_check_device; | ||
421 | |||
422 | register_reboot_notifier(&axon_msi_reboot_notifier); | ||
423 | 406 | ||
424 | pr_debug("axon_msi: registered callbacks!\n"); | 407 | static struct of_platform_driver axon_msi_driver = { |
425 | } | 408 | .match_table = axon_msi_device_id, |
409 | .probe = axon_msi_probe, | ||
410 | .shutdown = axon_msi_shutdown, | ||
411 | .driver = { | ||
412 | .name = "axon-msi" | ||
413 | }, | ||
414 | }; | ||
426 | 415 | ||
427 | return 0; | 416 | static int __init axon_msi_init(void) |
417 | { | ||
418 | return of_register_platform_driver(&axon_msi_driver); | ||
428 | } | 419 | } |
429 | arch_initcall(axon_msi_init); | 420 | subsys_initcall(axon_msi_init); |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index e6534b519c9a..a7f609b3b876 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -98,7 +98,7 @@ static int __init cell_publish_devices(void) | |||
98 | } | 98 | } |
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | machine_device_initcall(cell, cell_publish_devices); | 101 | machine_subsys_initcall(cell, cell_publish_devices); |
102 | 102 | ||
103 | static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc) | 103 | static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc) |
104 | { | 104 | { |
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index d3a349fb42e5..99610a6361f2 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile | |||
@@ -4,6 +4,8 @@ spufs-y += inode.o file.o context.o syscalls.o coredump.o | |||
4 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o | 4 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o |
5 | spufs-y += switch.o fault.o lscsa_alloc.o | 5 | spufs-y += switch.o fault.o lscsa_alloc.o |
6 | 6 | ||
7 | obj-$(CONFIG_SPU_TRACE) += sputrace.o | ||
8 | |||
7 | # Rules to build switch.o with the help of SPU tool chain | 9 | # Rules to build switch.o with the help of SPU tool chain |
8 | SPU_CROSS := spu- | 10 | SPU_CROSS := spu- |
9 | SPU_CC := $(SPU_CROSS)gcc | 11 | SPU_CC := $(SPU_CROSS)gcc |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 3fcd06418b01..1018acd1746b 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
30 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/marker.h> | ||
32 | 33 | ||
33 | #include <asm/io.h> | 34 | #include <asm/io.h> |
34 | #include <asm/semaphore.h> | 35 | #include <asm/semaphore.h> |
@@ -358,6 +359,8 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
358 | struct spu_context *ctx = vma->vm_file->private_data; | 359 | struct spu_context *ctx = vma->vm_file->private_data; |
359 | unsigned long area, offset = address - vma->vm_start; | 360 | unsigned long area, offset = address - vma->vm_start; |
360 | 361 | ||
362 | spu_context_nospu_trace(spufs_ps_nopfn__enter, ctx); | ||
363 | |||
361 | offset += vma->vm_pgoff << PAGE_SHIFT; | 364 | offset += vma->vm_pgoff << PAGE_SHIFT; |
362 | if (offset >= ps_size) | 365 | if (offset >= ps_size) |
363 | return NOPFN_SIGBUS; | 366 | return NOPFN_SIGBUS; |
@@ -375,11 +378,14 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
375 | 378 | ||
376 | if (ctx->state == SPU_STATE_SAVED) { | 379 | if (ctx->state == SPU_STATE_SAVED) { |
377 | up_read(¤t->mm->mmap_sem); | 380 | up_read(¤t->mm->mmap_sem); |
381 | spu_context_nospu_trace(spufs_ps_nopfn__sleep, ctx); | ||
378 | spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); | 382 | spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); |
383 | spu_context_trace(spufs_ps_nopfn__wake, ctx, ctx->spu); | ||
379 | down_read(¤t->mm->mmap_sem); | 384 | down_read(¤t->mm->mmap_sem); |
380 | } else { | 385 | } else { |
381 | area = ctx->spu->problem_phys + ps_offs; | 386 | area = ctx->spu->problem_phys + ps_offs; |
382 | vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT); | 387 | vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT); |
388 | spu_context_trace(spufs_ps_nopfn__insert, ctx, ctx->spu); | ||
383 | } | 389 | } |
384 | 390 | ||
385 | spu_release(ctx); | 391 | spu_release(ctx); |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index c0e968a4c211..90784c029f25 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -322,7 +322,7 @@ static struct spu_context * | |||
322 | spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, | 322 | spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, |
323 | struct file *filp) | 323 | struct file *filp) |
324 | { | 324 | { |
325 | struct spu_context *tmp, *neighbor; | 325 | struct spu_context *tmp, *neighbor, *err; |
326 | int count, node; | 326 | int count, node; |
327 | int aff_supp; | 327 | int aff_supp; |
328 | 328 | ||
@@ -354,11 +354,15 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, | |||
354 | if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) && | 354 | if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) && |
355 | !list_is_last(&neighbor->aff_list, &gang->aff_list_head) && | 355 | !list_is_last(&neighbor->aff_list, &gang->aff_list_head) && |
356 | !list_entry(neighbor->aff_list.next, struct spu_context, | 356 | !list_entry(neighbor->aff_list.next, struct spu_context, |
357 | aff_list)->aff_head) | 357 | aff_list)->aff_head) { |
358 | return ERR_PTR(-EEXIST); | 358 | err = ERR_PTR(-EEXIST); |
359 | goto out_put_neighbor; | ||
360 | } | ||
359 | 361 | ||
360 | if (gang != neighbor->gang) | 362 | if (gang != neighbor->gang) { |
361 | return ERR_PTR(-EINVAL); | 363 | err = ERR_PTR(-EINVAL); |
364 | goto out_put_neighbor; | ||
365 | } | ||
362 | 366 | ||
363 | count = 1; | 367 | count = 1; |
364 | list_for_each_entry(tmp, &gang->aff_list_head, aff_list) | 368 | list_for_each_entry(tmp, &gang->aff_list_head, aff_list) |
@@ -372,11 +376,17 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, | |||
372 | break; | 376 | break; |
373 | } | 377 | } |
374 | 378 | ||
375 | if (node == MAX_NUMNODES) | 379 | if (node == MAX_NUMNODES) { |
376 | return ERR_PTR(-EEXIST); | 380 | err = ERR_PTR(-EEXIST); |
381 | goto out_put_neighbor; | ||
382 | } | ||
377 | } | 383 | } |
378 | 384 | ||
379 | return neighbor; | 385 | return neighbor; |
386 | |||
387 | out_put_neighbor: | ||
388 | put_spu_context(neighbor); | ||
389 | return err; | ||
380 | } | 390 | } |
381 | 391 | ||
382 | static void | 392 | static void |
@@ -454,9 +464,12 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
454 | if (ret) | 464 | if (ret) |
455 | goto out_aff_unlock; | 465 | goto out_aff_unlock; |
456 | 466 | ||
457 | if (affinity) | 467 | if (affinity) { |
458 | spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx, | 468 | spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx, |
459 | neighbor); | 469 | neighbor); |
470 | if (neighbor) | ||
471 | put_spu_context(neighbor); | ||
472 | } | ||
460 | 473 | ||
461 | /* | 474 | /* |
462 | * get references for dget and mntget, will be released | 475 | * get references for dget and mntget, will be released |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index c01a09da1e56..b4814c740d8a 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -410,8 +410,11 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) | |||
410 | * since we have TIF_SINGLESTEP set, thus the kernel will do | 410 | * since we have TIF_SINGLESTEP set, thus the kernel will do |
411 | * it upon return from the syscall anyawy | 411 | * it upon return from the syscall anyawy |
412 | */ | 412 | */ |
413 | if ((status & SPU_STATUS_STOPPED_BY_STOP) | 413 | if (unlikely(status & SPU_STATUS_SINGLE_STEP)) |
414 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { | 414 | ret = -ERESTARTSYS; |
415 | |||
416 | else if (unlikely((status & SPU_STATUS_STOPPED_BY_STOP) | ||
417 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff)) { | ||
415 | force_sig(SIGTRAP, current); | 418 | force_sig(SIGTRAP, current); |
416 | ret = -ERESTARTSYS; | 419 | ret = -ERESTARTSYS; |
417 | } | 420 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 00d914232af1..5915343e2599 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/pid_namespace.h> | 39 | #include <linux/pid_namespace.h> |
40 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
41 | #include <linux/seq_file.h> | 41 | #include <linux/seq_file.h> |
42 | #include <linux/marker.h> | ||
42 | 43 | ||
43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
44 | #include <asm/mmu_context.h> | 45 | #include <asm/mmu_context.h> |
@@ -216,8 +217,8 @@ void do_notify_spus_active(void) | |||
216 | */ | 217 | */ |
217 | static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | 218 | static void spu_bind_context(struct spu *spu, struct spu_context *ctx) |
218 | { | 219 | { |
219 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, | 220 | spu_context_trace(spu_bind_context__enter, ctx, spu); |
220 | spu->number, spu->node); | 221 | |
221 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); | 222 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); |
222 | 223 | ||
223 | if (ctx->flags & SPU_CREATE_NOSCHED) | 224 | if (ctx->flags & SPU_CREATE_NOSCHED) |
@@ -399,8 +400,8 @@ static int has_affinity(struct spu_context *ctx) | |||
399 | */ | 400 | */ |
400 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | 401 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) |
401 | { | 402 | { |
402 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, | 403 | spu_context_trace(spu_unbind_context__enter, ctx, spu); |
403 | spu->pid, spu->number, spu->node); | 404 | |
404 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); | 405 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); |
405 | 406 | ||
406 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) | 407 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) |
@@ -528,6 +529,8 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
528 | struct spu *spu, *aff_ref_spu; | 529 | struct spu *spu, *aff_ref_spu; |
529 | int node, n; | 530 | int node, n; |
530 | 531 | ||
532 | spu_context_nospu_trace(spu_get_idle__enter, ctx); | ||
533 | |||
531 | if (ctx->gang) { | 534 | if (ctx->gang) { |
532 | mutex_lock(&ctx->gang->aff_mutex); | 535 | mutex_lock(&ctx->gang->aff_mutex); |
533 | if (has_affinity(ctx)) { | 536 | if (has_affinity(ctx)) { |
@@ -546,8 +549,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
546 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) | 549 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) |
547 | ctx->gang->aff_ref_spu = NULL; | 550 | ctx->gang->aff_ref_spu = NULL; |
548 | mutex_unlock(&ctx->gang->aff_mutex); | 551 | mutex_unlock(&ctx->gang->aff_mutex); |
549 | 552 | goto not_found; | |
550 | return NULL; | ||
551 | } | 553 | } |
552 | mutex_unlock(&ctx->gang->aff_mutex); | 554 | mutex_unlock(&ctx->gang->aff_mutex); |
553 | } | 555 | } |
@@ -565,12 +567,14 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
565 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 567 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
566 | } | 568 | } |
567 | 569 | ||
570 | not_found: | ||
571 | spu_context_nospu_trace(spu_get_idle__not_found, ctx); | ||
568 | return NULL; | 572 | return NULL; |
569 | 573 | ||
570 | found: | 574 | found: |
571 | spu->alloc_state = SPU_USED; | 575 | spu->alloc_state = SPU_USED; |
572 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 576 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
573 | pr_debug("Got SPU %d %d\n", spu->number, spu->node); | 577 | spu_context_trace(spu_get_idle__found, ctx, spu); |
574 | spu_init_channels(spu); | 578 | spu_init_channels(spu); |
575 | return spu; | 579 | return spu; |
576 | } | 580 | } |
@@ -587,6 +591,8 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
587 | struct spu *spu; | 591 | struct spu *spu; |
588 | int node, n; | 592 | int node, n; |
589 | 593 | ||
594 | spu_context_nospu_trace(spu_find_vitim__enter, ctx); | ||
595 | |||
590 | /* | 596 | /* |
591 | * Look for a possible preemption candidate on the local node first. | 597 | * Look for a possible preemption candidate on the local node first. |
592 | * If there is no candidate look at the other nodes. This isn't | 598 | * If there is no candidate look at the other nodes. This isn't |
@@ -640,6 +646,8 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
640 | goto restart; | 646 | goto restart; |
641 | } | 647 | } |
642 | 648 | ||
649 | spu_context_trace(__spu_deactivate__unload, ctx, spu); | ||
650 | |||
643 | mutex_lock(&cbe_spu_info[node].list_mutex); | 651 | mutex_lock(&cbe_spu_info[node].list_mutex); |
644 | cbe_spu_info[node].nr_active--; | 652 | cbe_spu_info[node].nr_active--; |
645 | spu_unbind_context(spu, victim); | 653 | spu_unbind_context(spu, victim); |
@@ -822,6 +830,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) | |||
822 | */ | 830 | */ |
823 | void spu_deactivate(struct spu_context *ctx) | 831 | void spu_deactivate(struct spu_context *ctx) |
824 | { | 832 | { |
833 | spu_context_nospu_trace(spu_deactivate__enter, ctx); | ||
825 | __spu_deactivate(ctx, 1, MAX_PRIO); | 834 | __spu_deactivate(ctx, 1, MAX_PRIO); |
826 | } | 835 | } |
827 | 836 | ||
@@ -835,6 +844,7 @@ void spu_deactivate(struct spu_context *ctx) | |||
835 | */ | 844 | */ |
836 | void spu_yield(struct spu_context *ctx) | 845 | void spu_yield(struct spu_context *ctx) |
837 | { | 846 | { |
847 | spu_context_nospu_trace(spu_yield__enter, ctx); | ||
838 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { | 848 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { |
839 | mutex_lock(&ctx->state_mutex); | 849 | mutex_lock(&ctx->state_mutex); |
840 | __spu_deactivate(ctx, 0, MAX_PRIO); | 850 | __spu_deactivate(ctx, 0, MAX_PRIO); |
@@ -864,11 +874,15 @@ static noinline void spusched_tick(struct spu_context *ctx) | |||
864 | goto out; | 874 | goto out; |
865 | 875 | ||
866 | spu = ctx->spu; | 876 | spu = ctx->spu; |
877 | |||
878 | spu_context_trace(spusched_tick__preempt, ctx, spu); | ||
879 | |||
867 | new = grab_runnable_context(ctx->prio + 1, spu->node); | 880 | new = grab_runnable_context(ctx->prio + 1, spu->node); |
868 | if (new) { | 881 | if (new) { |
869 | spu_unschedule(spu, ctx); | 882 | spu_unschedule(spu, ctx); |
870 | spu_add_to_rq(ctx); | 883 | spu_add_to_rq(ctx); |
871 | } else { | 884 | } else { |
885 | spu_context_nospu_trace(spusched_tick__newslice, ctx); | ||
872 | ctx->time_slice++; | 886 | ctx->time_slice++; |
873 | } | 887 | } |
874 | out: | 888 | out: |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 0e114038ea6f..795a1b52538b 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -325,4 +325,9 @@ extern void spu_free_lscsa(struct spu_state *csa); | |||
325 | extern void spuctx_switch_state(struct spu_context *ctx, | 325 | extern void spuctx_switch_state(struct spu_context *ctx, |
326 | enum spu_utilization_state new_state); | 326 | enum spu_utilization_state new_state); |
327 | 327 | ||
328 | #define spu_context_trace(name, ctx, spu) \ | ||
329 | trace_mark(name, "%p %p", ctx, spu); | ||
330 | #define spu_context_nospu_trace(name, ctx) \ | ||
331 | trace_mark(name, "%p", ctx); | ||
332 | |||
328 | #endif | 333 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c new file mode 100644 index 000000000000..2b1953f6f12e --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/sputrace.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 IBM Deutschland Entwicklung GmbH | ||
3 | * Released under GPL v2. | ||
4 | * | ||
5 | * Partially based on net/ipv4/tcp_probe.c. | ||
6 | * | ||
7 | * Simple tracing facility for spu contexts. | ||
8 | */ | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/marker.h> | ||
13 | #include <linux/proc_fs.h> | ||
14 | #include <linux/wait.h> | ||
15 | #include <asm/atomic.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include "spufs.h" | ||
18 | |||
19 | struct spu_probe { | ||
20 | const char *name; | ||
21 | const char *format; | ||
22 | marker_probe_func *probe_func; | ||
23 | }; | ||
24 | |||
25 | struct sputrace { | ||
26 | ktime_t tstamp; | ||
27 | int owner_tid; /* owner */ | ||
28 | int curr_tid; | ||
29 | const char *name; | ||
30 | int number; | ||
31 | }; | ||
32 | |||
33 | static int bufsize __read_mostly = 16384; | ||
34 | MODULE_PARM_DESC(bufsize, "Log buffer size (number of records)"); | ||
35 | module_param(bufsize, int, 0); | ||
36 | |||
37 | |||
38 | static DEFINE_SPINLOCK(sputrace_lock); | ||
39 | static DECLARE_WAIT_QUEUE_HEAD(sputrace_wait); | ||
40 | static ktime_t sputrace_start; | ||
41 | static unsigned long sputrace_head, sputrace_tail; | ||
42 | static struct sputrace *sputrace_log; | ||
43 | |||
44 | static int sputrace_used(void) | ||
45 | { | ||
46 | return (sputrace_head - sputrace_tail) % bufsize; | ||
47 | } | ||
48 | |||
49 | static inline int sputrace_avail(void) | ||
50 | { | ||
51 | return bufsize - sputrace_used(); | ||
52 | } | ||
53 | |||
54 | static int sputrace_sprint(char *tbuf, int n) | ||
55 | { | ||
56 | const struct sputrace *t = sputrace_log + sputrace_tail % bufsize; | ||
57 | struct timespec tv = | ||
58 | ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start)); | ||
59 | |||
60 | return snprintf(tbuf, n, | ||
61 | "[%lu.%09lu] %d: %s (thread = %d, spu = %d)\n", | ||
62 | (unsigned long) tv.tv_sec, | ||
63 | (unsigned long) tv.tv_nsec, | ||
64 | t->owner_tid, | ||
65 | t->name, | ||
66 | t->curr_tid, | ||
67 | t->number); | ||
68 | } | ||
69 | |||
70 | static ssize_t sputrace_read(struct file *file, char __user *buf, | ||
71 | size_t len, loff_t *ppos) | ||
72 | { | ||
73 | int error = 0, cnt = 0; | ||
74 | |||
75 | if (!buf || len < 0) | ||
76 | return -EINVAL; | ||
77 | |||
78 | while (cnt < len) { | ||
79 | char tbuf[128]; | ||
80 | int width; | ||
81 | |||
82 | error = wait_event_interruptible(sputrace_wait, | ||
83 | sputrace_used() > 0); | ||
84 | if (error) | ||
85 | break; | ||
86 | |||
87 | spin_lock(&sputrace_lock); | ||
88 | if (sputrace_head == sputrace_tail) { | ||
89 | spin_unlock(&sputrace_lock); | ||
90 | continue; | ||
91 | } | ||
92 | |||
93 | width = sputrace_sprint(tbuf, sizeof(tbuf)); | ||
94 | if (width < len) | ||
95 | sputrace_tail = (sputrace_tail + 1) % bufsize; | ||
96 | spin_unlock(&sputrace_lock); | ||
97 | |||
98 | if (width >= len) | ||
99 | break; | ||
100 | |||
101 | error = copy_to_user(buf + cnt, tbuf, width); | ||
102 | if (error) | ||
103 | break; | ||
104 | cnt += width; | ||
105 | } | ||
106 | |||
107 | return cnt == 0 ? error : cnt; | ||
108 | } | ||
109 | |||
110 | static int sputrace_open(struct inode *inode, struct file *file) | ||
111 | { | ||
112 | spin_lock(&sputrace_lock); | ||
113 | sputrace_head = sputrace_tail = 0; | ||
114 | sputrace_start = ktime_get(); | ||
115 | spin_unlock(&sputrace_lock); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static const struct file_operations sputrace_fops = { | ||
121 | .owner = THIS_MODULE, | ||
122 | .open = sputrace_open, | ||
123 | .read = sputrace_read, | ||
124 | }; | ||
125 | |||
126 | static void sputrace_log_item(const char *name, struct spu_context *ctx, | ||
127 | struct spu *spu) | ||
128 | { | ||
129 | spin_lock(&sputrace_lock); | ||
130 | if (sputrace_avail() > 1) { | ||
131 | struct sputrace *t = sputrace_log + sputrace_head; | ||
132 | |||
133 | t->tstamp = ktime_get(); | ||
134 | t->owner_tid = ctx->tid; | ||
135 | t->name = name; | ||
136 | t->curr_tid = current->pid; | ||
137 | t->number = spu ? spu->number : -1; | ||
138 | |||
139 | sputrace_head = (sputrace_head + 1) % bufsize; | ||
140 | } else { | ||
141 | printk(KERN_WARNING | ||
142 | "sputrace: lost samples due to full buffer.\n"); | ||
143 | } | ||
144 | spin_unlock(&sputrace_lock); | ||
145 | |||
146 | wake_up(&sputrace_wait); | ||
147 | } | ||
148 | |||
149 | static void spu_context_event(const struct marker *mdata, | ||
150 | void *private, const char *format, ...) | ||
151 | { | ||
152 | struct spu_probe *p = mdata->private; | ||
153 | va_list ap; | ||
154 | struct spu_context *ctx; | ||
155 | struct spu *spu; | ||
156 | |||
157 | va_start(ap, format); | ||
158 | ctx = va_arg(ap, struct spu_context *); | ||
159 | spu = va_arg(ap, struct spu *); | ||
160 | |||
161 | sputrace_log_item(p->name, ctx, spu); | ||
162 | va_end(ap); | ||
163 | } | ||
164 | |||
165 | static void spu_context_nospu_event(const struct marker *mdata, | ||
166 | void *private, const char *format, ...) | ||
167 | { | ||
168 | struct spu_probe *p = mdata->private; | ||
169 | va_list ap; | ||
170 | struct spu_context *ctx; | ||
171 | |||
172 | va_start(ap, format); | ||
173 | ctx = va_arg(ap, struct spu_context *); | ||
174 | |||
175 | sputrace_log_item(p->name, ctx, NULL); | ||
176 | va_end(ap); | ||
177 | } | ||
178 | |||
179 | struct spu_probe spu_probes[] = { | ||
180 | { "spu_bind_context__enter", "%p %p", spu_context_event }, | ||
181 | { "spu_unbind_context__enter", "%p %p", spu_context_event }, | ||
182 | { "spu_get_idle__enter", "%p", spu_context_nospu_event }, | ||
183 | { "spu_get_idle__found", "%p %p", spu_context_event }, | ||
184 | { "spu_get_idle__not_found", "%p", spu_context_nospu_event }, | ||
185 | { "spu_find_victim__enter", "%p", spu_context_nospu_event }, | ||
186 | { "spusched_tick__preempt", "%p %p", spu_context_event }, | ||
187 | { "spusched_tick__newslice", "%p", spu_context_nospu_event }, | ||
188 | { "spu_yield__enter", "%p", spu_context_nospu_event }, | ||
189 | { "spu_deactivate__enter", "%p", spu_context_nospu_event }, | ||
190 | { "__spu_deactivate__unload", "%p %p", spu_context_event }, | ||
191 | { "spufs_ps_nopfn__enter", "%p", spu_context_nospu_event }, | ||
192 | { "spufs_ps_nopfn__sleep", "%p", spu_context_nospu_event }, | ||
193 | { "spufs_ps_nopfn__wake", "%p %p", spu_context_event }, | ||
194 | { "spufs_ps_nopfn__insert", "%p %p", spu_context_event }, | ||
195 | { "spu_acquire_saved__enter", "%p", spu_context_nospu_event }, | ||
196 | { "destroy_spu_context__enter", "%p", spu_context_nospu_event }, | ||
197 | }; | ||
198 | |||
199 | static int __init sputrace_init(void) | ||
200 | { | ||
201 | struct proc_dir_entry *entry; | ||
202 | int i, error = -ENOMEM; | ||
203 | |||
204 | sputrace_log = kcalloc(sizeof(struct sputrace), | ||
205 | bufsize, GFP_KERNEL); | ||
206 | if (!sputrace_log) | ||
207 | goto out; | ||
208 | |||
209 | entry = create_proc_entry("sputrace", S_IRUSR, NULL); | ||
210 | if (!entry) | ||
211 | goto out_free_log; | ||
212 | entry->proc_fops = &sputrace_fops; | ||
213 | |||
214 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) { | ||
215 | struct spu_probe *p = &spu_probes[i]; | ||
216 | |||
217 | error = marker_probe_register(p->name, p->format, | ||
218 | p->probe_func, p); | ||
219 | if (error) | ||
220 | printk(KERN_INFO "Unable to register probe %s\n", | ||
221 | p->name); | ||
222 | |||
223 | error = marker_arm(p->name); | ||
224 | if (error) | ||
225 | printk(KERN_INFO "Unable to arm probe %s\n", p->name); | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | |||
230 | out_free_log: | ||
231 | kfree(sputrace_log); | ||
232 | out: | ||
233 | return -ENOMEM; | ||
234 | } | ||
235 | |||
236 | static void __exit sputrace_exit(void) | ||
237 | { | ||
238 | int i; | ||
239 | |||
240 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) | ||
241 | marker_probe_unregister(spu_probes[i].name); | ||
242 | |||
243 | remove_proc_entry("sputrace", NULL); | ||
244 | kfree(sputrace_log); | ||
245 | } | ||
246 | |||
247 | module_init(sputrace_init); | ||
248 | module_exit(sputrace_exit); | ||
249 | |||
250 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c index e12e9d298716..8864e4884980 100644 --- a/arch/powerpc/platforms/embedded6xx/storcenter.c +++ b/arch/powerpc/platforms/embedded6xx/storcenter.c | |||
@@ -132,33 +132,18 @@ static void __init storcenter_init_IRQ(void) | |||
132 | 132 | ||
133 | paddr = (phys_addr_t)of_translate_address(dnp, prop); | 133 | paddr = (phys_addr_t)of_translate_address(dnp, prop); |
134 | mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, | 134 | mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, |
135 | 4, 32, " EPIC "); | 135 | 16, 32, " OpenPIC "); |
136 | 136 | ||
137 | of_node_put(dnp); | 137 | of_node_put(dnp); |
138 | 138 | ||
139 | BUG_ON(mpic == NULL); | 139 | BUG_ON(mpic == NULL); |
140 | 140 | ||
141 | /* PCI IRQs */ | ||
142 | /* | 141 | /* |
143 | * 2.6.12 patch: | 142 | * 16 Serial Interrupts followed by 16 Internal Interrupts. |
144 | * openpic_set_sources(0, 5, OpenPIC_Addr + 0x10200); | 143 | * I2C is the second internal, so it is at 17, 0x11020. |
145 | * openpic_set_sources(5, 2, OpenPIC_Addr + 0x11120); | ||
146 | * first_irq, num_irqs, __iomem first_ISR | ||
147 | * o_ss: i, src: 0, fdf50200 | ||
148 | * o_ss: i, src: 1, fdf50220 | ||
149 | * o_ss: i, src: 2, fdf50240 | ||
150 | * o_ss: i, src: 3, fdf50260 | ||
151 | * o_ss: i, src: 4, fdf50280 | ||
152 | * o_ss: i, src: 5, fdf51120 | ||
153 | * o_ss: i, src: 6, fdf51140 | ||
154 | */ | 144 | */ |
155 | mpic_assign_isu(mpic, 0, paddr + 0x10200); | 145 | mpic_assign_isu(mpic, 0, paddr + 0x10200); |
156 | mpic_assign_isu(mpic, 1, paddr + 0x10220); | 146 | mpic_assign_isu(mpic, 1, paddr + 0x11000); |
157 | mpic_assign_isu(mpic, 2, paddr + 0x10240); | ||
158 | mpic_assign_isu(mpic, 3, paddr + 0x10260); | ||
159 | mpic_assign_isu(mpic, 4, paddr + 0x10280); | ||
160 | mpic_assign_isu(mpic, 5, paddr + 0x11120); | ||
161 | mpic_assign_isu(mpic, 6, paddr + 0x11140); | ||
162 | 147 | ||
163 | mpic_init(mpic); | 148 | mpic_init(mpic); |
164 | } | 149 | } |
@@ -178,7 +163,7 @@ static int __init storcenter_probe(void) | |||
178 | { | 163 | { |
179 | unsigned long root = of_get_flat_dt_root(); | 164 | unsigned long root = of_get_flat_dt_root(); |
180 | 165 | ||
181 | return of_flat_dt_is_compatible(root, "storcenter"); | 166 | return of_flat_dt_is_compatible(root, "iomega,storcenter"); |
182 | } | 167 | } |
183 | 168 | ||
184 | define_machine(storcenter){ | 169 | define_machine(storcenter){ |
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index c4ad54e0f288..1f032483c026 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
@@ -58,7 +58,7 @@ static void pseries_mach_cpu_die(void) | |||
58 | { | 58 | { |
59 | local_irq_disable(); | 59 | local_irq_disable(); |
60 | idle_task_exit(); | 60 | idle_task_exit(); |
61 | xics_teardown_cpu(0); | 61 | xics_teardown_cpu(); |
62 | unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow())); | 62 | unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow())); |
63 | rtas_stop_self(); | 63 | rtas_stop_self(); |
64 | /* Should never get here... */ | 64 | /* Should never get here... */ |
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c index 412a5e7aff2d..e9dd5fe081c9 100644 --- a/arch/powerpc/platforms/pseries/kexec.c +++ b/arch/powerpc/platforms/pseries/kexec.c | |||
@@ -54,7 +54,7 @@ void __init setup_kexec_cpu_down_mpic(void) | |||
54 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | 54 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) |
55 | { | 55 | { |
56 | pseries_kexec_cpu_down(crash_shutdown, secondary); | 56 | pseries_kexec_cpu_down(crash_shutdown, secondary); |
57 | xics_teardown_cpu(secondary); | 57 | xics_kexec_teardown_cpu(secondary); |
58 | } | 58 | } |
59 | 59 | ||
60 | void __init setup_kexec_cpu_down_xics(void) | 60 | void __init setup_kexec_cpu_down_xics(void) |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index c02f8742c54d..2800fced8c7c 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -167,6 +167,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) | |||
167 | 167 | ||
168 | if ((child = of_get_next_child(np, NULL))) { | 168 | if ((child = of_get_next_child(np, NULL))) { |
169 | of_node_put(child); | 169 | of_node_put(child); |
170 | of_node_put(parent); | ||
170 | return -EBUSY; | 171 | return -EBUSY; |
171 | } | 172 | } |
172 | 173 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 8f8dd9c3ca6b..ca52b587166d 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -160,6 +160,46 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) | |||
160 | 160 | ||
161 | /* High level handlers and init code */ | 161 | /* High level handlers and init code */ |
162 | 162 | ||
163 | static void xics_update_irq_servers(void) | ||
164 | { | ||
165 | int i, j; | ||
166 | struct device_node *np; | ||
167 | u32 ilen; | ||
168 | const u32 *ireg, *isize; | ||
169 | u32 hcpuid; | ||
170 | |||
171 | /* Find the server numbers for the boot cpu. */ | ||
172 | np = of_get_cpu_node(boot_cpuid, NULL); | ||
173 | BUG_ON(!np); | ||
174 | |||
175 | ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); | ||
176 | if (!ireg) { | ||
177 | of_node_put(np); | ||
178 | return; | ||
179 | } | ||
180 | |||
181 | i = ilen / sizeof(int); | ||
182 | hcpuid = get_hard_smp_processor_id(boot_cpuid); | ||
183 | |||
184 | /* Global interrupt distribution server is specified in the last | ||
185 | * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last | ||
186 | * entry fom this property for current boot cpu id and use it as | ||
187 | * default distribution server | ||
188 | */ | ||
189 | for (j = 0; j < i; j += 2) { | ||
190 | if (ireg[j] == hcpuid) { | ||
191 | default_server = hcpuid; | ||
192 | default_distrib_server = ireg[j+1]; | ||
193 | |||
194 | isize = of_get_property(np, | ||
195 | "ibm,interrupt-server#-size", NULL); | ||
196 | if (isize) | ||
197 | interrupt_server_size = *isize; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | of_node_put(np); | ||
202 | } | ||
163 | 203 | ||
164 | #ifdef CONFIG_SMP | 204 | #ifdef CONFIG_SMP |
165 | static int get_irq_server(unsigned int virq, unsigned int strict_check) | 205 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
@@ -169,6 +209,9 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check) | |||
169 | cpumask_t cpumask = irq_desc[virq].affinity; | 209 | cpumask_t cpumask = irq_desc[virq].affinity; |
170 | cpumask_t tmp = CPU_MASK_NONE; | 210 | cpumask_t tmp = CPU_MASK_NONE; |
171 | 211 | ||
212 | if (! cpu_isset(default_server, cpu_online_map)) | ||
213 | xics_update_irq_servers(); | ||
214 | |||
172 | if (!distribute_irqs) | 215 | if (!distribute_irqs) |
173 | return default_server; | 216 | return default_server; |
174 | 217 | ||
@@ -658,39 +701,11 @@ static void __init xics_setup_8259_cascade(void) | |||
658 | set_irq_chained_handler(cascade, pseries_8259_cascade); | 701 | set_irq_chained_handler(cascade, pseries_8259_cascade); |
659 | } | 702 | } |
660 | 703 | ||
661 | static struct device_node *cpuid_to_of_node(int cpu) | ||
662 | { | ||
663 | struct device_node *np; | ||
664 | u32 hcpuid = get_hard_smp_processor_id(cpu); | ||
665 | |||
666 | for_each_node_by_type(np, "cpu") { | ||
667 | int i, len; | ||
668 | const u32 *intserv; | ||
669 | |||
670 | intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", | ||
671 | &len); | ||
672 | |||
673 | if (!intserv) | ||
674 | intserv = of_get_property(np, "reg", &len); | ||
675 | |||
676 | i = len / sizeof(u32); | ||
677 | |||
678 | while (i--) | ||
679 | if (intserv[i] == hcpuid) | ||
680 | return np; | ||
681 | } | ||
682 | |||
683 | return NULL; | ||
684 | } | ||
685 | |||
686 | void __init xics_init_IRQ(void) | 704 | void __init xics_init_IRQ(void) |
687 | { | 705 | { |
688 | int i, j; | ||
689 | struct device_node *np; | 706 | struct device_node *np; |
690 | u32 ilen, indx = 0; | 707 | u32 indx = 0; |
691 | const u32 *ireg, *isize; | ||
692 | int found = 0; | 708 | int found = 0; |
693 | u32 hcpuid; | ||
694 | 709 | ||
695 | ppc64_boot_msg(0x20, "XICS Init"); | 710 | ppc64_boot_msg(0x20, "XICS Init"); |
696 | 711 | ||
@@ -709,34 +724,7 @@ void __init xics_init_IRQ(void) | |||
709 | return; | 724 | return; |
710 | 725 | ||
711 | xics_init_host(); | 726 | xics_init_host(); |
712 | 727 | xics_update_irq_servers(); | |
713 | /* Find the server numbers for the boot cpu. */ | ||
714 | np = cpuid_to_of_node(boot_cpuid); | ||
715 | BUG_ON(!np); | ||
716 | ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); | ||
717 | if (!ireg) | ||
718 | goto skip_gserver_check; | ||
719 | i = ilen / sizeof(int); | ||
720 | hcpuid = get_hard_smp_processor_id(boot_cpuid); | ||
721 | |||
722 | /* Global interrupt distribution server is specified in the last | ||
723 | * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last | ||
724 | * entry fom this property for current boot cpu id and use it as | ||
725 | * default distribution server | ||
726 | */ | ||
727 | for (j = 0; j < i; j += 2) { | ||
728 | if (ireg[j] == hcpuid) { | ||
729 | default_server = hcpuid; | ||
730 | default_distrib_server = ireg[j+1]; | ||
731 | |||
732 | isize = of_get_property(np, | ||
733 | "ibm,interrupt-server#-size", NULL); | ||
734 | if (isize) | ||
735 | interrupt_server_size = *isize; | ||
736 | } | ||
737 | } | ||
738 | skip_gserver_check: | ||
739 | of_node_put(np); | ||
740 | 728 | ||
741 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 729 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
742 | ppc_md.get_irq = xics_get_irq_lpar; | 730 | ppc_md.get_irq = xics_get_irq_lpar; |
@@ -775,11 +763,9 @@ void xics_request_IPIs(void) | |||
775 | } | 763 | } |
776 | #endif /* CONFIG_SMP */ | 764 | #endif /* CONFIG_SMP */ |
777 | 765 | ||
778 | void xics_teardown_cpu(int secondary) | 766 | void xics_teardown_cpu() |
779 | { | 767 | { |
780 | int cpu = smp_processor_id(); | 768 | int cpu = smp_processor_id(); |
781 | unsigned int ipi; | ||
782 | struct irq_desc *desc; | ||
783 | 769 | ||
784 | xics_set_cpu_priority(0); | 770 | xics_set_cpu_priority(0); |
785 | 771 | ||
@@ -790,9 +776,17 @@ void xics_teardown_cpu(int secondary) | |||
790 | lpar_qirr_info(cpu, 0xff); | 776 | lpar_qirr_info(cpu, 0xff); |
791 | else | 777 | else |
792 | direct_qirr_info(cpu, 0xff); | 778 | direct_qirr_info(cpu, 0xff); |
779 | } | ||
780 | |||
781 | void xics_kexec_teardown_cpu(int secondary) | ||
782 | { | ||
783 | unsigned int ipi; | ||
784 | struct irq_desc *desc; | ||
785 | |||
786 | xics_teardown_cpu(); | ||
793 | 787 | ||
794 | /* | 788 | /* |
795 | * we need to EOI the IPI if we got here from kexec down IPI | 789 | * we need to EOI the IPI |
796 | * | 790 | * |
797 | * probably need to check all the other interrupts too | 791 | * probably need to check all the other interrupts too |
798 | * should we be flagging idle loop instead? | 792 | * should we be flagging idle loop instead? |
@@ -880,8 +874,8 @@ void xics_migrate_irqs_away(void) | |||
880 | virq, cpu); | 874 | virq, cpu); |
881 | 875 | ||
882 | /* Reset affinity to all cpus */ | 876 | /* Reset affinity to all cpus */ |
877 | irq_desc[virq].affinity = CPU_MASK_ALL; | ||
883 | desc->chip->set_affinity(virq, CPU_MASK_ALL); | 878 | desc->chip->set_affinity(virq, CPU_MASK_ALL); |
884 | irq_desc[irq].affinity = CPU_MASK_ALL; | ||
885 | unlock: | 879 | unlock: |
886 | spin_unlock_irqrestore(&desc->lock, flags); | 880 | spin_unlock_irqrestore(&desc->lock, flags); |
887 | } | 881 | } |
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h index 9ffd809d29e2..c26bcff47b6d 100644 --- a/arch/powerpc/platforms/pseries/xics.h +++ b/arch/powerpc/platforms/pseries/xics.h | |||
@@ -16,7 +16,8 @@ | |||
16 | 16 | ||
17 | extern void xics_init_IRQ(void); | 17 | extern void xics_init_IRQ(void); |
18 | extern void xics_setup_cpu(void); | 18 | extern void xics_setup_cpu(void); |
19 | extern void xics_teardown_cpu(int secondary); | 19 | extern void xics_teardown_cpu(void); |
20 | extern void xics_kexec_teardown_cpu(int secondary); | ||
20 | extern void xics_cause_IPI(int cpu); | 21 | extern void xics_cause_IPI(int cpu); |
21 | extern void xics_request_IPIs(void); | 22 | extern void xics_request_IPIs(void); |
22 | extern void xics_migrate_irqs_away(void); | 23 | extern void xics_migrate_irqs_away(void); |
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 427027c7ea0f..437e48d3ae33 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c | |||
@@ -137,5 +137,6 @@ void dcr_unmap(dcr_host_t host, unsigned int dcr_c) | |||
137 | h.token = NULL; | 137 | h.token = NULL; |
138 | } | 138 | } |
139 | EXPORT_SYMBOL_GPL(dcr_unmap); | 139 | EXPORT_SYMBOL_GPL(dcr_unmap); |
140 | 140 | #else /* defined(CONFIG_PPC_DCR_NATIVE) */ | |
141 | #endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ | 141 | DEFINE_SPINLOCK(dcr_ind_lock); |
142 | #endif /* !defined(CONFIG_PPC_DCR_NATIVE) */ | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index e48b20e934ca..2c5388ce902a 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -1342,7 +1342,7 @@ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, | |||
1342 | if (ret) | 1342 | if (ret) |
1343 | goto unreg; | 1343 | goto unreg; |
1344 | 1344 | ||
1345 | ret = platform_device_register(pdev); | 1345 | ret = platform_device_add(pdev); |
1346 | if (ret) | 1346 | if (ret) |
1347 | goto unreg; | 1347 | goto unreg; |
1348 | 1348 | ||
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c index 0e74a4bd9827..5d2d5522ef41 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.c +++ b/arch/powerpc/sysdev/mpc8xx_pic.c | |||
@@ -174,15 +174,19 @@ int mpc8xx_pic_init(void) | |||
174 | goto out; | 174 | goto out; |
175 | 175 | ||
176 | siu_reg = ioremap(res.start, res.end - res.start + 1); | 176 | siu_reg = ioremap(res.start, res.end - res.start + 1); |
177 | if (siu_reg == NULL) | 177 | if (siu_reg == NULL) { |
178 | return -EINVAL; | 178 | ret = -EINVAL; |
179 | goto out; | ||
180 | } | ||
179 | 181 | ||
180 | mpc8xx_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR, | 182 | mpc8xx_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, |
181 | 64, &mpc8xx_pic_host_ops, 64); | 183 | 64, &mpc8xx_pic_host_ops, 64); |
182 | if (mpc8xx_pic_host == NULL) { | 184 | if (mpc8xx_pic_host == NULL) { |
183 | printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n"); | 185 | printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n"); |
184 | ret = -ENOMEM; | 186 | ret = -ENOMEM; |
187 | goto out; | ||
185 | } | 188 | } |
189 | return 0; | ||
186 | 190 | ||
187 | out: | 191 | out: |
188 | of_node_put(np); | 192 | of_node_put(np); |
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 5ef844da9355..6efbd5e5bb1b 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c | |||
@@ -66,7 +66,7 @@ phys_addr_t get_qe_base(void) | |||
66 | { | 66 | { |
67 | struct device_node *qe; | 67 | struct device_node *qe; |
68 | unsigned int size; | 68 | unsigned int size; |
69 | const void *prop; | 69 | const u32 *prop; |
70 | 70 | ||
71 | if (qebase != -1) | 71 | if (qebase != -1) |
72 | return qebase; | 72 | return qebase; |
@@ -79,7 +79,8 @@ phys_addr_t get_qe_base(void) | |||
79 | } | 79 | } |
80 | 80 | ||
81 | prop = of_get_property(qe, "reg", &size); | 81 | prop = of_get_property(qe, "reg", &size); |
82 | qebase = of_translate_address(qe, prop); | 82 | if (prop && size >= sizeof(*prop)) |
83 | qebase = of_translate_address(qe, prop); | ||
83 | of_node_put(qe); | 84 | of_node_put(qe); |
84 | 85 | ||
85 | return qebase; | 86 | return qebase; |
@@ -172,10 +173,9 @@ unsigned int get_brg_clk(void) | |||
172 | } | 173 | } |
173 | 174 | ||
174 | prop = of_get_property(qe, "brg-frequency", &size); | 175 | prop = of_get_property(qe, "brg-frequency", &size); |
175 | if (!prop || size != sizeof(*prop)) | 176 | if (prop && size == sizeof(*prop)) |
176 | return brg_clk; | 177 | brg_clk = *prop; |
177 | 178 | ||
178 | brg_clk = *prop; | ||
179 | of_node_put(qe); | 179 | of_node_put(qe); |
180 | 180 | ||
181 | return brg_clk; | 181 | return brg_clk; |
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 78ebfffc77e3..4a7a059ebaf7 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -1202,8 +1202,10 @@ static int __devexit ace_of_remove(struct of_device *op) | |||
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | /* Match table for of_platform binding */ | 1204 | /* Match table for of_platform binding */ |
1205 | static struct of_device_id __devinit ace_of_match[] = { | 1205 | static struct of_device_id ace_of_match[] __devinitdata = { |
1206 | { .compatible = "xilinx,xsysace", }, | 1206 | { .compatible = "xlnx,opb-sysace-1.00.b", }, |
1207 | { .compatible = "xlnx,opb-sysace-1.00.c", }, | ||
1208 | { .compatible = "xlnx,xps-sysace-1.00.a", }, | ||
1207 | {}, | 1209 | {}, |
1208 | }; | 1210 | }; |
1209 | MODULE_DEVICE_TABLE(of, ace_of_match); | 1211 | MODULE_DEVICE_TABLE(of, ace_of_match); |
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 8473b9f1da96..cac06bc1754b 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c | |||
@@ -558,7 +558,7 @@ static struct cdrom_device_ops viocd_dops = { | |||
558 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM | 558 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM |
559 | }; | 559 | }; |
560 | 560 | ||
561 | static int __init find_capability(const char *type) | 561 | static int find_capability(const char *type) |
562 | { | 562 | { |
563 | struct capability_entry *entry; | 563 | struct capability_entry *entry; |
564 | 564 | ||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 7927fd0faca3..f01ac9a07bf5 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -830,6 +830,16 @@ config DTLK | |||
830 | To compile this driver as a module, choose M here: the | 830 | To compile this driver as a module, choose M here: the |
831 | module will be called dtlk. | 831 | module will be called dtlk. |
832 | 832 | ||
833 | config XILINX_HWICAP | ||
834 | tristate "Xilinx HWICAP Support" | ||
835 | depends on XILINX_VIRTEX | ||
836 | help | ||
837 | This option enables support for Xilinx Internal Configuration | ||
838 | Access Port (ICAP) driver. The ICAP is used on Xilinx Virtex | ||
839 | FPGA platforms to partially reconfigure the FPGA at runtime. | ||
840 | |||
841 | If unsure, say N. | ||
842 | |||
833 | config R3964 | 843 | config R3964 |
834 | tristate "Siemens R3964 line discipline" | 844 | tristate "Siemens R3964 line discipline" |
835 | ---help--- | 845 | ---help--- |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 4396e37b3d0f..5407b7615614 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -76,6 +76,7 @@ obj-$(CONFIG_EFI_RTC) += efirtc.o | |||
76 | obj-$(CONFIG_SGI_DS1286) += ds1286.o | 76 | obj-$(CONFIG_SGI_DS1286) += ds1286.o |
77 | obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o | 77 | obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o |
78 | obj-$(CONFIG_DS1302) += ds1302.o | 78 | obj-$(CONFIG_DS1302) += ds1302.o |
79 | obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ | ||
79 | ifeq ($(CONFIG_GENERIC_NVRAM),y) | 80 | ifeq ($(CONFIG_GENERIC_NVRAM),y) |
80 | obj-$(CONFIG_NVRAM) += generic_nvram.o | 81 | obj-$(CONFIG_NVRAM) += generic_nvram.o |
81 | else | 82 | else |
diff --git a/drivers/char/xilinx_hwicap/Makefile b/drivers/char/xilinx_hwicap/Makefile new file mode 100644 index 000000000000..5491cbc42f43 --- /dev/null +++ b/drivers/char/xilinx_hwicap/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the Xilinx OPB hwicap driver | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap_m.o | ||
6 | |||
7 | xilinx_hwicap_m-y := xilinx_hwicap.o fifo_icap.o buffer_icap.o | ||
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c new file mode 100644 index 000000000000..dfea2bde162b --- /dev/null +++ b/drivers/char/xilinx_hwicap/buffer_icap.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Author: Xilinx, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" | ||
11 | * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND | ||
12 | * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, | ||
13 | * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, | ||
14 | * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION | ||
15 | * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, | ||
16 | * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE | ||
17 | * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY | ||
18 | * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE | ||
19 | * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR | ||
20 | * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF | ||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
22 | * FOR A PARTICULAR PURPOSE. | ||
23 | * | ||
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2003-2008 Xilinx Inc. | ||
28 | * All rights reserved. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | * | ||
34 | *****************************************************************************/ | ||
35 | |||
36 | #include "buffer_icap.h" | ||
37 | |||
38 | /* Indicates how many bytes will fit in a buffer. (1 BRAM) */ | ||
39 | #define XHI_MAX_BUFFER_BYTES 2048 | ||
40 | #define XHI_MAX_BUFFER_INTS (XHI_MAX_BUFFER_BYTES >> 2) | ||
41 | |||
42 | /* File access and error constants */ | ||
43 | #define XHI_DEVICE_READ_ERROR -1 | ||
44 | #define XHI_DEVICE_WRITE_ERROR -2 | ||
45 | #define XHI_BUFFER_OVERFLOW_ERROR -3 | ||
46 | |||
47 | #define XHI_DEVICE_READ 0x1 | ||
48 | #define XHI_DEVICE_WRITE 0x0 | ||
49 | |||
50 | /* Constants for checking transfer status */ | ||
51 | #define XHI_CYCLE_DONE 0 | ||
52 | #define XHI_CYCLE_EXECUTING 1 | ||
53 | |||
54 | /* buffer_icap register offsets */ | ||
55 | |||
56 | /* Size of transfer, read & write */ | ||
57 | #define XHI_SIZE_REG_OFFSET 0x800L | ||
58 | /* offset into bram, read & write */ | ||
59 | #define XHI_BRAM_OFFSET_REG_OFFSET 0x804L | ||
60 | /* Read not Configure, direction of transfer. Write only */ | ||
61 | #define XHI_RNC_REG_OFFSET 0x808L | ||
62 | /* Indicates transfer complete. Read only */ | ||
63 | #define XHI_STATUS_REG_OFFSET 0x80CL | ||
64 | |||
65 | /* Constants for setting the RNC register */ | ||
66 | #define XHI_CONFIGURE 0x0UL | ||
67 | #define XHI_READBACK 0x1UL | ||
68 | |||
69 | /* Constants for the Done register */ | ||
70 | #define XHI_NOT_FINISHED 0x0UL | ||
71 | #define XHI_FINISHED 0x1UL | ||
72 | |||
73 | #define XHI_BUFFER_START 0 | ||
74 | |||
75 | /** | ||
76 | * buffer_icap_get_status: Get the contents of the status register. | ||
77 | * @parameter base_address: is the base address of the device | ||
78 | * | ||
79 | * The status register contains the ICAP status and the done bit. | ||
80 | * | ||
81 | * D8 - cfgerr | ||
82 | * D7 - dalign | ||
83 | * D6 - rip | ||
84 | * D5 - in_abort_l | ||
85 | * D4 - Always 1 | ||
86 | * D3 - Always 1 | ||
87 | * D2 - Always 1 | ||
88 | * D1 - Always 1 | ||
89 | * D0 - Done bit | ||
90 | **/ | ||
91 | static inline u32 buffer_icap_get_status(void __iomem *base_address) | ||
92 | { | ||
93 | return in_be32(base_address + XHI_STATUS_REG_OFFSET); | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * buffer_icap_get_bram: Reads data from the storage buffer bram. | ||
98 | * @parameter base_address: contains the base address of the component. | ||
99 | * @parameter offset: The word offset from which the data should be read. | ||
100 | * | ||
101 | * A bram is used as a configuration memory cache. One frame of data can | ||
102 | * be stored in this "storage buffer". | ||
103 | **/ | ||
104 | static inline u32 buffer_icap_get_bram(void __iomem *base_address, | ||
105 | u32 offset) | ||
106 | { | ||
107 | return in_be32(base_address + (offset << 2)); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * buffer_icap_busy: Return true if the icap device is busy | ||
112 | * @parameter base_address: is the base address of the device | ||
113 | * | ||
114 | * The queries the low order bit of the status register, which | ||
115 | * indicates whether the current configuration or readback operation | ||
116 | * has completed. | ||
117 | **/ | ||
118 | static inline bool buffer_icap_busy(void __iomem *base_address) | ||
119 | { | ||
120 | return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED; | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * buffer_icap_busy: Return true if the icap device is not busy | ||
125 | * @parameter base_address: is the base address of the device | ||
126 | * | ||
127 | * The queries the low order bit of the status register, which | ||
128 | * indicates whether the current configuration or readback operation | ||
129 | * has completed. | ||
130 | **/ | ||
131 | static inline bool buffer_icap_done(void __iomem *base_address) | ||
132 | { | ||
133 | return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * buffer_icap_set_size: Set the size register. | ||
138 | * @parameter base_address: is the base address of the device | ||
139 | * @parameter data: The size in bytes. | ||
140 | * | ||
141 | * The size register holds the number of 8 bit bytes to transfer between | ||
142 | * bram and the icap (or icap to bram). | ||
143 | **/ | ||
144 | static inline void buffer_icap_set_size(void __iomem *base_address, | ||
145 | u32 data) | ||
146 | { | ||
147 | out_be32(base_address + XHI_SIZE_REG_OFFSET, data); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * buffer_icap_mSetoffsetReg: Set the bram offset register. | ||
152 | * @parameter base_address: contains the base address of the device. | ||
153 | * @parameter data: is the value to be written to the data register. | ||
154 | * | ||
155 | * The bram offset register holds the starting bram address to transfer | ||
156 | * data from during configuration or write data to during readback. | ||
157 | **/ | ||
158 | static inline void buffer_icap_set_offset(void __iomem *base_address, | ||
159 | u32 data) | ||
160 | { | ||
161 | out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * buffer_icap_set_rnc: Set the RNC (Readback not Configure) register. | ||
166 | * @parameter base_address: contains the base address of the device. | ||
167 | * @parameter data: is the value to be written to the data register. | ||
168 | * | ||
169 | * The RNC register determines the direction of the data transfer. It | ||
170 | * controls whether a configuration or readback take place. Writing to | ||
171 | * this register initiates the transfer. A value of 1 initiates a | ||
172 | * readback while writing a value of 0 initiates a configuration. | ||
173 | **/ | ||
174 | static inline void buffer_icap_set_rnc(void __iomem *base_address, | ||
175 | u32 data) | ||
176 | { | ||
177 | out_be32(base_address + XHI_RNC_REG_OFFSET, data); | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * buffer_icap_set_bram: Write data to the storage buffer bram. | ||
182 | * @parameter base_address: contains the base address of the component. | ||
183 | * @parameter offset: The word offset at which the data should be written. | ||
184 | * @parameter data: The value to be written to the bram offset. | ||
185 | * | ||
186 | * A bram is used as a configuration memory cache. One frame of data can | ||
187 | * be stored in this "storage buffer". | ||
188 | **/ | ||
189 | static inline void buffer_icap_set_bram(void __iomem *base_address, | ||
190 | u32 offset, u32 data) | ||
191 | { | ||
192 | out_be32(base_address + (offset << 2), data); | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * buffer_icap_device_read: Transfer bytes from ICAP to the storage buffer. | ||
197 | * @parameter drvdata: a pointer to the drvdata. | ||
198 | * @parameter offset: The storage buffer start address. | ||
199 | * @parameter count: The number of words (32 bit) to read from the | ||
200 | * device (ICAP). | ||
201 | **/ | ||
202 | static int buffer_icap_device_read(struct hwicap_drvdata *drvdata, | ||
203 | u32 offset, u32 count) | ||
204 | { | ||
205 | |||
206 | s32 retries = 0; | ||
207 | void __iomem *base_address = drvdata->base_address; | ||
208 | |||
209 | if (buffer_icap_busy(base_address)) | ||
210 | return -EBUSY; | ||
211 | |||
212 | if ((offset + count) > XHI_MAX_BUFFER_INTS) | ||
213 | return -EINVAL; | ||
214 | |||
215 | /* setSize count*4 to get bytes. */ | ||
216 | buffer_icap_set_size(base_address, (count << 2)); | ||
217 | buffer_icap_set_offset(base_address, offset); | ||
218 | buffer_icap_set_rnc(base_address, XHI_READBACK); | ||
219 | |||
220 | while (buffer_icap_busy(base_address)) { | ||
221 | retries++; | ||
222 | if (retries > XHI_MAX_RETRIES) | ||
223 | return -EBUSY; | ||
224 | } | ||
225 | return 0; | ||
226 | |||
227 | }; | ||
228 | |||
229 | /** | ||
230 | * buffer_icap_device_write: Transfer bytes from ICAP to the storage buffer. | ||
231 | * @parameter drvdata: a pointer to the drvdata. | ||
232 | * @parameter offset: The storage buffer start address. | ||
233 | * @parameter count: The number of words (32 bit) to read from the | ||
234 | * device (ICAP). | ||
235 | **/ | ||
236 | static int buffer_icap_device_write(struct hwicap_drvdata *drvdata, | ||
237 | u32 offset, u32 count) | ||
238 | { | ||
239 | |||
240 | s32 retries = 0; | ||
241 | void __iomem *base_address = drvdata->base_address; | ||
242 | |||
243 | if (buffer_icap_busy(base_address)) | ||
244 | return -EBUSY; | ||
245 | |||
246 | if ((offset + count) > XHI_MAX_BUFFER_INTS) | ||
247 | return -EINVAL; | ||
248 | |||
249 | /* setSize count*4 to get bytes. */ | ||
250 | buffer_icap_set_size(base_address, count << 2); | ||
251 | buffer_icap_set_offset(base_address, offset); | ||
252 | buffer_icap_set_rnc(base_address, XHI_CONFIGURE); | ||
253 | |||
254 | while (buffer_icap_busy(base_address)) { | ||
255 | retries++; | ||
256 | if (retries > XHI_MAX_RETRIES) | ||
257 | return -EBUSY; | ||
258 | } | ||
259 | return 0; | ||
260 | |||
261 | }; | ||
262 | |||
263 | /** | ||
264 | * buffer_icap_reset: Reset the logic of the icap device. | ||
265 | * @parameter drvdata: a pointer to the drvdata. | ||
266 | * | ||
267 | * Writing to the status register resets the ICAP logic in an internal | ||
268 | * version of the core. For the version of the core published in EDK, | ||
269 | * this is a noop. | ||
270 | **/ | ||
271 | void buffer_icap_reset(struct hwicap_drvdata *drvdata) | ||
272 | { | ||
273 | out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE); | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * buffer_icap_set_configuration: Load a partial bitstream from system memory. | ||
278 | * @parameter drvdata: a pointer to the drvdata. | ||
279 | * @parameter data: Kernel address of the partial bitstream. | ||
280 | * @parameter size: the size of the partial bitstream in 32 bit words. | ||
281 | **/ | ||
282 | int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, | ||
283 | u32 size) | ||
284 | { | ||
285 | int status; | ||
286 | s32 buffer_count = 0; | ||
287 | s32 num_writes = 0; | ||
288 | bool dirty = 0; | ||
289 | u32 i; | ||
290 | void __iomem *base_address = drvdata->base_address; | ||
291 | |||
292 | /* Loop through all the data */ | ||
293 | for (i = 0, buffer_count = 0; i < size; i++) { | ||
294 | |||
295 | /* Copy data to bram */ | ||
296 | buffer_icap_set_bram(base_address, buffer_count, data[i]); | ||
297 | dirty = 1; | ||
298 | |||
299 | if (buffer_count < XHI_MAX_BUFFER_INTS - 1) { | ||
300 | buffer_count++; | ||
301 | continue; | ||
302 | } | ||
303 | |||
304 | /* Write data to ICAP */ | ||
305 | status = buffer_icap_device_write( | ||
306 | drvdata, | ||
307 | XHI_BUFFER_START, | ||
308 | XHI_MAX_BUFFER_INTS); | ||
309 | if (status != 0) { | ||
310 | /* abort. */ | ||
311 | buffer_icap_reset(drvdata); | ||
312 | return status; | ||
313 | } | ||
314 | |||
315 | buffer_count = 0; | ||
316 | num_writes++; | ||
317 | dirty = 0; | ||
318 | } | ||
319 | |||
320 | /* Write unwritten data to ICAP */ | ||
321 | if (dirty) { | ||
322 | /* Write data to ICAP */ | ||
323 | status = buffer_icap_device_write(drvdata, XHI_BUFFER_START, | ||
324 | buffer_count); | ||
325 | if (status != 0) { | ||
326 | /* abort. */ | ||
327 | buffer_icap_reset(drvdata); | ||
328 | } | ||
329 | return status; | ||
330 | } | ||
331 | |||
332 | return 0; | ||
333 | }; | ||
334 | |||
335 | /** | ||
336 | * buffer_icap_get_configuration: Read configuration data from the device. | ||
337 | * @parameter drvdata: a pointer to the drvdata. | ||
338 | * @parameter data: Address of the data representing the partial bitstream | ||
339 | * @parameter size: the size of the partial bitstream in 32 bit words. | ||
340 | **/ | ||
341 | int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data, | ||
342 | u32 size) | ||
343 | { | ||
344 | int status; | ||
345 | s32 buffer_count = 0; | ||
346 | s32 read_count = 0; | ||
347 | u32 i; | ||
348 | void __iomem *base_address = drvdata->base_address; | ||
349 | |||
350 | /* Loop through all the data */ | ||
351 | for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) { | ||
352 | if (buffer_count == XHI_MAX_BUFFER_INTS) { | ||
353 | u32 words_remaining = size - i; | ||
354 | u32 words_to_read = | ||
355 | words_remaining < | ||
356 | XHI_MAX_BUFFER_INTS ? words_remaining : | ||
357 | XHI_MAX_BUFFER_INTS; | ||
358 | |||
359 | /* Read data from ICAP */ | ||
360 | status = buffer_icap_device_read( | ||
361 | drvdata, | ||
362 | XHI_BUFFER_START, | ||
363 | words_to_read); | ||
364 | if (status != 0) { | ||
365 | /* abort. */ | ||
366 | buffer_icap_reset(drvdata); | ||
367 | return status; | ||
368 | } | ||
369 | |||
370 | buffer_count = 0; | ||
371 | read_count++; | ||
372 | } | ||
373 | |||
374 | /* Copy data from bram */ | ||
375 | data[i] = buffer_icap_get_bram(base_address, buffer_count); | ||
376 | buffer_count++; | ||
377 | } | ||
378 | |||
379 | return 0; | ||
380 | }; | ||
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h new file mode 100644 index 000000000000..03184959fa00 --- /dev/null +++ b/drivers/char/xilinx_hwicap/buffer_icap.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Author: Xilinx, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" | ||
11 | * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND | ||
12 | * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, | ||
13 | * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, | ||
14 | * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION | ||
15 | * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, | ||
16 | * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE | ||
17 | * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY | ||
18 | * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE | ||
19 | * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR | ||
20 | * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF | ||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
22 | * FOR A PARTICULAR PURPOSE. | ||
23 | * | ||
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2003-2008 Xilinx Inc. | ||
28 | * All rights reserved. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | * | ||
34 | *****************************************************************************/ | ||
35 | |||
36 | #ifndef XILINX_BUFFER_ICAP_H_ /* prevent circular inclusions */ | ||
37 | #define XILINX_BUFFER_ICAP_H_ /* by using protection macros */ | ||
38 | |||
39 | #include <linux/types.h> | ||
40 | #include <linux/cdev.h> | ||
41 | #include <linux/version.h> | ||
42 | #include <linux/platform_device.h> | ||
43 | |||
44 | #include <asm/io.h> | ||
45 | #include "xilinx_hwicap.h" | ||
46 | |||
47 | void buffer_icap_reset(struct hwicap_drvdata *drvdata); | ||
48 | |||
49 | /* Loads a partial bitstream from system memory. */ | ||
50 | int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data, | ||
51 | u32 Size); | ||
52 | |||
53 | /* Loads a partial bitstream from system memory. */ | ||
54 | int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data, | ||
55 | u32 Size); | ||
56 | |||
57 | #endif | ||
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c new file mode 100644 index 000000000000..0988314694a6 --- /dev/null +++ b/drivers/char/xilinx_hwicap/fifo_icap.c | |||
@@ -0,0 +1,381 @@ | |||
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Author: Xilinx, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" | ||
11 | * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND | ||
12 | * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, | ||
13 | * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, | ||
14 | * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION | ||
15 | * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, | ||
16 | * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE | ||
17 | * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY | ||
18 | * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE | ||
19 | * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR | ||
20 | * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF | ||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
22 | * FOR A PARTICULAR PURPOSE. | ||
23 | * | ||
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2007-2008 Xilinx Inc. | ||
28 | * All rights reserved. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | * | ||
34 | *****************************************************************************/ | ||
35 | |||
36 | #include "fifo_icap.h" | ||
37 | |||
38 | /* Register offsets for the XHwIcap device. */ | ||
39 | #define XHI_GIER_OFFSET 0x1C /* Device Global Interrupt Enable Reg */ | ||
40 | #define XHI_IPISR_OFFSET 0x20 /* Interrupt Status Register */ | ||
41 | #define XHI_IPIER_OFFSET 0x28 /* Interrupt Enable Register */ | ||
42 | #define XHI_WF_OFFSET 0x100 /* Write FIFO */ | ||
43 | #define XHI_RF_OFFSET 0x104 /* Read FIFO */ | ||
44 | #define XHI_SZ_OFFSET 0x108 /* Size Register */ | ||
45 | #define XHI_CR_OFFSET 0x10C /* Control Register */ | ||
46 | #define XHI_SR_OFFSET 0x110 /* Status Register */ | ||
47 | #define XHI_WFV_OFFSET 0x114 /* Write FIFO Vacancy Register */ | ||
48 | #define XHI_RFO_OFFSET 0x118 /* Read FIFO Occupancy Register */ | ||
49 | |||
50 | /* Device Global Interrupt Enable Register (GIER) bit definitions */ | ||
51 | |||
52 | #define XHI_GIER_GIE_MASK 0x80000000 /* Global Interrupt enable Mask */ | ||
53 | |||
54 | /** | ||
55 | * HwIcap Device Interrupt Status/Enable Registers | ||
56 | * | ||
57 | * Interrupt Status Register (IPISR) : This register holds the | ||
58 | * interrupt status flags for the device. These bits are toggle on | ||
59 | * write. | ||
60 | * | ||
61 | * Interrupt Enable Register (IPIER) : This register is used to enable | ||
62 | * interrupt sources for the device. | ||
63 | * Writing a '1' to a bit enables the corresponding interrupt. | ||
64 | * Writing a '0' to a bit disables the corresponding interrupt. | ||
65 | * | ||
66 | * IPISR/IPIER registers have the same bit definitions and are only defined | ||
67 | * once. | ||
68 | */ | ||
69 | #define XHI_IPIXR_RFULL_MASK 0x00000008 /* Read FIFO Full */ | ||
70 | #define XHI_IPIXR_WEMPTY_MASK 0x00000004 /* Write FIFO Empty */ | ||
71 | #define XHI_IPIXR_RDP_MASK 0x00000002 /* Read FIFO half full */ | ||
72 | #define XHI_IPIXR_WRP_MASK 0x00000001 /* Write FIFO half full */ | ||
73 | #define XHI_IPIXR_ALL_MASK 0x0000000F /* Mask of all interrupts */ | ||
74 | |||
75 | /* Control Register (CR) */ | ||
76 | #define XHI_CR_SW_RESET_MASK 0x00000008 /* SW Reset Mask */ | ||
77 | #define XHI_CR_FIFO_CLR_MASK 0x00000004 /* FIFO Clear Mask */ | ||
78 | #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */ | ||
79 | #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */ | ||
80 | |||
81 | /* Status Register (SR) */ | ||
82 | #define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */ | ||
83 | #define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */ | ||
84 | #define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */ | ||
85 | #define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */ | ||
86 | #define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */ | ||
87 | |||
88 | |||
89 | #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */ | ||
90 | #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */ | ||
91 | /* The maximum amount we can request from fifo_icap_get_configuration | ||
92 | at once, in bytes. */ | ||
93 | #define XHI_MAX_READ_TRANSACTION_WORDS 0xFFF | ||
94 | |||
95 | |||
96 | /** | ||
97 | * fifo_icap_fifo_write: Write data to the write FIFO. | ||
98 | * @parameter drvdata: a pointer to the drvdata. | ||
99 | * @parameter data: the 32-bit value to be written to the FIFO. | ||
100 | * | ||
101 | * This function will silently fail if the fifo is full. | ||
102 | **/ | ||
103 | static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata, | ||
104 | u32 data) | ||
105 | { | ||
106 | dev_dbg(drvdata->dev, "fifo_write: %x\n", data); | ||
107 | out_be32(drvdata->base_address + XHI_WF_OFFSET, data); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * fifo_icap_fifo_read: Read data from the Read FIFO. | ||
112 | * @parameter drvdata: a pointer to the drvdata. | ||
113 | * | ||
114 | * This function will silently fail if the fifo is empty. | ||
115 | **/ | ||
116 | static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata) | ||
117 | { | ||
118 | u32 data = in_be32(drvdata->base_address + XHI_RF_OFFSET); | ||
119 | dev_dbg(drvdata->dev, "fifo_read: %x\n", data); | ||
120 | return data; | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * fifo_icap_set_read_size: Set the the size register. | ||
125 | * @parameter drvdata: a pointer to the drvdata. | ||
126 | * @parameter data: the size of the following read transaction, in words. | ||
127 | **/ | ||
128 | static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata, | ||
129 | u32 data) | ||
130 | { | ||
131 | out_be32(drvdata->base_address + XHI_SZ_OFFSET, data); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * fifo_icap_start_config: Initiate a configuration (write) to the device. | ||
136 | * @parameter drvdata: a pointer to the drvdata. | ||
137 | **/ | ||
138 | static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata) | ||
139 | { | ||
140 | out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_WRITE_MASK); | ||
141 | dev_dbg(drvdata->dev, "configuration started\n"); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * fifo_icap_start_readback: Initiate a readback from the device. | ||
146 | * @parameter drvdata: a pointer to the drvdata. | ||
147 | **/ | ||
148 | static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata) | ||
149 | { | ||
150 | out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_READ_MASK); | ||
151 | dev_dbg(drvdata->dev, "readback started\n"); | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * fifo_icap_busy: Return true if the ICAP is still processing a transaction. | ||
156 | * @parameter drvdata: a pointer to the drvdata. | ||
157 | **/ | ||
158 | static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata) | ||
159 | { | ||
160 | u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET); | ||
161 | dev_dbg(drvdata->dev, "Getting status = %x\n", status); | ||
162 | return (status & XHI_SR_DONE_MASK) ? 0 : 1; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * fifo_icap_write_fifo_vacancy: Query the write fifo available space. | ||
167 | * @parameter drvdata: a pointer to the drvdata. | ||
168 | * | ||
169 | * Return the number of words that can be safely pushed into the write fifo. | ||
170 | **/ | ||
171 | static inline u32 fifo_icap_write_fifo_vacancy( | ||
172 | struct hwicap_drvdata *drvdata) | ||
173 | { | ||
174 | return in_be32(drvdata->base_address + XHI_WFV_OFFSET); | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * fifo_icap_read_fifo_occupancy: Query the read fifo available data. | ||
179 | * @parameter drvdata: a pointer to the drvdata. | ||
180 | * | ||
181 | * Return the number of words that can be safely read from the read fifo. | ||
182 | **/ | ||
183 | static inline u32 fifo_icap_read_fifo_occupancy( | ||
184 | struct hwicap_drvdata *drvdata) | ||
185 | { | ||
186 | return in_be32(drvdata->base_address + XHI_RFO_OFFSET); | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * fifo_icap_set_configuration: Send configuration data to the ICAP. | ||
191 | * @parameter drvdata: a pointer to the drvdata. | ||
192 | * @parameter frame_buffer: a pointer to the data to be written to the | ||
193 | * ICAP device. | ||
194 | * @parameter num_words: the number of words (32 bit) to write to the ICAP | ||
195 | * device. | ||
196 | |||
197 | * This function writes the given user data to the Write FIFO in | ||
198 | * polled mode and starts the transfer of the data to | ||
199 | * the ICAP device. | ||
200 | **/ | ||
201 | int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata, | ||
202 | u32 *frame_buffer, u32 num_words) | ||
203 | { | ||
204 | |||
205 | u32 write_fifo_vacancy = 0; | ||
206 | u32 retries = 0; | ||
207 | u32 remaining_words; | ||
208 | |||
209 | dev_dbg(drvdata->dev, "fifo_set_configuration\n"); | ||
210 | |||
211 | /* | ||
212 | * Check if the ICAP device is Busy with the last Read/Write | ||
213 | */ | ||
214 | if (fifo_icap_busy(drvdata)) | ||
215 | return -EBUSY; | ||
216 | |||
217 | /* | ||
218 | * Set up the buffer pointer and the words to be transferred. | ||
219 | */ | ||
220 | remaining_words = num_words; | ||
221 | |||
222 | while (remaining_words > 0) { | ||
223 | /* | ||
224 | * Wait until we have some data in the fifo. | ||
225 | */ | ||
226 | while (write_fifo_vacancy == 0) { | ||
227 | write_fifo_vacancy = | ||
228 | fifo_icap_write_fifo_vacancy(drvdata); | ||
229 | retries++; | ||
230 | if (retries > XHI_MAX_RETRIES) | ||
231 | return -EIO; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Write data into the Write FIFO. | ||
236 | */ | ||
237 | while ((write_fifo_vacancy != 0) && | ||
238 | (remaining_words > 0)) { | ||
239 | fifo_icap_fifo_write(drvdata, *frame_buffer); | ||
240 | |||
241 | remaining_words--; | ||
242 | write_fifo_vacancy--; | ||
243 | frame_buffer++; | ||
244 | } | ||
245 | /* Start pushing whatever is in the FIFO into the ICAP. */ | ||
246 | fifo_icap_start_config(drvdata); | ||
247 | } | ||
248 | |||
249 | /* Wait until the write has finished. */ | ||
250 | while (fifo_icap_busy(drvdata)) { | ||
251 | retries++; | ||
252 | if (retries > XHI_MAX_RETRIES) | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | dev_dbg(drvdata->dev, "done fifo_set_configuration\n"); | ||
257 | |||
258 | /* | ||
259 | * If the requested number of words have not been read from | ||
260 | * the device then indicate failure. | ||
261 | */ | ||
262 | if (remaining_words != 0) | ||
263 | return -EIO; | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * fifo_icap_get_configuration: Read configuration data from the device. | ||
270 | * @parameter drvdata: a pointer to the drvdata. | ||
271 | * @parameter data: Address of the data representing the partial bitstream | ||
272 | * @parameter size: the size of the partial bitstream in 32 bit words. | ||
273 | * | ||
274 | * This function reads the specified number of words from the ICAP device in | ||
275 | * the polled mode. | ||
276 | */ | ||
277 | int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata, | ||
278 | u32 *frame_buffer, u32 num_words) | ||
279 | { | ||
280 | |||
281 | u32 read_fifo_occupancy = 0; | ||
282 | u32 retries = 0; | ||
283 | u32 *data = frame_buffer; | ||
284 | u32 remaining_words; | ||
285 | u32 words_to_read; | ||
286 | |||
287 | dev_dbg(drvdata->dev, "fifo_get_configuration\n"); | ||
288 | |||
289 | /* | ||
290 | * Check if the ICAP device is Busy with the last Write/Read | ||
291 | */ | ||
292 | if (fifo_icap_busy(drvdata)) | ||
293 | return -EBUSY; | ||
294 | |||
295 | remaining_words = num_words; | ||
296 | |||
297 | while (remaining_words > 0) { | ||
298 | words_to_read = remaining_words; | ||
299 | /* The hardware has a limit on the number of words | ||
300 | that can be read at one time. */ | ||
301 | if (words_to_read > XHI_MAX_READ_TRANSACTION_WORDS) | ||
302 | words_to_read = XHI_MAX_READ_TRANSACTION_WORDS; | ||
303 | |||
304 | remaining_words -= words_to_read; | ||
305 | |||
306 | fifo_icap_set_read_size(drvdata, words_to_read); | ||
307 | fifo_icap_start_readback(drvdata); | ||
308 | |||
309 | while (words_to_read > 0) { | ||
310 | /* Wait until we have some data in the fifo. */ | ||
311 | while (read_fifo_occupancy == 0) { | ||
312 | read_fifo_occupancy = | ||
313 | fifo_icap_read_fifo_occupancy(drvdata); | ||
314 | retries++; | ||
315 | if (retries > XHI_MAX_RETRIES) | ||
316 | return -EIO; | ||
317 | } | ||
318 | |||
319 | if (read_fifo_occupancy > words_to_read) | ||
320 | read_fifo_occupancy = words_to_read; | ||
321 | |||
322 | words_to_read -= read_fifo_occupancy; | ||
323 | |||
324 | /* Read the data from the Read FIFO. */ | ||
325 | while (read_fifo_occupancy != 0) { | ||
326 | *data++ = fifo_icap_fifo_read(drvdata); | ||
327 | read_fifo_occupancy--; | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | |||
332 | dev_dbg(drvdata->dev, "done fifo_get_configuration\n"); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * buffer_icap_reset: Reset the logic of the icap device. | ||
339 | * @parameter drvdata: a pointer to the drvdata. | ||
340 | * | ||
341 | * This function forces the software reset of the complete HWICAP device. | ||
342 | * All the registers will return to the default value and the FIFO is also | ||
343 | * flushed as a part of this software reset. | ||
344 | */ | ||
345 | void fifo_icap_reset(struct hwicap_drvdata *drvdata) | ||
346 | { | ||
347 | u32 reg_data; | ||
348 | /* | ||
349 | * Reset the device by setting/clearing the RESET bit in the | ||
350 | * Control Register. | ||
351 | */ | ||
352 | reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET); | ||
353 | |||
354 | out_be32(drvdata->base_address + XHI_CR_OFFSET, | ||
355 | reg_data | XHI_CR_SW_RESET_MASK); | ||
356 | |||
357 | out_be32(drvdata->base_address + XHI_CR_OFFSET, | ||
358 | reg_data & (~XHI_CR_SW_RESET_MASK)); | ||
359 | |||
360 | } | ||
361 | |||
362 | /** | ||
363 | * fifo_icap_flush_fifo: This function flushes the FIFOs in the device. | ||
364 | * @parameter drvdata: a pointer to the drvdata. | ||
365 | */ | ||
366 | void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata) | ||
367 | { | ||
368 | u32 reg_data; | ||
369 | /* | ||
370 | * Flush the FIFO by setting/clearing the FIFO Clear bit in the | ||
371 | * Control Register. | ||
372 | */ | ||
373 | reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET); | ||
374 | |||
375 | out_be32(drvdata->base_address + XHI_CR_OFFSET, | ||
376 | reg_data | XHI_CR_FIFO_CLR_MASK); | ||
377 | |||
378 | out_be32(drvdata->base_address + XHI_CR_OFFSET, | ||
379 | reg_data & (~XHI_CR_FIFO_CLR_MASK)); | ||
380 | } | ||
381 | |||
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h new file mode 100644 index 000000000000..4d3068dd0405 --- /dev/null +++ b/drivers/char/xilinx_hwicap/fifo_icap.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Author: Xilinx, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" | ||
11 | * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND | ||
12 | * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, | ||
13 | * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, | ||
14 | * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION | ||
15 | * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, | ||
16 | * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE | ||
17 | * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY | ||
18 | * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE | ||
19 | * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR | ||
20 | * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF | ||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
22 | * FOR A PARTICULAR PURPOSE. | ||
23 | * | ||
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2007-2008 Xilinx Inc. | ||
28 | * All rights reserved. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | * | ||
34 | *****************************************************************************/ | ||
35 | |||
36 | #ifndef XILINX_FIFO_ICAP_H_ /* prevent circular inclusions */ | ||
37 | #define XILINX_FIFO_ICAP_H_ /* by using protection macros */ | ||
38 | |||
39 | #include <linux/types.h> | ||
40 | #include <linux/cdev.h> | ||
41 | #include <linux/version.h> | ||
42 | #include <linux/platform_device.h> | ||
43 | |||
44 | #include <asm/io.h> | ||
45 | #include "xilinx_hwicap.h" | ||
46 | |||
47 | /* Reads integers from the device into the storage buffer. */ | ||
48 | int fifo_icap_get_configuration( | ||
49 | struct hwicap_drvdata *drvdata, | ||
50 | u32 *FrameBuffer, | ||
51 | u32 NumWords); | ||
52 | |||
53 | /* Writes integers to the device from the storage buffer. */ | ||
54 | int fifo_icap_set_configuration( | ||
55 | struct hwicap_drvdata *drvdata, | ||
56 | u32 *FrameBuffer, | ||
57 | u32 NumWords); | ||
58 | |||
59 | void fifo_icap_reset(struct hwicap_drvdata *drvdata); | ||
60 | void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata); | ||
61 | |||
62 | #endif | ||
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c new file mode 100644 index 000000000000..24f6aef0fd3c --- /dev/null +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -0,0 +1,904 @@ | |||
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Author: Xilinx, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" | ||
11 | * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND | ||
12 | * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, | ||
13 | * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, | ||
14 | * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION | ||
15 | * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, | ||
16 | * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE | ||
17 | * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY | ||
18 | * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE | ||
19 | * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR | ||
20 | * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF | ||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
22 | * FOR A PARTICULAR PURPOSE. | ||
23 | * | ||
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2002 Xilinx Inc., Systems Engineering Group | ||
28 | * (c) Copyright 2004 Xilinx Inc., Systems Engineering Group | ||
29 | * (c) Copyright 2007-2008 Xilinx Inc. | ||
30 | * All rights reserved. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public License along | ||
33 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
34 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
35 | * | ||
36 | *****************************************************************************/ | ||
37 | |||
38 | /* | ||
39 | * This is the code behind /dev/xilinx_icap -- it allows a user-space | ||
40 | * application to use the Xilinx ICAP subsystem. | ||
41 | * | ||
42 | * The following operations are possible: | ||
43 | * | ||
44 | * open open the port and initialize for access. | ||
45 | * release release port | ||
46 | * write Write a bitstream to the configuration processor. | ||
47 | * read Read a data stream from the configuration processor. | ||
48 | * | ||
49 | * After being opened, the port is initialized and accessed to avoid a | ||
50 | * corrupted first read which may occur with some hardware. The port | ||
51 | * is left in a desynched state, requiring that a synch sequence be | ||
52 | * transmitted before any valid configuration data. A user will have | ||
53 | * exclusive access to the device while it remains open, and the state | ||
54 | * of the ICAP cannot be guaranteed after the device is closed. Note | ||
55 | * that a complete reset of the core and the state of the ICAP cannot | ||
56 | * be performed on many versions of the cores, hence users of this | ||
57 | * device should avoid making inconsistent accesses to the device. In | ||
58 | * particular, accessing the read interface, without first generating | ||
59 | * a write containing a readback packet can leave the ICAP in an | ||
60 | * inaccessible state. | ||
61 | * | ||
62 | * Note that in order to use the read interface, it is first necessary | ||
63 | * to write a request packet to the write interface. i.e., it is not | ||
64 | * possible to simply readback the bitstream (or any configuration | ||
65 | * bits) from a device without specifically requesting them first. | ||
66 | * The code to craft such packets is intended to be part of the | ||
67 | * user-space application code that uses this device. The simplest | ||
68 | * way to use this interface is simply: | ||
69 | * | ||
70 | * cp foo.bit /dev/xilinx_icap | ||
71 | * | ||
72 | * Note that unless foo.bit is an appropriately constructed partial | ||
73 | * bitstream, this has a high likelyhood of overwriting the design | ||
74 | * currently programmed in the FPGA. | ||
75 | */ | ||
76 | |||
77 | #include <linux/version.h> | ||
78 | #include <linux/module.h> | ||
79 | #include <linux/kernel.h> | ||
80 | #include <linux/types.h> | ||
81 | #include <linux/ioport.h> | ||
82 | #include <linux/interrupt.h> | ||
83 | #include <linux/fcntl.h> | ||
84 | #include <linux/init.h> | ||
85 | #include <linux/poll.h> | ||
86 | #include <linux/proc_fs.h> | ||
87 | #include <asm/semaphore.h> | ||
88 | #include <linux/sysctl.h> | ||
89 | #include <linux/version.h> | ||
90 | #include <linux/fs.h> | ||
91 | #include <linux/cdev.h> | ||
92 | #include <linux/platform_device.h> | ||
93 | |||
94 | #include <asm/io.h> | ||
95 | #include <asm/uaccess.h> | ||
96 | #include <asm/system.h> | ||
97 | |||
98 | #ifdef CONFIG_OF | ||
99 | /* For open firmware. */ | ||
100 | #include <linux/of_device.h> | ||
101 | #include <linux/of_platform.h> | ||
102 | #endif | ||
103 | |||
104 | #include "xilinx_hwicap.h" | ||
105 | #include "buffer_icap.h" | ||
106 | #include "fifo_icap.h" | ||
107 | |||
108 | #define DRIVER_NAME "xilinx_icap" | ||
109 | |||
110 | #define HWICAP_REGS (0x10000) | ||
111 | |||
112 | /* dynamically allocate device number */ | ||
113 | static int xhwicap_major; | ||
114 | static int xhwicap_minor; | ||
115 | #define HWICAP_DEVICES 1 | ||
116 | |||
117 | module_param(xhwicap_major, int, S_IRUGO); | ||
118 | module_param(xhwicap_minor, int, S_IRUGO); | ||
119 | |||
120 | /* An array, which is set to true when the device is registered. */ | ||
121 | static bool probed_devices[HWICAP_DEVICES]; | ||
122 | |||
123 | static struct class *icap_class; | ||
124 | |||
125 | #define UNIMPLEMENTED 0xFFFF | ||
126 | |||
127 | static const struct config_registers v2_config_registers = { | ||
128 | .CRC = 0, | ||
129 | .FAR = 1, | ||
130 | .FDRI = 2, | ||
131 | .FDRO = 3, | ||
132 | .CMD = 4, | ||
133 | .CTL = 5, | ||
134 | .MASK = 6, | ||
135 | .STAT = 7, | ||
136 | .LOUT = 8, | ||
137 | .COR = 9, | ||
138 | .MFWR = 10, | ||
139 | .FLR = 11, | ||
140 | .KEY = 12, | ||
141 | .CBC = 13, | ||
142 | .IDCODE = 14, | ||
143 | .AXSS = UNIMPLEMENTED, | ||
144 | .C0R_1 = UNIMPLEMENTED, | ||
145 | .CSOB = UNIMPLEMENTED, | ||
146 | .WBSTAR = UNIMPLEMENTED, | ||
147 | .TIMER = UNIMPLEMENTED, | ||
148 | .BOOTSTS = UNIMPLEMENTED, | ||
149 | .CTL_1 = UNIMPLEMENTED, | ||
150 | }; | ||
151 | |||
152 | static const struct config_registers v4_config_registers = { | ||
153 | .CRC = 0, | ||
154 | .FAR = 1, | ||
155 | .FDRI = 2, | ||
156 | .FDRO = 3, | ||
157 | .CMD = 4, | ||
158 | .CTL = 5, | ||
159 | .MASK = 6, | ||
160 | .STAT = 7, | ||
161 | .LOUT = 8, | ||
162 | .COR = 9, | ||
163 | .MFWR = 10, | ||
164 | .FLR = UNIMPLEMENTED, | ||
165 | .KEY = UNIMPLEMENTED, | ||
166 | .CBC = 11, | ||
167 | .IDCODE = 12, | ||
168 | .AXSS = 13, | ||
169 | .C0R_1 = UNIMPLEMENTED, | ||
170 | .CSOB = UNIMPLEMENTED, | ||
171 | .WBSTAR = UNIMPLEMENTED, | ||
172 | .TIMER = UNIMPLEMENTED, | ||
173 | .BOOTSTS = UNIMPLEMENTED, | ||
174 | .CTL_1 = UNIMPLEMENTED, | ||
175 | }; | ||
176 | static const struct config_registers v5_config_registers = { | ||
177 | .CRC = 0, | ||
178 | .FAR = 1, | ||
179 | .FDRI = 2, | ||
180 | .FDRO = 3, | ||
181 | .CMD = 4, | ||
182 | .CTL = 5, | ||
183 | .MASK = 6, | ||
184 | .STAT = 7, | ||
185 | .LOUT = 8, | ||
186 | .COR = 9, | ||
187 | .MFWR = 10, | ||
188 | .FLR = UNIMPLEMENTED, | ||
189 | .KEY = UNIMPLEMENTED, | ||
190 | .CBC = 11, | ||
191 | .IDCODE = 12, | ||
192 | .AXSS = 13, | ||
193 | .C0R_1 = 14, | ||
194 | .CSOB = 15, | ||
195 | .WBSTAR = 16, | ||
196 | .TIMER = 17, | ||
197 | .BOOTSTS = 18, | ||
198 | .CTL_1 = 19, | ||
199 | }; | ||
200 | |||
201 | /** | ||
202 | * hwicap_command_desync: Send a DESYNC command to the ICAP port. | ||
203 | * @parameter drvdata: a pointer to the drvdata. | ||
204 | * | ||
205 | * This command desynchronizes the ICAP After this command, a | ||
206 | * bitstream containing a NULL packet, followed by a SYNCH packet is | ||
207 | * required before the ICAP will recognize commands. | ||
208 | */ | ||
209 | int hwicap_command_desync(struct hwicap_drvdata *drvdata) | ||
210 | { | ||
211 | u32 buffer[4]; | ||
212 | u32 index = 0; | ||
213 | |||
214 | /* | ||
215 | * Create the data to be written to the ICAP. | ||
216 | */ | ||
217 | buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1; | ||
218 | buffer[index++] = XHI_CMD_DESYNCH; | ||
219 | buffer[index++] = XHI_NOOP_PACKET; | ||
220 | buffer[index++] = XHI_NOOP_PACKET; | ||
221 | |||
222 | /* | ||
223 | * Write the data to the FIFO and intiate the transfer of data present | ||
224 | * in the FIFO to the ICAP device. | ||
225 | */ | ||
226 | return drvdata->config->set_configuration(drvdata, | ||
227 | &buffer[0], index); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * hwicap_command_capture: Send a CAPTURE command to the ICAP port. | ||
232 | * @parameter drvdata: a pointer to the drvdata. | ||
233 | * | ||
234 | * This command captures all of the flip flop states so they will be | ||
235 | * available during readback. One can use this command instead of | ||
236 | * enabling the CAPTURE block in the design. | ||
237 | */ | ||
238 | int hwicap_command_capture(struct hwicap_drvdata *drvdata) | ||
239 | { | ||
240 | u32 buffer[7]; | ||
241 | u32 index = 0; | ||
242 | |||
243 | /* | ||
244 | * Create the data to be written to the ICAP. | ||
245 | */ | ||
246 | buffer[index++] = XHI_DUMMY_PACKET; | ||
247 | buffer[index++] = XHI_SYNC_PACKET; | ||
248 | buffer[index++] = XHI_NOOP_PACKET; | ||
249 | buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1; | ||
250 | buffer[index++] = XHI_CMD_GCAPTURE; | ||
251 | buffer[index++] = XHI_DUMMY_PACKET; | ||
252 | buffer[index++] = XHI_DUMMY_PACKET; | ||
253 | |||
254 | /* | ||
255 | * Write the data to the FIFO and intiate the transfer of data | ||
256 | * present in the FIFO to the ICAP device. | ||
257 | */ | ||
258 | return drvdata->config->set_configuration(drvdata, | ||
259 | &buffer[0], index); | ||
260 | |||
261 | } | ||
262 | |||
263 | /** | ||
264 | * hwicap_get_configuration_register: Query a configuration register. | ||
265 | * @parameter drvdata: a pointer to the drvdata. | ||
266 | * @parameter reg: a constant which represents the configuration | ||
267 | * register value to be returned. | ||
268 | * Examples: XHI_IDCODE, XHI_FLR. | ||
269 | * @parameter RegData: returns the value of the register. | ||
270 | * | ||
271 | * Sends a query packet to the ICAP and then receives the response. | ||
272 | * The icap is left in Synched state. | ||
273 | */ | ||
274 | int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, | ||
275 | u32 reg, u32 *RegData) | ||
276 | { | ||
277 | int status; | ||
278 | u32 buffer[6]; | ||
279 | u32 index = 0; | ||
280 | |||
281 | /* | ||
282 | * Create the data to be written to the ICAP. | ||
283 | */ | ||
284 | buffer[index++] = XHI_DUMMY_PACKET; | ||
285 | buffer[index++] = XHI_SYNC_PACKET; | ||
286 | buffer[index++] = XHI_NOOP_PACKET; | ||
287 | buffer[index++] = hwicap_type_1_read(reg) | 1; | ||
288 | buffer[index++] = XHI_NOOP_PACKET; | ||
289 | buffer[index++] = XHI_NOOP_PACKET; | ||
290 | |||
291 | /* | ||
292 | * Write the data to the FIFO and intiate the transfer of data present | ||
293 | * in the FIFO to the ICAP device. | ||
294 | */ | ||
295 | status = drvdata->config->set_configuration(drvdata, | ||
296 | &buffer[0], index); | ||
297 | if (status) | ||
298 | return status; | ||
299 | |||
300 | /* | ||
301 | * Read the configuration register | ||
302 | */ | ||
303 | status = drvdata->config->get_configuration(drvdata, RegData, 1); | ||
304 | if (status) | ||
305 | return status; | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata) | ||
311 | { | ||
312 | int status; | ||
313 | u32 idcode; | ||
314 | |||
315 | dev_dbg(drvdata->dev, "initializing\n"); | ||
316 | |||
317 | /* Abort any current transaction, to make sure we have the | ||
318 | * ICAP in a good state. */ | ||
319 | dev_dbg(drvdata->dev, "Reset...\n"); | ||
320 | drvdata->config->reset(drvdata); | ||
321 | |||
322 | dev_dbg(drvdata->dev, "Desync...\n"); | ||
323 | status = hwicap_command_desync(drvdata); | ||
324 | if (status) | ||
325 | return status; | ||
326 | |||
327 | /* Attempt to read the IDCODE from ICAP. This | ||
328 | * may not be returned correctly, due to the design of the | ||
329 | * hardware. | ||
330 | */ | ||
331 | dev_dbg(drvdata->dev, "Reading IDCODE...\n"); | ||
332 | status = hwicap_get_configuration_register( | ||
333 | drvdata, drvdata->config_regs->IDCODE, &idcode); | ||
334 | dev_dbg(drvdata->dev, "IDCODE = %x\n", idcode); | ||
335 | if (status) | ||
336 | return status; | ||
337 | |||
338 | dev_dbg(drvdata->dev, "Desync...\n"); | ||
339 | status = hwicap_command_desync(drvdata); | ||
340 | if (status) | ||
341 | return status; | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static ssize_t | ||
347 | hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos) | ||
348 | { | ||
349 | struct hwicap_drvdata *drvdata = file->private_data; | ||
350 | ssize_t bytes_to_read = 0; | ||
351 | u32 *kbuf; | ||
352 | u32 words; | ||
353 | u32 bytes_remaining; | ||
354 | int status; | ||
355 | |||
356 | if (down_interruptible(&drvdata->sem)) | ||
357 | return -ERESTARTSYS; | ||
358 | |||
359 | if (drvdata->read_buffer_in_use) { | ||
360 | /* If there are leftover bytes in the buffer, just */ | ||
361 | /* return them and don't try to read more from the */ | ||
362 | /* ICAP device. */ | ||
363 | bytes_to_read = | ||
364 | (count < drvdata->read_buffer_in_use) ? count : | ||
365 | drvdata->read_buffer_in_use; | ||
366 | |||
367 | /* Return the data currently in the read buffer. */ | ||
368 | if (copy_to_user(buf, drvdata->read_buffer, bytes_to_read)) { | ||
369 | status = -EFAULT; | ||
370 | goto error; | ||
371 | } | ||
372 | drvdata->read_buffer_in_use -= bytes_to_read; | ||
373 | memcpy(drvdata->read_buffer + bytes_to_read, | ||
374 | drvdata->read_buffer, 4 - bytes_to_read); | ||
375 | } else { | ||
376 | /* Get new data from the ICAP, and return was was requested. */ | ||
377 | kbuf = (u32 *) get_zeroed_page(GFP_KERNEL); | ||
378 | if (!kbuf) { | ||
379 | status = -ENOMEM; | ||
380 | goto error; | ||
381 | } | ||
382 | |||
383 | /* The ICAP device is only able to read complete */ | ||
384 | /* words. If a number of bytes that do not correspond */ | ||
385 | /* to complete words is requested, then we read enough */ | ||
386 | /* words to get the required number of bytes, and then */ | ||
387 | /* save the remaining bytes for the next read. */ | ||
388 | |||
389 | /* Determine the number of words to read, rounding up */ | ||
390 | /* if necessary. */ | ||
391 | words = ((count + 3) >> 2); | ||
392 | bytes_to_read = words << 2; | ||
393 | |||
394 | if (bytes_to_read > PAGE_SIZE) | ||
395 | bytes_to_read = PAGE_SIZE; | ||
396 | |||
397 | /* Ensure we only read a complete number of words. */ | ||
398 | bytes_remaining = bytes_to_read & 3; | ||
399 | bytes_to_read &= ~3; | ||
400 | words = bytes_to_read >> 2; | ||
401 | |||
402 | status = drvdata->config->get_configuration(drvdata, | ||
403 | kbuf, words); | ||
404 | |||
405 | /* If we didn't read correctly, then bail out. */ | ||
406 | if (status) { | ||
407 | free_page((unsigned long)kbuf); | ||
408 | goto error; | ||
409 | } | ||
410 | |||
411 | /* If we fail to return the data to the user, then bail out. */ | ||
412 | if (copy_to_user(buf, kbuf, bytes_to_read)) { | ||
413 | free_page((unsigned long)kbuf); | ||
414 | status = -EFAULT; | ||
415 | goto error; | ||
416 | } | ||
417 | memcpy(kbuf, drvdata->read_buffer, bytes_remaining); | ||
418 | drvdata->read_buffer_in_use = bytes_remaining; | ||
419 | free_page((unsigned long)kbuf); | ||
420 | } | ||
421 | status = bytes_to_read; | ||
422 | error: | ||
423 | up(&drvdata->sem); | ||
424 | return status; | ||
425 | } | ||
426 | |||
427 | static ssize_t | ||
428 | hwicap_write(struct file *file, const char *buf, | ||
429 | size_t count, loff_t *ppos) | ||
430 | { | ||
431 | struct hwicap_drvdata *drvdata = file->private_data; | ||
432 | ssize_t written = 0; | ||
433 | ssize_t left = count; | ||
434 | u32 *kbuf; | ||
435 | ssize_t len; | ||
436 | ssize_t status; | ||
437 | |||
438 | if (down_interruptible(&drvdata->sem)) | ||
439 | return -ERESTARTSYS; | ||
440 | |||
441 | left += drvdata->write_buffer_in_use; | ||
442 | |||
443 | /* Only write multiples of 4 bytes. */ | ||
444 | if (left < 4) { | ||
445 | status = 0; | ||
446 | goto error; | ||
447 | } | ||
448 | |||
449 | kbuf = (u32 *) __get_free_page(GFP_KERNEL); | ||
450 | if (!kbuf) { | ||
451 | status = -ENOMEM; | ||
452 | goto error; | ||
453 | } | ||
454 | |||
455 | while (left > 3) { | ||
456 | /* only write multiples of 4 bytes, so there might */ | ||
457 | /* be as many as 3 bytes left (at the end). */ | ||
458 | len = left; | ||
459 | |||
460 | if (len > PAGE_SIZE) | ||
461 | len = PAGE_SIZE; | ||
462 | len &= ~3; | ||
463 | |||
464 | if (drvdata->write_buffer_in_use) { | ||
465 | memcpy(kbuf, drvdata->write_buffer, | ||
466 | drvdata->write_buffer_in_use); | ||
467 | if (copy_from_user( | ||
468 | (((char *)kbuf) + (drvdata->write_buffer_in_use)), | ||
469 | buf + written, | ||
470 | len - (drvdata->write_buffer_in_use))) { | ||
471 | free_page((unsigned long)kbuf); | ||
472 | status = -EFAULT; | ||
473 | goto error; | ||
474 | } | ||
475 | } else { | ||
476 | if (copy_from_user(kbuf, buf + written, len)) { | ||
477 | free_page((unsigned long)kbuf); | ||
478 | status = -EFAULT; | ||
479 | goto error; | ||
480 | } | ||
481 | } | ||
482 | |||
483 | status = drvdata->config->set_configuration(drvdata, | ||
484 | kbuf, len >> 2); | ||
485 | |||
486 | if (status) { | ||
487 | free_page((unsigned long)kbuf); | ||
488 | status = -EFAULT; | ||
489 | goto error; | ||
490 | } | ||
491 | if (drvdata->write_buffer_in_use) { | ||
492 | len -= drvdata->write_buffer_in_use; | ||
493 | left -= drvdata->write_buffer_in_use; | ||
494 | drvdata->write_buffer_in_use = 0; | ||
495 | } | ||
496 | written += len; | ||
497 | left -= len; | ||
498 | } | ||
499 | if ((left > 0) && (left < 4)) { | ||
500 | if (!copy_from_user(drvdata->write_buffer, | ||
501 | buf + written, left)) { | ||
502 | drvdata->write_buffer_in_use = left; | ||
503 | written += left; | ||
504 | left = 0; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | free_page((unsigned long)kbuf); | ||
509 | status = written; | ||
510 | error: | ||
511 | up(&drvdata->sem); | ||
512 | return status; | ||
513 | } | ||
514 | |||
515 | static int hwicap_open(struct inode *inode, struct file *file) | ||
516 | { | ||
517 | struct hwicap_drvdata *drvdata; | ||
518 | int status; | ||
519 | |||
520 | drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev); | ||
521 | |||
522 | if (down_interruptible(&drvdata->sem)) | ||
523 | return -ERESTARTSYS; | ||
524 | |||
525 | if (drvdata->is_open) { | ||
526 | status = -EBUSY; | ||
527 | goto error; | ||
528 | } | ||
529 | |||
530 | status = hwicap_initialize_hwicap(drvdata); | ||
531 | if (status) { | ||
532 | dev_err(drvdata->dev, "Failed to open file"); | ||
533 | goto error; | ||
534 | } | ||
535 | |||
536 | file->private_data = drvdata; | ||
537 | drvdata->write_buffer_in_use = 0; | ||
538 | drvdata->read_buffer_in_use = 0; | ||
539 | drvdata->is_open = 1; | ||
540 | |||
541 | error: | ||
542 | up(&drvdata->sem); | ||
543 | return status; | ||
544 | } | ||
545 | |||
546 | static int hwicap_release(struct inode *inode, struct file *file) | ||
547 | { | ||
548 | struct hwicap_drvdata *drvdata = file->private_data; | ||
549 | int i; | ||
550 | int status = 0; | ||
551 | |||
552 | if (down_interruptible(&drvdata->sem)) | ||
553 | return -ERESTARTSYS; | ||
554 | |||
555 | if (drvdata->write_buffer_in_use) { | ||
556 | /* Flush write buffer. */ | ||
557 | for (i = drvdata->write_buffer_in_use; i < 4; i++) | ||
558 | drvdata->write_buffer[i] = 0; | ||
559 | |||
560 | status = drvdata->config->set_configuration(drvdata, | ||
561 | (u32 *) drvdata->write_buffer, 1); | ||
562 | if (status) | ||
563 | goto error; | ||
564 | } | ||
565 | |||
566 | status = hwicap_command_desync(drvdata); | ||
567 | if (status) | ||
568 | goto error; | ||
569 | |||
570 | error: | ||
571 | drvdata->is_open = 0; | ||
572 | up(&drvdata->sem); | ||
573 | return status; | ||
574 | } | ||
575 | |||
576 | static struct file_operations hwicap_fops = { | ||
577 | .owner = THIS_MODULE, | ||
578 | .write = hwicap_write, | ||
579 | .read = hwicap_read, | ||
580 | .open = hwicap_open, | ||
581 | .release = hwicap_release, | ||
582 | }; | ||
583 | |||
584 | static int __devinit hwicap_setup(struct device *dev, int id, | ||
585 | const struct resource *regs_res, | ||
586 | const struct hwicap_driver_config *config, | ||
587 | const struct config_registers *config_regs) | ||
588 | { | ||
589 | dev_t devt; | ||
590 | struct hwicap_drvdata *drvdata = NULL; | ||
591 | int retval = 0; | ||
592 | |||
593 | dev_info(dev, "Xilinx icap port driver\n"); | ||
594 | |||
595 | if (id < 0) { | ||
596 | for (id = 0; id < HWICAP_DEVICES; id++) | ||
597 | if (!probed_devices[id]) | ||
598 | break; | ||
599 | } | ||
600 | if (id < 0 || id >= HWICAP_DEVICES) { | ||
601 | dev_err(dev, "%s%i too large\n", DRIVER_NAME, id); | ||
602 | return -EINVAL; | ||
603 | } | ||
604 | if (probed_devices[id]) { | ||
605 | dev_err(dev, "cannot assign to %s%i; it is already in use\n", | ||
606 | DRIVER_NAME, id); | ||
607 | return -EBUSY; | ||
608 | } | ||
609 | |||
610 | probed_devices[id] = 1; | ||
611 | |||
612 | devt = MKDEV(xhwicap_major, xhwicap_minor + id); | ||
613 | |||
614 | drvdata = kmalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL); | ||
615 | if (!drvdata) { | ||
616 | dev_err(dev, "Couldn't allocate device private record\n"); | ||
617 | return -ENOMEM; | ||
618 | } | ||
619 | memset((void *)drvdata, 0, sizeof(struct hwicap_drvdata)); | ||
620 | dev_set_drvdata(dev, (void *)drvdata); | ||
621 | |||
622 | if (!regs_res) { | ||
623 | dev_err(dev, "Couldn't get registers resource\n"); | ||
624 | retval = -EFAULT; | ||
625 | goto failed1; | ||
626 | } | ||
627 | |||
628 | drvdata->mem_start = regs_res->start; | ||
629 | drvdata->mem_end = regs_res->end; | ||
630 | drvdata->mem_size = regs_res->end - regs_res->start + 1; | ||
631 | |||
632 | if (!request_mem_region(drvdata->mem_start, | ||
633 | drvdata->mem_size, DRIVER_NAME)) { | ||
634 | dev_err(dev, "Couldn't lock memory region at %p\n", | ||
635 | (void *)regs_res->start); | ||
636 | retval = -EBUSY; | ||
637 | goto failed1; | ||
638 | } | ||
639 | |||
640 | drvdata->devt = devt; | ||
641 | drvdata->dev = dev; | ||
642 | drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size); | ||
643 | if (!drvdata->base_address) { | ||
644 | dev_err(dev, "ioremap() failed\n"); | ||
645 | goto failed2; | ||
646 | } | ||
647 | |||
648 | drvdata->config = config; | ||
649 | drvdata->config_regs = config_regs; | ||
650 | |||
651 | init_MUTEX(&drvdata->sem); | ||
652 | drvdata->is_open = 0; | ||
653 | |||
654 | dev_info(dev, "ioremap %lx to %p with size %x\n", | ||
655 | (unsigned long int)drvdata->mem_start, | ||
656 | drvdata->base_address, drvdata->mem_size); | ||
657 | |||
658 | cdev_init(&drvdata->cdev, &hwicap_fops); | ||
659 | drvdata->cdev.owner = THIS_MODULE; | ||
660 | retval = cdev_add(&drvdata->cdev, devt, 1); | ||
661 | if (retval) { | ||
662 | dev_err(dev, "cdev_add() failed\n"); | ||
663 | goto failed3; | ||
664 | } | ||
665 | /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */ | ||
666 | class_device_create(icap_class, NULL, devt, NULL, DRIVER_NAME); | ||
667 | return 0; /* success */ | ||
668 | |||
669 | failed3: | ||
670 | iounmap(drvdata->base_address); | ||
671 | |||
672 | failed2: | ||
673 | release_mem_region(regs_res->start, drvdata->mem_size); | ||
674 | |||
675 | failed1: | ||
676 | kfree(drvdata); | ||
677 | |||
678 | return retval; | ||
679 | } | ||
680 | |||
681 | static struct hwicap_driver_config buffer_icap_config = { | ||
682 | .get_configuration = buffer_icap_get_configuration, | ||
683 | .set_configuration = buffer_icap_set_configuration, | ||
684 | .reset = buffer_icap_reset, | ||
685 | }; | ||
686 | |||
687 | static struct hwicap_driver_config fifo_icap_config = { | ||
688 | .get_configuration = fifo_icap_get_configuration, | ||
689 | .set_configuration = fifo_icap_set_configuration, | ||
690 | .reset = fifo_icap_reset, | ||
691 | }; | ||
692 | |||
693 | static int __devexit hwicap_remove(struct device *dev) | ||
694 | { | ||
695 | struct hwicap_drvdata *drvdata; | ||
696 | |||
697 | drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev); | ||
698 | |||
699 | if (!drvdata) | ||
700 | return 0; | ||
701 | |||
702 | class_device_destroy(icap_class, drvdata->devt); | ||
703 | cdev_del(&drvdata->cdev); | ||
704 | iounmap(drvdata->base_address); | ||
705 | release_mem_region(drvdata->mem_start, drvdata->mem_size); | ||
706 | kfree(drvdata); | ||
707 | dev_set_drvdata(dev, NULL); | ||
708 | probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0; | ||
709 | |||
710 | return 0; /* success */ | ||
711 | } | ||
712 | |||
713 | static int __devinit hwicap_drv_probe(struct platform_device *pdev) | ||
714 | { | ||
715 | struct resource *res; | ||
716 | const struct config_registers *regs; | ||
717 | const char *family; | ||
718 | |||
719 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
720 | if (!res) | ||
721 | return -ENODEV; | ||
722 | |||
723 | /* It's most likely that we're using V4, if the family is not | ||
724 | specified */ | ||
725 | regs = &v4_config_registers; | ||
726 | family = pdev->dev.platform_data; | ||
727 | |||
728 | if (family) { | ||
729 | if (!strcmp(family, "virtex2p")) { | ||
730 | regs = &v2_config_registers; | ||
731 | } else if (!strcmp(family, "virtex4")) { | ||
732 | regs = &v4_config_registers; | ||
733 | } else if (!strcmp(family, "virtex5")) { | ||
734 | regs = &v5_config_registers; | ||
735 | } | ||
736 | } | ||
737 | |||
738 | return hwicap_setup(&pdev->dev, pdev->id, res, | ||
739 | &buffer_icap_config, regs); | ||
740 | } | ||
741 | |||
742 | static int __devexit hwicap_drv_remove(struct platform_device *pdev) | ||
743 | { | ||
744 | return hwicap_remove(&pdev->dev); | ||
745 | } | ||
746 | |||
747 | static struct platform_driver hwicap_platform_driver = { | ||
748 | .probe = hwicap_drv_probe, | ||
749 | .remove = hwicap_drv_remove, | ||
750 | .driver = { | ||
751 | .owner = THIS_MODULE, | ||
752 | .name = DRIVER_NAME, | ||
753 | }, | ||
754 | }; | ||
755 | |||
756 | /* --------------------------------------------------------------------- | ||
757 | * OF bus binding | ||
758 | */ | ||
759 | |||
760 | #if defined(CONFIG_OF) | ||
761 | static int __devinit | ||
762 | hwicap_of_probe(struct of_device *op, const struct of_device_id *match) | ||
763 | { | ||
764 | struct resource res; | ||
765 | const unsigned int *id; | ||
766 | const char *family; | ||
767 | int rc; | ||
768 | const struct hwicap_driver_config *config = match->data; | ||
769 | const struct config_registers *regs; | ||
770 | |||
771 | dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match); | ||
772 | |||
773 | rc = of_address_to_resource(op->node, 0, &res); | ||
774 | if (rc) { | ||
775 | dev_err(&op->dev, "invalid address\n"); | ||
776 | return rc; | ||
777 | } | ||
778 | |||
779 | id = of_get_property(op->node, "port-number", NULL); | ||
780 | |||
781 | /* It's most likely that we're using V4, if the family is not | ||
782 | specified */ | ||
783 | regs = &v4_config_registers; | ||
784 | family = of_get_property(op->node, "xlnx,family", NULL); | ||
785 | |||
786 | if (family) { | ||
787 | if (!strcmp(family, "virtex2p")) { | ||
788 | regs = &v2_config_registers; | ||
789 | } else if (!strcmp(family, "virtex4")) { | ||
790 | regs = &v4_config_registers; | ||
791 | } else if (!strcmp(family, "virtex5")) { | ||
792 | regs = &v5_config_registers; | ||
793 | } | ||
794 | } | ||
795 | return hwicap_setup(&op->dev, id ? *id : -1, &res, config, | ||
796 | regs); | ||
797 | } | ||
798 | |||
799 | static int __devexit hwicap_of_remove(struct of_device *op) | ||
800 | { | ||
801 | return hwicap_remove(&op->dev); | ||
802 | } | ||
803 | |||
804 | /* Match table for of_platform binding */ | ||
805 | static const struct of_device_id __devinit hwicap_of_match[] = { | ||
806 | { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config}, | ||
807 | { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config}, | ||
808 | {}, | ||
809 | }; | ||
810 | MODULE_DEVICE_TABLE(of, hwicap_of_match); | ||
811 | |||
812 | static struct of_platform_driver hwicap_of_driver = { | ||
813 | .owner = THIS_MODULE, | ||
814 | .name = DRIVER_NAME, | ||
815 | .match_table = hwicap_of_match, | ||
816 | .probe = hwicap_of_probe, | ||
817 | .remove = __devexit_p(hwicap_of_remove), | ||
818 | .driver = { | ||
819 | .name = DRIVER_NAME, | ||
820 | }, | ||
821 | }; | ||
822 | |||
823 | /* Registration helpers to keep the number of #ifdefs to a minimum */ | ||
824 | static inline int __devinit hwicap_of_register(void) | ||
825 | { | ||
826 | pr_debug("hwicap: calling of_register_platform_driver()\n"); | ||
827 | return of_register_platform_driver(&hwicap_of_driver); | ||
828 | } | ||
829 | |||
830 | static inline void __devexit hwicap_of_unregister(void) | ||
831 | { | ||
832 | of_unregister_platform_driver(&hwicap_of_driver); | ||
833 | } | ||
834 | #else /* CONFIG_OF */ | ||
835 | /* CONFIG_OF not enabled; do nothing helpers */ | ||
836 | static inline int __devinit hwicap_of_register(void) { return 0; } | ||
837 | static inline void __devexit hwicap_of_unregister(void) { } | ||
838 | #endif /* CONFIG_OF */ | ||
839 | |||
840 | static int __devinit hwicap_module_init(void) | ||
841 | { | ||
842 | dev_t devt; | ||
843 | int retval; | ||
844 | |||
845 | icap_class = class_create(THIS_MODULE, "xilinx_config"); | ||
846 | |||
847 | if (xhwicap_major) { | ||
848 | devt = MKDEV(xhwicap_major, xhwicap_minor); | ||
849 | retval = register_chrdev_region( | ||
850 | devt, | ||
851 | HWICAP_DEVICES, | ||
852 | DRIVER_NAME); | ||
853 | if (retval < 0) | ||
854 | return retval; | ||
855 | } else { | ||
856 | retval = alloc_chrdev_region(&devt, | ||
857 | xhwicap_minor, | ||
858 | HWICAP_DEVICES, | ||
859 | DRIVER_NAME); | ||
860 | if (retval < 0) | ||
861 | return retval; | ||
862 | xhwicap_major = MAJOR(devt); | ||
863 | } | ||
864 | |||
865 | retval = platform_driver_register(&hwicap_platform_driver); | ||
866 | |||
867 | if (retval) | ||
868 | goto failed1; | ||
869 | |||
870 | retval = hwicap_of_register(); | ||
871 | |||
872 | if (retval) | ||
873 | goto failed2; | ||
874 | |||
875 | return retval; | ||
876 | |||
877 | failed2: | ||
878 | platform_driver_unregister(&hwicap_platform_driver); | ||
879 | |||
880 | failed1: | ||
881 | unregister_chrdev_region(devt, HWICAP_DEVICES); | ||
882 | |||
883 | return retval; | ||
884 | } | ||
885 | |||
886 | static void __devexit hwicap_module_cleanup(void) | ||
887 | { | ||
888 | dev_t devt = MKDEV(xhwicap_major, xhwicap_minor); | ||
889 | |||
890 | class_destroy(icap_class); | ||
891 | |||
892 | platform_driver_unregister(&hwicap_platform_driver); | ||
893 | |||
894 | hwicap_of_unregister(); | ||
895 | |||
896 | unregister_chrdev_region(devt, HWICAP_DEVICES); | ||
897 | } | ||
898 | |||
899 | module_init(hwicap_module_init); | ||
900 | module_exit(hwicap_module_cleanup); | ||
901 | |||
902 | MODULE_AUTHOR("Xilinx, Inc; Xilinx Research Labs Group"); | ||
903 | MODULE_DESCRIPTION("Xilinx ICAP Port Driver"); | ||
904 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h new file mode 100644 index 000000000000..ae771cac1629 --- /dev/null +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h | |||
@@ -0,0 +1,193 @@ | |||
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Author: Xilinx, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" | ||
11 | * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND | ||
12 | * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, | ||
13 | * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, | ||
14 | * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION | ||
15 | * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, | ||
16 | * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE | ||
17 | * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY | ||
18 | * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE | ||
19 | * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR | ||
20 | * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF | ||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
22 | * FOR A PARTICULAR PURPOSE. | ||
23 | * | ||
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2003-2007 Xilinx Inc. | ||
28 | * All rights reserved. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License along | ||
31 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
32 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | * | ||
34 | *****************************************************************************/ | ||
35 | |||
36 | #ifndef XILINX_HWICAP_H_ /* prevent circular inclusions */ | ||
37 | #define XILINX_HWICAP_H_ /* by using protection macros */ | ||
38 | |||
39 | #include <linux/types.h> | ||
40 | #include <linux/cdev.h> | ||
41 | #include <linux/version.h> | ||
42 | #include <linux/platform_device.h> | ||
43 | |||
44 | #include <asm/io.h> | ||
45 | |||
46 | struct hwicap_drvdata { | ||
47 | u32 write_buffer_in_use; /* Always in [0,3] */ | ||
48 | u8 write_buffer[4]; | ||
49 | u32 read_buffer_in_use; /* Always in [0,3] */ | ||
50 | u8 read_buffer[4]; | ||
51 | u32 mem_start; /* phys. address of the control registers */ | ||
52 | u32 mem_end; /* phys. address of the control registers */ | ||
53 | u32 mem_size; | ||
54 | void __iomem *base_address;/* virt. address of the control registers */ | ||
55 | |||
56 | struct device *dev; | ||
57 | struct cdev cdev; /* Char device structure */ | ||
58 | dev_t devt; | ||
59 | |||
60 | const struct hwicap_driver_config *config; | ||
61 | const struct config_registers *config_regs; | ||
62 | void *private_data; | ||
63 | bool is_open; | ||
64 | struct semaphore sem; | ||
65 | }; | ||
66 | |||
67 | struct hwicap_driver_config { | ||
68 | int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data, | ||
69 | u32 size); | ||
70 | int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data, | ||
71 | u32 size); | ||
72 | void (*reset)(struct hwicap_drvdata *drvdata); | ||
73 | }; | ||
74 | |||
75 | /* Number of times to poll the done regsiter */ | ||
76 | #define XHI_MAX_RETRIES 10 | ||
77 | |||
78 | /************ Constant Definitions *************/ | ||
79 | |||
80 | #define XHI_PAD_FRAMES 0x1 | ||
81 | |||
82 | /* Mask for calculating configuration packet headers */ | ||
83 | #define XHI_WORD_COUNT_MASK_TYPE_1 0x7FFUL | ||
84 | #define XHI_WORD_COUNT_MASK_TYPE_2 0x1FFFFFUL | ||
85 | #define XHI_TYPE_MASK 0x7 | ||
86 | #define XHI_REGISTER_MASK 0xF | ||
87 | #define XHI_OP_MASK 0x3 | ||
88 | |||
89 | #define XHI_TYPE_SHIFT 29 | ||
90 | #define XHI_REGISTER_SHIFT 13 | ||
91 | #define XHI_OP_SHIFT 27 | ||
92 | |||
93 | #define XHI_TYPE_1 1 | ||
94 | #define XHI_TYPE_2 2 | ||
95 | #define XHI_OP_WRITE 2 | ||
96 | #define XHI_OP_READ 1 | ||
97 | |||
98 | /* Address Block Types */ | ||
99 | #define XHI_FAR_CLB_BLOCK 0 | ||
100 | #define XHI_FAR_BRAM_BLOCK 1 | ||
101 | #define XHI_FAR_BRAM_INT_BLOCK 2 | ||
102 | |||
103 | struct config_registers { | ||
104 | u32 CRC; | ||
105 | u32 FAR; | ||
106 | u32 FDRI; | ||
107 | u32 FDRO; | ||
108 | u32 CMD; | ||
109 | u32 CTL; | ||
110 | u32 MASK; | ||
111 | u32 STAT; | ||
112 | u32 LOUT; | ||
113 | u32 COR; | ||
114 | u32 MFWR; | ||
115 | u32 FLR; | ||
116 | u32 KEY; | ||
117 | u32 CBC; | ||
118 | u32 IDCODE; | ||
119 | u32 AXSS; | ||
120 | u32 C0R_1; | ||
121 | u32 CSOB; | ||
122 | u32 WBSTAR; | ||
123 | u32 TIMER; | ||
124 | u32 BOOTSTS; | ||
125 | u32 CTL_1; | ||
126 | }; | ||
127 | |||
128 | /* Configuration Commands */ | ||
129 | #define XHI_CMD_NULL 0 | ||
130 | #define XHI_CMD_WCFG 1 | ||
131 | #define XHI_CMD_MFW 2 | ||
132 | #define XHI_CMD_DGHIGH 3 | ||
133 | #define XHI_CMD_RCFG 4 | ||
134 | #define XHI_CMD_START 5 | ||
135 | #define XHI_CMD_RCAP 6 | ||
136 | #define XHI_CMD_RCRC 7 | ||
137 | #define XHI_CMD_AGHIGH 8 | ||
138 | #define XHI_CMD_SWITCH 9 | ||
139 | #define XHI_CMD_GRESTORE 10 | ||
140 | #define XHI_CMD_SHUTDOWN 11 | ||
141 | #define XHI_CMD_GCAPTURE 12 | ||
142 | #define XHI_CMD_DESYNCH 13 | ||
143 | #define XHI_CMD_IPROG 15 /* Only in Virtex5 */ | ||
144 | #define XHI_CMD_CRCC 16 /* Only in Virtex5 */ | ||
145 | #define XHI_CMD_LTIMER 17 /* Only in Virtex5 */ | ||
146 | |||
147 | /* Packet constants */ | ||
148 | #define XHI_SYNC_PACKET 0xAA995566UL | ||
149 | #define XHI_DUMMY_PACKET 0xFFFFFFFFUL | ||
150 | #define XHI_NOOP_PACKET (XHI_TYPE_1 << XHI_TYPE_SHIFT) | ||
151 | #define XHI_TYPE_2_READ ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \ | ||
152 | (XHI_OP_READ << XHI_OP_SHIFT)) | ||
153 | |||
154 | #define XHI_TYPE_2_WRITE ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \ | ||
155 | (XHI_OP_WRITE << XHI_OP_SHIFT)) | ||
156 | |||
157 | #define XHI_TYPE2_CNT_MASK 0x07FFFFFF | ||
158 | |||
159 | #define XHI_TYPE_1_PACKET_MAX_WORDS 2047UL | ||
160 | #define XHI_TYPE_1_HEADER_BYTES 4 | ||
161 | #define XHI_TYPE_2_HEADER_BYTES 8 | ||
162 | |||
163 | /* Constant to use for CRC check when CRC has been disabled */ | ||
164 | #define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL | ||
165 | |||
166 | /** | ||
167 | * hwicap_type_1_read: Generates a Type 1 read packet header. | ||
168 | * @parameter: Register is the address of the register to be read back. | ||
169 | * | ||
170 | * Generates a Type 1 read packet header, which is used to indirectly | ||
171 | * read registers in the configuration logic. This packet must then | ||
172 | * be sent through the icap device, and a return packet received with | ||
173 | * the information. | ||
174 | **/ | ||
175 | static inline u32 hwicap_type_1_read(u32 Register) | ||
176 | { | ||
177 | return (XHI_TYPE_1 << XHI_TYPE_SHIFT) | | ||
178 | (Register << XHI_REGISTER_SHIFT) | | ||
179 | (XHI_OP_READ << XHI_OP_SHIFT); | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * hwicap_type_1_write: Generates a Type 1 write packet header | ||
184 | * @parameter: Register is the address of the register to be read back. | ||
185 | **/ | ||
186 | static inline u32 hwicap_type_1_write(u32 Register) | ||
187 | { | ||
188 | return (XHI_TYPE_1 << XHI_TYPE_SHIFT) | | ||
189 | (Register << XHI_REGISTER_SHIFT) | | ||
190 | (XHI_OP_WRITE << XHI_OP_SHIFT); | ||
191 | } | ||
192 | |||
193 | #endif | ||
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7d170cd381c3..9cc25fd80b60 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1737,10 +1737,8 @@ config SC92031 | |||
1737 | 1737 | ||
1738 | config CPMAC | 1738 | config CPMAC |
1739 | tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" | 1739 | tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" |
1740 | depends on NET_ETHERNET && EXPERIMENTAL && AR7 | 1740 | depends on NET_ETHERNET && EXPERIMENTAL && AR7 && BROKEN |
1741 | select PHYLIB | 1741 | select PHYLIB |
1742 | select FIXED_PHY | ||
1743 | select FIXED_MII_100_FDX | ||
1744 | help | 1742 | help |
1745 | TI AR7 CPMAC Ethernet support | 1743 | TI AR7 CPMAC Ethernet support |
1746 | 1744 | ||
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 6ccebb830ff9..c85194f2cd2d 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c | |||
@@ -845,15 +845,6 @@ static void cpmac_adjust_link(struct net_device *dev) | |||
845 | spin_unlock(&priv->lock); | 845 | spin_unlock(&priv->lock); |
846 | } | 846 | } |
847 | 847 | ||
848 | static int cpmac_link_update(struct net_device *dev, | ||
849 | struct fixed_phy_status *status) | ||
850 | { | ||
851 | status->link = 1; | ||
852 | status->speed = 100; | ||
853 | status->duplex = 1; | ||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | static int cpmac_open(struct net_device *dev) | 848 | static int cpmac_open(struct net_device *dev) |
858 | { | 849 | { |
859 | int i, size, res; | 850 | int i, size, res; |
@@ -996,11 +987,11 @@ static int external_switch; | |||
996 | static int __devinit cpmac_probe(struct platform_device *pdev) | 987 | static int __devinit cpmac_probe(struct platform_device *pdev) |
997 | { | 988 | { |
998 | int rc, phy_id, i; | 989 | int rc, phy_id, i; |
990 | int mdio_bus_id = cpmac_mii.id; | ||
999 | struct resource *mem; | 991 | struct resource *mem; |
1000 | struct cpmac_priv *priv; | 992 | struct cpmac_priv *priv; |
1001 | struct net_device *dev; | 993 | struct net_device *dev; |
1002 | struct plat_cpmac_data *pdata; | 994 | struct plat_cpmac_data *pdata; |
1003 | struct fixed_info *fixed_phy; | ||
1004 | DECLARE_MAC_BUF(mac); | 995 | DECLARE_MAC_BUF(mac); |
1005 | 996 | ||
1006 | pdata = pdev->dev.platform_data; | 997 | pdata = pdev->dev.platform_data; |
@@ -1014,9 +1005,23 @@ static int __devinit cpmac_probe(struct platform_device *pdev) | |||
1014 | } | 1005 | } |
1015 | 1006 | ||
1016 | if (phy_id == PHY_MAX_ADDR) { | 1007 | if (phy_id == PHY_MAX_ADDR) { |
1017 | if (external_switch || dumb_switch) | 1008 | if (external_switch || dumb_switch) { |
1009 | struct fixed_phy_status status = {}; | ||
1010 | |||
1011 | mdio_bus_id = 0; | ||
1012 | |||
1013 | /* | ||
1014 | * FIXME: this should be in the platform code! | ||
1015 | * Since there is not platform code at all (that is, | ||
1016 | * no mainline users of that driver), place it here | ||
1017 | * for now. | ||
1018 | */ | ||
1018 | phy_id = 0; | 1019 | phy_id = 0; |
1019 | else { | 1020 | status.link = 1; |
1021 | status.duplex = 1; | ||
1022 | status.speed = 100; | ||
1023 | fixed_phy_add(PHY_POLL, phy_id, &status); | ||
1024 | } else { | ||
1020 | printk(KERN_ERR "cpmac: no PHY present\n"); | 1025 | printk(KERN_ERR "cpmac: no PHY present\n"); |
1021 | return -ENODEV; | 1026 | return -ENODEV; |
1022 | } | 1027 | } |
@@ -1060,32 +1065,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) | |||
1060 | priv->msg_enable = netif_msg_init(debug_level, 0xff); | 1065 | priv->msg_enable = netif_msg_init(debug_level, 0xff); |
1061 | memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); | 1066 | memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); |
1062 | 1067 | ||
1063 | if (phy_id == 31) { | 1068 | snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); |
1064 | snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, cpmac_mii.id, | ||
1065 | phy_id); | ||
1066 | } else { | ||
1067 | /* Let's try to get a free fixed phy... */ | ||
1068 | for (i = 0; i < MAX_PHY_AMNT; i++) { | ||
1069 | fixed_phy = fixed_mdio_get_phydev(i); | ||
1070 | if (!fixed_phy) | ||
1071 | continue; | ||
1072 | if (!fixed_phy->phydev->attached_dev) { | ||
1073 | strncpy(priv->phy_name, | ||
1074 | fixed_phy->phydev->dev.bus_id, | ||
1075 | BUS_ID_SIZE); | ||
1076 | fixed_mdio_set_link_update(fixed_phy->phydev, | ||
1077 | &cpmac_link_update); | ||
1078 | goto phy_found; | ||
1079 | } | ||
1080 | } | ||
1081 | if (netif_msg_drv(priv)) | ||
1082 | printk(KERN_ERR "%s: Could not find fixed PHY\n", | ||
1083 | dev->name); | ||
1084 | rc = -ENODEV; | ||
1085 | goto fail; | ||
1086 | } | ||
1087 | 1069 | ||
1088 | phy_found: | ||
1089 | priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, | 1070 | priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, |
1090 | PHY_INTERFACE_MODE_MII); | 1071 | PHY_INTERFACE_MODE_MII); |
1091 | if (IS_ERR(priv->phy)) { | 1072 | if (IS_ERR(priv->phy)) { |
diff --git a/drivers/of/base.c b/drivers/of/base.c index b306fef1ac41..80c9deca5f35 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -138,6 +138,31 @@ struct device_node *of_get_parent(const struct device_node *node) | |||
138 | EXPORT_SYMBOL(of_get_parent); | 138 | EXPORT_SYMBOL(of_get_parent); |
139 | 139 | ||
140 | /** | 140 | /** |
141 | * of_get_next_parent - Iterate to a node's parent | ||
142 | * @node: Node to get parent of | ||
143 | * | ||
144 | * This is like of_get_parent() except that it drops the | ||
145 | * refcount on the passed node, making it suitable for iterating | ||
146 | * through a node's parents. | ||
147 | * | ||
148 | * Returns a node pointer with refcount incremented, use | ||
149 | * of_node_put() on it when done. | ||
150 | */ | ||
151 | struct device_node *of_get_next_parent(struct device_node *node) | ||
152 | { | ||
153 | struct device_node *parent; | ||
154 | |||
155 | if (!node) | ||
156 | return NULL; | ||
157 | |||
158 | read_lock(&devtree_lock); | ||
159 | parent = of_node_get(node->parent); | ||
160 | of_node_put(node); | ||
161 | read_unlock(&devtree_lock); | ||
162 | return parent; | ||
163 | } | ||
164 | |||
165 | /** | ||
141 | * of_get_next_child - Iterate a node childs | 166 | * of_get_next_child - Iterate a node childs |
142 | * @node: parent node | 167 | * @node: parent node |
143 | * @prev: previous child of the parent node, or NULL to get first | 168 | * @prev: previous child of the parent node, or NULL to get first |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index b47bb2d7476a..ca09a63a64db 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -85,6 +85,15 @@ static int of_platform_device_resume(struct device * dev) | |||
85 | return error; | 85 | return error; |
86 | } | 86 | } |
87 | 87 | ||
88 | static void of_platform_device_shutdown(struct device *dev) | ||
89 | { | ||
90 | struct of_device *of_dev = to_of_device(dev); | ||
91 | struct of_platform_driver *drv = to_of_platform_driver(dev->driver); | ||
92 | |||
93 | if (dev->driver && drv->shutdown) | ||
94 | drv->shutdown(of_dev); | ||
95 | } | ||
96 | |||
88 | int of_bus_type_init(struct bus_type *bus, const char *name) | 97 | int of_bus_type_init(struct bus_type *bus, const char *name) |
89 | { | 98 | { |
90 | bus->name = name; | 99 | bus->name = name; |
@@ -93,6 +102,7 @@ int of_bus_type_init(struct bus_type *bus, const char *name) | |||
93 | bus->remove = of_platform_device_remove; | 102 | bus->remove = of_platform_device_remove; |
94 | bus->suspend = of_platform_device_suspend; | 103 | bus->suspend = of_platform_device_suspend; |
95 | bus->resume = of_platform_device_resume; | 104 | bus->resume = of_platform_device_resume; |
105 | bus->shutdown = of_platform_device_shutdown; | ||
96 | return bus_register(bus); | 106 | return bus_register(bus); |
97 | } | 107 | } |
98 | 108 | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 50d6e2214ddf..84a054d7e986 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -1142,17 +1142,17 @@ config SERIAL_SGI_L1_CONSOLE | |||
1142 | say Y. Otherwise, say N. | 1142 | say Y. Otherwise, say N. |
1143 | 1143 | ||
1144 | config SERIAL_MPC52xx | 1144 | config SERIAL_MPC52xx |
1145 | tristate "Freescale MPC52xx family PSC serial support" | 1145 | tristate "Freescale MPC52xx/MPC512x family PSC serial support" |
1146 | depends on PPC_MPC52xx | 1146 | depends on PPC_MPC52xx || PPC_MPC512x |
1147 | select SERIAL_CORE | 1147 | select SERIAL_CORE |
1148 | help | 1148 | help |
1149 | This drivers support the MPC52xx PSC serial ports. If you would | 1149 | This driver supports MPC52xx and MPC512x PSC serial ports. If you would |
1150 | like to use them, you must answer Y or M to this option. Not that | 1150 | like to use them, you must answer Y or M to this option. Note that |
1151 | for use as console, it must be included in kernel and not as a | 1151 | for use as console, it must be included in kernel and not as a |
1152 | module. | 1152 | module. |
1153 | 1153 | ||
1154 | config SERIAL_MPC52xx_CONSOLE | 1154 | config SERIAL_MPC52xx_CONSOLE |
1155 | bool "Console on a Freescale MPC52xx family PSC serial port" | 1155 | bool "Console on a Freescale MPC52xx/MPC512x family PSC serial port" |
1156 | depends on SERIAL_MPC52xx=y | 1156 | depends on SERIAL_MPC52xx=y |
1157 | select SERIAL_CORE_CONSOLE | 1157 | select SERIAL_CORE_CONSOLE |
1158 | help | 1158 | help |
@@ -1160,7 +1160,7 @@ config SERIAL_MPC52xx_CONSOLE | |||
1160 | of the Freescale MPC52xx family as a console. | 1160 | of the Freescale MPC52xx family as a console. |
1161 | 1161 | ||
1162 | config SERIAL_MPC52xx_CONSOLE_BAUD | 1162 | config SERIAL_MPC52xx_CONSOLE_BAUD |
1163 | int "Freescale MPC52xx family PSC serial port baud" | 1163 | int "Freescale MPC52xx/MPC512x family PSC serial port baud" |
1164 | depends on SERIAL_MPC52xx_CONSOLE=y | 1164 | depends on SERIAL_MPC52xx_CONSOLE=y |
1165 | default "9600" | 1165 | default "9600" |
1166 | help | 1166 | help |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 3c4d29e59b2c..a638f23c6c61 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -16,6 +16,9 @@ | |||
16 | * 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 |
17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. | 17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. |
18 | * | 18 | * |
19 | * Copyright (C) 2008 Freescale Semiconductor Inc. | ||
20 | * John Rigby <jrigby@gmail.com> | ||
21 | * Added support for MPC5121 | ||
19 | * Copyright (C) 2006 Secret Lab Technologies Ltd. | 22 | * Copyright (C) 2006 Secret Lab Technologies Ltd. |
20 | * Grant Likely <grant.likely@secretlab.ca> | 23 | * Grant Likely <grant.likely@secretlab.ca> |
21 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> | 24 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> |
@@ -67,7 +70,6 @@ | |||
67 | #include <linux/serial.h> | 70 | #include <linux/serial.h> |
68 | #include <linux/sysrq.h> | 71 | #include <linux/sysrq.h> |
69 | #include <linux/console.h> | 72 | #include <linux/console.h> |
70 | |||
71 | #include <linux/delay.h> | 73 | #include <linux/delay.h> |
72 | #include <linux/io.h> | 74 | #include <linux/io.h> |
73 | 75 | ||
@@ -79,6 +81,7 @@ | |||
79 | #endif | 81 | #endif |
80 | 82 | ||
81 | #include <asm/mpc52xx.h> | 83 | #include <asm/mpc52xx.h> |
84 | #include <asm/mpc512x.h> | ||
82 | #include <asm/mpc52xx_psc.h> | 85 | #include <asm/mpc52xx_psc.h> |
83 | 86 | ||
84 | #if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 87 | #if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
@@ -111,8 +114,8 @@ static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM]; | |||
111 | static void mpc52xx_uart_of_enumerate(void); | 114 | static void mpc52xx_uart_of_enumerate(void); |
112 | #endif | 115 | #endif |
113 | 116 | ||
117 | |||
114 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) | 118 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) |
115 | #define FIFO(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | ||
116 | 119 | ||
117 | 120 | ||
118 | /* Forward declaration of the interruption handling routine */ | 121 | /* Forward declaration of the interruption handling routine */ |
@@ -128,15 +131,301 @@ static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); | |||
128 | #define uart_console(port) (0) | 131 | #define uart_console(port) (0) |
129 | #endif | 132 | #endif |
130 | 133 | ||
134 | /* ======================================================================== */ | ||
135 | /* PSC fifo operations for isolating differences between 52xx and 512x */ | ||
136 | /* ======================================================================== */ | ||
137 | |||
138 | struct psc_ops { | ||
139 | void (*fifo_init)(struct uart_port *port); | ||
140 | int (*raw_rx_rdy)(struct uart_port *port); | ||
141 | int (*raw_tx_rdy)(struct uart_port *port); | ||
142 | int (*rx_rdy)(struct uart_port *port); | ||
143 | int (*tx_rdy)(struct uart_port *port); | ||
144 | int (*tx_empty)(struct uart_port *port); | ||
145 | void (*stop_rx)(struct uart_port *port); | ||
146 | void (*start_tx)(struct uart_port *port); | ||
147 | void (*stop_tx)(struct uart_port *port); | ||
148 | void (*rx_clr_irq)(struct uart_port *port); | ||
149 | void (*tx_clr_irq)(struct uart_port *port); | ||
150 | void (*write_char)(struct uart_port *port, unsigned char c); | ||
151 | unsigned char (*read_char)(struct uart_port *port); | ||
152 | void (*cw_disable_ints)(struct uart_port *port); | ||
153 | void (*cw_restore_ints)(struct uart_port *port); | ||
154 | unsigned long (*getuartclk)(void *p); | ||
155 | }; | ||
156 | |||
157 | #ifdef CONFIG_PPC_MPC52xx | ||
158 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | ||
159 | static void mpc52xx_psc_fifo_init(struct uart_port *port) | ||
160 | { | ||
161 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
162 | struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port); | ||
163 | |||
164 | /* /32 prescaler */ | ||
165 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); | ||
166 | |||
167 | out_8(&fifo->rfcntl, 0x00); | ||
168 | out_be16(&fifo->rfalarm, 0x1ff); | ||
169 | out_8(&fifo->tfcntl, 0x07); | ||
170 | out_be16(&fifo->tfalarm, 0x80); | ||
171 | |||
172 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | ||
173 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
174 | } | ||
175 | |||
176 | static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port) | ||
177 | { | ||
178 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
179 | & MPC52xx_PSC_SR_RXRDY; | ||
180 | } | ||
181 | |||
182 | static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port) | ||
183 | { | ||
184 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
185 | & MPC52xx_PSC_SR_TXRDY; | ||
186 | } | ||
187 | |||
188 | |||
189 | static int mpc52xx_psc_rx_rdy(struct uart_port *port) | ||
190 | { | ||
191 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
192 | & port->read_status_mask | ||
193 | & MPC52xx_PSC_IMR_RXRDY; | ||
194 | } | ||
195 | |||
196 | static int mpc52xx_psc_tx_rdy(struct uart_port *port) | ||
197 | { | ||
198 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
199 | & port->read_status_mask | ||
200 | & MPC52xx_PSC_IMR_TXRDY; | ||
201 | } | ||
202 | |||
203 | static int mpc52xx_psc_tx_empty(struct uart_port *port) | ||
204 | { | ||
205 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
206 | & MPC52xx_PSC_SR_TXEMP; | ||
207 | } | ||
208 | |||
209 | static void mpc52xx_psc_start_tx(struct uart_port *port) | ||
210 | { | ||
211 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | ||
212 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
213 | } | ||
214 | |||
215 | static void mpc52xx_psc_stop_tx(struct uart_port *port) | ||
216 | { | ||
217 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | ||
218 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
219 | } | ||
220 | |||
221 | static void mpc52xx_psc_stop_rx(struct uart_port *port) | ||
222 | { | ||
223 | port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY; | ||
224 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
225 | } | ||
226 | |||
227 | static void mpc52xx_psc_rx_clr_irq(struct uart_port *port) | ||
228 | { | ||
229 | } | ||
230 | |||
231 | static void mpc52xx_psc_tx_clr_irq(struct uart_port *port) | ||
232 | { | ||
233 | } | ||
234 | |||
235 | static void mpc52xx_psc_write_char(struct uart_port *port, unsigned char c) | ||
236 | { | ||
237 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, c); | ||
238 | } | ||
239 | |||
240 | static unsigned char mpc52xx_psc_read_char(struct uart_port *port) | ||
241 | { | ||
242 | return in_8(&PSC(port)->mpc52xx_psc_buffer_8); | ||
243 | } | ||
244 | |||
245 | static void mpc52xx_psc_cw_disable_ints(struct uart_port *port) | ||
246 | { | ||
247 | out_be16(&PSC(port)->mpc52xx_psc_imr, 0); | ||
248 | } | ||
249 | |||
250 | static void mpc52xx_psc_cw_restore_ints(struct uart_port *port) | ||
251 | { | ||
252 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
253 | } | ||
254 | |||
255 | /* Search for bus-frequency property in this node or a parent */ | ||
256 | static unsigned long mpc52xx_getuartclk(void *p) | ||
257 | { | ||
131 | #if defined(CONFIG_PPC_MERGE) | 258 | #if defined(CONFIG_PPC_MERGE) |
132 | static struct of_device_id mpc52xx_uart_of_match[] = { | 259 | /* |
133 | { .type = "serial", .compatible = "fsl,mpc5200-psc-uart", }, | 260 | * 5200 UARTs have a / 32 prescaler |
134 | { .type = "serial", .compatible = "mpc5200-psc-uart", }, /* lite5200 */ | 261 | * but the generic serial code assumes 16 |
135 | { .type = "serial", .compatible = "mpc5200-serial", }, /* efika */ | 262 | * so return ipb freq / 2 |
136 | {}, | 263 | */ |
264 | return mpc52xx_find_ipb_freq(p) / 2; | ||
265 | #else | ||
266 | pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n"); | ||
267 | return NULL; | ||
268 | #endif | ||
269 | } | ||
270 | |||
271 | static struct psc_ops mpc52xx_psc_ops = { | ||
272 | .fifo_init = mpc52xx_psc_fifo_init, | ||
273 | .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, | ||
274 | .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, | ||
275 | .rx_rdy = mpc52xx_psc_rx_rdy, | ||
276 | .tx_rdy = mpc52xx_psc_tx_rdy, | ||
277 | .tx_empty = mpc52xx_psc_tx_empty, | ||
278 | .stop_rx = mpc52xx_psc_stop_rx, | ||
279 | .start_tx = mpc52xx_psc_start_tx, | ||
280 | .stop_tx = mpc52xx_psc_stop_tx, | ||
281 | .rx_clr_irq = mpc52xx_psc_rx_clr_irq, | ||
282 | .tx_clr_irq = mpc52xx_psc_tx_clr_irq, | ||
283 | .write_char = mpc52xx_psc_write_char, | ||
284 | .read_char = mpc52xx_psc_read_char, | ||
285 | .cw_disable_ints = mpc52xx_psc_cw_disable_ints, | ||
286 | .cw_restore_ints = mpc52xx_psc_cw_restore_ints, | ||
287 | .getuartclk = mpc52xx_getuartclk, | ||
288 | }; | ||
289 | |||
290 | #endif /* CONFIG_MPC52xx */ | ||
291 | |||
292 | #ifdef CONFIG_PPC_MPC512x | ||
293 | #define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1)) | ||
294 | static void mpc512x_psc_fifo_init(struct uart_port *port) | ||
295 | { | ||
296 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
297 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
298 | out_be32(&FIFO_512x(port)->txalarm, 1); | ||
299 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
300 | |||
301 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
302 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
303 | out_be32(&FIFO_512x(port)->rxalarm, 1); | ||
304 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
305 | |||
306 | out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM); | ||
307 | out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM); | ||
308 | } | ||
309 | |||
310 | static int mpc512x_psc_raw_rx_rdy(struct uart_port *port) | ||
311 | { | ||
312 | return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY); | ||
313 | } | ||
314 | |||
315 | static int mpc512x_psc_raw_tx_rdy(struct uart_port *port) | ||
316 | { | ||
317 | return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL); | ||
318 | } | ||
319 | |||
320 | static int mpc512x_psc_rx_rdy(struct uart_port *port) | ||
321 | { | ||
322 | return in_be32(&FIFO_512x(port)->rxsr) | ||
323 | & in_be32(&FIFO_512x(port)->rximr) | ||
324 | & MPC512x_PSC_FIFO_ALARM; | ||
325 | } | ||
326 | |||
327 | static int mpc512x_psc_tx_rdy(struct uart_port *port) | ||
328 | { | ||
329 | return in_be32(&FIFO_512x(port)->txsr) | ||
330 | & in_be32(&FIFO_512x(port)->tximr) | ||
331 | & MPC512x_PSC_FIFO_ALARM; | ||
332 | } | ||
333 | |||
334 | static int mpc512x_psc_tx_empty(struct uart_port *port) | ||
335 | { | ||
336 | return in_be32(&FIFO_512x(port)->txsr) | ||
337 | & MPC512x_PSC_FIFO_EMPTY; | ||
338 | } | ||
339 | |||
340 | static void mpc512x_psc_stop_rx(struct uart_port *port) | ||
341 | { | ||
342 | unsigned long rx_fifo_imr; | ||
343 | |||
344 | rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr); | ||
345 | rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
346 | out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr); | ||
347 | } | ||
348 | |||
349 | static void mpc512x_psc_start_tx(struct uart_port *port) | ||
350 | { | ||
351 | unsigned long tx_fifo_imr; | ||
352 | |||
353 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
354 | tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM; | ||
355 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
356 | } | ||
357 | |||
358 | static void mpc512x_psc_stop_tx(struct uart_port *port) | ||
359 | { | ||
360 | unsigned long tx_fifo_imr; | ||
361 | |||
362 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
363 | tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
364 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
365 | } | ||
366 | |||
367 | static void mpc512x_psc_rx_clr_irq(struct uart_port *port) | ||
368 | { | ||
369 | out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr)); | ||
370 | } | ||
371 | |||
372 | static void mpc512x_psc_tx_clr_irq(struct uart_port *port) | ||
373 | { | ||
374 | out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr)); | ||
375 | } | ||
376 | |||
377 | static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c) | ||
378 | { | ||
379 | out_8(&FIFO_512x(port)->txdata_8, c); | ||
380 | } | ||
381 | |||
382 | static unsigned char mpc512x_psc_read_char(struct uart_port *port) | ||
383 | { | ||
384 | return in_8(&FIFO_512x(port)->rxdata_8); | ||
385 | } | ||
386 | |||
387 | static void mpc512x_psc_cw_disable_ints(struct uart_port *port) | ||
388 | { | ||
389 | port->read_status_mask = | ||
390 | in_be32(&FIFO_512x(port)->tximr) << 16 | | ||
391 | in_be32(&FIFO_512x(port)->rximr); | ||
392 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
393 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
394 | } | ||
395 | |||
396 | static void mpc512x_psc_cw_restore_ints(struct uart_port *port) | ||
397 | { | ||
398 | out_be32(&FIFO_512x(port)->tximr, | ||
399 | (port->read_status_mask >> 16) & 0x7f); | ||
400 | out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f); | ||
401 | } | ||
402 | |||
403 | static unsigned long mpc512x_getuartclk(void *p) | ||
404 | { | ||
405 | return mpc512x_find_ips_freq(p); | ||
406 | } | ||
407 | |||
408 | static struct psc_ops mpc512x_psc_ops = { | ||
409 | .fifo_init = mpc512x_psc_fifo_init, | ||
410 | .raw_rx_rdy = mpc512x_psc_raw_rx_rdy, | ||
411 | .raw_tx_rdy = mpc512x_psc_raw_tx_rdy, | ||
412 | .rx_rdy = mpc512x_psc_rx_rdy, | ||
413 | .tx_rdy = mpc512x_psc_tx_rdy, | ||
414 | .tx_empty = mpc512x_psc_tx_empty, | ||
415 | .stop_rx = mpc512x_psc_stop_rx, | ||
416 | .start_tx = mpc512x_psc_start_tx, | ||
417 | .stop_tx = mpc512x_psc_stop_tx, | ||
418 | .rx_clr_irq = mpc512x_psc_rx_clr_irq, | ||
419 | .tx_clr_irq = mpc512x_psc_tx_clr_irq, | ||
420 | .write_char = mpc512x_psc_write_char, | ||
421 | .read_char = mpc512x_psc_read_char, | ||
422 | .cw_disable_ints = mpc512x_psc_cw_disable_ints, | ||
423 | .cw_restore_ints = mpc512x_psc_cw_restore_ints, | ||
424 | .getuartclk = mpc512x_getuartclk, | ||
137 | }; | 425 | }; |
138 | #endif | 426 | #endif |
139 | 427 | ||
428 | static struct psc_ops *psc_ops; | ||
140 | 429 | ||
141 | /* ======================================================================== */ | 430 | /* ======================================================================== */ |
142 | /* UART operations */ | 431 | /* UART operations */ |
@@ -145,8 +434,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
145 | static unsigned int | 434 | static unsigned int |
146 | mpc52xx_uart_tx_empty(struct uart_port *port) | 435 | mpc52xx_uart_tx_empty(struct uart_port *port) |
147 | { | 436 | { |
148 | int status = in_be16(&PSC(port)->mpc52xx_psc_status); | 437 | return psc_ops->tx_empty(port) ? TIOCSER_TEMT : 0; |
149 | return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0; | ||
150 | } | 438 | } |
151 | 439 | ||
152 | static void | 440 | static void |
@@ -166,16 +454,14 @@ static void | |||
166 | mpc52xx_uart_stop_tx(struct uart_port *port) | 454 | mpc52xx_uart_stop_tx(struct uart_port *port) |
167 | { | 455 | { |
168 | /* port->lock taken by caller */ | 456 | /* port->lock taken by caller */ |
169 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | 457 | psc_ops->stop_tx(port); |
170 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
171 | } | 458 | } |
172 | 459 | ||
173 | static void | 460 | static void |
174 | mpc52xx_uart_start_tx(struct uart_port *port) | 461 | mpc52xx_uart_start_tx(struct uart_port *port) |
175 | { | 462 | { |
176 | /* port->lock taken by caller */ | 463 | /* port->lock taken by caller */ |
177 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 464 | psc_ops->start_tx(port); |
178 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
179 | } | 465 | } |
180 | 466 | ||
181 | static void | 467 | static void |
@@ -188,8 +474,7 @@ mpc52xx_uart_send_xchar(struct uart_port *port, char ch) | |||
188 | if (ch) { | 474 | if (ch) { |
189 | /* Make sure tx interrupts are on */ | 475 | /* Make sure tx interrupts are on */ |
190 | /* Truly necessary ??? They should be anyway */ | 476 | /* Truly necessary ??? They should be anyway */ |
191 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 477 | psc_ops->start_tx(port); |
192 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
193 | } | 478 | } |
194 | 479 | ||
195 | spin_unlock_irqrestore(&port->lock, flags); | 480 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -199,8 +484,7 @@ static void | |||
199 | mpc52xx_uart_stop_rx(struct uart_port *port) | 484 | mpc52xx_uart_stop_rx(struct uart_port *port) |
200 | { | 485 | { |
201 | /* port->lock taken by caller */ | 486 | /* port->lock taken by caller */ |
202 | port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY; | 487 | psc_ops->stop_rx(port); |
203 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
204 | } | 488 | } |
205 | 489 | ||
206 | static void | 490 | static void |
@@ -227,12 +511,12 @@ static int | |||
227 | mpc52xx_uart_startup(struct uart_port *port) | 511 | mpc52xx_uart_startup(struct uart_port *port) |
228 | { | 512 | { |
229 | struct mpc52xx_psc __iomem *psc = PSC(port); | 513 | struct mpc52xx_psc __iomem *psc = PSC(port); |
230 | struct mpc52xx_psc_fifo __iomem *fifo = FIFO(port); | ||
231 | int ret; | 514 | int ret; |
232 | 515 | ||
233 | /* Request IRQ */ | 516 | /* Request IRQ */ |
234 | ret = request_irq(port->irq, mpc52xx_uart_int, | 517 | ret = request_irq(port->irq, mpc52xx_uart_int, |
235 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "mpc52xx_psc_uart", port); | 518 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED, |
519 | "mpc52xx_psc_uart", port); | ||
236 | if (ret) | 520 | if (ret) |
237 | return ret; | 521 | return ret; |
238 | 522 | ||
@@ -242,15 +526,7 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
242 | 526 | ||
243 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ | 527 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ |
244 | 528 | ||
245 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */ | 529 | psc_ops->fifo_init(port); |
246 | |||
247 | out_8(&fifo->rfcntl, 0x00); | ||
248 | out_be16(&fifo->rfalarm, 0x1ff); | ||
249 | out_8(&fifo->tfcntl, 0x07); | ||
250 | out_be16(&fifo->tfalarm, 0x80); | ||
251 | |||
252 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | ||
253 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
254 | 530 | ||
255 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 531 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); |
256 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 532 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); |
@@ -333,8 +609,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
333 | * boot for the console, all stuff is not yet ready to receive at that | 609 | * boot for the console, all stuff is not yet ready to receive at that |
334 | * time and that just makes the kernel oops */ | 610 | * time and that just makes the kernel oops */ |
335 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ | 611 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ |
336 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 612 | while (!mpc52xx_uart_tx_empty(port) && --j) |
337 | --j) | ||
338 | udelay(1); | 613 | udelay(1); |
339 | 614 | ||
340 | if (!j) | 615 | if (!j) |
@@ -462,11 +737,9 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
462 | unsigned short status; | 737 | unsigned short status; |
463 | 738 | ||
464 | /* While we can read, do so ! */ | 739 | /* While we can read, do so ! */ |
465 | while ((status = in_be16(&PSC(port)->mpc52xx_psc_status)) & | 740 | while (psc_ops->raw_rx_rdy(port)) { |
466 | MPC52xx_PSC_SR_RXRDY) { | ||
467 | |||
468 | /* Get the char */ | 741 | /* Get the char */ |
469 | ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8); | 742 | ch = psc_ops->read_char(port); |
470 | 743 | ||
471 | /* Handle sysreq char */ | 744 | /* Handle sysreq char */ |
472 | #ifdef SUPPORT_SYSRQ | 745 | #ifdef SUPPORT_SYSRQ |
@@ -481,6 +754,8 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
481 | flag = TTY_NORMAL; | 754 | flag = TTY_NORMAL; |
482 | port->icount.rx++; | 755 | port->icount.rx++; |
483 | 756 | ||
757 | status = in_be16(&PSC(port)->mpc52xx_psc_status); | ||
758 | |||
484 | if (status & (MPC52xx_PSC_SR_PE | | 759 | if (status & (MPC52xx_PSC_SR_PE | |
485 | MPC52xx_PSC_SR_FE | | 760 | MPC52xx_PSC_SR_FE | |
486 | MPC52xx_PSC_SR_RB)) { | 761 | MPC52xx_PSC_SR_RB)) { |
@@ -510,7 +785,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
510 | 785 | ||
511 | tty_flip_buffer_push(tty); | 786 | tty_flip_buffer_push(tty); |
512 | 787 | ||
513 | return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY; | 788 | return psc_ops->raw_rx_rdy(port); |
514 | } | 789 | } |
515 | 790 | ||
516 | static inline int | 791 | static inline int |
@@ -520,7 +795,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
520 | 795 | ||
521 | /* Process out of band chars */ | 796 | /* Process out of band chars */ |
522 | if (port->x_char) { | 797 | if (port->x_char) { |
523 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char); | 798 | psc_ops->write_char(port, port->x_char); |
524 | port->icount.tx++; | 799 | port->icount.tx++; |
525 | port->x_char = 0; | 800 | port->x_char = 0; |
526 | return 1; | 801 | return 1; |
@@ -533,8 +808,8 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
533 | } | 808 | } |
534 | 809 | ||
535 | /* Send chars */ | 810 | /* Send chars */ |
536 | while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) { | 811 | while (psc_ops->raw_tx_rdy(port)) { |
537 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]); | 812 | psc_ops->write_char(port, xmit->buf[xmit->tail]); |
538 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 813 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
539 | port->icount.tx++; | 814 | port->icount.tx++; |
540 | if (uart_circ_empty(xmit)) | 815 | if (uart_circ_empty(xmit)) |
@@ -560,7 +835,6 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
560 | struct uart_port *port = dev_id; | 835 | struct uart_port *port = dev_id; |
561 | unsigned long pass = ISR_PASS_LIMIT; | 836 | unsigned long pass = ISR_PASS_LIMIT; |
562 | unsigned int keepgoing; | 837 | unsigned int keepgoing; |
563 | unsigned short status; | ||
564 | 838 | ||
565 | spin_lock(&port->lock); | 839 | spin_lock(&port->lock); |
566 | 840 | ||
@@ -569,18 +843,12 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
569 | /* If we don't find anything to do, we stop */ | 843 | /* If we don't find anything to do, we stop */ |
570 | keepgoing = 0; | 844 | keepgoing = 0; |
571 | 845 | ||
572 | /* Read status */ | 846 | psc_ops->rx_clr_irq(port); |
573 | status = in_be16(&PSC(port)->mpc52xx_psc_isr); | 847 | if (psc_ops->rx_rdy(port)) |
574 | status &= port->read_status_mask; | ||
575 | |||
576 | /* Do we need to receive chars ? */ | ||
577 | /* For this RX interrupts must be on and some chars waiting */ | ||
578 | if (status & MPC52xx_PSC_IMR_RXRDY) | ||
579 | keepgoing |= mpc52xx_uart_int_rx_chars(port); | 848 | keepgoing |= mpc52xx_uart_int_rx_chars(port); |
580 | 849 | ||
581 | /* Do we need to send chars ? */ | 850 | psc_ops->tx_clr_irq(port); |
582 | /* For this, TX must be ready and TX interrupt enabled */ | 851 | if (psc_ops->tx_rdy(port)) |
583 | if (status & MPC52xx_PSC_IMR_TXRDY) | ||
584 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 852 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
585 | 853 | ||
586 | /* Limit number of iteration */ | 854 | /* Limit number of iteration */ |
@@ -647,36 +915,33 @@ static void | |||
647 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | 915 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) |
648 | { | 916 | { |
649 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | 917 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; |
650 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
651 | unsigned int i, j; | 918 | unsigned int i, j; |
652 | 919 | ||
653 | /* Disable interrupts */ | 920 | /* Disable interrupts */ |
654 | out_be16(&psc->mpc52xx_psc_imr, 0); | 921 | psc_ops->cw_disable_ints(port); |
655 | 922 | ||
656 | /* Wait the TX buffer to be empty */ | 923 | /* Wait the TX buffer to be empty */ |
657 | j = 5000000; /* Maximum wait */ | 924 | j = 5000000; /* Maximum wait */ |
658 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 925 | while (!mpc52xx_uart_tx_empty(port) && --j) |
659 | --j) | ||
660 | udelay(1); | 926 | udelay(1); |
661 | 927 | ||
662 | /* Write all the chars */ | 928 | /* Write all the chars */ |
663 | for (i = 0; i < count; i++, s++) { | 929 | for (i = 0; i < count; i++, s++) { |
664 | /* Line return handling */ | 930 | /* Line return handling */ |
665 | if (*s == '\n') | 931 | if (*s == '\n') |
666 | out_8(&psc->mpc52xx_psc_buffer_8, '\r'); | 932 | psc_ops->write_char(port, '\r'); |
667 | 933 | ||
668 | /* Send the char */ | 934 | /* Send the char */ |
669 | out_8(&psc->mpc52xx_psc_buffer_8, *s); | 935 | psc_ops->write_char(port, *s); |
670 | 936 | ||
671 | /* Wait the TX buffer to be empty */ | 937 | /* Wait the TX buffer to be empty */ |
672 | j = 20000; /* Maximum wait */ | 938 | j = 20000; /* Maximum wait */ |
673 | while (!(in_be16(&psc->mpc52xx_psc_status) & | 939 | while (!mpc52xx_uart_tx_empty(port) && --j) |
674 | MPC52xx_PSC_SR_TXEMP) && --j) | ||
675 | udelay(1); | 940 | udelay(1); |
676 | } | 941 | } |
677 | 942 | ||
678 | /* Restore interrupt state */ | 943 | /* Restore interrupt state */ |
679 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 944 | psc_ops->cw_restore_ints(port); |
680 | } | 945 | } |
681 | 946 | ||
682 | #if !defined(CONFIG_PPC_MERGE) | 947 | #if !defined(CONFIG_PPC_MERGE) |
@@ -721,7 +986,7 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
721 | { | 986 | { |
722 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | 987 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; |
723 | struct device_node *np = mpc52xx_uart_nodes[co->index]; | 988 | struct device_node *np = mpc52xx_uart_nodes[co->index]; |
724 | unsigned int ipb_freq; | 989 | unsigned int uartclk; |
725 | struct resource res; | 990 | struct resource res; |
726 | int ret; | 991 | int ret; |
727 | 992 | ||
@@ -753,17 +1018,16 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
753 | return ret; | 1018 | return ret; |
754 | } | 1019 | } |
755 | 1020 | ||
756 | /* Search for bus-frequency property in this node or a parent */ | 1021 | uartclk = psc_ops->getuartclk(np); |
757 | ipb_freq = mpc52xx_find_ipb_freq(np); | 1022 | if (uartclk == 0) { |
758 | if (ipb_freq == 0) { | 1023 | pr_debug("Could not find uart clock frequency!\n"); |
759 | pr_debug("Could not find IPB bus frequency!\n"); | ||
760 | return -EINVAL; | 1024 | return -EINVAL; |
761 | } | 1025 | } |
762 | 1026 | ||
763 | /* Basic port init. Needed since we use some uart_??? func before | 1027 | /* Basic port init. Needed since we use some uart_??? func before |
764 | * real init for early access */ | 1028 | * real init for early access */ |
765 | spin_lock_init(&port->lock); | 1029 | spin_lock_init(&port->lock); |
766 | port->uartclk = ipb_freq / 2; | 1030 | port->uartclk = uartclk; |
767 | port->ops = &mpc52xx_uart_ops; | 1031 | port->ops = &mpc52xx_uart_ops; |
768 | port->mapbase = res.start; | 1032 | port->mapbase = res.start; |
769 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); | 1033 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); |
@@ -945,11 +1209,25 @@ static struct platform_driver mpc52xx_uart_platform_driver = { | |||
945 | /* OF Platform Driver */ | 1209 | /* OF Platform Driver */ |
946 | /* ======================================================================== */ | 1210 | /* ======================================================================== */ |
947 | 1211 | ||
1212 | static struct of_device_id mpc52xx_uart_of_match[] = { | ||
1213 | #ifdef CONFIG_PPC_MPC52xx | ||
1214 | { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, | ||
1215 | /* binding used by old lite5200 device trees: */ | ||
1216 | { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, | ||
1217 | /* binding used by efika: */ | ||
1218 | { .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, }, | ||
1219 | #endif | ||
1220 | #ifdef CONFIG_PPC_MPC512x | ||
1221 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, | ||
1222 | {}, | ||
1223 | #endif | ||
1224 | }; | ||
1225 | |||
948 | static int __devinit | 1226 | static int __devinit |
949 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | 1227 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) |
950 | { | 1228 | { |
951 | int idx = -1; | 1229 | int idx = -1; |
952 | unsigned int ipb_freq; | 1230 | unsigned int uartclk; |
953 | struct uart_port *port = NULL; | 1231 | struct uart_port *port = NULL; |
954 | struct resource res; | 1232 | struct resource res; |
955 | int ret; | 1233 | int ret; |
@@ -965,10 +1243,9 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
965 | pr_debug("Found %s assigned to ttyPSC%x\n", | 1243 | pr_debug("Found %s assigned to ttyPSC%x\n", |
966 | mpc52xx_uart_nodes[idx]->full_name, idx); | 1244 | mpc52xx_uart_nodes[idx]->full_name, idx); |
967 | 1245 | ||
968 | /* Search for bus-frequency property in this node or a parent */ | 1246 | uartclk = psc_ops->getuartclk(op->node); |
969 | ipb_freq = mpc52xx_find_ipb_freq(op->node); | 1247 | if (uartclk == 0) { |
970 | if (ipb_freq == 0) { | 1248 | dev_dbg(&op->dev, "Could not find uart clock frequency!\n"); |
971 | dev_dbg(&op->dev, "Could not find IPB bus frequency!\n"); | ||
972 | return -EINVAL; | 1249 | return -EINVAL; |
973 | } | 1250 | } |
974 | 1251 | ||
@@ -976,7 +1253,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
976 | port = &mpc52xx_uart_ports[idx]; | 1253 | port = &mpc52xx_uart_ports[idx]; |
977 | 1254 | ||
978 | spin_lock_init(&port->lock); | 1255 | spin_lock_init(&port->lock); |
979 | port->uartclk = ipb_freq / 2; | 1256 | port->uartclk = uartclk; |
980 | port->fifosize = 512; | 1257 | port->fifosize = 512; |
981 | port->iotype = UPIO_MEM; | 1258 | port->iotype = UPIO_MEM; |
982 | port->flags = UPF_BOOT_AUTOCONF | | 1259 | port->flags = UPF_BOOT_AUTOCONF | |
@@ -1080,15 +1357,19 @@ mpc52xx_uart_of_enumerate(void) | |||
1080 | static int enum_done; | 1357 | static int enum_done; |
1081 | struct device_node *np; | 1358 | struct device_node *np; |
1082 | const unsigned int *devno; | 1359 | const unsigned int *devno; |
1360 | const struct of_device_id *match; | ||
1083 | int i; | 1361 | int i; |
1084 | 1362 | ||
1085 | if (enum_done) | 1363 | if (enum_done) |
1086 | return; | 1364 | return; |
1087 | 1365 | ||
1088 | for_each_node_by_type(np, "serial") { | 1366 | for_each_node_by_type(np, "serial") { |
1089 | if (!of_match_node(mpc52xx_uart_of_match, np)) | 1367 | match = of_match_node(mpc52xx_uart_of_match, np); |
1368 | if (!match) | ||
1090 | continue; | 1369 | continue; |
1091 | 1370 | ||
1371 | psc_ops = match->data; | ||
1372 | |||
1092 | /* Is a particular device number requested? */ | 1373 | /* Is a particular device number requested? */ |
1093 | devno = of_get_property(np, "port-number", NULL); | 1374 | devno = of_get_property(np, "port-number", NULL); |
1094 | mpc52xx_uart_of_assign(np, devno ? *devno : -1); | 1375 | mpc52xx_uart_of_assign(np, devno ? *devno : -1); |
@@ -1149,6 +1430,7 @@ mpc52xx_uart_init(void) | |||
1149 | return ret; | 1430 | return ret; |
1150 | } | 1431 | } |
1151 | #else | 1432 | #else |
1433 | psc_ops = &mpc52xx_psc_ops; | ||
1152 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); | 1434 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); |
1153 | if (ret) { | 1435 | if (ret) { |
1154 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", | 1436 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", |
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index bacf68dca01a..4e06ab6bcb6e 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c | |||
@@ -17,10 +17,21 @@ | |||
17 | #include <linux/tty.h> | 17 | #include <linux/tty.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/init.h> | ||
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | #if defined(CONFIG_OF) | 22 | #if defined(CONFIG_OF) |
23 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
23 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
26 | |||
27 | /* Match table for of_platform binding */ | ||
28 | static struct of_device_id ulite_of_match[] __devinitdata = { | ||
29 | { .compatible = "xlnx,opb-uartlite-1.00.b", }, | ||
30 | { .compatible = "xlnx,xps-uartlite-1.00.a", }, | ||
31 | {} | ||
32 | }; | ||
33 | MODULE_DEVICE_TABLE(of, ulite_of_match); | ||
34 | |||
24 | #endif | 35 | #endif |
25 | 36 | ||
26 | #define ULITE_NAME "ttyUL" | 37 | #define ULITE_NAME "ttyUL" |
@@ -275,6 +286,9 @@ static void ulite_release_port(struct uart_port *port) | |||
275 | 286 | ||
276 | static int ulite_request_port(struct uart_port *port) | 287 | static int ulite_request_port(struct uart_port *port) |
277 | { | 288 | { |
289 | pr_debug("ulite console: port=%p; port->mapbase=%x\n", | ||
290 | port, port->mapbase); | ||
291 | |||
278 | if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) { | 292 | if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) { |
279 | dev_err(port->dev, "Memory region busy\n"); | 293 | dev_err(port->dev, "Memory region busy\n"); |
280 | return -EBUSY; | 294 | return -EBUSY; |
@@ -375,32 +389,6 @@ static void ulite_console_write(struct console *co, const char *s, | |||
375 | spin_unlock_irqrestore(&port->lock, flags); | 389 | spin_unlock_irqrestore(&port->lock, flags); |
376 | } | 390 | } |
377 | 391 | ||
378 | #if defined(CONFIG_OF) | ||
379 | static inline void __init ulite_console_of_find_device(int id) | ||
380 | { | ||
381 | struct device_node *np; | ||
382 | struct resource res; | ||
383 | const unsigned int *of_id; | ||
384 | int rc; | ||
385 | |||
386 | for_each_compatible_node(np, NULL, "xilinx,uartlite") { | ||
387 | of_id = of_get_property(np, "port-number", NULL); | ||
388 | if ((!of_id) || (*of_id != id)) | ||
389 | continue; | ||
390 | |||
391 | rc = of_address_to_resource(np, 0, &res); | ||
392 | if (rc) | ||
393 | continue; | ||
394 | |||
395 | ulite_ports[id].mapbase = res.start; | ||
396 | of_node_put(np); | ||
397 | return; | ||
398 | } | ||
399 | } | ||
400 | #else /* CONFIG_OF */ | ||
401 | static inline void __init ulite_console_of_find_device(int id) { /* do nothing */ } | ||
402 | #endif /* CONFIG_OF */ | ||
403 | |||
404 | static int __init ulite_console_setup(struct console *co, char *options) | 392 | static int __init ulite_console_setup(struct console *co, char *options) |
405 | { | 393 | { |
406 | struct uart_port *port; | 394 | struct uart_port *port; |
@@ -414,11 +402,7 @@ static int __init ulite_console_setup(struct console *co, char *options) | |||
414 | 402 | ||
415 | port = &ulite_ports[co->index]; | 403 | port = &ulite_ports[co->index]; |
416 | 404 | ||
417 | /* Check if it is an OF device */ | 405 | /* Has the device been initialized yet? */ |
418 | if (!port->mapbase) | ||
419 | ulite_console_of_find_device(co->index); | ||
420 | |||
421 | /* Do we have a device now? */ | ||
422 | if (!port->mapbase) { | 406 | if (!port->mapbase) { |
423 | pr_debug("console on ttyUL%i not present\n", co->index); | 407 | pr_debug("console on ttyUL%i not present\n", co->index); |
424 | return -ENODEV; | 408 | return -ENODEV; |
@@ -617,13 +601,6 @@ static int __devexit ulite_of_remove(struct of_device *op) | |||
617 | return ulite_release(&op->dev); | 601 | return ulite_release(&op->dev); |
618 | } | 602 | } |
619 | 603 | ||
620 | /* Match table for of_platform binding */ | ||
621 | static struct of_device_id __devinit ulite_of_match[] = { | ||
622 | { .type = "serial", .compatible = "xilinx,uartlite", }, | ||
623 | {}, | ||
624 | }; | ||
625 | MODULE_DEVICE_TABLE(of, ulite_of_match); | ||
626 | |||
627 | static struct of_platform_driver ulite_of_driver = { | 604 | static struct of_platform_driver ulite_of_driver = { |
628 | .owner = THIS_MODULE, | 605 | .owner = THIS_MODULE, |
629 | .name = "uartlite", | 606 | .name = "uartlite", |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index e38d3b7c3ad7..7b3a8423f485 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -459,8 +459,8 @@ static int __devexit xilinxfb_of_remove(struct of_device *op) | |||
459 | } | 459 | } |
460 | 460 | ||
461 | /* Match table for of_platform binding */ | 461 | /* Match table for of_platform binding */ |
462 | static struct of_device_id __devinit xilinxfb_of_match[] = { | 462 | static struct of_device_id xilinxfb_of_match[] __devinitdata = { |
463 | { .compatible = "xilinx,ml300-fb", }, | 463 | { .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", }, |
464 | {}, | 464 | {}, |
465 | }; | 465 | }; |
466 | MODULE_DEVICE_TABLE(of, xilinxfb_of_match); | 466 | MODULE_DEVICE_TABLE(of, xilinxfb_of_match); |
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 528ef183c221..1e79673b7316 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h | |||
@@ -46,7 +46,7 @@ enum powerpc_oprofile_type { | |||
46 | PPC_OPROFILE_RS64 = 1, | 46 | PPC_OPROFILE_RS64 = 1, |
47 | PPC_OPROFILE_POWER4 = 2, | 47 | PPC_OPROFILE_POWER4 = 2, |
48 | PPC_OPROFILE_G4 = 3, | 48 | PPC_OPROFILE_G4 = 3, |
49 | PPC_OPROFILE_BOOKE = 4, | 49 | PPC_OPROFILE_FSL_EMB = 4, |
50 | PPC_OPROFILE_CELL = 5, | 50 | PPC_OPROFILE_CELL = 5, |
51 | PPC_OPROFILE_PA6T = 6, | 51 | PPC_OPROFILE_PA6T = 6, |
52 | }; | 52 | }; |
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h index af5fb31af559..be6c879e8760 100644 --- a/include/asm-powerpc/dcr-native.h +++ b/include/asm-powerpc/dcr-native.h | |||
@@ -59,25 +59,36 @@ do { \ | |||
59 | /* R/W of indirect DCRs make use of standard naming conventions for DCRs */ | 59 | /* R/W of indirect DCRs make use of standard naming conventions for DCRs */ |
60 | extern spinlock_t dcr_ind_lock; | 60 | extern spinlock_t dcr_ind_lock; |
61 | 61 | ||
62 | #define mfdcri(base, reg) \ | 62 | static inline unsigned __mfdcri(int base_addr, int base_data, int reg) |
63 | ({ \ | 63 | { |
64 | unsigned long flags; \ | 64 | unsigned long flags; |
65 | unsigned int val; \ | 65 | unsigned int val; |
66 | spin_lock_irqsave(&dcr_ind_lock, flags); \ | ||
67 | mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \ | ||
68 | val = mfdcr(DCRN_ ## base ## _CONFIG_DATA); \ | ||
69 | spin_unlock_irqrestore(&dcr_ind_lock, flags); \ | ||
70 | val; \ | ||
71 | }) | ||
72 | 66 | ||
73 | #define mtdcri(base, reg, data) \ | 67 | spin_lock_irqsave(&dcr_ind_lock, flags); |
74 | do { \ | 68 | __mtdcr(base_addr, reg); |
75 | unsigned long flags; \ | 69 | val = __mfdcr(base_data); |
76 | spin_lock_irqsave(&dcr_ind_lock, flags); \ | 70 | spin_unlock_irqrestore(&dcr_ind_lock, flags); |
77 | mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \ | 71 | return val; |
78 | mtdcr(DCRN_ ## base ## _CONFIG_DATA, data); \ | 72 | } |
79 | spin_unlock_irqrestore(&dcr_ind_lock, flags); \ | 73 | |
80 | } while (0) | 74 | static inline void __mtdcri(int base_addr, int base_data, int reg, |
75 | unsigned val) | ||
76 | { | ||
77 | unsigned long flags; | ||
78 | |||
79 | spin_lock_irqsave(&dcr_ind_lock, flags); | ||
80 | __mtdcr(base_addr, reg); | ||
81 | __mtdcr(base_data, val); | ||
82 | spin_unlock_irqrestore(&dcr_ind_lock, flags); | ||
83 | } | ||
84 | |||
85 | #define mfdcri(base, reg) __mfdcri(DCRN_ ## base ## _CONFIG_ADDR, \ | ||
86 | DCRN_ ## base ## _CONFIG_DATA, \ | ||
87 | reg) | ||
88 | |||
89 | #define mtdcri(base, reg, data) __mtdcri(DCRN_ ## base ## _CONFIG_ADDR, \ | ||
90 | DCRN_ ## base ## _CONFIG_DATA, \ | ||
91 | reg, data) | ||
81 | 92 | ||
82 | #endif /* __ASSEMBLY__ */ | 93 | #endif /* __ASSEMBLY__ */ |
83 | #endif /* __KERNEL__ */ | 94 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index 6bd07ef78ac4..9080d85cb9d0 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h | |||
@@ -165,8 +165,10 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32]; | |||
165 | * This is used to ensure we don't load something for the wrong architecture. | 165 | * This is used to ensure we don't load something for the wrong architecture. |
166 | */ | 166 | */ |
167 | #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) | 167 | #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) |
168 | #define compat_elf_check_arch(x) ((x)->e_machine == EM_PPC) | ||
168 | 169 | ||
169 | #define USE_ELF_CORE_DUMP | 170 | #define USE_ELF_CORE_DUMP |
171 | #define CORE_DUMP_USE_REGSET | ||
170 | #define ELF_EXEC_PAGESIZE PAGE_SIZE | 172 | #define ELF_EXEC_PAGESIZE PAGE_SIZE |
171 | 173 | ||
172 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical | 174 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical |
diff --git a/include/asm-powerpc/mpc512x.h b/include/asm-powerpc/mpc512x.h new file mode 100644 index 000000000000..c48a1658eeac --- /dev/null +++ b/include/asm-powerpc/mpc512x.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com>, Friday Apr 13 2007 | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121 Prototypes and definitions | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * 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 | */ | ||
15 | |||
16 | #ifndef __ASM_POWERPC_MPC512x_H__ | ||
17 | #define __ASM_POWERPC_MPC512x_H__ | ||
18 | |||
19 | extern unsigned long mpc512x_find_ips_freq(struct device_node *node); | ||
20 | |||
21 | #endif /* __ASM_POWERPC_MPC512x_H__ */ | ||
22 | |||
diff --git a/include/asm-powerpc/mpc52xx_psc.h b/include/asm-powerpc/mpc52xx_psc.h index bea42b95390f..710c5d36efaa 100644 --- a/include/asm-powerpc/mpc52xx_psc.h +++ b/include/asm-powerpc/mpc52xx_psc.h | |||
@@ -190,5 +190,53 @@ struct mpc52xx_psc_fifo { | |||
190 | u16 tflwfptr; /* PSC + 0x9e */ | 190 | u16 tflwfptr; /* PSC + 0x9e */ |
191 | }; | 191 | }; |
192 | 192 | ||
193 | #define MPC512x_PSC_FIFO_RESET_SLICE 0x80 | ||
194 | #define MPC512x_PSC_FIFO_ENABLE_SLICE 0x01 | ||
195 | #define MPC512x_PSC_FIFO_ENABLE_DMA 0x04 | ||
196 | |||
197 | #define MPC512x_PSC_FIFO_EMPTY 0x1 | ||
198 | #define MPC512x_PSC_FIFO_FULL 0x2 | ||
199 | #define MPC512x_PSC_FIFO_ALARM 0x4 | ||
200 | #define MPC512x_PSC_FIFO_URERR 0x8 | ||
201 | #define MPC512x_PSC_FIFO_ORERR 0x01 | ||
202 | #define MPC512x_PSC_FIFO_MEMERROR 0x02 | ||
203 | |||
204 | struct mpc512x_psc_fifo { | ||
205 | u32 reserved1[10]; | ||
206 | u32 txcmd; /* PSC + 0x80 */ | ||
207 | u32 txalarm; /* PSC + 0x84 */ | ||
208 | u32 txsr; /* PSC + 0x88 */ | ||
209 | u32 txisr; /* PSC + 0x8c */ | ||
210 | u32 tximr; /* PSC + 0x90 */ | ||
211 | u32 txcnt; /* PSC + 0x94 */ | ||
212 | u32 txptr; /* PSC + 0x98 */ | ||
213 | u32 txsz; /* PSC + 0x9c */ | ||
214 | u32 reserved2[7]; | ||
215 | union { | ||
216 | u8 txdata_8; | ||
217 | u16 txdata_16; | ||
218 | u32 txdata_32; | ||
219 | } txdata; /* PSC + 0xbc */ | ||
220 | #define txdata_8 txdata.txdata_8 | ||
221 | #define txdata_16 txdata.txdata_16 | ||
222 | #define txdata_32 txdata.txdata_32 | ||
223 | u32 rxcmd; /* PSC + 0xc0 */ | ||
224 | u32 rxalarm; /* PSC + 0xc4 */ | ||
225 | u32 rxsr; /* PSC + 0xc8 */ | ||
226 | u32 rxisr; /* PSC + 0xcc */ | ||
227 | u32 rximr; /* PSC + 0xd0 */ | ||
228 | u32 rxcnt; /* PSC + 0xd4 */ | ||
229 | u32 rxptr; /* PSC + 0xd8 */ | ||
230 | u32 rxsz; /* PSC + 0xdc */ | ||
231 | u32 reserved3[7]; | ||
232 | union { | ||
233 | u8 rxdata_8; | ||
234 | u16 rxdata_16; | ||
235 | u32 rxdata_32; | ||
236 | } rxdata; /* PSC + 0xfc */ | ||
237 | #define rxdata_8 rxdata.rxdata_8 | ||
238 | #define rxdata_16 rxdata.rxdata_16 | ||
239 | #define rxdata_32 rxdata.rxdata_32 | ||
240 | }; | ||
193 | 241 | ||
194 | #endif /* __ASM_MPC52xx_PSC_H__ */ | 242 | #endif /* __ASM_MPC52xx_PSC_H__ */ |
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h index 938fefb4c4bc..95035c602ba6 100644 --- a/include/asm-powerpc/oprofile_impl.h +++ b/include/asm-powerpc/oprofile_impl.h | |||
@@ -54,7 +54,7 @@ struct op_powerpc_model { | |||
54 | int num_counters; | 54 | int num_counters; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | extern struct op_powerpc_model op_model_fsl_booke; | 57 | extern struct op_powerpc_model op_model_fsl_emb; |
58 | extern struct op_powerpc_model op_model_rs64; | 58 | extern struct op_powerpc_model op_model_rs64; |
59 | extern struct op_powerpc_model op_model_power4; | 59 | extern struct op_powerpc_model op_model_power4; |
60 | extern struct op_powerpc_model op_model_7450; | 60 | extern struct op_powerpc_model op_model_7450; |
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h index ffc150f602b8..891d68932f39 100644 --- a/include/asm-powerpc/ptrace.h +++ b/include/asm-powerpc/ptrace.h | |||
@@ -55,6 +55,8 @@ struct pt_regs { | |||
55 | 55 | ||
56 | #ifdef __powerpc64__ | 56 | #ifdef __powerpc64__ |
57 | 57 | ||
58 | #define __ARCH_WANT_COMPAT_SYS_PTRACE | ||
59 | |||
58 | #define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ | 60 | #define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ |
59 | 61 | ||
60 | /* Size of dummy stack frame allocated when calling signal handler. */ | 62 | /* Size of dummy stack frame allocated when calling signal handler. */ |
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 2408a29507e5..0d6238987df8 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h | |||
@@ -18,6 +18,10 @@ | |||
18 | #include <asm/reg_booke.h> | 18 | #include <asm/reg_booke.h> |
19 | #endif /* CONFIG_BOOKE || CONFIG_40x */ | 19 | #endif /* CONFIG_BOOKE || CONFIG_40x */ |
20 | 20 | ||
21 | #ifdef CONFIG_FSL_EMB_PERFMON | ||
22 | #include <asm/reg_fsl_emb.h> | ||
23 | #endif | ||
24 | |||
21 | #ifdef CONFIG_8xx | 25 | #ifdef CONFIG_8xx |
22 | #include <asm/reg_8xx.h> | 26 | #include <asm/reg_8xx.h> |
23 | #endif /* CONFIG_8xx */ | 27 | #endif /* CONFIG_8xx */ |
diff --git a/include/asm-powerpc/reg_booke.h b/include/asm-powerpc/reg_booke.h index 0405ef479814..cf54a3f31753 100644 --- a/include/asm-powerpc/reg_booke.h +++ b/include/asm-powerpc/reg_booke.h | |||
@@ -9,68 +9,6 @@ | |||
9 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ | 9 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ |
10 | #define __ASM_POWERPC_REG_BOOKE_H__ | 10 | #define __ASM_POWERPC_REG_BOOKE_H__ |
11 | 11 | ||
12 | #ifndef __ASSEMBLY__ | ||
13 | /* Performance Monitor Registers */ | ||
14 | #define mfpmr(rn) ({unsigned int rval; \ | ||
15 | asm volatile("mfpmr %0," __stringify(rn) \ | ||
16 | : "=r" (rval)); rval;}) | ||
17 | #define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v)) | ||
18 | #endif /* __ASSEMBLY__ */ | ||
19 | |||
20 | /* Freescale Book E Performance Monitor APU Registers */ | ||
21 | #define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */ | ||
22 | #define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */ | ||
23 | #define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */ | ||
24 | #define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */ | ||
25 | #define PMRN_PMLCA0 0x090 /* PM Local Control A0 */ | ||
26 | #define PMRN_PMLCA1 0x091 /* PM Local Control A1 */ | ||
27 | #define PMRN_PMLCA2 0x092 /* PM Local Control A2 */ | ||
28 | #define PMRN_PMLCA3 0x093 /* PM Local Control A3 */ | ||
29 | |||
30 | #define PMLCA_FC 0x80000000 /* Freeze Counter */ | ||
31 | #define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */ | ||
32 | #define PMLCA_FCU 0x20000000 /* Freeze in User */ | ||
33 | #define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */ | ||
34 | #define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */ | ||
35 | #define PMLCA_CE 0x04000000 /* Condition Enable */ | ||
36 | |||
37 | #define PMLCA_EVENT_MASK 0x007f0000 /* Event field */ | ||
38 | #define PMLCA_EVENT_SHIFT 16 | ||
39 | |||
40 | #define PMRN_PMLCB0 0x110 /* PM Local Control B0 */ | ||
41 | #define PMRN_PMLCB1 0x111 /* PM Local Control B1 */ | ||
42 | #define PMRN_PMLCB2 0x112 /* PM Local Control B2 */ | ||
43 | #define PMRN_PMLCB3 0x113 /* PM Local Control B3 */ | ||
44 | |||
45 | #define PMLCB_THRESHMUL_MASK 0x0700 /* Threshhold Multiple Field */ | ||
46 | #define PMLCB_THRESHMUL_SHIFT 8 | ||
47 | |||
48 | #define PMLCB_THRESHOLD_MASK 0x003f /* Threshold Field */ | ||
49 | #define PMLCB_THRESHOLD_SHIFT 0 | ||
50 | |||
51 | #define PMRN_PMGC0 0x190 /* PM Global Control 0 */ | ||
52 | |||
53 | #define PMGC0_FAC 0x80000000 /* Freeze all Counters */ | ||
54 | #define PMGC0_PMIE 0x40000000 /* Interrupt Enable */ | ||
55 | #define PMGC0_FCECE 0x20000000 /* Freeze countes on | ||
56 | Enabled Condition or | ||
57 | Event */ | ||
58 | |||
59 | #define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */ | ||
60 | #define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */ | ||
61 | #define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */ | ||
62 | #define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */ | ||
63 | #define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */ | ||
64 | #define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */ | ||
65 | #define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */ | ||
66 | #define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */ | ||
67 | #define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */ | ||
68 | #define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */ | ||
69 | #define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */ | ||
70 | #define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */ | ||
71 | #define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */ | ||
72 | |||
73 | |||
74 | /* Machine State Register (MSR) Fields */ | 12 | /* Machine State Register (MSR) Fields */ |
75 | #define MSR_UCLE (1<<26) /* User-mode cache lock enable */ | 13 | #define MSR_UCLE (1<<26) /* User-mode cache lock enable */ |
76 | #define MSR_SPE (1<<25) /* Enable SPE */ | 14 | #define MSR_SPE (1<<25) /* Enable SPE */ |
diff --git a/include/asm-powerpc/reg_fsl_emb.h b/include/asm-powerpc/reg_fsl_emb.h new file mode 100644 index 000000000000..1e180a594589 --- /dev/null +++ b/include/asm-powerpc/reg_fsl_emb.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Contains register definitions for the Freescale Embedded Performance | ||
3 | * Monitor. | ||
4 | */ | ||
5 | #ifdef __KERNEL__ | ||
6 | #ifndef __ASM_POWERPC_REG_FSL_EMB_H__ | ||
7 | #define __ASM_POWERPC_REG_FSL_EMB_H__ | ||
8 | |||
9 | #ifndef __ASSEMBLY__ | ||
10 | /* Performance Monitor Registers */ | ||
11 | #define mfpmr(rn) ({unsigned int rval; \ | ||
12 | asm volatile("mfpmr %0," __stringify(rn) \ | ||
13 | : "=r" (rval)); rval;}) | ||
14 | #define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v)) | ||
15 | #endif /* __ASSEMBLY__ */ | ||
16 | |||
17 | /* Freescale Book E Performance Monitor APU Registers */ | ||
18 | #define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */ | ||
19 | #define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */ | ||
20 | #define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */ | ||
21 | #define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */ | ||
22 | #define PMRN_PMLCA0 0x090 /* PM Local Control A0 */ | ||
23 | #define PMRN_PMLCA1 0x091 /* PM Local Control A1 */ | ||
24 | #define PMRN_PMLCA2 0x092 /* PM Local Control A2 */ | ||
25 | #define PMRN_PMLCA3 0x093 /* PM Local Control A3 */ | ||
26 | |||
27 | #define PMLCA_FC 0x80000000 /* Freeze Counter */ | ||
28 | #define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */ | ||
29 | #define PMLCA_FCU 0x20000000 /* Freeze in User */ | ||
30 | #define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */ | ||
31 | #define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */ | ||
32 | #define PMLCA_CE 0x04000000 /* Condition Enable */ | ||
33 | |||
34 | #define PMLCA_EVENT_MASK 0x007f0000 /* Event field */ | ||
35 | #define PMLCA_EVENT_SHIFT 16 | ||
36 | |||
37 | #define PMRN_PMLCB0 0x110 /* PM Local Control B0 */ | ||
38 | #define PMRN_PMLCB1 0x111 /* PM Local Control B1 */ | ||
39 | #define PMRN_PMLCB2 0x112 /* PM Local Control B2 */ | ||
40 | #define PMRN_PMLCB3 0x113 /* PM Local Control B3 */ | ||
41 | |||
42 | #define PMLCB_THRESHMUL_MASK 0x0700 /* Threshhold Multiple Field */ | ||
43 | #define PMLCB_THRESHMUL_SHIFT 8 | ||
44 | |||
45 | #define PMLCB_THRESHOLD_MASK 0x003f /* Threshold Field */ | ||
46 | #define PMLCB_THRESHOLD_SHIFT 0 | ||
47 | |||
48 | #define PMRN_PMGC0 0x190 /* PM Global Control 0 */ | ||
49 | |||
50 | #define PMGC0_FAC 0x80000000 /* Freeze all Counters */ | ||
51 | #define PMGC0_PMIE 0x40000000 /* Interrupt Enable */ | ||
52 | #define PMGC0_FCECE 0x20000000 /* Freeze countes on | ||
53 | Enabled Condition or | ||
54 | Event */ | ||
55 | |||
56 | #define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */ | ||
57 | #define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */ | ||
58 | #define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */ | ||
59 | #define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */ | ||
60 | #define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */ | ||
61 | #define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */ | ||
62 | #define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */ | ||
63 | #define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */ | ||
64 | #define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */ | ||
65 | #define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */ | ||
66 | #define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */ | ||
67 | #define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */ | ||
68 | #define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */ | ||
69 | |||
70 | |||
71 | #endif /* __ASM_POWERPC_REG_FSL_EMB_H__ */ | ||
72 | #endif /* __KERNEL__ */ | ||
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index 2a65ae637204..29552ff182aa 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
@@ -65,7 +65,7 @@ | |||
65 | struct task_struct; | 65 | struct task_struct; |
66 | struct pt_regs; | 66 | struct pt_regs; |
67 | 67 | ||
68 | #ifdef CONFIG_DEBUGGER | 68 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
69 | 69 | ||
70 | extern int (*__debugger)(struct pt_regs *regs); | 70 | extern int (*__debugger)(struct pt_regs *regs); |
71 | extern int (*__debugger_ipi)(struct pt_regs *regs); | 71 | extern int (*__debugger_ipi)(struct pt_regs *regs); |
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 9204c15839c5..56512a968dab 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h | |||
@@ -66,7 +66,7 @@ extern void __devinit vio_unregister_device(struct vio_dev *dev); | |||
66 | 66 | ||
67 | struct device_node; | 67 | struct device_node; |
68 | 68 | ||
69 | extern struct vio_dev * __devinit vio_register_device_node( | 69 | extern struct vio_dev *vio_register_device_node( |
70 | struct device_node *node_vdev); | 70 | struct device_node *node_vdev); |
71 | extern const void *vio_get_attribute(struct vio_dev *vdev, char *which, | 71 | extern const void *vio_get_attribute(struct vio_dev *vdev, char *which, |
72 | int *length); | 72 | int *length); |
diff --git a/include/linux/elf.h b/include/linux/elf.h index ed98c761bae7..bad1b16ec49a 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h | |||
@@ -357,6 +357,7 @@ typedef struct elf64_shdr { | |||
357 | #define NT_AUXV 6 | 357 | #define NT_AUXV 6 |
358 | #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ | 358 | #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ |
359 | #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ | 359 | #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ |
360 | #define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */ | ||
360 | #define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ | 361 | #define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ |
361 | 362 | ||
362 | 363 | ||
diff --git a/include/linux/of.h b/include/linux/of.h index b5f33efcb8e2..6981016dcc25 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -50,6 +50,7 @@ extern struct device_node *of_find_matching_node(struct device_node *from, | |||
50 | extern struct device_node *of_find_node_by_path(const char *path); | 50 | extern struct device_node *of_find_node_by_path(const char *path); |
51 | extern struct device_node *of_find_node_by_phandle(phandle handle); | 51 | extern struct device_node *of_find_node_by_phandle(phandle handle); |
52 | extern struct device_node *of_get_parent(const struct device_node *node); | 52 | extern struct device_node *of_get_parent(const struct device_node *node); |
53 | extern struct device_node *of_get_next_parent(struct device_node *node); | ||
53 | extern struct device_node *of_get_next_child(const struct device_node *node, | 54 | extern struct device_node *of_get_next_child(const struct device_node *node, |
54 | struct device_node *prev); | 55 | struct device_node *prev); |
55 | #define for_each_child_of_node(parent, child) \ | 56 | #define for_each_child_of_node(parent, child) \ |