Merge branch 'for-2.6.23' into merge
This commit is contained in:
		
						commit
						bf22f6fe2d
					
				| @ -253,7 +253,7 @@ Here are the routines, one by one: | ||||
| 
 | ||||
| 	The first of these two routines is invoked after map_vm_area() | ||||
| 	has installed the page table entries.  The second is invoked | ||||
| 	before unmap_vm_area() deletes the page table entries. | ||||
| 	before unmap_kernel_range() deletes the page table entries. | ||||
| 
 | ||||
| There exists another whole class of cpu cache issues which currently | ||||
| require a whole different set of interfaces to handle properly. | ||||
|  | ||||
| @ -330,3 +330,15 @@ Who:  Tejun Heo <htejun@gmail.com> | ||||
| 
 | ||||
| --------------------------- | ||||
| 
 | ||||
| What: The arch/ppc and include/asm-ppc directories | ||||
| When: Jun 2008 | ||||
| Why:  The arch/powerpc tree is the merged architecture for ppc32 and ppc64 | ||||
|       platforms.  Currently there are efforts underway to port the remaining | ||||
|       arch/ppc platforms to the merged tree.  New submissions to the arch/ppc | ||||
|       tree have been frozen with the 2.6.22 kernel release and that tree will | ||||
|       remain in bug-fix only mode until its scheduled removal.  Platforms | ||||
|       that are not ported by June 2008 will be removed due to the lack of an | ||||
|       interested maintainer. | ||||
| Who:  linuxppc-dev@ozlabs.org | ||||
| 
 | ||||
| --------------------------- | ||||
|  | ||||
| @ -42,15 +42,16 @@ Table of Contents | ||||
|     1) Defining child nodes of an SOC | ||||
|     2) Representing devices without a current OF specification | ||||
|       a) MDIO IO device | ||||
|       c) PHY nodes | ||||
|       b) Gianfar-compatible ethernet nodes | ||||
|       c) PHY nodes | ||||
|       d) Interrupt controllers | ||||
|       e) I2C | ||||
|       f) Freescale SOC USB controllers | ||||
|       g) Freescale SOC SEC Security Engines | ||||
|       h) Board Control and Status (BCSR) | ||||
|       i) Freescale QUICC Engine module (QE) | ||||
|       g) Flash chip nodes | ||||
|       j) Flash chip nodes | ||||
|       k) Global Utilities Block | ||||
| 
 | ||||
|   VII - Specifying interrupt information for devices | ||||
|     1) interrupts property | ||||
| @ -626,6 +627,14 @@ So the node content can be summarized as a start token, a full path, | ||||
| a list of properties, a list of child nodes, and an end token. Every | ||||
| child node is a full node structure itself as defined above. | ||||
| 
 | ||||
| NOTE: The above definition requires that all property definitions for | ||||
| a particular node MUST precede any subnode definitions for that node. | ||||
| Although the structure would not be ambiguous if properties and | ||||
| subnodes were intermingled, the kernel parser requires that the | ||||
| properties come first (up until at least 2.6.22).  Any tools | ||||
| manipulating a flattened tree must take care to preserve this | ||||
| constraint. | ||||
| 
 | ||||
| 4) Device tree "strings" block | ||||
| 
 | ||||
| In order to save space, property names, which are generally redundant, | ||||
| @ -1782,6 +1791,33 @@ platforms are moved over to use the flattened-device-tree model. | ||||
|  		partition-names = "fs\0firmware"; | ||||
|  	}; | ||||
| 
 | ||||
|    k) Global Utilities Block | ||||
| 
 | ||||
|    The global utilities block controls power management, I/O device | ||||
|    enabling, power-on-reset configuration monitoring, general-purpose | ||||
|    I/O signal configuration, alternate function selection for multiplexed | ||||
|    signals, and clock control. | ||||
| 
 | ||||
|    Required properties: | ||||
| 
 | ||||
|     - compatible : Should define the compatible device type for | ||||
|       global-utilities. | ||||
|     - reg : Offset and length of the register set for the device. | ||||
| 
 | ||||
|   Recommended properties: | ||||
| 
 | ||||
|     - fsl,has-rstcr : Indicates that the global utilities register set | ||||
|       contains a functioning "reset control register" (i.e. the board | ||||
|       is wired to reset upon setting the HRESET_REQ bit in this register). | ||||
| 
 | ||||
|     Example: | ||||
| 
 | ||||
| 	global-utilities@e0000 {	/* global utilities block */ | ||||
| 		compatible = "fsl,mpc8548-guts"; | ||||
| 		reg = <e0000 1000>; | ||||
| 		fsl,has-rstcr; | ||||
| 	}; | ||||
| 
 | ||||
|    More devices will be defined as this spec matures. | ||||
| 
 | ||||
| VII - Specifying interrupt information for devices | ||||
|  | ||||
| @ -4,17 +4,7 @@ | ||||
| 
 | ||||
| mainmenu "Linux/PowerPC Kernel Configuration" | ||||
| 
 | ||||
| config PPC64 | ||||
| 	bool "64-bit kernel" | ||||
| 	default n | ||||
| 	help | ||||
| 	  This option selects whether a 32-bit or a 64-bit kernel | ||||
| 	  will be built. | ||||
| 
 | ||||
| config PPC_PM_NEEDS_RTC_LIB | ||||
| 	bool | ||||
| 	select RTC_LIB | ||||
| 	default y if PM | ||||
| source "arch/powerpc/platforms/Kconfig.cputype" | ||||
| 
 | ||||
| config PPC32 | ||||
| 	bool | ||||
| @ -132,123 +122,6 @@ config PPC64_SWSUSP | ||||
| 	depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL)) | ||||
| 	default y | ||||
| 
 | ||||
| menu "Processor support" | ||||
| choice | ||||
| 	prompt "Processor Type" | ||||
| 	depends on PPC32 | ||||
| 	default 6xx | ||||
| 
 | ||||
| config CLASSIC32 | ||||
| 	bool "52xx/6xx/7xx/74xx" | ||||
| 	select PPC_FPU | ||||
| 	select 6xx | ||||
| 	help | ||||
| 	  There are four families of PowerPC chips supported.  The more common | ||||
| 	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded | ||||
| 	  versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC | ||||
| 	  embedded versions (403 and 405) and the high end 64 bit Power | ||||
| 	  processors (POWER 3, POWER4, and IBM PPC970 also known as G5). | ||||
| 
 | ||||
| 	  This option is the catch-all for 6xx types, including some of the | ||||
| 	  embedded versions.  Unless there is see an option for the specific | ||||
| 	  chip family you are using, you want this option. | ||||
| 	   | ||||
| 	  You do not want this if you are building a kernel for a 64 bit | ||||
| 	  IBM RS/6000 or an Apple G5, choose 6xx. | ||||
| 	   | ||||
| 	  If unsure, select this option | ||||
| 	   | ||||
| 	  Note that the kernel runs in 32-bit mode even on 64-bit chips. | ||||
| 
 | ||||
| config PPC_82xx | ||||
| 	bool "Freescale 82xx" | ||||
| 	select 6xx | ||||
| 	select PPC_FPU | ||||
| 
 | ||||
| config PPC_83xx | ||||
| 	bool "Freescale 83xx" | ||||
| 	select 6xx | ||||
| 	select FSL_SOC | ||||
| 	select 83xx | ||||
| 	select PPC_FPU | ||||
| 	select WANT_DEVICE_TREE | ||||
| 
 | ||||
| config PPC_85xx | ||||
| 	bool "Freescale 85xx" | ||||
| 	select E500 | ||||
| 	select FSL_SOC | ||||
| 	select 85xx | ||||
| 	select WANT_DEVICE_TREE | ||||
| 
 | ||||
| config PPC_86xx | ||||
| 	bool "Freescale 86xx" | ||||
| 	select 6xx | ||||
| 	select FSL_SOC | ||||
| 	select FSL_PCIE | ||||
| 	select PPC_FPU | ||||
| 	select ALTIVEC | ||||
| 	help | ||||
| 	  The Freescale E600 SoCs have 74xx cores. | ||||
| 
 | ||||
| config PPC_8xx | ||||
| 	bool "Freescale 8xx" | ||||
| 	select FSL_SOC | ||||
| 	select 8xx | ||||
| 
 | ||||
| config 40x | ||||
| 	bool "AMCC 40x" | ||||
| 	select PPC_DCR_NATIVE | ||||
| 
 | ||||
| config 44x | ||||
| 	bool "AMCC 44x" | ||||
| 	select PPC_DCR_NATIVE | ||||
| 	select WANT_DEVICE_TREE | ||||
| 
 | ||||
| config E200 | ||||
| 	bool "Freescale e200" | ||||
| 
 | ||||
| endchoice | ||||
| 
 | ||||
| config POWER4_ONLY | ||||
| 	bool "Optimize for POWER4" | ||||
| 	depends on PPC64 | ||||
| 	default n | ||||
| 	---help--- | ||||
| 	  Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. | ||||
| 	  The resulting binary will not work on POWER3 or RS64 processors | ||||
| 	  when compiled with binutils 2.15 or later. | ||||
| 
 | ||||
| config POWER3 | ||||
| 	bool | ||||
| 	depends on PPC64 | ||||
| 	default y if !POWER4_ONLY | ||||
| 
 | ||||
| config POWER4 | ||||
| 	depends on PPC64 | ||||
| 	def_bool y | ||||
| 
 | ||||
| config 6xx | ||||
| 	bool | ||||
| 
 | ||||
| # this is temp to handle compat with arch=ppc | ||||
| config 8xx | ||||
| 	bool | ||||
| 
 | ||||
| # this is temp to handle compat with arch=ppc | ||||
| config 83xx | ||||
| 	bool | ||||
| 
 | ||||
| # this is temp to handle compat with arch=ppc | ||||
| config 85xx | ||||
| 	bool | ||||
| 
 | ||||
| config E500 | ||||
| 	bool | ||||
| 
 | ||||
| config PPC_FPU | ||||
| 	bool | ||||
| 	default y if PPC64 | ||||
| 
 | ||||
| config PPC_DCR_NATIVE | ||||
| 	bool | ||||
| 	default n | ||||
| @ -267,134 +140,6 @@ config PPC_OF_PLATFORM_PCI | ||||
| 	depends on PPC64 # not supported on 32 bits yet | ||||
| 	default n | ||||
| 
 | ||||
| config 4xx | ||||
| 	bool | ||||
| 	depends on 40x || 44x | ||||
| 	default y | ||||
| 
 | ||||
| config BOOKE | ||||
| 	bool | ||||
| 	depends on E200 || E500 || 44x | ||||
| 	default y | ||||
| 
 | ||||
| config FSL_BOOKE | ||||
| 	bool | ||||
| 	depends on E200 || E500 | ||||
| 	default y | ||||
| 
 | ||||
| config PTE_64BIT | ||||
| 	bool | ||||
| 	depends on 44x || E500 | ||||
| 	default y if 44x | ||||
| 	default y if E500 && PHYS_64BIT | ||||
| 
 | ||||
| config PHYS_64BIT | ||||
| 	bool 'Large physical address support' if E500 | ||||
| 	depends on 44x || E500 | ||||
| 	select RESOURCES_64BIT | ||||
| 	default y if 44x | ||||
| 	---help--- | ||||
| 	  This option enables kernel support for larger than 32-bit physical | ||||
| 	  addresses.  This features is not be available on all e500 cores. | ||||
| 
 | ||||
| 	  If in doubt, say N here. | ||||
| 
 | ||||
| config ALTIVEC | ||||
| 	bool "AltiVec Support" | ||||
| 	depends on CLASSIC32 || POWER4 | ||||
| 	---help--- | ||||
| 	  This option enables kernel support for the Altivec extensions to the | ||||
| 	  PowerPC processor. The kernel currently supports saving and restoring | ||||
| 	  altivec registers, and turning on the 'altivec enable' bit so user | ||||
| 	  processes can execute altivec instructions. | ||||
| 
 | ||||
| 	  This option is only usefully if you have a processor that supports | ||||
| 	  altivec (G4, otherwise known as 74xx series), but does not have | ||||
| 	  any affect on a non-altivec cpu (it does, however add code to the | ||||
| 	  kernel). | ||||
| 
 | ||||
| 	  If in doubt, say Y here. | ||||
| 
 | ||||
| config SPE | ||||
| 	bool "SPE Support" | ||||
| 	depends on E200 || E500 | ||||
| 	default y | ||||
| 	---help--- | ||||
| 	  This option enables kernel support for the Signal Processing | ||||
| 	  Extensions (SPE) to the PowerPC processor. The kernel currently | ||||
| 	  supports saving and restoring SPE registers, and turning on the | ||||
| 	  'spe enable' bit so user processes can execute SPE instructions. | ||||
| 
 | ||||
| 	  This option is only useful if you have a processor that supports | ||||
| 	  SPE (e500, otherwise known as 85xx series), but does not have any | ||||
| 	  effect on a non-spe cpu (it does, however add code to the kernel). | ||||
| 
 | ||||
| 	  If in doubt, say Y here. | ||||
| 
 | ||||
| config PPC_STD_MMU | ||||
| 	bool | ||||
| 	depends on 6xx || POWER3 || POWER4 || PPC64 | ||||
| 	default y | ||||
| 
 | ||||
| config PPC_STD_MMU_32 | ||||
| 	def_bool y | ||||
| 	depends on PPC_STD_MMU && PPC32 | ||||
| 
 | ||||
| config PPC_MM_SLICES | ||||
| 	bool | ||||
| 	default y if HUGETLB_PAGE | ||||
| 	default n | ||||
| 
 | ||||
| config VIRT_CPU_ACCOUNTING | ||||
| 	bool "Deterministic task and CPU time accounting" | ||||
| 	depends on PPC64 | ||||
| 	default y | ||||
| 	help | ||||
| 	  Select this option to enable more accurate task and CPU time | ||||
| 	  accounting.  This is done by reading a CPU counter on each | ||||
| 	  kernel entry and exit and on transitions within the kernel | ||||
| 	  between system, softirq and hardirq state, so there is a | ||||
| 	  small performance impact.  This also enables accounting of | ||||
| 	  stolen time on logically-partitioned systems running on | ||||
| 	  IBM POWER5-based machines. | ||||
| 
 | ||||
| 	  If in doubt, say Y here. | ||||
| 
 | ||||
| config SMP | ||||
| 	depends on PPC_STD_MMU | ||||
| 	bool "Symmetric multi-processing support" | ||||
| 	---help--- | ||||
| 	  This enables support for systems with more than one CPU. If you have | ||||
| 	  a system with only one CPU, say N. If you have a system with more | ||||
| 	  than one CPU, say Y.  Note that the kernel does not currently | ||||
| 	  support SMP machines with 603/603e/603ev or PPC750 ("G3") processors | ||||
| 	  since they have inadequate hardware support for multiprocessor | ||||
| 	  operation. | ||||
| 
 | ||||
| 	  If you say N here, the kernel will run on single and multiprocessor | ||||
| 	  machines, but will use only one CPU of a multiprocessor machine. If | ||||
| 	  you say Y here, the kernel will run on single-processor machines. | ||||
| 	  On a single-processor machine, the kernel will run faster if you say | ||||
| 	  N here. | ||||
| 
 | ||||
| 	  If you don't know what to do here, say N. | ||||
| 
 | ||||
| config NR_CPUS | ||||
| 	int "Maximum number of CPUs (2-128)" | ||||
| 	range 2 128 | ||||
| 	depends on SMP | ||||
| 	default "32" if PPC64 | ||||
| 	default "4" | ||||
| 
 | ||||
| config NOT_COHERENT_CACHE | ||||
| 	bool | ||||
| 	depends on 4xx || 8xx || E200 | ||||
| 	default y | ||||
| 
 | ||||
| config CONFIG_CHECK_CACHE_COHERENCY | ||||
| 	bool | ||||
| endmenu | ||||
| 
 | ||||
| source "init/Kconfig" | ||||
| 
 | ||||
| source "arch/powerpc/platforms/Kconfig" | ||||
| @ -674,10 +419,6 @@ config SBUS | ||||
| config FSL_SOC | ||||
| 	bool | ||||
| 
 | ||||
| config FSL_PCIE | ||||
| 	bool | ||||
| 	depends on PPC_86xx | ||||
| 
 | ||||
| # Yes MCA RS/6000s exist but Linux-PPC does not currently support any | ||||
| config MCA | ||||
| 	bool | ||||
| @ -685,10 +426,10 @@ config MCA | ||||
| config PCI | ||||
| 	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ | ||||
| 		|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ | ||||
| 		|| MPC7448HPC2 || PPC_PS3 || PPC_HOLLY | ||||
| 	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ | ||||
| 		|| PPC_PS3 | ||||
| 	default y if !40x && !CPM2 && !8xx && !PPC_83xx \ | ||||
| 		&& !PPC_85xx && !PPC_86xx | ||||
| 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS | ||||
| 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx | ||||
| 	default PCI_QSPAN if !4xx && !CPM2 && 8xx | ||||
| 	select ARCH_SUPPORTS_MSI | ||||
| 	help | ||||
|  | ||||
| @ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) | ||||
| 
 | ||||
| CPPFLAGS_vmlinux.lds	:= -Upowerpc | ||||
| 
 | ||||
| BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage | ||||
| BOOT_TARGETS = zImage zImage.initrd uImage | ||||
| 
 | ||||
| PHONY += $(BOOT_TARGETS) | ||||
| 
 | ||||
|  | ||||
| @ -38,3 +38,48 @@ void ibm44x_fixup_memsize(void) | ||||
| 
 | ||||
| 	dt_fixup_memory(0, memsize); | ||||
| } | ||||
| 
 | ||||
| #define SPRN_DBCR0		0x134 | ||||
| #define   DBCR0_RST_SYSTEM	0x30000000 | ||||
| 
 | ||||
| void ibm44x_dbcr_reset(void) | ||||
| { | ||||
| 	unsigned long tmp; | ||||
| 
 | ||||
| 	asm volatile ( | ||||
| 		"mfspr	%0,%1\n" | ||||
| 		"oris	%0,%0,%2@h\n" | ||||
| 		"mtspr	%1,%0" | ||||
| 		: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) | ||||
| 		); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
 | ||||
|  * banks into the OPB address space */ | ||||
| void ibm4xx_fixup_ebc_ranges(const char *ebc) | ||||
| { | ||||
| 	void *devp; | ||||
| 	u32 bxcr; | ||||
| 	u32 ranges[EBC_NUM_BANKS*4]; | ||||
| 	u32 *p = ranges; | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < EBC_NUM_BANKS; i++) { | ||||
| 		mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i)); | ||||
| 		bxcr = mfdcr(DCRN_EBC0_CFGDATA); | ||||
| 
 | ||||
| 		if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) { | ||||
| 			*p++ = i; | ||||
| 			*p++ = 0; | ||||
| 			*p++ = bxcr & EBC_BXCR_BAS; | ||||
| 			*p++ = EBC_BXCR_BANK_SIZE(bxcr); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	devp = finddevice(ebc); | ||||
| 	if (! devp) | ||||
| 		fatal("Couldn't locate EBC node %s\n\r", ebc); | ||||
| 
 | ||||
| 	setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32)); | ||||
| } | ||||
|  | ||||
| @ -11,6 +11,9 @@ | ||||
| #define _PPC_BOOT_44X_H_ | ||||
| 
 | ||||
| void ibm44x_fixup_memsize(void); | ||||
| void ibm4xx_fixup_ebc_ranges(const char *ebc); | ||||
| 
 | ||||
| void ibm44x_dbcr_reset(void); | ||||
| void ebony_init(void *mac0, void *mac1); | ||||
| 
 | ||||
| #endif /* _PPC_BOOT_44X_H_ */ | ||||
|  | ||||
| @ -43,10 +43,11 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ | ||||
| 
 | ||||
| src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
 | ||||
| 		ns16550.c serial.c simple_alloc.c div64.S util.S \
 | ||||
| 		gunzip_util.c elf_util.c $(zlib) devtree.c \
 | ||||
| 		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c | ||||
| 		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
 | ||||
| 		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c | ||||
| src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
 | ||||
| 		cuboot-ebony.c treeboot-ebony.c prpmc2800.c | ||||
| 		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
 | ||||
| 		ps3-head.S ps3-hvcall.S ps3.c | ||||
| src-boot := $(src-wlib) $(src-plat) empty.c | ||||
| 
 | ||||
| src-boot := $(addprefix $(obj)/, $(src-boot)) | ||||
| @ -75,11 +76,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/% | ||||
| $(obj)/empty.c: | ||||
| 	@touch $@ | ||||
| 
 | ||||
| $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S | ||||
| $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S | ||||
| 	@cp $< $@ | ||||
| 
 | ||||
| clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
 | ||||
| 		empty.c zImage.coff.lds zImage.lds | ||||
| 		empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds | ||||
| 
 | ||||
| quiet_cmd_bootcc = BOOTCC  $@ | ||||
|       cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< | ||||
| @ -102,7 +103,7 @@ hostprogs-y	:= addnote addRamDisk hack-coff mktree | ||||
| 
 | ||||
| targets		+= $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) | ||||
| extra-y		:= $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
 | ||||
| 		   $(obj)/zImage.lds $(obj)/zImage.coff.lds | ||||
| 		   $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds | ||||
| 
 | ||||
| wrapper		:=$(srctree)/$(src)/wrapper | ||||
| wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
 | ||||
| @ -132,7 +133,7 @@ image-$(CONFIG_PPC_CELLEB)		+= zImage.pseries | ||||
| image-$(CONFIG_PPC_CHRP)		+= zImage.chrp | ||||
| image-$(CONFIG_PPC_EFIKA)		+= zImage.chrp | ||||
| image-$(CONFIG_PPC_PMAC)		+= zImage.pmac | ||||
| image-$(CONFIG_PPC_HOLLY)		+= zImage.holly-elf | ||||
| image-$(CONFIG_PPC_HOLLY)		+= zImage.holly | ||||
| image-$(CONFIG_PPC_PRPMC2800)		+= zImage.prpmc2800 | ||||
| image-$(CONFIG_PPC_ISERIES)		+= zImage.iseries | ||||
| image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage | ||||
| @ -157,55 +158,43 @@ targets	+= $(image-y) $(initrd-y) | ||||
| 
 | ||||
| $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz | ||||
| 
 | ||||
| dts-  := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-)) | ||||
| dts-y := $(patsubst zImage%, zImage.dts%, $(image-y)) | ||||
| dts-y := $(filter-out $(image-y), $(dts-y)) | ||||
| targets	+= $(image-y) $(dts-y) | ||||
| 
 | ||||
| dts_initrd-  := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-)) | ||||
| dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y)) | ||||
| dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y)) | ||||
| targets	+= $(image-y) $(dts_initrd-y) | ||||
| 
 | ||||
| $(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz | ||||
| # If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an
 | ||||
| # empty string, define 'dts' to be path to the dts
 | ||||
| # CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
 | ||||
| ifeq ($(CONFIG_WANT_DEVICE_TREE),y) | ||||
| ifneq ($(CONFIG_DEVICE_TREE),"") | ||||
| dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
 | ||||
| 	,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) | ||||
| endif | ||||
| endif | ||||
| 
 | ||||
| # Don't put the ramdisk on the pattern rule; when its missing make will try
 | ||||
| # the pattern rule with less dependencies that also matches (even with the
 | ||||
| # hard dependency listed).
 | ||||
| $(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz | ||||
| $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts) | ||||
| 	$(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) | ||||
| 
 | ||||
| $(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts) | ||||
| $(obj)/zImage.%: vmlinux $(wrapperbits) $(dts) | ||||
| 	$(call if_changed,wrap,$*,$(dts)) | ||||
| 
 | ||||
| $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) | ||||
| 	$(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) | ||||
| 
 | ||||
| $(obj)/zImage.%: vmlinux $(wrapperbits) | ||||
| 	$(call if_changed,wrap,$*) | ||||
| # This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
 | ||||
| # prefix
 | ||||
| $(obj)/vmlinux.strip: vmlinux | ||||
| 	$(STRIP) -s -R .comment $< -o $@ | ||||
| 
 | ||||
| $(obj)/zImage.iseries: vmlinux | ||||
| 	$(STRIP) -s -R .comment $< -o $@ | ||||
| 
 | ||||
| $(obj)/zImage.ps3: vmlinux | ||||
| 	$(STRIP) -s -R .comment $< -o $@ | ||||
| $(obj)/zImage.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts | ||||
| 	$(STRIP) -s -R .comment $< -o vmlinux.strip | ||||
| 	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,) | ||||
| 
 | ||||
| $(obj)/zImage.initrd.ps3: vmlinux | ||||
| 	@echo "  WARNING zImage.initrd.ps3 not supported (yet)" | ||||
| 
 | ||||
| $(obj)/zImage.holly-elf: vmlinux $(wrapperbits) | ||||
| 	$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,) | ||||
| 
 | ||||
| $(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz | ||||
| 	$(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz) | ||||
| $(obj)/zImage.initrd.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz | ||||
| 	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz) | ||||
| 
 | ||||
| $(obj)/uImage: vmlinux $(wrapperbits) | ||||
| 	$(call if_changed,wrap,uboot) | ||||
| 
 | ||||
| # CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
 | ||||
| dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
 | ||||
| 	,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) | ||||
| 
 | ||||
| $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits) | ||||
| 	$(call if_changed,wrap,cuboot-$*,$(dts)) | ||||
| 
 | ||||
| @ -215,22 +204,22 @@ $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits) | ||||
| $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits) | ||||
| 	$(call if_changed,wrap,treeboot-$*,$(dts)) | ||||
| 
 | ||||
| # If there isn't a platform selected then just strip the vmlinux.
 | ||||
| ifeq (,$(image-y)) | ||||
| image-y := vmlinux.strip | ||||
| endif | ||||
| 
 | ||||
| $(obj)/zImage:		$(addprefix $(obj)/, $(image-y)) | ||||
| 	@rm -f $@; ln $< $@ | ||||
| $(obj)/zImage.initrd:	$(addprefix $(obj)/, $(initrd-y)) | ||||
| 	@rm -f $@; ln $< $@ | ||||
| $(obj)/zImage.dts:	$(addprefix $(obj)/, $(dts-y)) | ||||
| 	@rm -f $@; ln $< $@ | ||||
| $(obj)/zImage.dts_initrd:	$(addprefix $(obj)/, $(dts_initrd-y)) | ||||
| 	@rm -f $@; ln $< $@ | ||||
| 
 | ||||
| 
 | ||||
| install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) | ||||
| 	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< | ||||
| 
 | ||||
| # anything not in $(targets)
 | ||||
| clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \
 | ||||
| 	treeImage.* zImage.dts zImage.dts_initrd | ||||
| clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
 | ||||
| 	otheros.bld | ||||
| 
 | ||||
| # clean up files cached by wrapper
 | ||||
| clean-kernel := vmlinux.strip vmlinux.bin | ||||
|  | ||||
| @ -12,12 +12,12 @@ | ||||
| 
 | ||||
| #include "ops.h" | ||||
| #include "stdio.h" | ||||
| #include "cuboot.h" | ||||
| 
 | ||||
| #define TARGET_83xx | ||||
| #include "ppcboot.h" | ||||
| 
 | ||||
| static bd_t bd; | ||||
| extern char _end[]; | ||||
| extern char _dtb_start[], _dtb_end[]; | ||||
| 
 | ||||
| static void platform_fixups(void) | ||||
| @ -52,16 +52,7 @@ static void platform_fixups(void) | ||||
| void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||||
|                    unsigned long r6, unsigned long r7) | ||||
| { | ||||
| 	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | ||||
| 	unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||||
| 
 | ||||
| 	memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||||
| 	loader_info.initrd_addr = r4; | ||||
| 	loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||||
| 	loader_info.cmdline = (char *)r6; | ||||
| 	loader_info.cmdline_len = r7 - r6; | ||||
| 
 | ||||
| 	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||||
| 	CUBOOT_INIT(); | ||||
| 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | ||||
| 	serial_console_init(); | ||||
| 	platform_ops.fixups = platform_fixups; | ||||
|  | ||||
| @ -12,12 +12,12 @@ | ||||
| 
 | ||||
| #include "ops.h" | ||||
| #include "stdio.h" | ||||
| #include "cuboot.h" | ||||
| 
 | ||||
| #define TARGET_85xx | ||||
| #include "ppcboot.h" | ||||
| 
 | ||||
| static bd_t bd; | ||||
| extern char _end[]; | ||||
| extern char _dtb_start[], _dtb_end[]; | ||||
| 
 | ||||
| static void platform_fixups(void) | ||||
| @ -53,16 +53,7 @@ static void platform_fixups(void) | ||||
| void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||||
|                    unsigned long r6, unsigned long r7) | ||||
| { | ||||
| 	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | ||||
| 	unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||||
| 
 | ||||
| 	memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||||
| 	loader_info.initrd_addr = r4; | ||||
| 	loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||||
| 	loader_info.cmdline = (char *)r6; | ||||
| 	loader_info.cmdline_len = r7 - r6; | ||||
| 
 | ||||
| 	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||||
| 	CUBOOT_INIT(); | ||||
| 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | ||||
| 	serial_console_init(); | ||||
| 	platform_ops.fixups = platform_fixups; | ||||
|  | ||||
| @ -15,28 +15,16 @@ | ||||
| #include "ops.h" | ||||
| #include "stdio.h" | ||||
| #include "44x.h" | ||||
| #include "cuboot.h" | ||||
| 
 | ||||
| #define TARGET_44x | ||||
| #include "ppcboot.h" | ||||
| 
 | ||||
| static bd_t bd; | ||||
| extern char _end[]; | ||||
| 
 | ||||
| BSS_STACK(4096); | ||||
| 
 | ||||
| void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||||
|                    unsigned long r6, unsigned long r7) | ||||
| { | ||||
| 	unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | ||||
| 	unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||||
| 
 | ||||
| 	memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||||
| 	loader_info.initrd_addr = r4; | ||||
| 	loader_info.initrd_size = r4 ? r5 : 0; | ||||
| 	loader_info.cmdline = (char *)r6; | ||||
| 	loader_info.cmdline_len = r7 - r6; | ||||
| 
 | ||||
| 	simple_alloc_init(_end, avail_ram, 32, 64); | ||||
| 
 | ||||
| 	CUBOOT_INIT(); | ||||
| 	ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr); | ||||
| } | ||||
|  | ||||
							
								
								
									
										35
									
								
								arch/powerpc/boot/cuboot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								arch/powerpc/boot/cuboot.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| /*
 | ||||
|  * Compatibility for old (not device tree aware) U-Boot versions | ||||
|  * | ||||
|  * Author: Scott Wood <scottwood@freescale.com> | ||||
|  * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au> | ||||
|  * | ||||
|  * Copyright 2007 David Gibson, IBM Corporation. | ||||
|  * Copyright (c) 2007 Freescale Semiconductor, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU General Public License version 2 as published | ||||
|  * by the Free Software Foundation. | ||||
|  */ | ||||
| 
 | ||||
| #include "ops.h" | ||||
| #include "stdio.h" | ||||
| 
 | ||||
| #include "ppcboot.h" | ||||
| 
 | ||||
| extern char _end[]; | ||||
| extern char _dtb_start[], _dtb_end[]; | ||||
| 
 | ||||
| void cuboot_init(unsigned long r4, unsigned long r5, | ||||
| 		 unsigned long r6, unsigned long r7, | ||||
| 		 unsigned long end_of_ram) | ||||
| { | ||||
| 	unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||||
| 
 | ||||
| 	loader_info.initrd_addr = r4; | ||||
| 	loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||||
| 	loader_info.cmdline = (char *)r6; | ||||
| 	loader_info.cmdline_len = r7 - r6; | ||||
| 
 | ||||
| 	simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||||
| } | ||||
							
								
								
									
										14
									
								
								arch/powerpc/boot/cuboot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								arch/powerpc/boot/cuboot.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| #ifndef _PPC_BOOT_CUBOOT_H_ | ||||
| #define _PPC_BOOT_CUBOOT_H_ | ||||
| 
 | ||||
| void cuboot_init(unsigned long r4, unsigned long r5, | ||||
| 		 unsigned long r6, unsigned long r7, | ||||
| 		 unsigned long end_of_ram); | ||||
| 
 | ||||
| #define CUBOOT_INIT() \ | ||||
| 	do { \ | ||||
| 		memcpy(&bd, (bd_t *)r3, sizeof(bd)); \ | ||||
| 		cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #endif /* _PPC_BOOT_CUBOOT_H_ */ | ||||
| @ -26,6 +26,43 @@ static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2C | ||||
| #define			SDRAM_CONFIG_BANK_SIZE(reg)	\ | ||||
| 	(0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17)) | ||||
| 
 | ||||
| /* 440GP External Bus Controller (EBC) */ | ||||
| #define DCRN_EBC0_CFGADDR				0x012 | ||||
| #define DCRN_EBC0_CFGDATA				0x013 | ||||
| #define   EBC_NUM_BANKS					  8 | ||||
| #define   EBC_B0CR					  0x00 | ||||
| #define   EBC_B1CR					  0x01 | ||||
| #define   EBC_B2CR					  0x02 | ||||
| #define   EBC_B3CR					  0x03 | ||||
| #define   EBC_B4CR					  0x04 | ||||
| #define   EBC_B5CR					  0x05 | ||||
| #define   EBC_B6CR					  0x06 | ||||
| #define   EBC_B7CR					  0x07 | ||||
| #define   EBC_BXCR(n)					  (n) | ||||
| #define	    EBC_BXCR_BAS				    0xfff00000 | ||||
| #define	    EBC_BXCR_BS				  	    0x000e0000 | ||||
| #define	    EBC_BXCR_BANK_SIZE(reg) \ | ||||
| 	(0x100000 << (((reg) & EBC_BXCR_BS) >> 17)) | ||||
| #define	    EBC_BXCR_BU				  	    0x00018000 | ||||
| #define	      EBC_BXCR_BU_OFF			  	      0x00000000 | ||||
| #define	      EBC_BXCR_BU_RO			  	      0x00008000 | ||||
| #define	      EBC_BXCR_BU_WO			  	      0x00010000 | ||||
| #define	      EBC_BXCR_BU_RW			  	      0x00018000 | ||||
| #define	    EBC_BXCR_BW				  	    0x00006000 | ||||
| #define   EBC_B0AP					  0x10 | ||||
| #define   EBC_B1AP					  0x11 | ||||
| #define   EBC_B2AP					  0x12 | ||||
| #define   EBC_B3AP					  0x13 | ||||
| #define   EBC_B4AP					  0x14 | ||||
| #define   EBC_B5AP					  0x15 | ||||
| #define   EBC_B6AP					  0x16 | ||||
| #define   EBC_B7AP					  0x17 | ||||
| #define   EBC_BXAP(n)					  (0x10+(n)) | ||||
| #define   EBC_BEAR					  0x20 | ||||
| #define   EBC_BESR					  0x21 | ||||
| #define   EBC_CFG					  0x23 | ||||
| #define   EBC_CID					  0x24 | ||||
| 
 | ||||
| /* 440GP Clock, PM, chip control */ | ||||
| #define DCRN_CPC0_SR					0x0b0 | ||||
| #define DCRN_CPC0_ER					0x0b1 | ||||
|  | ||||
| @ -31,8 +31,8 @@ | ||||
| 			reg = <0>; | ||||
| 			clock-frequency = <0>; // Filled in by zImage | ||||
| 			timebase-frequency = <0>; // Filled in by zImage | ||||
| 			i-cache-line-size = <32>; | ||||
| 			d-cache-line-size = <32>; | ||||
| 			i-cache-line-size = <20>; | ||||
| 			d-cache-line-size = <20>; | ||||
| 			i-cache-size = <8000>; /* 32 kB */ | ||||
| 			d-cache-size = <8000>; /* 32 kB */ | ||||
| 			dcr-controller; | ||||
| @ -135,11 +135,9 @@ | ||||
| 				#address-cells = <2>; | ||||
| 				#size-cells = <1>; | ||||
| 				clock-frequency = <0>; // Filled in by zImage | ||||
| 				ranges = <0 00000000 fff00000 100000 | ||||
| 					  1 00000000 48000000 100000 | ||||
| 					  2 00000000 ff800000 400000 | ||||
| 					  3 00000000 48200000 100000 | ||||
| 					  7 00000000 48300000 100000>; | ||||
| 				// ranges property is supplied by zImage | ||||
| 				// based on firmware's configuration of the | ||||
| 				// EBC bridge | ||||
| 				interrupts = <5 4>; | ||||
| 				interrupt-parent = <&UIC1>; | ||||
| 
 | ||||
|  | ||||
| @ -46,7 +46,7 @@ | ||||
| 
 | ||||
|   	tsi109@c0000000 { | ||||
| 		device_type = "tsi-bridge"; | ||||
| 		compatible = "tsi-bridge"; | ||||
| 		compatible = "tsi109-bridge", "tsi108-bridge"; | ||||
| 		#address-cells = <1>; | ||||
| 		#size-cells = <1>; | ||||
| 		ranges = <00000000 c0000000 00010000>; | ||||
| @ -54,52 +54,55 @@ | ||||
| 
 | ||||
| 		i2c@7000 { | ||||
| 			device_type = "i2c"; | ||||
| 			compatible  = "tsi-i2c"; | ||||
| 			interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | ||||
| 			compatible  = "tsi109-i2c", "tsi108-i2c"; | ||||
| 			interrupt-parent = <&MPIC>; | ||||
| 			interrupts = <e 2>; | ||||
| 			reg = <7000 400>; | ||||
| 		}; | ||||
| 
 | ||||
| 		mdio@6000 { | ||||
| 		MDIO: mdio@6000 { | ||||
| 			device_type = "mdio"; | ||||
| 			compatible = "tsi-ethernet"; | ||||
| 			compatible = "tsi109-mdio", "tsi108-mdio"; | ||||
| 			reg = <6000 50>; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <0>; | ||||
| 
 | ||||
| 			PHY1: ethernet-phy@6000 { | ||||
| 				device_type = "ethernet-phy"; | ||||
| 				compatible = "bcm54xx"; | ||||
| 				reg = <6000 50>; | ||||
| 				phy-id = <1>; | ||||
| 			PHY1: ethernet-phy@1 { | ||||
| 				compatible = "bcm5461a"; | ||||
| 				reg = <1>; | ||||
| 				txc-rxc-delay-disable; | ||||
| 			}; | ||||
| 
 | ||||
| 			PHY2: ethernet-phy@6400 { | ||||
| 				device_type = "ethernet-phy"; | ||||
| 				compatible = "bcm54xx"; | ||||
| 				reg = <6000 50>; | ||||
| 				phy-id = <2>; | ||||
| 			PHY2: ethernet-phy@2 { | ||||
| 				compatible = "bcm5461a"; | ||||
| 				reg = <2>; | ||||
| 				txc-rxc-delay-disable; | ||||
| 			}; | ||||
| 		}; | ||||
| 
 | ||||
| 		ethernet@6200 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "tsi-ethernet"; | ||||
| 			compatible = "tsi109-ethernet", "tsi108-ethernet"; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <0>; | ||||
| 			reg = <6000 200>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | ||||
| 			interrupt-parent = <&MPIC>; | ||||
| 			interrupts = <10 2>; | ||||
| 			mdio-handle = <&MDIO>; | ||||
| 			phy-handle = <&PHY1>; | ||||
| 		}; | ||||
| 
 | ||||
| 		ethernet@6600 { | ||||
| 			device_type = "network"; | ||||
| 			compatible = "tsi-ethernet"; | ||||
| 			compatible = "tsi109-ethernet", "tsi108-ethernet"; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <0>; | ||||
| 			reg = <6400 200>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | ||||
| 			interrupt-parent = <&MPIC>; | ||||
| 			interrupts = <11 2>; | ||||
| 			mdio-handle = <&MDIO>; | ||||
| 			phy-handle = <&PHY2>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -110,7 +113,7 @@ | ||||
| 			virtual-reg = <c0007808>; | ||||
| 			clock-frequency = <3F9C6000>; | ||||
| 			current-speed = <1c200>; | ||||
| 			interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | ||||
| 			interrupt-parent = <&MPIC>; | ||||
| 			interrupts = <c 2>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -121,7 +124,7 @@ | ||||
| 			virtual-reg = <c0007c08>; | ||||
| 			clock-frequency = <3F9C6000>; | ||||
| 			current-speed = <1c200>; | ||||
| 			interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | ||||
| 			interrupt-parent = <&MPIC>; | ||||
| 			interrupts = <d 2>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -136,7 +139,7 @@ | ||||
| 
 | ||||
| 		pci@1000 { | ||||
| 			device_type = "pci"; | ||||
| 			compatible = "tsi109"; | ||||
| 			compatible = "tsi109-pci", "tsi108-pci"; | ||||
| 			#interrupt-cells = <1>; | ||||
| 			#size-cells = <2>; | ||||
| 			#address-cells = <3>; | ||||
| @ -150,7 +153,7 @@ | ||||
| 			ranges = <02000000 0 40000000 40000000 0 10000000 | ||||
| 				  01000000 0 00000000 7e000000 0 00010000>; | ||||
| 			clock-frequency = <7f28154>; | ||||
| 			interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | ||||
| 			interrupt-parent = <&MPIC>; | ||||
| 			interrupts = <17 2>; | ||||
| 			interrupt-map-mask = <f800 0 0 7>; | ||||
| 			/*----------------------------------------------------+ | ||||
| @ -186,13 +189,12 @@ | ||||
|  				#address-cells = <0>; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <17 2>; | ||||
| 				interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | ||||
| 				interrupt-parent = <&MPIC>; | ||||
| 			}; | ||||
| 		}; | ||||
| 	}; | ||||
| 
 | ||||
| 	chosen { | ||||
| 		linux,stdout-path = "/tsi109@c0000000/serial@7808"; | ||||
| 		bootargs = "console=ttyS0,115200"; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| @ -45,7 +45,7 @@ | ||||
| 		#address-cells = <1>; | ||||
| 		#size-cells = <1>; | ||||
| 		#interrupt-cells = <2>; | ||||
| 		device_type = "tsi-bridge"; | ||||
| 		device_type = "tsi108-bridge"; | ||||
| 		ranges = <00000000 c0000000 00010000>; | ||||
| 		reg = <c0000000 00010000>; | ||||
| 		bus-frequency = <0>; | ||||
| @ -55,27 +55,26 @@ | ||||
| 			interrupts = <E 0>; | ||||
| 			reg = <7000 400>; | ||||
| 			device_type = "i2c"; | ||||
| 			compatible  = "tsi-i2c"; | ||||
| 			compatible  = "tsi108-i2c"; | ||||
| 		}; | ||||
| 
 | ||||
| 		mdio@6000 { | ||||
| 		MDIO: mdio@6000 { | ||||
| 			device_type = "mdio"; | ||||
| 			compatible = "tsi-ethernet"; | ||||
| 			compatible = "tsi108-mdio"; | ||||
| 			reg = <6000 50>; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <0>; | ||||
| 
 | ||||
| 			phy8: ethernet-phy@6000 { | ||||
| 			phy8: ethernet-phy@8 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <2 1>; | ||||
| 				reg = <6000 50>; | ||||
| 				phy-id = <8>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 				reg = <8>; | ||||
| 			}; | ||||
| 
 | ||||
| 			phy9: ethernet-phy@6400 { | ||||
| 			phy9: ethernet-phy@9 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <2 1>; | ||||
| 				reg = <6000 50>; | ||||
| 				phy-id = <9>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 				reg = <9>; | ||||
| 			}; | ||||
| 
 | ||||
| 		}; | ||||
| @ -83,12 +82,12 @@ | ||||
| 		ethernet@6200 { | ||||
| 			#size-cells = <0>; | ||||
| 			device_type = "network"; | ||||
| 			model = "TSI-ETH"; | ||||
| 			compatible = "tsi-ethernet"; | ||||
| 			compatible = "tsi108-ethernet"; | ||||
| 			reg = <6000 200>; | ||||
| 			address = [ 00 06 D2 00 00 01 ]; | ||||
| 			interrupts = <10 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			mdio-handle = <&MDIO>; | ||||
| 			phy-handle = <&phy8>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -96,12 +95,12 @@ | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <0>; | ||||
| 			device_type = "network"; | ||||
| 			model = "TSI-ETH"; | ||||
| 			compatible = "tsi-ethernet"; | ||||
| 			compatible = "tsi108-ethernet"; | ||||
| 			reg = <6400 200>; | ||||
| 			address = [ 00 06 D2 00 00 02 ]; | ||||
| 			interrupts = <11 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			mdio-handle = <&MDIO>; | ||||
| 			phy-handle = <&phy9>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -135,7 +134,7 @@ | ||||
|                        	big-endian; | ||||
| 		}; | ||||
| 		pci@1000 { | ||||
| 			compatible = "tsi10x"; | ||||
| 			compatible = "tsi108-pci"; | ||||
| 			device_type = "pci"; | ||||
| 			#interrupt-cells = <1>; | ||||
| 			#size-cells = <2>; | ||||
|  | ||||
| @ -14,12 +14,10 @@ | ||||
|        compatible = "MPC8260ADS"; | ||||
|        #address-cells = <1>; | ||||
|        #size-cells = <1>; | ||||
|        linux,phandle = <100>; | ||||
| 
 | ||||
|        cpus { | ||||
|                #address-cells = <1>; | ||||
|                #size-cells = <0>; | ||||
|                linux,phandle = <200>; | ||||
| 
 | ||||
|                PowerPC,8272@0 { | ||||
|                        device_type = "cpu"; | ||||
| @ -32,12 +30,10 @@ | ||||
|                        bus-frequency = <0>; | ||||
|                        clock-frequency = <0>; | ||||
|                        32-bit; | ||||
|                        linux,phandle = <201>; | ||||
|                }; | ||||
|        }; | ||||
| 
 | ||||
|        interrupt-controller@f8200000 { | ||||
|                linux,phandle = <f8200000>; | ||||
| 		pci_pic: interrupt-controller@f8200000 { | ||||
|                #address-cells = <0>; | ||||
|                #interrupt-cells = <2>; | ||||
|                interrupt-controller; | ||||
| @ -47,15 +43,13 @@ | ||||
|        }; | ||||
|        memory { | ||||
|                device_type = "memory"; | ||||
|                linux,phandle = <300>; | ||||
|                reg = <00000000 4000000 f4500000 00000020>; | ||||
|        }; | ||||
| 
 | ||||
|        chosen { | ||||
|                name = "chosen"; | ||||
|                linux,platform = <0>; | ||||
|                interrupt-controller = <10c00>; | ||||
|                linux,phandle = <400>; | ||||
| 		interrupt-controller = <&Cpm_pic>; | ||||
|        }; | ||||
| 
 | ||||
|        soc8272@f0000000 { | ||||
| @ -70,20 +64,17 @@ | ||||
|                        device_type = "mdio"; | ||||
|                        compatible = "fs_enet"; | ||||
|                        reg = <0 0>; | ||||
|                        linux,phandle = <24520>; | ||||
|                        #address-cells = <1>; | ||||
|                        #size-cells = <0>; | ||||
|                        ethernet-phy@0 { | ||||
|                                linux,phandle = <2452000>; | ||||
|                                interrupt-parent = <10c00>; | ||||
| 			phy0:ethernet-phy@0 { | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
|                                interrupts = <17 4>; | ||||
|                                reg = <0>; | ||||
|                                bitbang = [ 12 12 13 02 02 01 ]; | ||||
|                                device_type = "ethernet-phy"; | ||||
|                        }; | ||||
|                        ethernet-phy@1 { | ||||
|                                linux,phandle = <2452001>; | ||||
|                                interrupt-parent = <10c00>; | ||||
| 			phy1:ethernet-phy@1 { | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
|                                interrupts = <17 4>; | ||||
|                                bitbang = [ 12 12 13 02 02 01 ]; | ||||
|                                reg = <3>; | ||||
| @ -101,8 +92,8 @@ | ||||
|                        reg = <11300 20 8400 100 11380 30>; | ||||
|                        mac-address = [ 00 11 2F 99 43 54 ]; | ||||
|                        interrupts = <20 2>; | ||||
|                        interrupt-parent = <10c00>; | ||||
|                        phy-handle = <2452000>; | ||||
| 			interrupt-parent = <&Cpm_pic>; | ||||
| 			phy-handle = <&Phy0>; | ||||
|                        rx-clock = <13>; | ||||
|                        tx-clock = <12>; | ||||
|                }; | ||||
| @ -115,14 +106,13 @@ | ||||
|                        reg = <11320 20 8500 100 113b0 30>; | ||||
|                        mac-address = [ 00 11 2F 99 44 54 ]; | ||||
|                        interrupts = <21 2>; | ||||
|                        interrupt-parent = <10c00>; | ||||
|                        phy-handle = <2452001>; | ||||
| 			interrupt-parent = <&Cpm_pic>; | ||||
| 			phy-handle = <&Phy1>; | ||||
|                        rx-clock = <17>; | ||||
|                        tx-clock = <18>; | ||||
|                }; | ||||
| 
 | ||||
|                cpm@f0000000 { | ||||
|                        linux,phandle = <f0000000>; | ||||
|                        #address-cells = <1>; | ||||
|                        #size-cells = <1>; | ||||
|                        #interrupt-cells = <2>; | ||||
| @ -142,7 +132,7 @@ | ||||
|                                reg = <11a00 20 8000 100>; | ||||
|                                current-speed = <1c200>; | ||||
|                                interrupts = <28 2>; | ||||
|                                interrupt-parent = <10c00>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
|                                clock-setup = <0 00ffffff>; | ||||
|                                rx-clock = <1>; | ||||
|                                tx-clock = <1>; | ||||
| @ -156,15 +146,14 @@ | ||||
|                                reg = <11a60 20 8300 100>; | ||||
|                                current-speed = <1c200>; | ||||
|                                interrupts = <2b 2>; | ||||
|                                interrupt-parent = <10c00>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
|                                clock-setup = <1b ffffff00>; | ||||
|                                rx-clock = <4>; | ||||
|                                tx-clock = <4>; | ||||
|                        }; | ||||
| 
 | ||||
|                }; | ||||
|                interrupt-controller@10c00 { | ||||
|                        linux,phandle = <10c00>; | ||||
| 			cpm_pic:interrupt-controller@10c00 { | ||||
|                        #address-cells = <0>; | ||||
|                        #interrupt-cells = <2>; | ||||
|                        interrupt-controller; | ||||
| @ -174,7 +163,6 @@ | ||||
| 		       compatible = "CPM2"; | ||||
|                }; | ||||
|                pci@0500 { | ||||
|                        linux,phandle = <0500>; | ||||
|                        #interrupt-cells = <1>; | ||||
|                        #size-cells = <2>; | ||||
|                        #address-cells = <3>; | ||||
| @ -202,7 +190,7 @@ | ||||
|                                         c000 0 0 2 f8200000 43 8 | ||||
|                                         c000 0 0 3 f8200000 40 8 | ||||
|                                         c000 0 0 4 f8200000 41 8>; | ||||
|                        interrupt-parent = <10c00>; | ||||
| 			interrupt-parent = <&Cpm_pic>; | ||||
|                        interrupts = <14 8>; | ||||
|                        bus-range = <0 0>; | ||||
|                        ranges = <02000000 0 80000000 80000000 0 40000000 | ||||
| @ -216,7 +204,7 @@ | ||||
|                        compatible = "talitos"; | ||||
|                        reg = <30000 10000>; | ||||
|                        interrupts = <b 2>; | ||||
|                        interrupt-parent = <10c00>; | ||||
| 			interrupt-parent = <&Cpm_pic>; | ||||
|                        num-channels = <4>; | ||||
|                        channel-fifo-len = <18>; | ||||
|                        exec-units-mask = <0000007e>; | ||||
|  | ||||
| @ -272,7 +272,13 @@ | ||||
| 			reg = <2200 200>; | ||||
| 			interrupts = <22>; | ||||
| 			interrupt-parent = < &qeic >; | ||||
| 			mac-address = [ 00 04 9f 00 23 23 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <19>; | ||||
| 			tx-clock = <1a>; | ||||
| 			phy-handle = < &phy3 >; | ||||
| @ -287,7 +293,13 @@ | ||||
| 			reg = <3000 200>; | ||||
| 			interrupts = <23>; | ||||
| 			interrupt-parent = < &qeic >; | ||||
| 			mac-address = [ 00 11 22 33 44 55 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <17>; | ||||
| 			tx-clock = <18>; | ||||
| 			phy-handle = < &phy4 >; | ||||
|  | ||||
| @ -231,7 +231,13 @@ | ||||
| 			reg = <3000 200>; | ||||
| 			interrupts = <21>; | ||||
| 			interrupt-parent = <&qeic>; | ||||
| 			mac-address = [ 00 04 9f ef 03 02 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <20>; | ||||
| 			tx-clock = <13>; | ||||
| 			phy-handle = <&phy00>; | ||||
| @ -246,7 +252,13 @@ | ||||
| 			reg = <2200 200>; | ||||
| 			interrupts = <22>; | ||||
| 			interrupt-parent = <&qeic>; | ||||
| 			mac-address = [ 00 04 9f ef 03 01 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <19>; | ||||
| 			tx-clock = <1a>; | ||||
| 			phy-handle = <&phy04>; | ||||
|  | ||||
| @ -131,6 +131,11 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <20 8 21 8 22 8>; | ||||
| @ -145,6 +150,11 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 8 24 8 25 8>; | ||||
|  | ||||
| @ -136,6 +136,11 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <20 8 21 8 22 8>; | ||||
| @ -150,6 +155,11 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 8 24 8 25 8>; | ||||
|  | ||||
| @ -301,7 +301,13 @@ | ||||
| 			reg = <2000 200>; | ||||
| 			interrupts = <20>; | ||||
| 			interrupt-parent = < &qeic >; | ||||
| 			mac-address = [ 00 04 9f 00 23 23 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <0>; | ||||
| 			tx-clock = <19>; | ||||
| 			phy-handle = < &phy0 >; | ||||
| @ -317,7 +323,13 @@ | ||||
| 			reg = <3000 200>; | ||||
| 			interrupts = <21>; | ||||
| 			interrupt-parent = < &qeic >; | ||||
| 			mac-address = [ 00 11 22 33 44 55 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <0>; | ||||
| 			tx-clock = <14>; | ||||
| 			phy-handle = < &phy1 >; | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
| 			compatible = "fsl,8540-memory-controller"; | ||||
| 			reg = <2000 1000>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <2 2>; | ||||
| 			interrupts = <12 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		l2-cache-controller@20000 { | ||||
| @ -61,14 +61,14 @@ | ||||
| 			cache-line-size = <20>;	// 32 bytes | ||||
| 			cache-size = <40000>;	// L2, 256K | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <0 2>; | ||||
| 			interrupts = <10 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		i2c@3000 { | ||||
| 			device_type = "i2c"; | ||||
| 			compatible = "fsl-i2c"; | ||||
| 			reg = <3000 100>; | ||||
| 			interrupts = <1b 2>; | ||||
| 			interrupts = <2b 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			dfsrr; | ||||
| 		}; | ||||
| @ -81,19 +81,19 @@ | ||||
| 			reg = <24520 20>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 1>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 1>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy3: ethernet-phy@3 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <37 1>; | ||||
| 				interrupts = <7 1>; | ||||
| 				reg = <3>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -106,9 +106,14 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			address = [ 00 E0 0C 00 73 00 ]; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 00 ]; | ||||
| 			interrupts = <d 2 e 2 12 2>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy0>; | ||||
| 		}; | ||||
| @ -120,9 +125,14 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			address = [ 00 E0 0C 00 73 01 ]; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 01 ]; | ||||
| 			interrupts = <13 2 14 2 18 2>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 2 24 2 28 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy1>; | ||||
| 		}; | ||||
| @ -134,9 +144,14 @@ | ||||
| 			model = "FEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <26000 1000>; | ||||
| 			address = [ 00 E0 0C 00 73 02 ]; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 02 ]; | ||||
| 			interrupts = <19 2>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <29 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy3>; | ||||
| 		}; | ||||
| @ -146,7 +161,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4500 100>; 	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -155,7 +170,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4600 100>;	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 		pci@8000 { | ||||
| @ -163,78 +178,78 @@ | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 				/* IDSEL 0x02 */ | ||||
| 				1000 0 0 1 &mpic 31 1 | ||||
| 				1000 0 0 2 &mpic 32 1 | ||||
| 				1000 0 0 3 &mpic 33 1 | ||||
| 				1000 0 0 4 &mpic 34 1 | ||||
| 				1000 0 0 1 &mpic 1 1 | ||||
| 				1000 0 0 2 &mpic 2 1 | ||||
| 				1000 0 0 3 &mpic 3 1 | ||||
| 				1000 0 0 4 &mpic 4 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x03 */ | ||||
| 				1800 0 0 1 &mpic 34 1 | ||||
| 				1800 0 0 2 &mpic 31 1 | ||||
| 				1800 0 0 3 &mpic 32 1 | ||||
| 				1800 0 0 4 &mpic 33 1 | ||||
| 				1800 0 0 1 &mpic 4 1 | ||||
| 				1800 0 0 2 &mpic 1 1 | ||||
| 				1800 0 0 3 &mpic 2 1 | ||||
| 				1800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x04 */ | ||||
| 				2000 0 0 1 &mpic 33 1 | ||||
| 				2000 0 0 2 &mpic 34 1 | ||||
| 				2000 0 0 3 &mpic 31 1 | ||||
| 				2000 0 0 4 &mpic 32 1 | ||||
| 				2000 0 0 1 &mpic 3 1 | ||||
| 				2000 0 0 2 &mpic 4 1 | ||||
| 				2000 0 0 3 &mpic 1 1 | ||||
| 				2000 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x05 */ | ||||
| 				2800 0 0 1 &mpic 32 1 | ||||
| 				2800 0 0 2 &mpic 33 1 | ||||
| 				2800 0 0 3 &mpic 34 1 | ||||
| 				2800 0 0 4 &mpic 31 1 | ||||
| 				2800 0 0 1 &mpic 2 1 | ||||
| 				2800 0 0 2 &mpic 3 1 | ||||
| 				2800 0 0 3 &mpic 4 1 | ||||
| 				2800 0 0 4 &mpic 1 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x0c */ | ||||
| 				6000 0 0 1 &mpic 31 1 | ||||
| 				6000 0 0 2 &mpic 32 1 | ||||
| 				6000 0 0 3 &mpic 33 1 | ||||
| 				6000 0 0 4 &mpic 34 1 | ||||
| 				6000 0 0 1 &mpic 1 1 | ||||
| 				6000 0 0 2 &mpic 2 1 | ||||
| 				6000 0 0 3 &mpic 3 1 | ||||
| 				6000 0 0 4 &mpic 4 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x0d */ | ||||
| 				6800 0 0 1 &mpic 34 1 | ||||
| 				6800 0 0 2 &mpic 31 1 | ||||
| 				6800 0 0 3 &mpic 32 1 | ||||
| 				6800 0 0 4 &mpic 33 1 | ||||
| 				6800 0 0 1 &mpic 4 1 | ||||
| 				6800 0 0 2 &mpic 1 1 | ||||
| 				6800 0 0 3 &mpic 2 1 | ||||
| 				6800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x0e */ | ||||
| 				7000 0 0 1 &mpic 33 1 | ||||
| 				7000 0 0 2 &mpic 34 1 | ||||
| 				7000 0 0 3 &mpic 31 1 | ||||
| 				7000 0 0 4 &mpic 32 1 | ||||
| 				7000 0 0 1 &mpic 3 1 | ||||
| 				7000 0 0 2 &mpic 4 1 | ||||
| 				7000 0 0 3 &mpic 1 1 | ||||
| 				7000 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x0f */ | ||||
| 				7800 0 0 1 &mpic 32 1 | ||||
| 				7800 0 0 2 &mpic 33 1 | ||||
| 				7800 0 0 3 &mpic 34 1 | ||||
| 				7800 0 0 4 &mpic 31 1 | ||||
| 				7800 0 0 1 &mpic 2 1 | ||||
| 				7800 0 0 2 &mpic 3 1 | ||||
| 				7800 0 0 3 &mpic 4 1 | ||||
| 				7800 0 0 4 &mpic 1 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x12 */ | ||||
| 				9000 0 0 1 &mpic 31 1 | ||||
| 				9000 0 0 2 &mpic 32 1 | ||||
| 				9000 0 0 3 &mpic 33 1 | ||||
| 				9000 0 0 4 &mpic 34 1 | ||||
| 				9000 0 0 1 &mpic 1 1 | ||||
| 				9000 0 0 2 &mpic 2 1 | ||||
| 				9000 0 0 3 &mpic 3 1 | ||||
| 				9000 0 0 4 &mpic 4 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x13 */ | ||||
| 				9800 0 0 1 &mpic 34 1 | ||||
| 				9800 0 0 2 &mpic 31 1 | ||||
| 				9800 0 0 3 &mpic 32 1 | ||||
| 				9800 0 0 4 &mpic 33 1 | ||||
| 				9800 0 0 1 &mpic 4 1 | ||||
| 				9800 0 0 2 &mpic 1 1 | ||||
| 				9800 0 0 3 &mpic 2 1 | ||||
| 				9800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x14 */ | ||||
| 				a000 0 0 1 &mpic 33 1 | ||||
| 				a000 0 0 2 &mpic 34 1 | ||||
| 				a000 0 0 3 &mpic 31 1 | ||||
| 				a000 0 0 4 &mpic 32 1 | ||||
| 				a000 0 0 1 &mpic 3 1 | ||||
| 				a000 0 0 2 &mpic 4 1 | ||||
| 				a000 0 0 3 &mpic 1 1 | ||||
| 				a000 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x15 */ | ||||
| 				a800 0 0 1 &mpic 32 1 | ||||
| 				a800 0 0 2 &mpic 33 1 | ||||
| 				a800 0 0 3 &mpic 34 1 | ||||
| 				a800 0 0 4 &mpic 31 1>; | ||||
| 				a800 0 0 1 &mpic 2 1 | ||||
| 				a800 0 0 2 &mpic 3 1 | ||||
| 				a800 0 0 3 &mpic 4 1 | ||||
| 				a800 0 0 4 &mpic 1 1>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <08 2>; | ||||
| 			interrupts = <18 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 80000000 80000000 0 20000000 | ||||
| 				  01000000 0 00000000 e2000000 0 00100000>; | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
| 			compatible = "fsl,8541-memory-controller"; | ||||
| 			reg = <2000 1000>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <2 2>; | ||||
| 			interrupts = <12 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		l2-cache-controller@20000 { | ||||
| @ -61,14 +61,14 @@ | ||||
| 			cache-line-size = <20>;	// 32 bytes | ||||
| 			cache-size = <40000>;	// L2, 256K | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <0 2>; | ||||
| 			interrupts = <10 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		i2c@3000 { | ||||
| 			device_type = "i2c"; | ||||
| 			compatible = "fsl-i2c"; | ||||
| 			reg = <3000 100>; | ||||
| 			interrupts = <1b 2>; | ||||
| 			interrupts = <2b 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			dfsrr; | ||||
| 		}; | ||||
| @ -81,13 +81,13 @@ | ||||
| 			reg = <24520 20>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -100,8 +100,8 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 00 ]; | ||||
| 			interrupts = <d 2 e 2 12 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy0>; | ||||
| 		}; | ||||
| @ -113,8 +113,8 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 01 ]; | ||||
| 			interrupts = <13 2 14 2 18 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 2 24 2 28 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy1>; | ||||
| 		}; | ||||
| @ -124,7 +124,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4500 100>; 	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -133,7 +133,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4600 100>;	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -142,49 +142,49 @@ | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 				/* IDSEL 0x10 */ | ||||
| 				08000 0 0 1 &mpic 30 1 | ||||
| 				08000 0 0 2 &mpic 31 1 | ||||
| 				08000 0 0 3 &mpic 32 1 | ||||
| 				08000 0 0 4 &mpic 33 1 | ||||
| 				08000 0 0 1 &mpic 0 1 | ||||
| 				08000 0 0 2 &mpic 1 1 | ||||
| 				08000 0 0 3 &mpic 2 1 | ||||
| 				08000 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x11 */ | ||||
| 				08800 0 0 1 &mpic 30 1 | ||||
| 				08800 0 0 2 &mpic 31 1 | ||||
| 				08800 0 0 3 &mpic 32 1 | ||||
| 				08800 0 0 4 &mpic 33 1 | ||||
| 				08800 0 0 1 &mpic 0 1 | ||||
| 				08800 0 0 2 &mpic 1 1 | ||||
| 				08800 0 0 3 &mpic 2 1 | ||||
| 				08800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x12 (Slot 1) */ | ||||
| 				09000 0 0 1 &mpic 30 1 | ||||
| 				09000 0 0 2 &mpic 31 1 | ||||
| 				09000 0 0 3 &mpic 32 1 | ||||
| 				09000 0 0 4 &mpic 33 1 | ||||
| 				09000 0 0 1 &mpic 0 1 | ||||
| 				09000 0 0 2 &mpic 1 1 | ||||
| 				09000 0 0 3 &mpic 2 1 | ||||
| 				09000 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x13 (Slot 2) */ | ||||
| 				09800 0 0 1 &mpic 31 1 | ||||
| 				09800 0 0 2 &mpic 32 1 | ||||
| 				09800 0 0 3 &mpic 33 1 | ||||
| 				09800 0 0 4 &mpic 30 1 | ||||
| 				09800 0 0 1 &mpic 1 1 | ||||
| 				09800 0 0 2 &mpic 2 1 | ||||
| 				09800 0 0 3 &mpic 3 1 | ||||
| 				09800 0 0 4 &mpic 0 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x14 (Slot 3) */ | ||||
| 				0a000 0 0 1 &mpic 32 1 | ||||
| 				0a000 0 0 2 &mpic 33 1 | ||||
| 				0a000 0 0 3 &mpic 30 1 | ||||
| 				0a000 0 0 4 &mpic 31 1 | ||||
| 				0a000 0 0 1 &mpic 2 1 | ||||
| 				0a000 0 0 2 &mpic 3 1 | ||||
| 				0a000 0 0 3 &mpic 0 1 | ||||
| 				0a000 0 0 4 &mpic 1 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x15 (Slot 4) */ | ||||
| 				0a800 0 0 1 &mpic 33 1 | ||||
| 				0a800 0 0 2 &mpic 30 1 | ||||
| 				0a800 0 0 3 &mpic 31 1 | ||||
| 				0a800 0 0 4 &mpic 32 1 | ||||
| 				0a800 0 0 1 &mpic 3 1 | ||||
| 				0a800 0 0 2 &mpic 0 1 | ||||
| 				0a800 0 0 3 &mpic 1 1 | ||||
| 				0a800 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 				/* Bus 1 (Tundra Bridge) */ | ||||
| 				/* IDSEL 0x12 (ISA bridge) */ | ||||
| 				19000 0 0 1 &mpic 30 1 | ||||
| 				19000 0 0 2 &mpic 31 1 | ||||
| 				19000 0 0 3 &mpic 32 1 | ||||
| 				19000 0 0 4 &mpic 33 1>; | ||||
| 				19000 0 0 1 &mpic 0 1 | ||||
| 				19000 0 0 2 &mpic 1 1 | ||||
| 				19000 0 0 3 &mpic 2 1 | ||||
| 				19000 0 0 4 &mpic 3 1>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <08 2>; | ||||
| 			interrupts = <18 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 80000000 80000000 0 20000000 | ||||
| 				  01000000 0 00000000 e2000000 0 00100000>; | ||||
| @ -216,12 +216,12 @@ | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 				/* IDSEL 0x15 */ | ||||
| 				a800 0 0 1 &mpic 3b 1 | ||||
| 				a800 0 0 2 &mpic 3b 1 | ||||
| 				a800 0 0 3 &mpic 3b 1 | ||||
| 				a800 0 0 4 &mpic 3b 1>; | ||||
| 				a800 0 0 1 &mpic b 1 | ||||
| 				a800 0 0 2 &mpic b 1 | ||||
| 				a800 0 0 3 &mpic b 1 | ||||
| 				a800 0 0 4 &mpic b 1>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <09 2>; | ||||
| 			interrupts = <19 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 a0000000 a0000000 0 20000000 | ||||
| 				  01000000 0 00000000 e3000000 0 00100000>; | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
| 			compatible = "fsl,8544-memory-controller"; | ||||
| 			reg = <2000 1000>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <2 2>; | ||||
| 			interrupts = <12 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		l2-cache-controller@20000 { | ||||
| @ -61,14 +61,14 @@ | ||||
| 			cache-line-size = <20>;	// 32 bytes | ||||
| 			cache-size = <40000>;	// L2, 256K | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <0 2>; | ||||
| 			interrupts = <10 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		i2c@3000 { | ||||
| 			device_type = "i2c"; | ||||
| 			compatible = "fsl-i2c"; | ||||
| 			reg = <3000 100>; | ||||
| 			interrupts = <1b 2>; | ||||
| 			interrupts = <2b 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			dfsrr; | ||||
| 		}; | ||||
| @ -81,13 +81,13 @@ | ||||
| 			reg = <24520 20>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <3a 1>; | ||||
| 				interrupts = <a 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <3a 1>; | ||||
| 				interrupts = <a 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -101,7 +101,7 @@ | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <d 2 e 2 12 2>; | ||||
| 			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy0>; | ||||
| 		}; | ||||
| @ -114,7 +114,7 @@ | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <26000 1000>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <f 2 10 2 11 2>; | ||||
| 			interrupts = <1f 2 20 2 21 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy1>; | ||||
| 		}; | ||||
| @ -124,7 +124,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4500 100>; | ||||
| 			clock-frequency = <0>; | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -133,7 +133,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4600 100>; | ||||
| 			clock-frequency = <0>; | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
| 			compatible = "fsl,8548-memory-controller"; | ||||
| 			reg = <2000 1000>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <2 2>; | ||||
| 			interrupts = <12 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		l2-cache-controller@20000 { | ||||
| @ -61,14 +61,14 @@ | ||||
| 			cache-line-size = <20>;	// 32 bytes | ||||
| 			cache-size = <80000>;	// L2, 512K | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <0 2>; | ||||
| 			interrupts = <10 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		i2c@3000 { | ||||
| 			device_type = "i2c"; | ||||
| 			compatible = "fsl-i2c"; | ||||
| 			reg = <3000 100>; | ||||
| 			interrupts = <1b 2>; | ||||
| 			interrupts = <2b 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			dfsrr; | ||||
| 		}; | ||||
| @ -81,25 +81,25 @@ | ||||
| 			reg = <24520 20>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy2: ethernet-phy@2 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <2>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy3: ethernet-phy@3 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <3>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -112,8 +112,8 @@ | ||||
| 			model = "eTSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 00 ]; | ||||
| 			interrupts = <d 2 e 2 12 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy0>; | ||||
| 		}; | ||||
| @ -125,8 +125,8 @@ | ||||
| 			model = "eTSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 01 ]; | ||||
| 			interrupts = <13 2 14 2 18 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 2 24 2 28 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy1>; | ||||
| 		}; | ||||
| @ -139,8 +139,8 @@ | ||||
| 			model = "eTSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <26000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 02 ]; | ||||
| 			interrupts = <f 2 10 2 11 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1f 2 20 2 21 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy2>; | ||||
| 		}; | ||||
| @ -152,8 +152,8 @@ | ||||
| 			model = "eTSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <27000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 03 ]; | ||||
| 			interrupts = <15 2 16 2 17 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <25 2 26 2 27 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy3>; | ||||
| 		}; | ||||
| @ -164,7 +164,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4500 100>; 	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -173,58 +173,64 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4600 100>;	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| 		global-utilities@e0000 {	//global utilities reg | ||||
| 			compatible = "fsl,mpc8548-guts"; | ||||
| 			reg = <e0000 1000>; | ||||
| 			fsl,has-rstcr; | ||||
| 		}; | ||||
| 
 | ||||
| 		pci1: pci@8000 { | ||||
| 			interrupt-map-mask = <1f800 0 0 7>; | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 				/* IDSEL 0x10 */ | ||||
| 				08000 0 0 1 &mpic 30 1 | ||||
| 				08000 0 0 2 &mpic 31 1 | ||||
| 				08000 0 0 3 &mpic 32 1 | ||||
| 				08000 0 0 4 &mpic 33 1 | ||||
| 				08000 0 0 1 &mpic 0 1 | ||||
| 				08000 0 0 2 &mpic 1 1 | ||||
| 				08000 0 0 3 &mpic 2 1 | ||||
| 				08000 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x11 */ | ||||
| 				08800 0 0 1 &mpic 30 1 | ||||
| 				08800 0 0 2 &mpic 31 1 | ||||
| 				08800 0 0 3 &mpic 32 1 | ||||
| 				08800 0 0 4 &mpic 33 1 | ||||
| 				08800 0 0 1 &mpic 0 1 | ||||
| 				08800 0 0 2 &mpic 1 1 | ||||
| 				08800 0 0 3 &mpic 2 1 | ||||
| 				08800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x12 (Slot 1) */ | ||||
| 				09000 0 0 1 &mpic 30 1 | ||||
| 				09000 0 0 2 &mpic 31 1 | ||||
| 				09000 0 0 3 &mpic 32 1 | ||||
| 				09000 0 0 4 &mpic 33 1 | ||||
| 				09000 0 0 1 &mpic 0 1 | ||||
| 				09000 0 0 2 &mpic 1 1 | ||||
| 				09000 0 0 3 &mpic 2 1 | ||||
| 				09000 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x13 (Slot 2) */ | ||||
| 				09800 0 0 1 &mpic 31 1 | ||||
| 				09800 0 0 2 &mpic 32 1 | ||||
| 				09800 0 0 3 &mpic 33 1 | ||||
| 				09800 0 0 4 &mpic 30 1 | ||||
| 				09800 0 0 1 &mpic 1 1 | ||||
| 				09800 0 0 2 &mpic 2 1 | ||||
| 				09800 0 0 3 &mpic 3 1 | ||||
| 				09800 0 0 4 &mpic 0 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x14 (Slot 3) */ | ||||
| 				0a000 0 0 1 &mpic 32 1 | ||||
| 				0a000 0 0 2 &mpic 33 1 | ||||
| 				0a000 0 0 3 &mpic 30 1 | ||||
| 				0a000 0 0 4 &mpic 31 1 | ||||
| 				0a000 0 0 1 &mpic 2 1 | ||||
| 				0a000 0 0 2 &mpic 3 1 | ||||
| 				0a000 0 0 3 &mpic 0 1 | ||||
| 				0a000 0 0 4 &mpic 1 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x15 (Slot 4) */ | ||||
| 				0a800 0 0 1 &mpic 33 1 | ||||
| 				0a800 0 0 2 &mpic 30 1 | ||||
| 				0a800 0 0 3 &mpic 31 1 | ||||
| 				0a800 0 0 4 &mpic 32 1 | ||||
| 				0a800 0 0 1 &mpic 3 1 | ||||
| 				0a800 0 0 2 &mpic 0 1 | ||||
| 				0a800 0 0 3 &mpic 1 1 | ||||
| 				0a800 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 				/* Bus 1 (Tundra Bridge) */ | ||||
| 				/* IDSEL 0x12 (ISA bridge) */ | ||||
| 				19000 0 0 1 &mpic 30 1 | ||||
| 				19000 0 0 2 &mpic 31 1 | ||||
| 				19000 0 0 3 &mpic 32 1 | ||||
| 				19000 0 0 4 &mpic 33 1>; | ||||
| 				19000 0 0 1 &mpic 0 1 | ||||
| 				19000 0 0 2 &mpic 1 1 | ||||
| 				19000 0 0 3 &mpic 2 1 | ||||
| 				19000 0 0 4 &mpic 3 1>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <08 2>; | ||||
| 			interrupts = <18 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 80000000 80000000 0 20000000 | ||||
| 				  01000000 0 00000000 e2000000 0 00100000>; | ||||
| @ -256,12 +262,12 @@ | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 				/* IDSEL 0x15 */ | ||||
| 				a800 0 0 1 &mpic 3b 1 | ||||
| 				a800 0 0 2 &mpic 3b 1 | ||||
| 				a800 0 0 3 &mpic 3b 1 | ||||
| 				a800 0 0 4 &mpic 3b 1>; | ||||
| 				a800 0 0 1 &mpic b 1 | ||||
| 				a800 0 0 2 &mpic b 1 | ||||
| 				a800 0 0 3 &mpic b 1 | ||||
| 				a800 0 0 4 &mpic b 1>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <09 2>; | ||||
| 			interrupts = <19 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 a0000000 a0000000 0 20000000 | ||||
| 				  01000000 0 00000000 e3000000 0 00100000>; | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
| 			compatible = "fsl,8555-memory-controller"; | ||||
| 			reg = <2000 1000>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <2 2>; | ||||
| 			interrupts = <12 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		l2-cache-controller@20000 { | ||||
| @ -61,14 +61,14 @@ | ||||
| 			cache-line-size = <20>;	// 32 bytes | ||||
| 			cache-size = <40000>;	// L2, 256K | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <0 2>; | ||||
| 			interrupts = <10 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		i2c@3000 { | ||||
| 			device_type = "i2c"; | ||||
| 			compatible = "fsl-i2c"; | ||||
| 			reg = <3000 100>; | ||||
| 			interrupts = <1b 2>; | ||||
| 			interrupts = <2b 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			dfsrr; | ||||
| 		}; | ||||
| @ -81,13 +81,13 @@ | ||||
| 			reg = <24520 20>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 0>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -100,8 +100,8 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 00 ]; | ||||
| 			interrupts = <0d 2 0e 2 12 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy0>; | ||||
| 		}; | ||||
| @ -113,8 +113,8 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			local-mac-address = [ 00 E0 0C 00 73 01 ]; | ||||
| 			interrupts = <13 2 14 2 18 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 2 24 2 28 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy1>; | ||||
| 		}; | ||||
| @ -124,7 +124,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4500 100>; 	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -133,7 +133,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4600 100>;	// reg base, size | ||||
| 			clock-frequency = <0>; 	// should we fill in in uboot? | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -142,49 +142,49 @@ | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 				/* IDSEL 0x10 */ | ||||
| 				08000 0 0 1 &mpic 30 1 | ||||
| 				08000 0 0 2 &mpic 31 1 | ||||
| 				08000 0 0 3 &mpic 32 1 | ||||
| 				08000 0 0 4 &mpic 33 1 | ||||
| 				08000 0 0 1 &mpic 0 1 | ||||
| 				08000 0 0 2 &mpic 1 1 | ||||
| 				08000 0 0 3 &mpic 2 1 | ||||
| 				08000 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x11 */ | ||||
| 				08800 0 0 1 &mpic 30 1 | ||||
| 				08800 0 0 2 &mpic 31 1 | ||||
| 				08800 0 0 3 &mpic 32 1 | ||||
| 				08800 0 0 4 &mpic 33 1 | ||||
| 				08800 0 0 1 &mpic 0 1 | ||||
| 				08800 0 0 2 &mpic 1 1 | ||||
| 				08800 0 0 3 &mpic 2 1 | ||||
| 				08800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x12 (Slot 1) */ | ||||
| 				09000 0 0 1 &mpic 30 1 | ||||
| 				09000 0 0 2 &mpic 31 1 | ||||
| 				09000 0 0 3 &mpic 32 1 | ||||
| 				09000 0 0 4 &mpic 33 1 | ||||
| 				09000 0 0 1 &mpic 0 1 | ||||
| 				09000 0 0 2 &mpic 1 1 | ||||
| 				09000 0 0 3 &mpic 2 1 | ||||
| 				09000 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x13 (Slot 2) */ | ||||
| 				09800 0 0 1 &mpic 31 1 | ||||
| 				09800 0 0 2 &mpic 32 1 | ||||
| 				09800 0 0 3 &mpic 33 1 | ||||
| 				09800 0 0 4 &mpic 30 1 | ||||
| 				09800 0 0 1 &mpic 1 1 | ||||
| 				09800 0 0 2 &mpic 2 1 | ||||
| 				09800 0 0 3 &mpic 3 1 | ||||
| 				09800 0 0 4 &mpic 0 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x14 (Slot 3) */ | ||||
| 				0a000 0 0 1 &mpic 32 1 | ||||
| 				0a000 0 0 2 &mpic 33 1 | ||||
| 				0a000 0 0 3 &mpic 30 1 | ||||
| 				0a000 0 0 4 &mpic 31 1 | ||||
| 				0a000 0 0 1 &mpic 2 1 | ||||
| 				0a000 0 0 2 &mpic 3 1 | ||||
| 				0a000 0 0 3 &mpic 0 1 | ||||
| 				0a000 0 0 4 &mpic 1 1 | ||||
| 
 | ||||
| 				/* IDSEL 0x15 (Slot 4) */ | ||||
| 				0a800 0 0 1 &mpic 33 1 | ||||
| 				0a800 0 0 2 &mpic 30 1 | ||||
| 				0a800 0 0 3 &mpic 31 1 | ||||
| 				0a800 0 0 4 &mpic 32 1 | ||||
| 				0a800 0 0 1 &mpic 3 1 | ||||
| 				0a800 0 0 2 &mpic 0 1 | ||||
| 				0a800 0 0 3 &mpic 1 1 | ||||
| 				0a800 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 				/* Bus 1 (Tundra Bridge) */ | ||||
| 				/* IDSEL 0x12 (ISA bridge) */ | ||||
| 				19000 0 0 1 &mpic 30 1 | ||||
| 				19000 0 0 2 &mpic 31 1 | ||||
| 				19000 0 0 3 &mpic 32 1 | ||||
| 				19000 0 0 4 &mpic 33 1>; | ||||
| 				19000 0 0 1 &mpic 0 1 | ||||
| 				19000 0 0 2 &mpic 1 1 | ||||
| 				19000 0 0 3 &mpic 2 1 | ||||
| 				19000 0 0 4 &mpic 3 1>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <08 2>; | ||||
| 			interrupts = <18 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 80000000 80000000 0 20000000 | ||||
| 				  01000000 0 00000000 e2000000 0 00100000>; | ||||
| @ -216,12 +216,12 @@ | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 				/* IDSEL 0x15 */ | ||||
| 				a800 0 0 1 &mpic 3b 1 | ||||
| 				a800 0 0 2 &mpic 3b 1 | ||||
| 				a800 0 0 3 &mpic 3b 1 | ||||
| 				a800 0 0 4 &mpic 3b 1>; | ||||
| 				a800 0 0 1 &mpic b 1 | ||||
| 				a800 0 0 2 &mpic b 1 | ||||
| 				a800 0 0 3 &mpic b 1 | ||||
| 				a800 0 0 4 &mpic b 1>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <09 2>; | ||||
| 			interrupts = <19 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 a0000000 a0000000 0 20000000 | ||||
| 				  01000000 0 00000000 e3000000 0 00100000>; | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
| 			compatible = "fsl,8540-memory-controller"; | ||||
| 			reg = <2000 1000>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <2 2>; | ||||
| 			interrupts = <12 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		l2-cache-controller@20000 { | ||||
| @ -61,7 +61,7 @@ | ||||
| 			cache-line-size = <20>;	// 32 bytes | ||||
| 			cache-size = <40000>;	// L2, 256K | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <0 2>; | ||||
| 			interrupts = <10 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		mdio@24520 { | ||||
| @ -72,25 +72,25 @@ | ||||
| 			#size-cells = <0>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 1>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <35 1>; | ||||
| 				interrupts = <5 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy2: ethernet-phy@2 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <37 1>; | ||||
| 				interrupts = <7 1>; | ||||
| 				reg = <2>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy3: ethernet-phy@3 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <37 1>; | ||||
| 				interrupts = <7 1>; | ||||
| 				reg = <3>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -101,8 +101,14 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			address = [ 00 00 0C 00 00 FD ]; | ||||
| 			interrupts = <d 2 e 2 12 2>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy0>; | ||||
| 		}; | ||||
| @ -114,8 +120,14 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			address = [ 00 00 0C 00 01 FD ]; | ||||
| 			interrupts = <13 2 14 2 18 2>; | ||||
| 			/* | ||||
| 			 * address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 2 24 2 28 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy1>; | ||||
| 		}; | ||||
| @ -132,79 +144,79 @@ | ||||
| 			interrupt-map = < | ||||
| 
 | ||||
| 					/* IDSEL 0x2 */ | ||||
| 					 1000 0 0 1 &mpic 31 1 | ||||
| 					 1000 0 0 2 &mpic 32 1 | ||||
| 					 1000 0 0 3 &mpic 33 1 | ||||
| 					 1000 0 0 4 &mpic 34 1 | ||||
| 					 1000 0 0 1 &mpic 1 1 | ||||
| 					 1000 0 0 2 &mpic 2 1 | ||||
| 					 1000 0 0 3 &mpic 3 1 | ||||
| 					 1000 0 0 4 &mpic 4 1 | ||||
| 
 | ||||
| 					/* IDSEL 0x3 */ | ||||
| 					 1800 0 0 1 &mpic 34 1 | ||||
| 					 1800 0 0 2 &mpic 31 1 | ||||
| 					 1800 0 0 3 &mpic 32 1 | ||||
| 					 1800 0 0 4 &mpic 33 1 | ||||
| 					 1800 0 0 1 &mpic 4 1 | ||||
| 					 1800 0 0 2 &mpic 1 1 | ||||
| 					 1800 0 0 3 &mpic 2 1 | ||||
| 					 1800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 					/* IDSEL 0x4 */ | ||||
| 					 2000 0 0 1 &mpic 33 1 | ||||
| 					 2000 0 0 2 &mpic 34 1 | ||||
| 					 2000 0 0 3 &mpic 31 1 | ||||
| 					 2000 0 0 4 &mpic 32 1 | ||||
| 					 2000 0 0 1 &mpic 3 1 | ||||
| 					 2000 0 0 2 &mpic 4 1 | ||||
| 					 2000 0 0 3 &mpic 1 1 | ||||
| 					 2000 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 					/* IDSEL 0x5  */ | ||||
| 					 2800 0 0 1 &mpic 32 1 | ||||
| 					 2800 0 0 2 &mpic 33 1 | ||||
| 					 2800 0 0 3 &mpic 34 1 | ||||
| 					 2800 0 0 4 &mpic 31 1 | ||||
| 					 2800 0 0 1 &mpic 2 1 | ||||
| 					 2800 0 0 2 &mpic 3 1 | ||||
| 					 2800 0 0 3 &mpic 4 1 | ||||
| 					 2800 0 0 4 &mpic 1 1 | ||||
| 
 | ||||
| 					/* IDSEL 12 */ | ||||
| 					 6000 0 0 1 &mpic 31 1 | ||||
| 					 6000 0 0 2 &mpic 32 1 | ||||
| 					 6000 0 0 3 &mpic 33 1 | ||||
| 					 6000 0 0 4 &mpic 34 1 | ||||
| 					 6000 0 0 1 &mpic 1 1 | ||||
| 					 6000 0 0 2 &mpic 2 1 | ||||
| 					 6000 0 0 3 &mpic 3 1 | ||||
| 					 6000 0 0 4 &mpic 4 1 | ||||
| 
 | ||||
| 					/* IDSEL 13 */ | ||||
| 					 6800 0 0 1 &mpic 34 1 | ||||
| 					 6800 0 0 2 &mpic 31 1 | ||||
| 					 6800 0 0 3 &mpic 32 1 | ||||
| 					 6800 0 0 4 &mpic 33 1 | ||||
| 					 6800 0 0 1 &mpic 4 1 | ||||
| 					 6800 0 0 2 &mpic 1 1 | ||||
| 					 6800 0 0 3 &mpic 2 1 | ||||
| 					 6800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 					/* IDSEL 14*/ | ||||
| 					 7000 0 0 1 &mpic 33 1 | ||||
| 					 7000 0 0 2 &mpic 34 1 | ||||
| 					 7000 0 0 3 &mpic 31 1 | ||||
| 					 7000 0 0 4 &mpic 32 1 | ||||
| 					 7000 0 0 1 &mpic 3 1 | ||||
| 					 7000 0 0 2 &mpic 4 1 | ||||
| 					 7000 0 0 3 &mpic 1 1 | ||||
| 					 7000 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 					/* IDSEL 15 */ | ||||
| 					 7800 0 0 1 &mpic 32 1 | ||||
| 					 7800 0 0 2 &mpic 33 1 | ||||
| 					 7800 0 0 3 &mpic 34 1 | ||||
| 					 7800 0 0 4 &mpic 31 1 | ||||
| 					 7800 0 0 1 &mpic 2 1 | ||||
| 					 7800 0 0 2 &mpic 3 1 | ||||
| 					 7800 0 0 3 &mpic 4 1 | ||||
| 					 7800 0 0 4 &mpic 1 1 | ||||
| 
 | ||||
| 					/* IDSEL 18 */ | ||||
| 					 9000 0 0 1 &mpic 31 1 | ||||
| 					 9000 0 0 2 &mpic 32 1 | ||||
| 					 9000 0 0 3 &mpic 33 1 | ||||
| 					 9000 0 0 4 &mpic 34 1 | ||||
| 					 9000 0 0 1 &mpic 1 1 | ||||
| 					 9000 0 0 2 &mpic 2 1 | ||||
| 					 9000 0 0 3 &mpic 3 1 | ||||
| 					 9000 0 0 4 &mpic 4 1 | ||||
| 
 | ||||
| 					/* IDSEL 19 */ | ||||
| 					 9800 0 0 1 &mpic 34 1 | ||||
| 					 9800 0 0 2 &mpic 31 1 | ||||
| 					 9800 0 0 3 &mpic 32 1 | ||||
| 					 9800 0 0 4 &mpic 33 1 | ||||
| 					 9800 0 0 1 &mpic 4 1 | ||||
| 					 9800 0 0 2 &mpic 1 1 | ||||
| 					 9800 0 0 3 &mpic 2 1 | ||||
| 					 9800 0 0 4 &mpic 3 1 | ||||
| 
 | ||||
| 					/* IDSEL 20 */ | ||||
| 					 a000 0 0 1 &mpic 33 1 | ||||
| 					 a000 0 0 2 &mpic 34 1 | ||||
| 					 a000 0 0 3 &mpic 31 1 | ||||
| 					 a000 0 0 4 &mpic 32 1 | ||||
| 					 a000 0 0 1 &mpic 3 1 | ||||
| 					 a000 0 0 2 &mpic 4 1 | ||||
| 					 a000 0 0 3 &mpic 1 1 | ||||
| 					 a000 0 0 4 &mpic 2 1 | ||||
| 
 | ||||
| 					/* IDSEL 21 */ | ||||
| 					 a800 0 0 1 &mpic 32 1 | ||||
| 					 a800 0 0 2 &mpic 33 1 | ||||
| 					 a800 0 0 3 &mpic 34 1 | ||||
| 					 a800 0 0 4 &mpic 31 1>; | ||||
| 					 a800 0 0 1 &mpic 2 1 | ||||
| 					 a800 0 0 2 &mpic 3 1 | ||||
| 					 a800 0 0 3 &mpic 4 1 | ||||
| 					 a800 0 0 4 &mpic 1 1>; | ||||
| 
 | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <8 0>; | ||||
| 			interrupts = <18 2>; | ||||
| 			bus-range = <0 0>; | ||||
| 			ranges = <02000000 0 80000000 80000000 0 20000000 | ||||
| 				  01000000 0 00000000 e2000000 0 01000000>; | ||||
| @ -234,7 +246,7 @@ | ||||
| 				interrupt-controller; | ||||
| 				#address-cells = <0>; | ||||
| 				#interrupt-cells = <2>; | ||||
| 				interrupts = <1e 0>; | ||||
| 				interrupts = <2e 2>; | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				reg = <90c00 80>; | ||||
| 				built-in; | ||||
| @ -275,7 +287,13 @@ | ||||
| 				model = "FCC"; | ||||
| 				device-id = <2>; | ||||
| 				reg = <91320 20 88500 100 913a0 30>; | ||||
| 				mac-address = [ 00 00 0C 00 02 FD ]; | ||||
| 				/* | ||||
| 				 * mac-address is deprecated and will be removed | ||||
| 				 * in 2.6.25.  Only recent versions of | ||||
| 				 * U-Boot support local-mac-address, however. | ||||
| 				 */ | ||||
| 				mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 				local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 				clock-setup = <ff00ffff 250000>; | ||||
| 				rx-clock = <15>; | ||||
| 				tx-clock = <16>; | ||||
| @ -290,7 +308,13 @@ | ||||
| 				model = "FCC"; | ||||
| 				device-id = <3>; | ||||
| 				reg = <91340 20 88600 100 913d0 30>; | ||||
| 				mac-address = [ 00 00 0C 00 03 FD ]; | ||||
| 				/* | ||||
| 				 * mac-address is deprecated and will be removed | ||||
| 				 * in 2.6.25.  Only recent versions of | ||||
| 				 * U-Boot support local-mac-address, however. | ||||
| 				 */ | ||||
| 				mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 				local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 				clock-setup = <ffff00ff 3700>; | ||||
| 				rx-clock = <17>; | ||||
| 				tx-clock = <18>; | ||||
|  | ||||
| @ -61,7 +61,7 @@ | ||||
| 			compatible = "fsl,8568-memory-controller"; | ||||
| 			reg = <2000 1000>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <2 2>; | ||||
| 			interrupts = <12 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		l2-cache-controller@20000 { | ||||
| @ -70,14 +70,14 @@ | ||||
| 			cache-line-size = <20>;	// 32 bytes | ||||
| 			cache-size = <80000>;	// L2, 512K | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			interrupts = <0 2>; | ||||
| 			interrupts = <10 2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		i2c@3000 { | ||||
| 			device_type = "i2c"; | ||||
| 			compatible = "fsl-i2c"; | ||||
| 			reg = <3000 100>; | ||||
| 			interrupts = <1b 2>; | ||||
| 			interrupts = <2b 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			dfsrr; | ||||
| 		}; | ||||
| @ -86,7 +86,7 @@ | ||||
| 			device_type = "i2c"; | ||||
| 			compatible = "fsl-i2c"; | ||||
| 			reg = <3100 100>; | ||||
| 			interrupts = <1b 2>; | ||||
| 			interrupts = <2b 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			dfsrr; | ||||
| 		}; | ||||
| @ -99,25 +99,25 @@ | ||||
| 			reg = <24520 20>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <31 1>; | ||||
| 				interrupts = <1 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <32 1>; | ||||
| 				interrupts = <2 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy2: ethernet-phy@2 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <31 1>; | ||||
| 				interrupts = <1 1>; | ||||
| 				reg = <2>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy3: ethernet-phy@3 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <32 1>; | ||||
| 				interrupts = <2 1>; | ||||
| 				reg = <3>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -130,8 +130,14 @@ | ||||
| 			model = "eTSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <d 2 e 2 12 2>; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
|  			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy2>; | ||||
| 		}; | ||||
| @ -143,8 +149,14 @@ | ||||
| 			model = "eTSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			mac-address = [ 00 00 00 00 00 00]; | ||||
| 			interrupts = <13 2 14 2 18 2>; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
|  			interrupts = <23 2 24 2 28 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy3>; | ||||
| 		}; | ||||
| @ -154,7 +166,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4500 100>; | ||||
| 			clock-frequency = <0>; | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -163,7 +175,7 @@ | ||||
| 			compatible = "ns16550"; | ||||
| 			reg = <4600 100>; | ||||
| 			clock-frequency = <0>; | ||||
| 			interrupts = <1a 2>; | ||||
| 			interrupts = <2a 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
| @ -172,7 +184,7 @@ | ||||
| 			model = "SEC2"; | ||||
| 			compatible = "talitos"; | ||||
| 			reg = <30000 f000>; | ||||
| 			interrupts = <1d 2>; | ||||
| 			interrupts = <2d 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			num-channels = <4>; | ||||
| 			channel-fifo-len = <18>; | ||||
| @ -300,7 +312,13 @@ | ||||
| 			reg = <2000 200>; | ||||
| 			interrupts = <20>; | ||||
| 			interrupt-parent = <&qeic>; | ||||
| 			mac-address = [ 00 04 9f 00 23 23 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <0>; | ||||
| 			tx-clock = <19>; | ||||
| 			phy-handle = <&qe_phy0>; | ||||
| @ -316,7 +334,13 @@ | ||||
| 			reg = <3000 200>; | ||||
| 			interrupts = <21>; | ||||
| 			interrupt-parent = <&qeic>; | ||||
| 			mac-address = [ 00 11 22 33 44 55 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			rx-clock = <0>; | ||||
| 			tx-clock = <14>; | ||||
| 			phy-handle = <&qe_phy1>; | ||||
| @ -335,25 +359,25 @@ | ||||
| 			 * gianfar's MDIO bus */ | ||||
| 			qe_phy0: ethernet-phy@00 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <31 1>; | ||||
| 				interrupts = <1 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			qe_phy1: ethernet-phy@01 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <32 1>; | ||||
| 				interrupts = <2 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			qe_phy2: ethernet-phy@02 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <31 1>; | ||||
| 				interrupts = <1 1>; | ||||
| 				reg = <2>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			qe_phy3: ethernet-phy@03 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <32 1>; | ||||
| 				interrupts = <2 1>; | ||||
| 				reg = <3>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -367,7 +391,7 @@ | ||||
| 			reg = <80 80>; | ||||
| 			built-in; | ||||
| 			big-endian; | ||||
| 			interrupts = <1e 2 1e 2>; //high:30 low:30 | ||||
| 			interrupts = <2e 2 2e 2>; //high:30 low:30 | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 		}; | ||||
| 
 | ||||
|  | ||||
| @ -56,8 +56,12 @@ | ||||
| 		#size-cells = <1>; | ||||
| 		#interrupt-cells = <2>; | ||||
| 		device_type = "soc"; | ||||
| 		ranges = <0 f8000000 00100000>; | ||||
| 		reg = <f8000000 00100000>;	// CCSRBAR 1M | ||||
| 		ranges = <00001000 f8001000 000ff000 | ||||
| 			  80000000 80000000 20000000 | ||||
| 			  e2000000 e2000000 00100000 | ||||
| 			  a0000000 a0000000 20000000 | ||||
| 			  e3000000 e3000000 00100000>; | ||||
| 		reg = <f8000000 00001000>;	// CCSRBAR | ||||
| 		bus-frequency = <0>; | ||||
| 
 | ||||
| 		i2c@3000 { | ||||
| @ -86,25 +90,25 @@ | ||||
| 			reg = <24520 20>; | ||||
| 			phy0: ethernet-phy@0 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <4a 1>; | ||||
| 				interrupts = <a 1>; | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy1: ethernet-phy@1 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <4a 1>; | ||||
| 				interrupts = <a 1>; | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy2: ethernet-phy@2 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <4a 1>; | ||||
| 				interrupts = <a 1>; | ||||
| 				reg = <2>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			phy3: ethernet-phy@3 { | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 				interrupts = <4a 1>; | ||||
| 				interrupts = <a 1>; | ||||
| 				reg = <3>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -117,7 +121,13 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <24000 1000>; | ||||
| 			mac-address = [ 00 E0 0C 00 73 00 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1d 2 1e 2 22 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy0>; | ||||
| @ -130,7 +140,13 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <25000 1000>; | ||||
| 			mac-address = [ 00 E0 0C 00 73 01 ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <23 2 24 2 28 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy1>; | ||||
| @ -143,7 +159,13 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <26000 1000>; | ||||
| 			mac-address = [ 00 E0 0C 00 02 FD ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <1F 2 20 2 21 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy2>; | ||||
| @ -156,7 +178,13 @@ | ||||
| 			model = "TSEC"; | ||||
| 			compatible = "gianfar"; | ||||
| 			reg = <27000 1000>; | ||||
| 			mac-address = [ 00 E0 0C 00 03 FD ]; | ||||
| 			/* | ||||
| 			 * mac-address is deprecated and will be removed | ||||
| 			 * in 2.6.25.  Only recent versions of | ||||
| 			 * U-Boot support local-mac-address, however. | ||||
| 			 */ | ||||
| 			mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			local-mac-address = [ 00 00 00 00 00 00 ]; | ||||
| 			interrupts = <25 2 26 2 27 2>; | ||||
| 			interrupt-parent = <&mpic>; | ||||
| 			phy-handle = <&phy3>; | ||||
| @ -186,7 +214,7 @@ | ||||
| 			#size-cells = <2>; | ||||
| 			#address-cells = <3>; | ||||
| 			reg = <8000 1000>; | ||||
| 			bus-range = <0 fe>; | ||||
| 			bus-range = <0 ff>; | ||||
| 			ranges = <02000000 0 80000000 80000000 0 20000000 | ||||
| 				  01000000 0 00000000 e2000000 0 00100000>; | ||||
| 			clock-frequency = <1fca055>; | ||||
| @ -285,17 +313,84 @@ | ||||
| 				f800 0 0 3 &i8259 0 0 | ||||
| 				f800 0 0 4 &i8259 0 0 | ||||
| 				>; | ||||
| 			i8259: i8259@4d0 { | ||||
| 				clock-frequency = <0>; | ||||
| 				interrupt-controller; | ||||
| 				device_type = "interrupt-controller"; | ||||
| 				#address-cells = <0>; | ||||
| 				#interrupt-cells = <2>; | ||||
| 				built-in; | ||||
| 				compatible = "chrp,iic"; | ||||
|                 	        big-endian; | ||||
| 				interrupts = <49 2>; | ||||
| 				interrupt-parent = <&mpic>; | ||||
| 			uli1575@0 { | ||||
| 				reg = <0 0 0 0 0>; | ||||
| 				#size-cells = <2>; | ||||
| 				#address-cells = <3>; | ||||
| 				ranges = <02000000 0 80000000 | ||||
| 					  02000000 0 80000000 | ||||
| 					  0 20000000 | ||||
| 					  01000000 0 00000000 | ||||
| 					  01000000 0 00000000 | ||||
| 					  0 00100000>; | ||||
| 
 | ||||
| 				pci_bridge@0 { | ||||
| 					reg = <0 0 0 0 0>; | ||||
| 					#size-cells = <2>; | ||||
| 					#address-cells = <3>; | ||||
| 					ranges = <02000000 0 80000000 | ||||
| 						  02000000 0 80000000 | ||||
| 						  0 20000000 | ||||
| 						  01000000 0 00000000 | ||||
| 						  01000000 0 00000000 | ||||
| 						  0 00100000>; | ||||
| 
 | ||||
| 					isa@1e { | ||||
| 						device_type = "isa"; | ||||
| 						#interrupt-cells = <2>; | ||||
| 						#size-cells = <1>; | ||||
| 						#address-cells = <2>; | ||||
| 						reg = <f000 0 0 0 0>; | ||||
| 						ranges = <1 0 01000000 0 0 | ||||
| 							  00001000>; | ||||
| 						interrupt-parent = <&i8259>; | ||||
| 
 | ||||
| 						i8259: interrupt-controller@20 { | ||||
| 							reg = <1 20 2 | ||||
| 							       1 a0 2 | ||||
| 							       1 4d0 2>; | ||||
| 							clock-frequency = <0>; | ||||
| 							interrupt-controller; | ||||
| 							device_type = "interrupt-controller"; | ||||
| 							#address-cells = <0>; | ||||
| 							#interrupt-cells = <2>; | ||||
| 							built-in; | ||||
| 							compatible = "chrp,iic"; | ||||
| 							interrupts = <9 2>; | ||||
| 							interrupt-parent = | ||||
| 								<&mpic>; | ||||
| 						}; | ||||
| 
 | ||||
| 						i8042@60 { | ||||
| 							#size-cells = <0>; | ||||
| 							#address-cells = <1>; | ||||
| 							reg = <1 60 1 1 64 1>; | ||||
| 							interrupts = <1 3 c 3>; | ||||
| 							interrupt-parent = | ||||
| 								<&i8259>; | ||||
| 
 | ||||
| 							keyboard@0 { | ||||
| 								reg = <0>; | ||||
| 								compatible = "pnpPNP,303"; | ||||
| 							}; | ||||
| 
 | ||||
| 							mouse@1 { | ||||
| 								reg = <1>; | ||||
| 								compatible = "pnpPNP,f03"; | ||||
| 							}; | ||||
| 						}; | ||||
| 
 | ||||
| 						rtc@70 { | ||||
| 							compatible = | ||||
| 								"pnpPNP,b00"; | ||||
| 							reg = <1 70 2>; | ||||
| 						}; | ||||
| 
 | ||||
| 						gpio@400 { | ||||
| 							reg = <1 400 80>; | ||||
| 						}; | ||||
| 					}; | ||||
| 				}; | ||||
| 			}; | ||||
| 
 | ||||
| 		}; | ||||
| @ -316,10 +411,10 @@ | ||||
| 			interrupt-map-mask = <f800 0 0 7>; | ||||
| 			interrupt-map = < | ||||
| 				/* IDSEL 0x0 */ | ||||
| 				0000 0 0 1 &mpic 44 1 | ||||
| 				0000 0 0 2 &mpic 45 1 | ||||
| 				0000 0 0 3 &mpic 46 1 | ||||
| 				0000 0 0 4 &mpic 47 1 | ||||
| 				0000 0 0 1 &mpic 4 1 | ||||
| 				0000 0 0 2 &mpic 5 1 | ||||
| 				0000 0 0 3 &mpic 6 1 | ||||
| 				0000 0 0 4 &mpic 7 1 | ||||
| 				>; | ||||
| 		}; | ||||
| 
 | ||||
|  | ||||
| @ -15,12 +15,10 @@ | ||||
| 	compatible = "mpc8xx"; | ||||
| 	#address-cells = <1>; | ||||
| 	#size-cells = <1>; | ||||
| 	linux,phandle = <100>; | ||||
| 
 | ||||
| 	cpus { | ||||
| 		#address-cells = <1>; | ||||
| 		#size-cells = <0>; | ||||
| 		linux,phandle = <200>; | ||||
| 
 | ||||
| 		PowerPC,866@0 { | ||||
| 			device_type = "cpu"; | ||||
| @ -34,14 +32,12 @@ | ||||
| 			clock-frequency = <0>; | ||||
| 			32-bit; | ||||
| 			interrupts = <f 2>;	// decrementer interrupt | ||||
| 			interrupt-parent = <ff000000>; | ||||
| 			linux,phandle = <201>; | ||||
| 			interrupt-parent = <&Mpc8xx_pic>; | ||||
| 		}; | ||||
| 	}; | ||||
| 
 | ||||
| 	memory { | ||||
| 		device_type = "memory"; | ||||
| 		linux,phandle = <300>; | ||||
| 		reg = <00000000 800000>; | ||||
| 	}; | ||||
| 
 | ||||
| @ -57,11 +53,9 @@ | ||||
| 			device_type = "mdio"; | ||||
| 			compatible = "fs_enet"; | ||||
| 			reg = <e80 8>; | ||||
| 			linux,phandle = <e80>; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <0>; | ||||
| 			ethernet-phy@f { | ||||
| 				linux,phandle = <e800f>; | ||||
| 			phy: ethernet-phy@f { | ||||
| 				reg = <f>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -75,12 +69,11 @@ | ||||
| 			reg = <e00 188>; | ||||
| 			mac-address = [ 00 00 0C 00 01 FD ]; | ||||
| 			interrupts = <3 1>; | ||||
| 			interrupt-parent = <ff000000>; | ||||
| 			phy-handle = <e800f>; | ||||
| 			interrupt-parent = <&Mpc8xx_pic>; | ||||
| 			phy-handle = <&Phy>; | ||||
| 		}; | ||||
| 
 | ||||
| 		pic@ff000000 { | ||||
| 			linux,phandle = <ff000000>; | ||||
| 		mpc8xx_pic: pic@ff000000 { | ||||
| 			interrupt-controller; | ||||
| 			#address-cells = <0>; | ||||
| 			#interrupt-cells = <2>; | ||||
| @ -91,7 +84,6 @@ | ||||
| 		}; | ||||
| 
 | ||||
| 		cpm@ff000000 { | ||||
| 			linux,phandle = <ff000000>; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <1>; | ||||
| 			#interrupt-cells = <2>; | ||||
| @ -102,15 +94,14 @@ | ||||
| 			command-proc = <9c0>; | ||||
| 			brg-frequency = <0>; | ||||
| 			interrupts = <0 2>;	// cpm error interrupt | ||||
| 			interrupt-parent = <930>; | ||||
| 			interrupt-parent = <&Cpm_pic>; | ||||
| 
 | ||||
| 			pic@930 { | ||||
| 				linux,phandle = <930>; | ||||
| 			cpm_pic: pic@930 { | ||||
| 				interrupt-controller; | ||||
| 				#address-cells = <0>; | ||||
| 				#interrupt-cells = <2>; | ||||
| 				interrupts = <5 2 0 2>; | ||||
| 				interrupt-parent = <ff000000>; | ||||
| 				interrupt-parent = <&Mpc8xx_pic>; | ||||
| 				reg = <930 20>; | ||||
| 				built-in; | ||||
| 				device_type = "cpm-pic"; | ||||
| @ -128,7 +119,7 @@ | ||||
| 				tx-clock = <1>; | ||||
| 				current-speed = <0>; | ||||
| 				interrupts = <4 3>; | ||||
| 				interrupt-parent = <930>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
| 			}; | ||||
| 
 | ||||
| 			smc@a90 { | ||||
| @ -142,7 +133,7 @@ | ||||
| 				tx-clock = <2>; | ||||
| 				current-speed = <0>; | ||||
| 				interrupts = <3 3>; | ||||
| 				interrupt-parent = <930>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
| 			}; | ||||
| 
 | ||||
| 			scc@a00 { | ||||
| @ -153,7 +144,7 @@ | ||||
| 				reg = <a00 18 3c00 80>; | ||||
| 				mac-address = [ 00 00 0C 00 03 FD ]; | ||||
| 				interrupts = <1e 3>; | ||||
| 				interrupt-parent = <930>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
| 			}; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| @ -15,12 +15,10 @@ | ||||
| 	compatible = "mpc8xx"; | ||||
| 	#address-cells = <1>; | ||||
| 	#size-cells = <1>; | ||||
| 	linux,phandle = <100>; | ||||
| 
 | ||||
| 	cpus { | ||||
| 		#address-cells = <1>; | ||||
| 		#size-cells = <0>; | ||||
| 		linux,phandle = <200>; | ||||
| 
 | ||||
| 		PowerPC,885@0 { | ||||
| 			device_type = "cpu"; | ||||
| @ -34,14 +32,12 @@ | ||||
| 			clock-frequency = <0>; | ||||
| 			32-bit; | ||||
| 			interrupts = <f 2>;	// decrementer interrupt | ||||
| 			interrupt-parent = <ff000000>; | ||||
| 			linux,phandle = <201>; | ||||
| 			interrupt-parent = <&Mpc8xx_pic>; | ||||
| 		}; | ||||
| 	}; | ||||
| 
 | ||||
| 	memory { | ||||
| 		device_type = "memory"; | ||||
| 		linux,phandle = <300>; | ||||
| 		reg = <00000000 800000>; | ||||
| 	}; | ||||
| 
 | ||||
| @ -57,21 +53,17 @@ | ||||
| 			device_type = "mdio"; | ||||
| 			compatible = "fs_enet"; | ||||
| 			reg = <e80 8>; | ||||
| 			linux,phandle = <e80>; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <0>; | ||||
| 			ethernet-phy@0 { | ||||
| 				linux,phandle = <e8000>; | ||||
| 			Phy0: ethernet-phy@0 { | ||||
| 				reg = <0>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			ethernet-phy@1 { | ||||
| 				linux,phandle = <e8001>; | ||||
| 			Phy1: ethernet-phy@1 { | ||||
| 				reg = <1>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| 			ethernet-phy@2 { | ||||
| 				linux,phandle = <e8002>; | ||||
| 			Phy2: ethernet-phy@2 { | ||||
| 				reg = <2>; | ||||
| 				device_type = "ethernet-phy"; | ||||
| 			}; | ||||
| @ -85,8 +77,8 @@ | ||||
| 			reg = <e00 188>; | ||||
| 			mac-address = [ 00 00 0C 00 01 FD ]; | ||||
| 			interrupts = <3 1>; | ||||
| 			interrupt-parent = <ff000000>; | ||||
| 			phy-handle = <e8000>; | ||||
| 			interrupt-parent = <&Mpc8xx_pic>; | ||||
| 			phy-handle = <&Phy1>; | ||||
| 		}; | ||||
| 
 | ||||
| 		fec@1e00 { | ||||
| @ -97,12 +89,11 @@ | ||||
| 			reg = <1e00 188>; | ||||
| 			mac-address = [ 00 00 0C 00 02 FD ]; | ||||
| 			interrupts = <7 1>; | ||||
| 			interrupt-parent = <ff000000>; | ||||
| 			phy-handle = <e8001>; | ||||
| 			interrupt-parent = <&Mpc8xx_pic>; | ||||
| 			phy-handle = <&Phy2>; | ||||
| 		}; | ||||
| 
 | ||||
| 		pic@ff000000 { | ||||
| 			linux,phandle = <ff000000>; | ||||
| 		Mpc8xx_pic: pic@ff000000 { | ||||
| 			interrupt-controller; | ||||
| 			#address-cells = <0>; | ||||
| 			#interrupt-cells = <2>; | ||||
| @ -112,8 +103,18 @@ | ||||
| 			compatible = "CPM"; | ||||
| 		}; | ||||
| 
 | ||||
| 		pcmcia@0080 { | ||||
| 			#address-cells = <3>; | ||||
| 			#interrupt-cells = <1>; | ||||
| 			#size-cells = <2>; | ||||
| 			compatible = "fsl,pq-pcmcia"; | ||||
| 			device_type = "pcmcia"; | ||||
| 			reg = <80 80>; | ||||
| 			interrupt-parent = <&Mpc8xx_pic>; | ||||
| 			interrupts = <d 1>; | ||||
| 		}; | ||||
| 
 | ||||
| 		cpm@ff000000 { | ||||
| 			linux,phandle = <ff000000>; | ||||
| 			#address-cells = <1>; | ||||
| 			#size-cells = <1>; | ||||
| 			#interrupt-cells = <2>; | ||||
| @ -124,15 +125,14 @@ | ||||
| 			command-proc = <9c0>; | ||||
| 			brg-frequency = <0>; | ||||
| 			interrupts = <0 2>;	// cpm error interrupt | ||||
| 			interrupt-parent = <930>; | ||||
| 			interrupt-parent = <&Cpm_pic>; | ||||
| 
 | ||||
| 			pic@930 { | ||||
| 				linux,phandle = <930>; | ||||
| 			Cpm_pic: pic@930 { | ||||
| 				interrupt-controller; | ||||
| 				#address-cells = <0>; | ||||
| 				#interrupt-cells = <2>; | ||||
| 				interrupts = <5 2 0 2>; | ||||
| 				interrupt-parent = <ff000000>; | ||||
| 				interrupt-parent = <&Mpc8xx_pic>; | ||||
| 				reg = <930 20>; | ||||
| 				built-in; | ||||
| 				device_type = "cpm-pic"; | ||||
| @ -150,7 +150,7 @@ | ||||
| 				tx-clock = <1>; | ||||
| 				current-speed = <0>; | ||||
| 				interrupts = <4 3>; | ||||
| 				interrupt-parent = <930>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
| 			}; | ||||
| 
 | ||||
| 			smc@a90 { | ||||
| @ -164,7 +164,7 @@ | ||||
| 				tx-clock = <2>; | ||||
| 				current-speed = <0>; | ||||
| 				interrupts = <3 3>; | ||||
| 				interrupt-parent = <930>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
| 			}; | ||||
| 
 | ||||
| 			scc@a40 { | ||||
| @ -175,8 +175,8 @@ | ||||
| 				reg = <a40 18 3e00 80>; | ||||
| 				mac-address = [ 00 00 0C 00 03 FD ]; | ||||
| 				interrupts = <1c 3>; | ||||
| 				interrupt-parent = <930>; | ||||
| 				phy-handle = <e8002>; | ||||
| 				interrupt-parent = <&Cpm_pic>; | ||||
| 				phy-handle = <&Phy2>; | ||||
| 			}; | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
| @ -309,7 +309,7 @@ | ||||
| 	}; | ||||
| 
 | ||||
| 	chosen { | ||||
| 		bootargs = "ip=on console=ttyMM0"; | ||||
| 		bootargs = "ip=on"; | ||||
| 		linux,stdout-path = "/mv64x60@f1000000/mpsc@8000"; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										68
									
								
								arch/powerpc/boot/dts/ps3.dts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								arch/powerpc/boot/dts/ps3.dts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| /* | ||||
|  *  PS3 Game Console device tree. | ||||
|  * | ||||
|  *  Copyright (C) 2007 Sony Computer Entertainment Inc. | ||||
|  *  Copyright 2007 Sony Corp. | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation; version 2 of the License. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program; if not, write to the Free Software | ||||
|  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| 
 | ||||
| / { | ||||
| 	model = "SonyPS3"; | ||||
| 	compatible = "sony,ps3"; | ||||
| 	#size-cells = <2>; | ||||
| 	#address-cells = <2>; | ||||
| 
 | ||||
| 	chosen { | ||||
| 	}; | ||||
| 
 | ||||
| 	/* | ||||
| 	 * We'll get the size of the bootmem block from lv1 after startup, | ||||
| 	 * so we'll put a null entry here. | ||||
| 	 */ | ||||
| 
 | ||||
| 	memory { | ||||
| 		device_type = "memory"; | ||||
| 		reg = <0 0 0 0>; | ||||
| 	}; | ||||
| 
 | ||||
| 	/* | ||||
| 	 * The boot cpu is always zero for PS3. | ||||
| 	 * | ||||
| 	 * dtc expects a clock-frequency and timebase-frequency entries, so | ||||
| 	 * we'll put a null entries here.  These will be initialized after | ||||
| 	 * startup with data from lv1. | ||||
| 	 * | ||||
| 	 * Seems the only way currently to indicate a processor has multiple | ||||
| 	 * threads is with an ibm,ppc-interrupt-server#s entry.  We'll put one | ||||
| 	 * here so we can bring up both of ours.  See smp_setup_cpu_maps(). | ||||
| 	 */ | ||||
| 
 | ||||
| 	cpus { | ||||
| 		#size-cells = <0>; | ||||
| 		#address-cells = <1>; | ||||
| 
 | ||||
| 		cpu@0 { | ||||
| 			device_type = "cpu"; | ||||
| 			reg = <0>; | ||||
| 			ibm,ppc-interrupt-server#s = <0 1>; | ||||
| 			clock-frequency = <0>; | ||||
| 			timebase-frequency = <0>; | ||||
| 			i-cache-size = <8000>; | ||||
| 			d-cache-size = <8000>; | ||||
| 			i-cache-line-size = <80>; | ||||
| 			d-cache-line-size = <80>; | ||||
| 		}; | ||||
| 	}; | ||||
| }; | ||||
| @ -100,28 +100,13 @@ static void ebony_fixups(void) | ||||
| 	ibm440gp_fixup_clocks(sysclk, 6 * 1843200); | ||||
| 	ibm44x_fixup_memsize(); | ||||
| 	dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); | ||||
| } | ||||
| 
 | ||||
| #define SPRN_DBCR0		0x134 | ||||
| #define   DBCR0_RST_SYSTEM	0x30000000 | ||||
| 
 | ||||
| static void ebony_exit(void) | ||||
| { | ||||
| 	unsigned long tmp; | ||||
| 
 | ||||
| 	asm volatile ( | ||||
| 		"mfspr	%0,%1\n" | ||||
| 		"oris	%0,%0,%2@h\n" | ||||
| 		"mtspr	%1,%0" | ||||
| 		: "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) | ||||
| 		); | ||||
| 
 | ||||
| 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); | ||||
| } | ||||
| 
 | ||||
| void ebony_init(void *mac0, void *mac1) | ||||
| { | ||||
| 	platform_ops.fixups = ebony_fixups; | ||||
| 	platform_ops.exit = ebony_exit; | ||||
| 	platform_ops.exit = ibm44x_dbcr_reset; | ||||
| 	ebony_mac0 = mac0; | ||||
| 	ebony_mac1 = mac1; | ||||
| 	ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | ||||
|  | ||||
| @ -36,8 +36,6 @@ struct addr_range { | ||||
| 	unsigned long size; | ||||
| }; | ||||
| 
 | ||||
| typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); | ||||
| 
 | ||||
| #undef DEBUG | ||||
| 
 | ||||
| static struct addr_range prep_kernel(void) | ||||
|  | ||||
| @ -15,8 +15,7 @@ | ||||
| #include "page.h" | ||||
| #include "ops.h" | ||||
| 
 | ||||
| typedef void *ihandle; | ||||
| typedef void *phandle; | ||||
| #include "of.h" | ||||
| 
 | ||||
| extern char _end[]; | ||||
| 
 | ||||
| @ -25,154 +24,10 @@ extern char _end[]; | ||||
| #define RAM_END		(512<<20)	/* Fixme: use OF */ | ||||
| #define	ONE_MB		0x100000 | ||||
| 
 | ||||
| int (*prom) (void *); | ||||
| 
 | ||||
| 
 | ||||
| static unsigned long claim_base; | ||||
| 
 | ||||
| static int call_prom(const char *service, int nargs, int nret, ...) | ||||
| { | ||||
| 	int i; | ||||
| 	struct prom_args { | ||||
| 		const char *service; | ||||
| 		int nargs; | ||||
| 		int nret; | ||||
| 		unsigned int args[12]; | ||||
| 	} args; | ||||
| 	va_list list; | ||||
| 
 | ||||
| 	args.service = service; | ||||
| 	args.nargs = nargs; | ||||
| 	args.nret = nret; | ||||
| 
 | ||||
| 	va_start(list, nret); | ||||
| 	for (i = 0; i < nargs; i++) | ||||
| 		args.args[i] = va_arg(list, unsigned int); | ||||
| 	va_end(list); | ||||
| 
 | ||||
| 	for (i = 0; i < nret; i++) | ||||
| 		args.args[nargs+i] = 0; | ||||
| 
 | ||||
| 	if (prom(&args) < 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	return (nret > 0)? args.args[nargs]: 0; | ||||
| } | ||||
| 
 | ||||
| static int call_prom_ret(const char *service, int nargs, int nret, | ||||
| 		  unsigned int *rets, ...) | ||||
| { | ||||
| 	int i; | ||||
| 	struct prom_args { | ||||
| 		const char *service; | ||||
| 		int nargs; | ||||
| 		int nret; | ||||
| 		unsigned int args[12]; | ||||
| 	} args; | ||||
| 	va_list list; | ||||
| 
 | ||||
| 	args.service = service; | ||||
| 	args.nargs = nargs; | ||||
| 	args.nret = nret; | ||||
| 
 | ||||
| 	va_start(list, rets); | ||||
| 	for (i = 0; i < nargs; i++) | ||||
| 		args.args[i] = va_arg(list, unsigned int); | ||||
| 	va_end(list); | ||||
| 
 | ||||
| 	for (i = 0; i < nret; i++) | ||||
| 		args.args[nargs+i] = 0; | ||||
| 
 | ||||
| 	if (prom(&args) < 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (rets != (void *) 0) | ||||
| 		for (i = 1; i < nret; ++i) | ||||
| 			rets[i-1] = args.args[nargs+i]; | ||||
| 
 | ||||
| 	return (nret > 0)? args.args[nargs]: 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Older OF's require that when claiming a specific range of addresses, | ||||
|  * we claim the physical space in the /memory node and the virtual | ||||
|  * space in the chosen mmu node, and then do a map operation to | ||||
|  * map virtual to physical. | ||||
|  */ | ||||
| static int need_map = -1; | ||||
| static ihandle chosen_mmu; | ||||
| static phandle memory; | ||||
| 
 | ||||
| /* returns true if s2 is a prefix of s1 */ | ||||
| static int string_match(const char *s1, const char *s2) | ||||
| { | ||||
| 	for (; *s2; ++s2) | ||||
| 		if (*s1++ != *s2) | ||||
| 			return 0; | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static int check_of_version(void) | ||||
| { | ||||
| 	phandle oprom, chosen; | ||||
| 	char version[64]; | ||||
| 
 | ||||
| 	oprom = finddevice("/openprom"); | ||||
| 	if (oprom == (phandle) -1) | ||||
| 		return 0; | ||||
| 	if (getprop(oprom, "model", version, sizeof(version)) <= 0) | ||||
| 		return 0; | ||||
| 	version[sizeof(version)-1] = 0; | ||||
| 	printf("OF version = '%s'\r\n", version); | ||||
| 	if (!string_match(version, "Open Firmware, 1.") | ||||
| 	    && !string_match(version, "FirmWorks,3.")) | ||||
| 		return 0; | ||||
| 	chosen = finddevice("/chosen"); | ||||
| 	if (chosen == (phandle) -1) { | ||||
| 		chosen = finddevice("/chosen@0"); | ||||
| 		if (chosen == (phandle) -1) { | ||||
| 			printf("no chosen\n"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||||
| 		printf("no mmu\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	memory = (ihandle) call_prom("open", 1, 1, "/memory"); | ||||
| 	if (memory == (ihandle) -1) { | ||||
| 		memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); | ||||
| 		if (memory == (ihandle) -1) { | ||||
| 			printf("no memory node\n"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	printf("old OF detected\r\n"); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static void *claim(unsigned long virt, unsigned long size, unsigned long align) | ||||
| { | ||||
| 	int ret; | ||||
| 	unsigned int result; | ||||
| 
 | ||||
| 	if (need_map < 0) | ||||
| 		need_map = check_of_version(); | ||||
| 	if (align || !need_map) | ||||
| 		return (void *) call_prom("claim", 3, 1, virt, size, align); | ||||
| 
 | ||||
| 	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, | ||||
| 			    align, size, virt); | ||||
| 	if (ret != 0 || result == -1) | ||||
| 		return (void *) -1; | ||||
| 	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||||
| 			    align, size, virt); | ||||
| 	/* 0x12 == coherent + read/write */ | ||||
| 	ret = call_prom("call-method", 6, 1, "map", chosen_mmu, | ||||
| 			0x12, size, virt, virt); | ||||
| 	return (void *) virt; | ||||
| } | ||||
| 
 | ||||
| static void *of_try_claim(unsigned long size) | ||||
| { | ||||
| 	unsigned long addr = 0; | ||||
| @ -184,7 +39,7 @@ static void *of_try_claim(unsigned long size) | ||||
| #ifdef DEBUG | ||||
| 		printf("    trying: 0x%08lx\n\r", claim_base); | ||||
| #endif | ||||
| 		addr = (unsigned long)claim(claim_base, size, 0); | ||||
| 		addr = (unsigned long)of_claim(claim_base, size, 0); | ||||
| 		if ((void *)addr != (void *)-1) | ||||
| 			break; | ||||
| 	} | ||||
| @ -208,64 +63,6 @@ static void of_image_hdr(const void *hdr) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void *of_vmlinux_alloc(unsigned long size) | ||||
| { | ||||
| 	void *p = malloc(size); | ||||
| 
 | ||||
| 	if (!p) | ||||
| 		fatal("Can't allocate memory for kernel image!\n\r"); | ||||
| 
 | ||||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| static void of_exit(void) | ||||
| { | ||||
| 	call_prom("exit", 0, 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * OF device tree routines | ||||
|  */ | ||||
| static void *of_finddevice(const char *name) | ||||
| { | ||||
| 	return (phandle) call_prom("finddevice", 1, 1, name); | ||||
| } | ||||
| 
 | ||||
| static int of_getprop(const void *phandle, const char *name, void *buf, | ||||
| 		const int buflen) | ||||
| { | ||||
| 	return call_prom("getprop", 4, 1, phandle, name, buf, buflen); | ||||
| } | ||||
| 
 | ||||
| static int of_setprop(const void *phandle, const char *name, const void *buf, | ||||
| 		const int buflen) | ||||
| { | ||||
| 	return call_prom("setprop", 4, 1, phandle, name, buf, buflen); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * OF console routines | ||||
|  */ | ||||
| static void *of_stdout_handle; | ||||
| 
 | ||||
| static int of_console_open(void) | ||||
| { | ||||
| 	void *devp; | ||||
| 
 | ||||
| 	if (((devp = finddevice("/chosen")) != NULL) | ||||
| 			&& (getprop(devp, "stdout", &of_stdout_handle, | ||||
| 				sizeof(of_stdout_handle)) | ||||
| 				== sizeof(of_stdout_handle))) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| static void of_console_write(char *buf, int len) | ||||
| { | ||||
| 	call_prom("write", 3, 1, of_stdout_handle, buf, len); | ||||
| } | ||||
| 
 | ||||
| void platform_init(unsigned long a1, unsigned long a2, void *promptr) | ||||
| { | ||||
| 	platform_ops.image_hdr = of_image_hdr; | ||||
| @ -277,10 +74,9 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr) | ||||
| 	dt_ops.getprop = of_getprop; | ||||
| 	dt_ops.setprop = of_setprop; | ||||
| 
 | ||||
| 	console_ops.open = of_console_open; | ||||
| 	console_ops.write = of_console_write; | ||||
| 	of_console_init(); | ||||
| 
 | ||||
| 	prom = (int (*)(void *))promptr; | ||||
| 	of_init(promptr); | ||||
| 	loader_info.promptr = promptr; | ||||
| 	if (a1 && a2 && a2 != 0xdeadbeef) { | ||||
| 		loader_info.initrd_addr = a1; | ||||
|  | ||||
							
								
								
									
										21
									
								
								arch/powerpc/boot/of.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								arch/powerpc/boot/of.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| #ifndef _PPC_BOOT_OF_H_ | ||||
| #define _PPC_BOOT_OF_H_ | ||||
| 
 | ||||
| typedef void *phandle; | ||||
| typedef void *ihandle; | ||||
| 
 | ||||
| void of_init(void *promptr); | ||||
| int of_call_prom(const char *service, int nargs, int nret, ...); | ||||
| void *of_claim(unsigned long virt, unsigned long size, unsigned long align); | ||||
| void *of_vmlinux_alloc(unsigned long size); | ||||
| void of_exit(void); | ||||
| void *of_finddevice(const char *name); | ||||
| int of_getprop(const void *phandle, const char *name, void *buf, | ||||
| 	       const int buflen); | ||||
| int of_setprop(const void *phandle, const char *name, const void *buf, | ||||
| 	       const int buflen); | ||||
| 
 | ||||
| /* Console functions */ | ||||
| void of_console_init(void); | ||||
| 
 | ||||
| #endif /* _PPC_BOOT_OF_H_ */ | ||||
							
								
								
									
										45
									
								
								arch/powerpc/boot/ofconsole.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								arch/powerpc/boot/ofconsole.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| /*
 | ||||
|  * OF console routines | ||||
|  * | ||||
|  * Copyright (C) Paul Mackerras 1997. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * as published by the Free Software Foundation; either version | ||||
|  * 2 of the License, or (at your option) any later version. | ||||
|  */ | ||||
| #include <stddef.h> | ||||
| #include "types.h" | ||||
| #include "elf.h" | ||||
| #include "string.h" | ||||
| #include "stdio.h" | ||||
| #include "page.h" | ||||
| #include "ops.h" | ||||
| 
 | ||||
| #include "of.h" | ||||
| 
 | ||||
| static void *of_stdout_handle; | ||||
| 
 | ||||
| static int of_console_open(void) | ||||
| { | ||||
| 	void *devp; | ||||
| 
 | ||||
| 	if (((devp = of_finddevice("/chosen")) != NULL) | ||||
| 	    && (of_getprop(devp, "stdout", &of_stdout_handle, | ||||
| 			   sizeof(of_stdout_handle)) | ||||
| 		== sizeof(of_stdout_handle))) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| static void of_console_write(const char *buf, int len) | ||||
| { | ||||
| 	of_call_prom("write", 3, 1, of_stdout_handle, buf, len); | ||||
| } | ||||
| 
 | ||||
| void of_console_init(void) | ||||
| { | ||||
| 	console_ops.open = of_console_open; | ||||
| 	console_ops.write = of_console_write; | ||||
| } | ||||
							
								
								
									
										202
									
								
								arch/powerpc/boot/oflib.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								arch/powerpc/boot/oflib.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,202 @@ | ||||
| /*
 | ||||
|  * Copyright (C) Paul Mackerras 1997. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * as published by the Free Software Foundation; either version | ||||
|  * 2 of the License, or (at your option) any later version. | ||||
|  */ | ||||
| #include <stddef.h> | ||||
| #include "types.h" | ||||
| #include "elf.h" | ||||
| #include "string.h" | ||||
| #include "stdio.h" | ||||
| #include "page.h" | ||||
| #include "ops.h" | ||||
| 
 | ||||
| #include "of.h" | ||||
| 
 | ||||
| static int (*prom) (void *); | ||||
| 
 | ||||
| void of_init(void *promptr) | ||||
| { | ||||
| 	prom = (int (*)(void *))promptr; | ||||
| } | ||||
| 
 | ||||
| int of_call_prom(const char *service, int nargs, int nret, ...) | ||||
| { | ||||
| 	int i; | ||||
| 	struct prom_args { | ||||
| 		const char *service; | ||||
| 		int nargs; | ||||
| 		int nret; | ||||
| 		unsigned int args[12]; | ||||
| 	} args; | ||||
| 	va_list list; | ||||
| 
 | ||||
| 	args.service = service; | ||||
| 	args.nargs = nargs; | ||||
| 	args.nret = nret; | ||||
| 
 | ||||
| 	va_start(list, nret); | ||||
| 	for (i = 0; i < nargs; i++) | ||||
| 		args.args[i] = va_arg(list, unsigned int); | ||||
| 	va_end(list); | ||||
| 
 | ||||
| 	for (i = 0; i < nret; i++) | ||||
| 		args.args[nargs+i] = 0; | ||||
| 
 | ||||
| 	if (prom(&args) < 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	return (nret > 0)? args.args[nargs]: 0; | ||||
| } | ||||
| 
 | ||||
| static int of_call_prom_ret(const char *service, int nargs, int nret, | ||||
| 			    unsigned int *rets, ...) | ||||
| { | ||||
| 	int i; | ||||
| 	struct prom_args { | ||||
| 		const char *service; | ||||
| 		int nargs; | ||||
| 		int nret; | ||||
| 		unsigned int args[12]; | ||||
| 	} args; | ||||
| 	va_list list; | ||||
| 
 | ||||
| 	args.service = service; | ||||
| 	args.nargs = nargs; | ||||
| 	args.nret = nret; | ||||
| 
 | ||||
| 	va_start(list, rets); | ||||
| 	for (i = 0; i < nargs; i++) | ||||
| 		args.args[i] = va_arg(list, unsigned int); | ||||
| 	va_end(list); | ||||
| 
 | ||||
| 	for (i = 0; i < nret; i++) | ||||
| 		args.args[nargs+i] = 0; | ||||
| 
 | ||||
| 	if (prom(&args) < 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (rets != (void *) 0) | ||||
| 		for (i = 1; i < nret; ++i) | ||||
| 			rets[i-1] = args.args[nargs+i]; | ||||
| 
 | ||||
| 	return (nret > 0)? args.args[nargs]: 0; | ||||
| } | ||||
| 
 | ||||
| /* returns true if s2 is a prefix of s1 */ | ||||
| static int string_match(const char *s1, const char *s2) | ||||
| { | ||||
| 	for (; *s2; ++s2) | ||||
| 		if (*s1++ != *s2) | ||||
| 			return 0; | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Older OF's require that when claiming a specific range of addresses, | ||||
|  * we claim the physical space in the /memory node and the virtual | ||||
|  * space in the chosen mmu node, and then do a map operation to | ||||
|  * map virtual to physical. | ||||
|  */ | ||||
| static int need_map = -1; | ||||
| static ihandle chosen_mmu; | ||||
| static phandle memory; | ||||
| 
 | ||||
| static int check_of_version(void) | ||||
| { | ||||
| 	phandle oprom, chosen; | ||||
| 	char version[64]; | ||||
| 
 | ||||
| 	oprom = of_finddevice("/openprom"); | ||||
| 	if (oprom == (phandle) -1) | ||||
| 		return 0; | ||||
| 	if (of_getprop(oprom, "model", version, sizeof(version)) <= 0) | ||||
| 		return 0; | ||||
| 	version[sizeof(version)-1] = 0; | ||||
| 	printf("OF version = '%s'\r\n", version); | ||||
| 	if (!string_match(version, "Open Firmware, 1.") | ||||
| 	    && !string_match(version, "FirmWorks,3.")) | ||||
| 		return 0; | ||||
| 	chosen = of_finddevice("/chosen"); | ||||
| 	if (chosen == (phandle) -1) { | ||||
| 		chosen = of_finddevice("/chosen@0"); | ||||
| 		if (chosen == (phandle) -1) { | ||||
| 			printf("no chosen\n"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||||
| 		printf("no mmu\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	memory = (ihandle) of_call_prom("open", 1, 1, "/memory"); | ||||
| 	if (memory == (ihandle) -1) { | ||||
| 		memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0"); | ||||
| 		if (memory == (ihandle) -1) { | ||||
| 			printf("no memory node\n"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	printf("old OF detected\r\n"); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| void *of_claim(unsigned long virt, unsigned long size, unsigned long align) | ||||
| { | ||||
| 	int ret; | ||||
| 	unsigned int result; | ||||
| 
 | ||||
| 	if (need_map < 0) | ||||
| 		need_map = check_of_version(); | ||||
| 	if (align || !need_map) | ||||
| 		return (void *) of_call_prom("claim", 3, 1, virt, size, align); | ||||
| 
 | ||||
| 	ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory, | ||||
| 			       align, size, virt); | ||||
| 	if (ret != 0 || result == -1) | ||||
| 		return (void *) -1; | ||||
| 	ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||||
| 			       align, size, virt); | ||||
| 	/* 0x12 == coherent + read/write */ | ||||
| 	ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu, | ||||
| 			   0x12, size, virt, virt); | ||||
| 	return (void *) virt; | ||||
| } | ||||
| 
 | ||||
| void *of_vmlinux_alloc(unsigned long size) | ||||
| { | ||||
| 	void *p = malloc(size); | ||||
| 
 | ||||
| 	if (!p) | ||||
| 		fatal("Can't allocate memory for kernel image!\n\r"); | ||||
| 
 | ||||
| 	return p; | ||||
| } | ||||
| 
 | ||||
| void of_exit(void) | ||||
| { | ||||
| 	of_call_prom("exit", 0, 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * OF device tree routines | ||||
|  */ | ||||
| void *of_finddevice(const char *name) | ||||
| { | ||||
| 	return (phandle) of_call_prom("finddevice", 1, 1, name); | ||||
| } | ||||
| 
 | ||||
| int of_getprop(const void *phandle, const char *name, void *buf, | ||||
| 	       const int buflen) | ||||
| { | ||||
| 	return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen); | ||||
| } | ||||
| 
 | ||||
| int of_setprop(const void *phandle, const char *name, const void *buf, | ||||
| 	       const int buflen) | ||||
| { | ||||
| 	return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen); | ||||
| } | ||||
| @ -19,6 +19,8 @@ | ||||
| #define	MAX_PATH_LEN		256 | ||||
| #define	MAX_PROP_LEN		256 /* What should this be? */ | ||||
| 
 | ||||
| typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5); | ||||
| 
 | ||||
| /* Platform specific operations */ | ||||
| struct platform_ops { | ||||
| 	void	(*fixups)(void); | ||||
| @ -51,7 +53,7 @@ extern struct dt_ops dt_ops; | ||||
| /* Console operations */ | ||||
| struct console_ops { | ||||
| 	int	(*open)(void); | ||||
| 	void	(*write)(char *buf, int len); | ||||
| 	void	(*write)(const char *buf, int len); | ||||
| 	void	(*edit_cmdline)(char *buf, int len); | ||||
| 	void	(*close)(void); | ||||
| 	void	*data; | ||||
|  | ||||
							
								
								
									
										80
									
								
								arch/powerpc/boot/ps3-head.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								arch/powerpc/boot/ps3-head.S
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| /* | ||||
|  *  PS3 bootwrapper entry. | ||||
|  * | ||||
|  *  Copyright (C) 2007 Sony Computer Entertainment Inc. | ||||
|  *  Copyright 2007 Sony Corp. | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or modify
 | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation; version 2 of the License.
 | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program; if not, write to the Free Software
 | ||||
|  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "ppc_asm.h" | ||||
| 
 | ||||
| 	.text | ||||
| 
 | ||||
| /* | ||||
|  * __system_reset_overlay - The PS3 first stage entry. | ||||
|  * | ||||
|  * The bootwraper build script copies the 0x100 bytes at symbol | ||||
|  * __system_reset_overlay to offset 0x100 of the rom image. | ||||
|  * | ||||
|  * The PS3 has a single processor with two threads. | ||||
|  */ | ||||
| 
 | ||||
| 	.globl __system_reset_overlay
 | ||||
| __system_reset_overlay: | ||||
| 
 | ||||
| 	/* Switch to 32-bit mode. */ | ||||
| 
 | ||||
| 	mfmsr	r9 | ||||
| 	clrldi	r9,r9,1 | ||||
| 	mtmsrd	r9 | ||||
| 	nop | ||||
| 
 | ||||
| 	/* Get thread number in r3 and branch. */ | ||||
| 
 | ||||
| 	mfspr	r3, 0x88 | ||||
| 	cntlzw.	r3, r3 | ||||
| 	li	r4, 0 | ||||
| 	li	r5, 0 | ||||
| 	beq	1f | ||||
| 
 | ||||
| 	/* Secondary goes to __secondary_hold in kernel. */ | ||||
| 
 | ||||
| 	li	r4, 0x60 | ||||
| 	mtctr	r4 | ||||
| 	bctr | ||||
| 
 | ||||
| 	/* Primary delays then goes to _zimage_start in wrapper. */ | ||||
| 1: | ||||
| 	or	31, 31, 31 /* db16cyc */ | ||||
| 	or	31, 31, 31 /* db16cyc */ | ||||
| 
 | ||||
| 	lis	r4, _zimage_start@ha
 | ||||
| 	addi	r4, r4, _zimage_start@l
 | ||||
| 	mtctr	r4 | ||||
| 	bctr | ||||
| 
 | ||||
| /* | ||||
|  * __system_reset_kernel - Place holder for the kernel reset vector. | ||||
|  * | ||||
|  * The bootwrapper build script copies 0x100 bytes from offset 0x100 | ||||
|  * of the rom image to the symbol __system_reset_kernel.  At runtime | ||||
|  * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel | ||||
|  * to ram address 0x100.  This symbol must occupy 0x100 bytes. | ||||
|  */ | ||||
| 
 | ||||
| 	.globl __system_reset_kernel
 | ||||
| __system_reset_kernel: | ||||
| 
 | ||||
| 	. = __system_reset_kernel + 0x100 | ||||
							
								
								
									
										184
									
								
								arch/powerpc/boot/ps3-hvcall.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								arch/powerpc/boot/ps3-hvcall.S
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,184 @@ | ||||
| /* | ||||
|  *  PS3 bootwrapper hvcalls. | ||||
|  * | ||||
|  *  Copyright (C) 2007 Sony Computer Entertainment Inc. | ||||
|  *  Copyright 2007 Sony Corp. | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or modify
 | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation; version 2 of the License.
 | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program; if not, write to the Free Software
 | ||||
|  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "ppc_asm.h" | ||||
| 
 | ||||
| /* | ||||
|  * The PS3 hypervisor uses a 64 bit "C" language calling convention. | ||||
|  * The routines here marshal arguments between the 32 bit wrapper | ||||
|  * program and the 64 bit hvcalls. | ||||
|  * | ||||
|  *  wrapper           lv1 | ||||
|  *  32-bit (h,l)      64-bit | ||||
|  * | ||||
|  *  1: r3,r4          <-> r3 | ||||
|  *  2: r5,r6          <-> r4 | ||||
|  *  3: r7,r8          <-> r5 | ||||
|  *  4: r9,r10         <-> r6 | ||||
|  *  5: 8(r1),12(r1)   <-> r7 | ||||
|  *  6: 16(r1),20(r1)  <-> r8 | ||||
|  *  7: 24(r1),28(r1)  <-> r9 | ||||
|  *  8: 32(r1),36(r1)  <-> r10 | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| .macro GLOBAL name | ||||
| 	.section ".text" | ||||
| 	.balign 4
 | ||||
| 	.globl \name | ||||
| \name: | ||||
| .endm | ||||
| 
 | ||||
| .macro NO_SUPPORT name | ||||
| 	GLOBAL \name | ||||
| 	b ps3_no_support | ||||
| .endm | ||||
| 
 | ||||
| .macro HVCALL num | ||||
| 	li r11, \num | ||||
| 	.long 0x44000022
 | ||||
| 	extsw r3, r3 | ||||
| .endm | ||||
| 
 | ||||
| .macro SAVE_LR offset=4 | ||||
| 	mflr r0 | ||||
| 	stw r0, \offset(r1) | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_LR offset=4 | ||||
| 	lwz r0, \offset(r1) | ||||
| 	mtlr r0 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_64_REG target,high,low | ||||
| 	sldi r11, \high, 32 | ||||
| 	or \target, r11, \low | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_64_STACK target,offset | ||||
| 	ld \target, \offset(r1) | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R3
 | ||||
| 	LOAD_64_REG r3,r3,r4 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R4
 | ||||
| 	LOAD_64_REG r4,r5,r6 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R5
 | ||||
| 	LOAD_64_REG r5,r7,r8 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R6
 | ||||
| 	LOAD_64_REG r6,r9,r10 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R7
 | ||||
| 	LOAD_64_STACK r7,8 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R8
 | ||||
| 	LOAD_64_STACK r8,16 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R9
 | ||||
| 	LOAD_64_STACK r9,24 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_R10
 | ||||
| 	LOAD_64_STACK r10,32 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_REGS_0
 | ||||
| 	stwu 1,-16(1) | ||||
| 	stw 3, 8(1) | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_REGS_5
 | ||||
| 	LOAD_R3 | ||||
| 	LOAD_R4 | ||||
| 	LOAD_R5 | ||||
| 	LOAD_R6 | ||||
| 	LOAD_R7 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_REGS_6
 | ||||
| 	LOAD_REGS_5 | ||||
| 	LOAD_R8 | ||||
| .endm | ||||
| 
 | ||||
| .macro LOAD_REGS_8
 | ||||
| 	LOAD_REGS_6 | ||||
| 	LOAD_R9 | ||||
| 	LOAD_R10 | ||||
| .endm | ||||
| 
 | ||||
| .macro STORE_REGS_0_1
 | ||||
| 	lwz r11, 8(r1) | ||||
| 	std r4, 0(r11) | ||||
| 	mr r4, r3 | ||||
| 	li r3, 0 | ||||
| 	addi r1,r1,16 | ||||
| .endm | ||||
| 
 | ||||
| .macro STORE_REGS_5_2
 | ||||
| 	lwz r11, 16(r1) | ||||
| 	std r4, 0(r11) | ||||
| 	lwz r11, 24(r1) | ||||
| 	std r5, 0(r11) | ||||
| .endm | ||||
| 
 | ||||
| .macro STORE_REGS_6_1
 | ||||
| 	lwz r11, 24(r1) | ||||
| 	std r4, 0(r11) | ||||
| .endm | ||||
| 
 | ||||
| GLOBAL lv1_get_logical_ppe_id | ||||
| 	SAVE_LR | ||||
| 	LOAD_REGS_0 | ||||
| 	HVCALL 69 | ||||
| 	STORE_REGS_0_1 | ||||
| 	LOAD_LR | ||||
| 	blr | ||||
| 
 | ||||
| GLOBAL lv1_get_logical_partition_id | ||||
| 	SAVE_LR | ||||
| 	LOAD_REGS_0 | ||||
| 	HVCALL 74 | ||||
| 	STORE_REGS_0_1 | ||||
| 	LOAD_LR | ||||
| 	blr | ||||
| 
 | ||||
| GLOBAL lv1_get_repository_node_value | ||||
| 	SAVE_LR | ||||
| 	LOAD_REGS_5 | ||||
| 	HVCALL 91 | ||||
| 	STORE_REGS_5_2 | ||||
| 	LOAD_LR | ||||
| 	blr | ||||
| 
 | ||||
| GLOBAL lv1_panic | ||||
| 	SAVE_LR | ||||
| 	LOAD_REGS_8 | ||||
| 	HVCALL 255 | ||||
| 	LOAD_LR | ||||
| 	blr | ||||
							
								
								
									
										161
									
								
								arch/powerpc/boot/ps3.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								arch/powerpc/boot/ps3.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,161 @@ | ||||
| /*
 | ||||
|  *  PS3 bootwrapper support. | ||||
|  * | ||||
|  *  Copyright (C) 2007 Sony Computer Entertainment Inc. | ||||
|  *  Copyright 2007 Sony Corp. | ||||
|  * | ||||
|  *  This program is free software; you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation; version 2 of the License. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program; if not, write to the Free Software | ||||
|  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| 
 | ||||
| #include <stdarg.h> | ||||
| #include <stddef.h> | ||||
| #include "types.h" | ||||
| #include "elf.h" | ||||
| #include "string.h" | ||||
| #include "stdio.h" | ||||
| #include "page.h" | ||||
| #include "ops.h" | ||||
| 
 | ||||
| extern s64 lv1_panic(u64 in_1); | ||||
| extern s64 lv1_get_logical_partition_id(u64 *out_1); | ||||
| extern s64 lv1_get_logical_ppe_id(u64 *out_1); | ||||
| extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3, | ||||
| 	u64 in_4, u64 in_5, u64 *out_1, u64 *out_2); | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| #define DBG(fmt...) printf(fmt) | ||||
| #else | ||||
| static inline int __attribute__ ((format (printf, 1, 2))) DBG( | ||||
| 	const char *fmt, ...) {return 0;} | ||||
| #endif | ||||
| 
 | ||||
| BSS_STACK(4096); | ||||
| 
 | ||||
| /* A buffer that may be edited by tools operating on a zImage binary so as to
 | ||||
|  * edit the command line passed to vmlinux (by setting /chosen/bootargs). | ||||
|  * The buffer is put in it's own section so that tools may locate it easier. | ||||
|  */ | ||||
| static char cmdline[COMMAND_LINE_SIZE] | ||||
| 	__attribute__((__section__("__builtin_cmdline"))); | ||||
| 
 | ||||
| static void prep_cmdline(void *chosen) | ||||
| { | ||||
| 	if (cmdline[0] == '\0') | ||||
| 		getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1); | ||||
| 	else | ||||
| 		setprop_str(chosen, "bootargs", cmdline); | ||||
| 
 | ||||
| 	printf("cmdline: '%s'\n", cmdline); | ||||
| } | ||||
| 
 | ||||
| static void ps3_console_write(const char *buf, int len) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static void ps3_exit(void) | ||||
| { | ||||
| 	printf("ps3_exit\n"); | ||||
| 
 | ||||
| 	/* lv1_panic will shutdown the lpar. */ | ||||
| 
 | ||||
| 	lv1_panic(0); /* zero = do not reboot */ | ||||
| 	while (1); | ||||
| } | ||||
| 
 | ||||
| static int ps3_repository_read_rm_size(u64 *rm_size) | ||||
| { | ||||
| 	s64 result; | ||||
| 	u64 lpar_id; | ||||
| 	u64 ppe_id; | ||||
| 	u64 v2; | ||||
| 
 | ||||
| 	result = lv1_get_logical_partition_id(&lpar_id); | ||||
| 
 | ||||
| 	if (result) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	result = lv1_get_logical_ppe_id(&ppe_id); | ||||
| 
 | ||||
| 	if (result) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * n1: 0000000062690000 : ....bi.. | ||||
| 	 * n2: 7075000000000000 : pu...... | ||||
| 	 * n3: 0000000000000001 : ........ | ||||
| 	 * n4: 726d5f73697a6500 : rm_size. | ||||
| 	*/ | ||||
| 
 | ||||
| 	result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL, | ||||
| 		0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size, | ||||
| 		&v2); | ||||
| 
 | ||||
| 	printf("%s:%d: ppe_id  %lu \n", __func__, __LINE__, | ||||
| 		(unsigned long)ppe_id); | ||||
| 	printf("%s:%d: lpar_id %lu \n", __func__, __LINE__, | ||||
| 		(unsigned long)lpar_id); | ||||
| 	printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size); | ||||
| 
 | ||||
| 	return result ? -1 : 0; | ||||
| } | ||||
| 
 | ||||
| void ps3_copy_vectors(void) | ||||
| { | ||||
| 	extern char __system_reset_kernel[]; | ||||
| 
 | ||||
| 	memcpy((void *)0x100, __system_reset_kernel, 0x100); | ||||
| 	flush_cache((void *)0x100, 0x100); | ||||
| } | ||||
| 
 | ||||
| void platform_init(void) | ||||
| { | ||||
| 	extern char _end[]; | ||||
| 	extern char _dtb_start[]; | ||||
| 	extern char _initrd_start[]; | ||||
| 	extern char _initrd_end[]; | ||||
| 	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */ | ||||
| 	void *chosen; | ||||
| 	unsigned long ft_addr; | ||||
| 	u64 rm_size; | ||||
| 
 | ||||
| 	console_ops.write = ps3_console_write; | ||||
| 	platform_ops.exit = ps3_exit; | ||||
| 
 | ||||
| 	printf("\n-- PS3 bootwrapper --\n"); | ||||
| 
 | ||||
| 	simple_alloc_init(_end, heapsize, 32, 64); | ||||
| 	ft_init(_dtb_start, 0, 4); | ||||
| 
 | ||||
| 	chosen = finddevice("/chosen"); | ||||
| 
 | ||||
| 	ps3_repository_read_rm_size(&rm_size); | ||||
| 	dt_fixup_memory(0, rm_size); | ||||
| 
 | ||||
| 	if (_initrd_end > _initrd_start) { | ||||
| 		setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start)); | ||||
| 		setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end)); | ||||
| 	} | ||||
| 
 | ||||
| 	prep_cmdline(chosen); | ||||
| 
 | ||||
| 	ft_addr = dt_ops.finalize(); | ||||
| 
 | ||||
| 	ps3_copy_vectors(); | ||||
| 
 | ||||
| 	printf(" flat tree at 0x%lx\n\r", ft_addr); | ||||
| 
 | ||||
| 	((kernel_entry_t)0)(ft_addr, 0, NULL); | ||||
| 
 | ||||
| 	ps3_exit(); | ||||
| } | ||||
| @ -27,7 +27,7 @@ static int serial_open(void) | ||||
| 	return scdp->open(); | ||||
| } | ||||
| 
 | ||||
| static void serial_write(char *buf, int len) | ||||
| static void serial_write(const char *buf, int len) | ||||
| { | ||||
| 	struct serial_console_data *scdp = console_ops.data; | ||||
| 
 | ||||
|  | ||||
| @ -190,7 +190,11 @@ int vsprintf(char *buf, const char *fmt, va_list args) | ||||
| 
 | ||||
| 		/* get the conversion qualifier */ | ||||
| 		qualifier = -1; | ||||
| 		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { | ||||
| 		if (*fmt == 'l' && *(fmt + 1) == 'l') { | ||||
| 			qualifier = 'q'; | ||||
| 			fmt += 2; | ||||
| 		} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' | ||||
| 			|| *fmt == 'Z') { | ||||
| 			qualifier = *fmt; | ||||
| 			++fmt; | ||||
| 		} | ||||
| @ -281,6 +285,10 @@ int vsprintf(char *buf, const char *fmt, va_list args) | ||||
| 			num = va_arg(args, unsigned long); | ||||
| 			if (flags & SIGN) | ||||
| 				num = (signed long) num; | ||||
| 		} else if (qualifier == 'q') { | ||||
| 			num = va_arg(args, unsigned long long); | ||||
| 			if (flags & SIGN) | ||||
| 				num = (signed long long) num; | ||||
| 		} else if (qualifier == 'Z') { | ||||
| 			num = va_arg(args, size_t); | ||||
| 		} else if (qualifier == 'h') { | ||||
|  | ||||
| @ -7,6 +7,10 @@ typedef unsigned char		u8; | ||||
| typedef unsigned short		u16; | ||||
| typedef unsigned int		u32; | ||||
| typedef unsigned long long	u64; | ||||
| typedef signed char		s8; | ||||
| typedef short			s16; | ||||
| typedef int			s32; | ||||
| typedef long long		s64; | ||||
| 
 | ||||
| #define min(x,y) ({ \ | ||||
| 	typeof(x) _x = (x);	\ | ||||
|  | ||||
| @ -144,6 +144,15 @@ miboot|uboot) | ||||
| cuboot*) | ||||
|     gzip= | ||||
|     ;; | ||||
| ps3) | ||||
|     platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o" | ||||
|     lds=$object/zImage.ps3.lds | ||||
|     gzip= | ||||
|     ext=bin | ||||
|     objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data" | ||||
|     ksection=.kernel:vmlinux.bin | ||||
|     isection=.kernel:initrd | ||||
|     ;; | ||||
| esac | ||||
| 
 | ||||
| vmz="$tmpdir/`basename \"$kernel\"`.$ext" | ||||
| @ -239,4 +248,50 @@ treeboot*) | ||||
|     fi | ||||
|     exit 0 | ||||
|     ;; | ||||
| ps3) | ||||
|     # The ps3's loader supports loading gzipped binary images from flash | ||||
|     # rom to addr zero. The loader enters the image at addr 0x100.  A | ||||
|     # bootwrapper overlay is use to arrange for the kernel to be loaded | ||||
|     # to addr zero and to have a suitable bootwrapper entry at 0x100. | ||||
|     # To construct the rom image, 0x100 bytes from offset 0x100 in the | ||||
|     # kernel is copied to the bootwrapper symbol __system_reset_kernel. | ||||
|     # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is | ||||
|     # then copied to offset 0x100.  At runtime the bootwrapper program | ||||
|     # copies the 0x100 bytes at __system_reset_kernel to addr 0x100. | ||||
| 
 | ||||
|     system_reset_overlay=0x`${CROSS}nm "$ofile" \ | ||||
|         | grep ' __system_reset_overlay$'       \ | ||||
|         | cut -d' ' -f1` | ||||
|     system_reset_overlay=`printf "%d" $system_reset_overlay` | ||||
|     system_reset_kernel=0x`${CROSS}nm "$ofile" \ | ||||
|         | grep ' __system_reset_kernel$'       \ | ||||
|         | cut -d' ' -f1` | ||||
|     system_reset_kernel=`printf "%d" $system_reset_kernel` | ||||
|     overlay_dest="256" | ||||
|     overlay_size="256" | ||||
| 
 | ||||
|     rm -f "$object/otheros.bld" | ||||
| 
 | ||||
|     ${CROSS}objcopy -O binary "$ofile" "$ofile.bin" | ||||
| 
 | ||||
|     msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ | ||||
|         skip=$overlay_dest seek=$system_reset_kernel      \ | ||||
|         count=$overlay_size bs=1 2>&1) | ||||
| 
 | ||||
|     if [ $? -ne "0" ]; then | ||||
|        echo $msg | ||||
|        exit 1 | ||||
|     fi | ||||
| 
 | ||||
|     msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ | ||||
|         skip=$system_reset_overlay seek=$overlay_dest     \ | ||||
|         count=$overlay_size bs=1 2>&1) | ||||
| 
 | ||||
|     if [ $? -ne "0" ]; then | ||||
|        echo $msg | ||||
|        exit 2 | ||||
|     fi | ||||
| 
 | ||||
|     gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld" | ||||
|     ;; | ||||
| esac | ||||
|  | ||||
							
								
								
									
										50
									
								
								arch/powerpc/boot/zImage.ps3.lds.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								arch/powerpc/boot/zImage.ps3.lds.S
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| OUTPUT_ARCH(powerpc:common) | ||||
| ENTRY(_zimage_start) | ||||
| EXTERN(_zimage_start) | ||||
| SECTIONS | ||||
| { | ||||
|   _vmlinux_start =  .;
 | ||||
|   .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) } | ||||
|   _vmlinux_end =  .;
 | ||||
| 
 | ||||
|   . = ALIGN(4096);
 | ||||
|   _dtb_start = .;
 | ||||
|   .kernel:dtb : { *(.kernel:dtb) } | ||||
|   _dtb_end = .;
 | ||||
| 
 | ||||
|   . = ALIGN(4096);
 | ||||
|   _initrd_start =  .;
 | ||||
|   .kernel:initrd : { *(.kernel:initrd) } | ||||
|   _initrd_end =  .;
 | ||||
| 
 | ||||
|   _start = .;
 | ||||
|   .text      : | ||||
|   { | ||||
|     *(.text) | ||||
|     *(.fixup) | ||||
|   } | ||||
|   _etext = .;
 | ||||
|   . = ALIGN(4096);
 | ||||
|   .data    : | ||||
|   { | ||||
|     *(.rodata*) | ||||
|     *(.data*) | ||||
|     *(.sdata*) | ||||
|     __got2_start = .;
 | ||||
|     *(.got2) | ||||
|     __got2_end = .;
 | ||||
|   } | ||||
| 
 | ||||
|   . = ALIGN(4096);
 | ||||
|   _edata  =  .;
 | ||||
| 
 | ||||
|   . = ALIGN(4096);
 | ||||
|   __bss_start = .;
 | ||||
|   .bss       : | ||||
|   { | ||||
|    *(.sbss) | ||||
|    *(.bss) | ||||
|   } | ||||
|   . = ALIGN(4096);
 | ||||
|   _end = . ;
 | ||||
| } | ||||
| @ -190,10 +190,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 | ||||
| # CONFIG_RESOURCES_64BIT is not set | ||||
| CONFIG_ZONE_DMA_FLAG=1 | ||||
| CONFIG_PROC_DEVICETREE=y | ||||
| # CONFIG_CMDLINE_BOOL is not set | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| CONFIG_CMDLINE="console=ttyS0,115200" | ||||
| # CONFIG_PM is not set | ||||
| # CONFIG_SECCOMP is not set | ||||
| # CONFIG_WANT_DEVICE_TREE is not set | ||||
| CONFIG_WANT_DEVICE_TREE=y | ||||
| CONFIG_DEVICE_TREE="holly.dts" | ||||
| CONFIG_ISA_DMA_API=y | ||||
| 
 | ||||
| # | ||||
|  | ||||
| @ -156,7 +156,11 @@ CONFIG_PS3_HTAB_SIZE=20 | ||||
| CONFIG_PS3_USE_LPAR_ADDR=y | ||||
| CONFIG_PS3_VUART=y | ||||
| CONFIG_PS3_PS3AV=y | ||||
| CONFIG_PS3_SYS_MANAGER=y | ||||
| CONFIG_PS3_SYS_MANAGER=m | ||||
| CONFIG_PS3_STORAGE=y | ||||
| CONFIG_PS3_DISK=y | ||||
| CONFIG_PS3_ROM=y | ||||
| CONFIG_PS3_FLASH=y | ||||
| CONFIG_PPC_CELL=y | ||||
| # CONFIG_PPC_CELL_NATIVE is not set | ||||
| # CONFIG_PPC_IBM_CELL_BLADE is not set | ||||
| @ -335,7 +339,7 @@ CONFIG_BT=m | ||||
| CONFIG_BT_L2CAP=m | ||||
| CONFIG_BT_SCO=m | ||||
| CONFIG_BT_RFCOMM=m | ||||
| # CONFIG_BT_RFCOMM_TTY is not set | ||||
| CONFIG_BT_RFCOMM_TTY=y | ||||
| # CONFIG_BT_BNEP is not set | ||||
| CONFIG_BT_HIDP=m | ||||
| 
 | ||||
| @ -344,7 +348,9 @@ CONFIG_BT_HIDP=m | ||||
| # | ||||
| CONFIG_BT_HCIUSB=m | ||||
| CONFIG_BT_HCIUSB_SCO=y | ||||
| # CONFIG_BT_HCIUART is not set | ||||
| CONFIG_BT_HCIUART=m | ||||
| CONFIG_BT_HCIUART_H4=y | ||||
| CONFIG_BT_HCIUART_BCSP=y | ||||
| # CONFIG_BT_HCIBCM203X is not set | ||||
| # CONFIG_BT_HCIBPA10X is not set | ||||
| # CONFIG_BT_HCIBFUSB is not set | ||||
| @ -435,7 +441,7 @@ CONFIG_CHR_DEV_SG=m | ||||
| # | ||||
| # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | ||||
| # | ||||
| # CONFIG_SCSI_MULTI_LUN is not set | ||||
| CONFIG_SCSI_MULTI_LUN=y | ||||
| # CONFIG_SCSI_CONSTANTS is not set | ||||
| # CONFIG_SCSI_LOGGING is not set | ||||
| # CONFIG_SCSI_SCAN_ASYNC is not set | ||||
| @ -479,6 +485,7 @@ CONFIG_NETDEVICES=y | ||||
| CONFIG_MII=m | ||||
| CONFIG_NETDEV_1000=y | ||||
| CONFIG_NETDEV_10000=y | ||||
| CONFIG_GELIC_NET=y | ||||
| 
 | ||||
| # | ||||
| # Wireless LAN | ||||
| @ -546,7 +553,27 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | ||||
| # | ||||
| # CONFIG_INPUT_KEYBOARD is not set | ||||
| # CONFIG_INPUT_MOUSE is not set | ||||
| # CONFIG_INPUT_JOYSTICK is not set | ||||
| CONFIG_INPUT_JOYSTICK=y | ||||
| # CONFIG_JOYSTICK_ANALOG is not set | ||||
| # CONFIG_JOYSTICK_A3D is not set | ||||
| # CONFIG_JOYSTICK_ADI is not set | ||||
| # CONFIG_JOYSTICK_COBRA is not set | ||||
| # CONFIG_JOYSTICK_GF2K is not set | ||||
| # CONFIG_JOYSTICK_GRIP is not set | ||||
| # CONFIG_JOYSTICK_GRIP_MP is not set | ||||
| # CONFIG_JOYSTICK_GUILLEMOT is not set | ||||
| # CONFIG_JOYSTICK_INTERACT is not set | ||||
| # CONFIG_JOYSTICK_SIDEWINDER is not set | ||||
| # CONFIG_JOYSTICK_TMDC is not set | ||||
| # CONFIG_JOYSTICK_IFORCE is not set | ||||
| # CONFIG_JOYSTICK_WARRIOR is not set | ||||
| # CONFIG_JOYSTICK_MAGELLAN is not set | ||||
| # CONFIG_JOYSTICK_SPACEORB is not set | ||||
| # CONFIG_JOYSTICK_SPACEBALL is not set | ||||
| # CONFIG_JOYSTICK_STINGER is not set | ||||
| # CONFIG_JOYSTICK_TWIDJOY is not set | ||||
| # CONFIG_JOYSTICK_JOYDUMP is not set | ||||
| # CONFIG_JOYSTICK_XPAD is not set | ||||
| # CONFIG_INPUT_TABLET is not set | ||||
| # CONFIG_INPUT_TOUCHSCREEN is not set | ||||
| # CONFIG_INPUT_MISC is not set | ||||
| @ -563,7 +590,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | ||||
| CONFIG_VT=y | ||||
| CONFIG_VT_CONSOLE=y | ||||
| CONFIG_HW_CONSOLE=y | ||||
| # CONFIG_VT_HW_CONSOLE_BINDING is not set | ||||
| CONFIG_VT_HW_CONSOLE_BINDING=y | ||||
| # CONFIG_SERIAL_NONSTANDARD is not set | ||||
| 
 | ||||
| # | ||||
| @ -1086,7 +1113,7 @@ CONFIG_HAS_DMA=y | ||||
| # | ||||
| # CONFIG_PRINTK_TIME is not set | ||||
| CONFIG_ENABLE_MUST_CHECK=y | ||||
| # CONFIG_MAGIC_SYSRQ is not set | ||||
| CONFIG_MAGIC_SYSRQ=y | ||||
| # CONFIG_UNUSED_SYMBOLS is not set | ||||
| # CONFIG_DEBUG_FS is not set | ||||
| # CONFIG_HEADERS_CHECK is not set | ||||
| @ -1116,16 +1143,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y | ||||
| # CONFIG_DEBUGGER is not set | ||||
| CONFIG_IRQSTACKS=y | ||||
| # CONFIG_BOOTX_TEXT is not set | ||||
| CONFIG_PPC_EARLY_DEBUG=y | ||||
| # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_BEAT is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG_44x is not set | ||||
| # CONFIG_PPC_EARLY_DEBUG is not set | ||||
| 
 | ||||
| # | ||||
| # Security options | ||||
|  | ||||
| @ -12,7 +12,8 @@ endif | ||||
| 
 | ||||
| obj-y				:= semaphore.o cputable.o ptrace.o syscalls.o \
 | ||||
| 				   irq.o align.o signal_32.o pmc.o vdso.o \
 | ||||
| 				   init_task.o process.o systbl.o idle.o | ||||
| 				   init_task.o process.o systbl.o idle.o \
 | ||||
| 				   signal.o | ||||
| obj-y				+= vdso32/ | ||||
| obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
 | ||||
| 				   signal_64.o ptrace32.o \
 | ||||
| @ -65,9 +66,9 @@ obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o | ||||
| module-$(CONFIG_PPC64)		+= module_64.o | ||||
| obj-$(CONFIG_MODULES)		+= $(module-y) | ||||
| 
 | ||||
| pci64-$(CONFIG_PPC64)		+= pci_64.o pci_dn.o | ||||
| pci64-$(CONFIG_PPC64)		+= pci_64.o pci_dn.o isa-bridge.o | ||||
| pci32-$(CONFIG_PPC32)		:= pci_32.o | ||||
| obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y) | ||||
| obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y) pci-common.o | ||||
| obj-$(CONFIG_PCI_MSI)		+= msi.o | ||||
| kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o | ||||
| kexec-$(CONFIG_PPC32)		:= machine_kexec_32.o | ||||
|  | ||||
| @ -294,6 +294,21 @@ static struct cpu_spec cpu_specs[] = { | ||||
| 		.oprofile_mmcra_sipr	= MMCRA_SIPR, | ||||
| 		.platform		= "power5", | ||||
| 	}, | ||||
| 	{	/* Power5++ */ | ||||
| 		.pvr_mask		= 0xffffff00, | ||||
| 		.pvr_value		= 0x003b0300, | ||||
| 		.cpu_name		= "POWER5+ (gs)", | ||||
| 		.cpu_features		= CPU_FTRS_POWER5, | ||||
| 		.cpu_user_features	= COMMON_USER_POWER5_PLUS, | ||||
| 		.icache_bsize		= 128, | ||||
| 		.dcache_bsize		= 128, | ||||
| 		.num_pmcs		= 6, | ||||
| 		.oprofile_cpu_type	= "ppc64/power5++", | ||||
| 		.oprofile_type		= PPC_OPROFILE_POWER4, | ||||
| 		.oprofile_mmcra_sihv	= MMCRA_SIHV, | ||||
| 		.oprofile_mmcra_sipr	= MMCRA_SIPR, | ||||
| 		.platform		= "power5+", | ||||
| 	}, | ||||
| 	{	/* Power5 GS */ | ||||
| 		.pvr_mask		= 0xffff0000, | ||||
| 		.pvr_value		= 0x003b0000, | ||||
| @ -1178,8 +1193,8 @@ static struct cpu_spec cpu_specs[] = { | ||||
| 		.platform		= "ppc440", | ||||
| 	}, | ||||
| 	{ /* 440SP Rev. A */ | ||||
| 		.pvr_mask		= 0xff000fff, | ||||
| 		.pvr_value		= 0x53000891, | ||||
| 		.pvr_mask		= 0xfff00fff, | ||||
| 		.pvr_value		= 0x53200891, | ||||
| 		.cpu_name		= "440SP Rev. A", | ||||
| 		.cpu_features		= CPU_FTRS_44X, | ||||
| 		.cpu_user_features	= COMMON_USER_BOOKE, | ||||
| @ -1188,9 +1203,19 @@ static struct cpu_spec cpu_specs[] = { | ||||
| 		.platform		= "ppc440", | ||||
| 	}, | ||||
| 	{ /* 440SPe Rev. A */ | ||||
| 		.pvr_mask		= 0xff000fff, | ||||
| 		.pvr_value		= 0x53000890, | ||||
| 		.cpu_name		= "440SPe Rev. A", | ||||
| 		.pvr_mask               = 0xfff00fff, | ||||
| 		.pvr_value              = 0x53400890, | ||||
| 		.cpu_name               = "440SPe Rev. A", | ||||
| 		.cpu_features		= CPU_FTRS_44X, | ||||
| 		.cpu_user_features      = COMMON_USER_BOOKE, | ||||
| 		.icache_bsize           = 32, | ||||
| 		.dcache_bsize           = 32, | ||||
| 		.platform               = "ppc440", | ||||
| 	}, | ||||
| 	{ /* 440SPe Rev. B */ | ||||
| 		.pvr_mask		= 0xfff00fff, | ||||
| 		.pvr_value		= 0x53400891, | ||||
| 		.cpu_name		= "440SPe Rev. B", | ||||
| 		.cpu_features		= CPU_FTRS_44X, | ||||
| 		.cpu_user_features	= COMMON_USER_BOOKE, | ||||
| 		.icache_bsize		= 32, | ||||
|  | ||||
| @ -9,7 +9,6 @@ | ||||
|  *  rewritten by Paul Mackerras. | ||||
|  *    Copyright (C) 1996 Paul Mackerras. | ||||
|  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
 | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
 | ||||
|  * | ||||
|  *  This file contains the low-level support and setup for the | ||||
|  *  PowerPC platform, including trap and interrupt dispatch. | ||||
| @ -32,10 +31,6 @@ | ||||
| #include <asm/ppc_asm.h> | ||||
| #include <asm/asm-offsets.h> | ||||
| 
 | ||||
| #ifdef CONFIG_APUS | ||||
| #include <asm/amigappc.h> | ||||
| #endif | ||||
| 
 | ||||
| /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */ | ||||
| #define LOAD_BAT(n, reg, RA, RB)	\ | ||||
| 	/* see the comment for clear_bats() -- Cort */ \ | ||||
| @ -92,11 +87,6 @@ _start: | ||||
|  *  r4: virtual address of boot_infos_t | ||||
|  *  r5: 0 | ||||
|  * | ||||
|  * APUS | ||||
|  *   r3: 'APUS' | ||||
|  *   r4: physical address of memory base | ||||
|  *   Linux/m68k style BootInfo structure at &_end. | ||||
|  * | ||||
|  * PREP | ||||
|  * This is jumped to on prep systems right after the kernel is relocated | ||||
|  * to its proper place in memory by the boot loader.  The expected layout | ||||
| @ -150,14 +140,6 @@ __start: | ||||
|  */ | ||||
| 	bl	early_init | ||||
| 
 | ||||
| #ifdef CONFIG_APUS | ||||
| /* On APUS the __va/__pa constants need to be set to the correct | ||||
|  * values before continuing. | ||||
|  */ | ||||
| 	mr	r4,r30 | ||||
| 	bl	fix_mem_constants | ||||
| #endif /* CONFIG_APUS */ | ||||
| 
 | ||||
| /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains | ||||
|  * the physical address we are running at, returned by early_init() | ||||
|  */ | ||||
| @ -167,7 +149,7 @@ __after_mmu_off: | ||||
| 	bl	flush_tlbs | ||||
| 
 | ||||
| 	bl	initial_bats | ||||
| #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) | ||||
| #if defined(CONFIG_BOOTX_TEXT) | ||||
| 	bl	setup_disp_bat | ||||
| #endif | ||||
| 
 | ||||
| @ -183,7 +165,6 @@ __after_mmu_off: | ||||
| #endif /* CONFIG_6xx */ | ||||
| 
 | ||||
| 
 | ||||
| #ifndef CONFIG_APUS | ||||
| /* | ||||
|  * We need to run with _start at physical address 0. | ||||
|  * On CHRP, we are loaded at 0x10000 since OF on CHRP uses | ||||
| @ -196,7 +177,6 @@ __after_mmu_off: | ||||
| 	addis	r4,r3,KERNELBASE@h	/* current address of _start */
 | ||||
| 	cmpwi	0,r4,0			/* are we already running at 0? */ | ||||
| 	bne	relocate_kernel | ||||
| #endif /* CONFIG_APUS */ | ||||
| /* | ||||
|  * we now have the 1st 16M of ram mapped with the bats. | ||||
|  * prep needs the mmu to be turned on here, but pmac already has it on. | ||||
| @ -881,85 +861,6 @@ _GLOBAL(copy_and_flush) | ||||
| 	addi	r6,r6,4 | ||||
| 	blr | ||||
| 
 | ||||
| #ifdef CONFIG_APUS | ||||
| /* | ||||
|  * On APUS the physical base address of the kernel is not known at compile | ||||
|  * time, which means the __pa/__va constants used are incorrect. In the | ||||
|  * __init section is recorded the virtual addresses of instructions using | ||||
|  * these constants, so all that has to be done is fix these before | ||||
|  * continuing the kernel boot. | ||||
|  * | ||||
|  * r4 = The physical address of the kernel base. | ||||
|  */ | ||||
| fix_mem_constants: | ||||
| 	mr	r10,r4 | ||||
| 	addis	r10,r10,-KERNELBASE@h    /* virt_to_phys constant */
 | ||||
| 	neg	r11,r10	                 /* phys_to_virt constant */ | ||||
| 
 | ||||
| 	lis	r12,__vtop_table_begin@h
 | ||||
| 	ori	r12,r12,__vtop_table_begin@l
 | ||||
| 	add	r12,r12,r10	         /* table begin phys address */ | ||||
| 	lis	r13,__vtop_table_end@h
 | ||||
| 	ori	r13,r13,__vtop_table_end@l
 | ||||
| 	add	r13,r13,r10	         /* table end phys address */ | ||||
| 	subi	r12,r12,4 | ||||
| 	subi	r13,r13,4 | ||||
| 1:	lwzu	r14,4(r12)               /* virt address of instruction */ | ||||
| 	add     r14,r14,r10              /* phys address of instruction */ | ||||
| 	lwz     r15,0(r14)               /* instruction, now insert top */ | ||||
| 	rlwimi  r15,r10,16,16,31         /* half of vp const in low half */ | ||||
| 	stw	r15,0(r14)               /* of instruction and restore. */ | ||||
| 	dcbst	r0,r14			 /* write it to memory */ | ||||
| 	sync | ||||
| 	icbi	r0,r14			 /* flush the icache line */ | ||||
| 	cmpw	r12,r13 | ||||
| 	bne     1b | ||||
| 	sync				/* additional sync needed on g4 */ | ||||
| 	isync | ||||
| 
 | ||||
| /* | ||||
|  * Map the memory where the exception handlers will | ||||
|  * be copied to when hash constants have been patched. | ||||
|  */ | ||||
| #ifdef CONFIG_APUS_FAST_EXCEPT | ||||
| 	lis	r8,0xfff0 | ||||
| #else | ||||
| 	lis	r8,0 | ||||
| #endif | ||||
| 	ori	r8,r8,0x2		/* 128KB, supervisor */ | ||||
| 	mtspr	SPRN_DBAT3U,r8 | ||||
| 	mtspr	SPRN_DBAT3L,r8 | ||||
| 
 | ||||
| 	lis	r12,__ptov_table_begin@h
 | ||||
| 	ori	r12,r12,__ptov_table_begin@l
 | ||||
| 	add	r12,r12,r10	         /* table begin phys address */ | ||||
| 	lis	r13,__ptov_table_end@h
 | ||||
| 	ori	r13,r13,__ptov_table_end@l
 | ||||
| 	add	r13,r13,r10	         /* table end phys address */ | ||||
| 	subi	r12,r12,4 | ||||
| 	subi	r13,r13,4 | ||||
| 1:	lwzu	r14,4(r12)               /* virt address of instruction */ | ||||
| 	add     r14,r14,r10              /* phys address of instruction */ | ||||
| 	lwz     r15,0(r14)               /* instruction, now insert top */ | ||||
| 	rlwimi  r15,r11,16,16,31         /* half of pv const in low half*/ | ||||
| 	stw	r15,0(r14)               /* of instruction and restore. */ | ||||
| 	dcbst	r0,r14			 /* write it to memory */ | ||||
| 	sync | ||||
| 	icbi	r0,r14			 /* flush the icache line */ | ||||
| 	cmpw	r12,r13 | ||||
| 	bne     1b | ||||
| 
 | ||||
| 	sync				/* additional sync needed on g4 */ | ||||
| 	isync				/* No speculative loading until now */ | ||||
| 	blr | ||||
| 
 | ||||
| /*********************************************************************** | ||||
|  *  Please note that on APUS the exception handlers are located at the | ||||
|  *  physical address 0xfff0000. For this reason, the exception handlers | ||||
|  *  cannot use relative branches to access the code below. | ||||
|  ***********************************************************************/ | ||||
| #endif /* CONFIG_APUS */ | ||||
| 
 | ||||
| #ifdef CONFIG_SMP | ||||
| #ifdef CONFIG_GEMINI | ||||
| 	.globl	__secondary_start_gemini
 | ||||
| @ -1135,19 +1036,6 @@ start_here: | ||||
| 	bl	__save_cpu_setup | ||||
| 	bl	MMU_init | ||||
| 
 | ||||
| #ifdef CONFIG_APUS | ||||
| 	/* Copy exception code to exception vector base on APUS. */ | ||||
| 	lis	r4,KERNELBASE@h
 | ||||
| #ifdef CONFIG_APUS_FAST_EXCEPT | ||||
| 	lis	r3,0xfff0		/* Copy to 0xfff00000 */ | ||||
| #else | ||||
| 	lis	r3,0			/* Copy to 0x00000000 */ | ||||
| #endif | ||||
| 	li	r5,0x4000		/* # bytes of memory to copy */ | ||||
| 	li	r6,0 | ||||
| 	bl	copy_and_flush		/* copy the first 0x4000 bytes */ | ||||
| #endif  /* CONFIG_APUS */ | ||||
| 
 | ||||
| /* | ||||
|  * Go back to running unmapped so we can load up new values | ||||
|  * for SDR1 (hash table pointer) and the segment registers | ||||
| @ -1324,11 +1212,7 @@ initial_bats: | ||||
| #else | ||||
| 	ori	r8,r8,2			/* R/W access */ | ||||
| #endif /* CONFIG_SMP */ | ||||
| #ifdef CONFIG_APUS | ||||
| 	ori	r11,r11,BL_8M<<2|0x2	/* set up 8MB BAT registers for 604 */ | ||||
| #else | ||||
| 	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */ | ||||
| #endif /* CONFIG_APUS */ | ||||
| 
 | ||||
| 	mtspr	SPRN_DBAT0L,r8		/* N.B. 6xx (not 601) have valid */ | ||||
| 	mtspr	SPRN_DBAT0U,r11		/* bit in upper BAT register */ | ||||
| @ -1338,7 +1222,7 @@ initial_bats: | ||||
| 	blr | ||||
| 
 | ||||
| 
 | ||||
| #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) | ||||
| #ifdef CONFIG_BOOTX_TEXT | ||||
| setup_disp_bat: | ||||
| 	/* | ||||
| 	 * setup the display bat prepared for us in prom.c | ||||
| @ -1362,7 +1246,7 @@ setup_disp_bat: | ||||
| 1:	mtspr	SPRN_IBAT3L,r8 | ||||
| 	mtspr	SPRN_IBAT3U,r11 | ||||
| 	blr | ||||
| #endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */ | ||||
| #endif /* CONFIG_BOOTX_TEXT */ | ||||
| 
 | ||||
| #ifdef CONFIG_8260 | ||||
| /* Jump into the system reset for the rom. | ||||
|  | ||||
| @ -103,8 +103,8 @@ __secondary_hold_acknowledge: | ||||
| 
 | ||||
| 	. = 0x60 | ||||
| /* | ||||
|  * The following code is used on pSeries to hold secondary processors | ||||
|  * in a spin loop after they have been freed from OpenFirmware, but | ||||
|  * The following code is used to hold secondary processors | ||||
|  * in a spin loop after they have entered the kernel, but | ||||
|  * before the bulk of the kernel has been relocated.  This code | ||||
|  * is relocated to physical address 0x60 before prom_init is run. | ||||
|  * All of it must fit below the first exception vector at 0x100. | ||||
|  | ||||
| @ -35,7 +35,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count) | ||||
| 	asm volatile("sync"); | ||||
| 	do { | ||||
| 		tmp = *port; | ||||
| 		asm volatile("eieio"); | ||||
| 		eieio(); | ||||
| 		*tbuf++ = tmp; | ||||
| 	} while (--count != 0); | ||||
| 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | ||||
| @ -66,7 +66,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count) | ||||
| 	asm volatile("sync"); | ||||
| 	do { | ||||
| 		tmp = *port; | ||||
| 		asm volatile("eieio"); | ||||
| 		eieio(); | ||||
| 		*tbuf++ = tmp; | ||||
| 	} while (--count != 0); | ||||
| 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | ||||
| @ -97,7 +97,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count) | ||||
| 	asm volatile("sync"); | ||||
| 	do { | ||||
| 		tmp = *port; | ||||
| 		asm volatile("eieio"); | ||||
| 		eieio(); | ||||
| 		*tbuf++ = tmp; | ||||
| 	} while (--count != 0); | ||||
| 	asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | ||||
| @ -155,21 +155,21 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src, | ||||
| 	__asm__ __volatile__ ("sync" : : : "memory"); | ||||
| 	while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { | ||||
| 		*((u8 *)dest) = *((volatile u8 *)vsrc); | ||||
| 		__asm__ __volatile__ ("eieio" : : : "memory"); | ||||
| 		eieio(); | ||||
| 		vsrc++; | ||||
| 		dest++; | ||||
| 		n--; | ||||
| 	} | ||||
| 	while(n > 4) { | ||||
| 		*((u32 *)dest) = *((volatile u32 *)vsrc); | ||||
| 		__asm__ __volatile__ ("eieio" : : : "memory"); | ||||
| 		eieio(); | ||||
| 		vsrc += 4; | ||||
| 		dest += 4; | ||||
| 		n -= 4; | ||||
| 	} | ||||
| 	while(n) { | ||||
| 		*((u8 *)dest) = *((volatile u8 *)vsrc); | ||||
| 		__asm__ __volatile__ ("eieio" : : : "memory"); | ||||
| 		eieio(); | ||||
| 		vsrc++; | ||||
| 		dest++; | ||||
| 		n--; | ||||
|  | ||||
| @ -7,7 +7,6 @@ | ||||
|  *    Copyright (C) 1996-2001 Cort Dougan | ||||
|  *  Adapted for Power Macintosh by Paul Mackerras | ||||
|  *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
| @ -337,7 +336,8 @@ void do_IRQ(struct pt_regs *regs) | ||||
| 
 | ||||
| void __init init_IRQ(void) | ||||
| { | ||||
| 	ppc_md.init_IRQ(); | ||||
| 	if (ppc_md.init_IRQ) | ||||
| 		ppc_md.init_IRQ(); | ||||
| #ifdef CONFIG_PPC64 | ||||
| 	irq_ctx_init(); | ||||
| #endif | ||||
| @ -597,6 +597,49 @@ static void irq_radix_rdunlock(unsigned long flags) | ||||
| 	local_irq_restore(flags); | ||||
| } | ||||
| 
 | ||||
| static int irq_setup_virq(struct irq_host *host, unsigned int virq, | ||||
| 			    irq_hw_number_t hwirq) | ||||
| { | ||||
| 	/* Clear IRQ_NOREQUEST flag */ | ||||
| 	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | ||||
| 
 | ||||
| 	/* map it */ | ||||
| 	smp_wmb(); | ||||
| 	irq_map[virq].hwirq = hwirq; | ||||
| 	smp_mb(); | ||||
| 
 | ||||
| 	if (host->ops->map(host, virq, hwirq)) { | ||||
| 		pr_debug("irq: -> mapping failed, freeing\n"); | ||||
| 		irq_free_virt(virq, 1); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| unsigned int irq_create_direct_mapping(struct irq_host *host) | ||||
| { | ||||
| 	unsigned int virq; | ||||
| 
 | ||||
| 	if (host == NULL) | ||||
| 		host = irq_default_host; | ||||
| 
 | ||||
| 	BUG_ON(host == NULL); | ||||
| 	WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP); | ||||
| 
 | ||||
| 	virq = irq_alloc_virt(host, 1, 0); | ||||
| 	if (virq == NO_IRQ) { | ||||
| 		pr_debug("irq: create_direct virq allocation failed\n"); | ||||
| 		return NO_IRQ; | ||||
| 	} | ||||
| 
 | ||||
| 	pr_debug("irq: create_direct obtained virq %d\n", virq); | ||||
| 
 | ||||
| 	if (irq_setup_virq(host, virq, virq)) | ||||
| 		return NO_IRQ; | ||||
| 
 | ||||
| 	return virq; | ||||
| } | ||||
| 
 | ||||
| unsigned int irq_create_mapping(struct irq_host *host, | ||||
| 				irq_hw_number_t hwirq) | ||||
| @ -645,18 +688,9 @@ unsigned int irq_create_mapping(struct irq_host *host, | ||||
| 	} | ||||
| 	pr_debug("irq: -> obtained virq %d\n", virq); | ||||
| 
 | ||||
| 	/* Clear IRQ_NOREQUEST flag */ | ||||
| 	get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | ||||
| 
 | ||||
| 	/* map it */ | ||||
| 	smp_wmb(); | ||||
| 	irq_map[virq].hwirq = hwirq; | ||||
| 	smp_mb(); | ||||
| 	if (host->ops->map(host, virq, hwirq)) { | ||||
| 		pr_debug("irq: -> mapping failed, freeing\n"); | ||||
| 		irq_free_virt(virq, 1); | ||||
| 	if (irq_setup_virq(host, virq, hwirq)) | ||||
| 		return NO_IRQ; | ||||
| 	} | ||||
| 
 | ||||
| 	return virq; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(irq_create_mapping); | ||||
|  | ||||
							
								
								
									
										271
									
								
								arch/powerpc/kernel/isa-bridge.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								arch/powerpc/kernel/isa-bridge.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,271 @@ | ||||
| /*
 | ||||
|  * Routines for tracking a legacy ISA bridge | ||||
|  * | ||||
|  * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. | ||||
|  * | ||||
|  * Some bits and pieces moved over from pci_64.c | ||||
|  * | ||||
|  * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp. | ||||
|  * | ||||
|  *      This program is free software; you can redistribute it and/or | ||||
|  *      modify it under the terms of the GNU General Public License | ||||
|  *      as published by the Free Software Foundation; either version | ||||
|  *      2 of the License, or (at your option) any later version. | ||||
|  */ | ||||
| 
 | ||||
| #define DEBUG | ||||
| 
 | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/notifier.h> | ||||
| 
 | ||||
| #include <asm/processor.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/prom.h> | ||||
| #include <asm/pci-bridge.h> | ||||
| #include <asm/machdep.h> | ||||
| #include <asm/ppc-pci.h> | ||||
| #include <asm/firmware.h> | ||||
| 
 | ||||
| unsigned long isa_io_base;	/* NULL if no ISA bus */ | ||||
| EXPORT_SYMBOL(isa_io_base); | ||||
| 
 | ||||
| /* Cached ISA bridge dev. */ | ||||
| static struct device_node *isa_bridge_devnode; | ||||
| struct pci_dev *isa_bridge_pcidev; | ||||
| EXPORT_SYMBOL_GPL(isa_bridge_pcidev); | ||||
| 
 | ||||
| #define ISA_SPACE_MASK 0x1 | ||||
| #define ISA_SPACE_IO 0x1 | ||||
| 
 | ||||
| static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, | ||||
| 						unsigned long phb_io_base_phys) | ||||
| { | ||||
| 	/* We should get some saner parsing here and remove these structs */ | ||||
| 	struct pci_address { | ||||
| 		u32 a_hi; | ||||
| 		u32 a_mid; | ||||
| 		u32 a_lo; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct isa_address { | ||||
| 		u32 a_hi; | ||||
| 		u32 a_lo; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct isa_range { | ||||
| 		struct isa_address isa_addr; | ||||
| 		struct pci_address pci_addr; | ||||
| 		unsigned int size; | ||||
| 	}; | ||||
| 
 | ||||
| 	const struct isa_range *range; | ||||
| 	unsigned long pci_addr; | ||||
| 	unsigned int isa_addr; | ||||
| 	unsigned int size; | ||||
| 	int rlen = 0; | ||||
| 
 | ||||
| 	range = of_get_property(isa_node, "ranges", &rlen); | ||||
| 	if (range == NULL || (rlen < sizeof(struct isa_range))) | ||||
| 		goto inval_range; | ||||
| 
 | ||||
| 	/* From "ISA Binding to 1275"
 | ||||
| 	 * The ranges property is laid out as an array of elements, | ||||
| 	 * each of which comprises: | ||||
| 	 *   cells 0 - 1:	an ISA address | ||||
| 	 *   cells 2 - 4:	a PCI address | ||||
| 	 *			(size depending on dev->n_addr_cells) | ||||
| 	 *   cell 5:		the size of the range | ||||
| 	 */ | ||||
| 	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) { | ||||
| 		range++; | ||||
| 		rlen -= sizeof(struct isa_range); | ||||
| 		if (rlen < sizeof(struct isa_range)) | ||||
| 			goto inval_range; | ||||
| 	} | ||||
| 	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) | ||||
| 		goto inval_range; | ||||
| 
 | ||||
| 	isa_addr = range->isa_addr.a_lo; | ||||
| 	pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | | ||||
| 		range->pci_addr.a_lo; | ||||
| 
 | ||||
| 	/* Assume these are both zero. Note: We could fix that and
 | ||||
| 	 * do a proper parsing instead ... oh well, that will do for | ||||
| 	 * now as nobody uses fancy mappings for ISA bridges | ||||
| 	 */ | ||||
| 	if ((pci_addr != 0) || (isa_addr != 0)) { | ||||
| 		printk(KERN_ERR "unexpected isa to pci mapping: %s\n", | ||||
| 		       __FUNCTION__); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Align size and make sure it's cropped to 64K */ | ||||
| 	size = PAGE_ALIGN(range->size); | ||||
| 	if (size > 0x10000) | ||||
| 		size = 0x10000; | ||||
| 
 | ||||
| 	printk(KERN_ERR "no ISA IO ranges or unexpected isa range," | ||||
| 	       "mapping 64k\n"); | ||||
| 
 | ||||
| 	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | ||||
| 		     size, _PAGE_NO_CACHE|_PAGE_GUARDED); | ||||
| 	return; | ||||
| 
 | ||||
| inval_range: | ||||
| 	printk(KERN_ERR "no ISA IO ranges or unexpected isa range," | ||||
| 	       "mapping 64k\n"); | ||||
| 	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | ||||
| 		     0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * isa_bridge_find_early - Find and map the ISA IO space early before | ||||
|  *                         main PCI discovery. This is optionally called by | ||||
|  *                         the arch code when adding PCI PHBs to get early | ||||
|  *                         access to ISA IO ports | ||||
|  */ | ||||
| void __init isa_bridge_find_early(struct pci_controller *hose) | ||||
| { | ||||
| 	struct device_node *np, *parent = NULL, *tmp; | ||||
| 
 | ||||
| 	/* If we already have an ISA bridge, bail off */ | ||||
| 	if (isa_bridge_devnode != NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* For each "isa" node in the system. Note : we do a search by
 | ||||
| 	 * type and not by name. It might be better to do by name but that's | ||||
| 	 * what the code used to do and I don't want to break too much at | ||||
| 	 * once. We can look into changing that separately | ||||
| 	 */ | ||||
| 	for_each_node_by_type(np, "isa") { | ||||
| 		/* Look for our hose being a parent */ | ||||
| 		for (parent = of_get_parent(np); parent;) { | ||||
| 			if (parent == hose->arch_data) { | ||||
| 				of_node_put(parent); | ||||
| 				break; | ||||
| 			} | ||||
| 			tmp = parent; | ||||
| 			parent = of_get_parent(parent); | ||||
| 			of_node_put(tmp); | ||||
| 		} | ||||
| 		if (parent != NULL) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (np == NULL) | ||||
| 		return; | ||||
| 	isa_bridge_devnode = np; | ||||
| 
 | ||||
| 	/* Now parse the "ranges" property and setup the ISA mapping */ | ||||
| 	pci_process_ISA_OF_ranges(np, hose->io_base_phys); | ||||
| 
 | ||||
| 	/* Set the global ISA io base to indicate we have an ISA bridge */ | ||||
| 	isa_io_base = ISA_IO_BASE; | ||||
| 
 | ||||
| 	pr_debug("ISA bridge (early) is %s\n", np->full_name); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * isa_bridge_find_late - Find and map the ISA IO space upon discovery of | ||||
|  *                        a new ISA bridge | ||||
|  */ | ||||
| static void __devinit isa_bridge_find_late(struct pci_dev *pdev, | ||||
| 					   struct device_node *devnode) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||||
| 
 | ||||
| 	/* Store ISA device node and PCI device */ | ||||
| 	isa_bridge_devnode = of_node_get(devnode); | ||||
| 	isa_bridge_pcidev = pdev; | ||||
| 
 | ||||
| 	/* Now parse the "ranges" property and setup the ISA mapping */ | ||||
| 	pci_process_ISA_OF_ranges(devnode, hose->io_base_phys); | ||||
| 
 | ||||
| 	/* Set the global ISA io base to indicate we have an ISA bridge */ | ||||
| 	isa_io_base = ISA_IO_BASE; | ||||
| 
 | ||||
| 	pr_debug("ISA bridge (late) is %s on %s\n", | ||||
| 		 devnode->full_name, pci_name(pdev)); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * isa_bridge_remove - Remove/unmap an ISA bridge | ||||
|  */ | ||||
| static void isa_bridge_remove(void) | ||||
| { | ||||
| 	pr_debug("ISA bridge removed !\n"); | ||||
| 
 | ||||
| 	/* Clear the global ISA io base to indicate that we have no more
 | ||||
| 	 * ISA bridge. Note that drivers don't quite handle that, though | ||||
| 	 * we should probably do something about it. But do we ever really | ||||
| 	 * have ISA bridges being removed on machines using legacy devices ? | ||||
| 	 */ | ||||
| 	isa_io_base = ISA_IO_BASE; | ||||
| 
 | ||||
| 	/* Clear references to the bridge */ | ||||
| 	of_node_put(isa_bridge_devnode); | ||||
| 	isa_bridge_devnode = NULL; | ||||
| 	isa_bridge_pcidev = NULL; | ||||
| 
 | ||||
| 	/* Unmap the ISA area */ | ||||
| 	__iounmap_at((void *)ISA_IO_BASE, 0x10000); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * isa_bridge_notify - Get notified of PCI devices addition/removal | ||||
|  */ | ||||
| static int __devinit isa_bridge_notify(struct notifier_block *nb, | ||||
| 				       unsigned long action, void *data) | ||||
| { | ||||
| 	struct device *dev = data; | ||||
| 	struct pci_dev *pdev = to_pci_dev(dev); | ||||
| 	struct device_node *devnode = pci_device_to_OF_node(pdev); | ||||
| 
 | ||||
| 	switch(action) { | ||||
| 	case BUS_NOTIFY_ADD_DEVICE: | ||||
| 		/* Check if we have an early ISA device, without PCI dev */ | ||||
| 		if (isa_bridge_devnode && isa_bridge_devnode == devnode && | ||||
| 		    !isa_bridge_pcidev) { | ||||
| 			pr_debug("ISA bridge PCI attached: %s\n", | ||||
| 				 pci_name(pdev)); | ||||
| 			isa_bridge_pcidev = pdev; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Check if we have no ISA device, and this happens to be one,
 | ||||
| 		 * register it as such if it has an OF device | ||||
| 		 */ | ||||
| 		if (!isa_bridge_devnode && devnode && devnode->type && | ||||
| 		    !strcmp(devnode->type, "isa")) | ||||
| 			isa_bridge_find_late(pdev, devnode); | ||||
| 
 | ||||
| 		return 0; | ||||
| 	case BUS_NOTIFY_DEL_DEVICE: | ||||
| 		/* Check if this our existing ISA device */ | ||||
| 		if (pdev == isa_bridge_pcidev || | ||||
| 		    (devnode && devnode == isa_bridge_devnode)) | ||||
| 			isa_bridge_remove(); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static struct notifier_block isa_bridge_notifier = { | ||||
| 	.notifier_call = isa_bridge_notify | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * isa_bridge_init - register to be notified of ISA bridge addition/removal | ||||
|  * | ||||
|  */ | ||||
| static int __init isa_bridge_init(void) | ||||
| { | ||||
| 	if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||||
| 		return 0; | ||||
| 	bus_register_notifier(&pci_bus_type, &isa_bridge_notifier); | ||||
| 	return 0; | ||||
| } | ||||
| arch_initcall(isa_bridge_init); | ||||
| @ -392,7 +392,7 @@ BEGIN_FTR_SECTION | ||||
| 	mtspr   SPRN_L1CSR0,r3 | ||||
| 	isync | ||||
| 	blr | ||||
| END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | ||||
| END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) | ||||
| 	mfspr	r3,SPRN_L1CSR1 | ||||
| 	ori	r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR | ||||
| 	mtspr	SPRN_L1CSR1,r3 | ||||
| @ -419,7 +419,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | ||||
| _GLOBAL(__flush_icache_range) | ||||
| BEGIN_FTR_SECTION | ||||
| 	blr				/* for 601, do nothing */ | ||||
| END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | ||||
| END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) | ||||
| 	li	r5,L1_CACHE_BYTES-1 | ||||
| 	andc	r3,r3,r5 | ||||
| 	subf	r4,r3,r4 | ||||
| @ -514,8 +514,8 @@ _GLOBAL(invalidate_dcache_range) | ||||
|  */ | ||||
| _GLOBAL(__flush_dcache_icache) | ||||
| BEGIN_FTR_SECTION | ||||
| 	blr					/* for 601, do nothing */ | ||||
| END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | ||||
| 	blr | ||||
| END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) | ||||
| 	rlwinm	r3,r3,0,0,19			/* Get page base address */ | ||||
| 	li	r4,4096/L1_CACHE_BYTES	/* Number of lines in a page */ | ||||
| 	mtctr	r4 | ||||
| @ -543,7 +543,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | ||||
| _GLOBAL(__flush_dcache_icache_phys) | ||||
| BEGIN_FTR_SECTION | ||||
| 	blr					/* for 601, do nothing */ | ||||
| END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | ||||
| END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) | ||||
| 	mfmsr	r10 | ||||
| 	rlwinm	r0,r10,0,28,26			/* clear DR */ | ||||
| 	mtmsr	r0 | ||||
|  | ||||
| @ -646,6 +646,19 @@ _GLOBAL(kexec_sequence) | ||||
| 	/* turn off mmu */ | ||||
| 	bl	real_mode | ||||
| 
 | ||||
| 	/* copy  0x100 bytes starting at start to 0 */ | ||||
| 	li	r3,0 | ||||
| 	mr	r4,r30		/* start, aka phys mem offset */ | ||||
| 	li	r5,0x100 | ||||
| 	li	r6,0 | ||||
| 	bl	.copy_and_flush	/* (dest, src, copy limit, start offset) */ | ||||
| 1:	/* assume normal blr return */ | ||||
| 
 | ||||
| 	/* release other cpus to the new kernel secondary start at 0x60 */ | ||||
| 	mflr	r5 | ||||
| 	li	r6,1 | ||||
| 	stw	r6,kexec_flag-1b(5) | ||||
| 
 | ||||
| 	/* clear out hardware hash page table and tlb */ | ||||
| 	ld	r5,0(r27)		/* deref function descriptor */ | ||||
| 	mtctr	r5 | ||||
| @ -676,19 +689,6 @@ _GLOBAL(kexec_sequence) | ||||
|  *    are the boot cpu ????? | ||||
|  *    other device tree differences (prop sizes, va vs pa, etc)... | ||||
|  */ | ||||
| 
 | ||||
| 	/* copy  0x100 bytes starting at start to 0 */ | ||||
| 	li	r3,0 | ||||
| 	mr	r4,r30 | ||||
| 	li	r5,0x100 | ||||
| 	li	r6,0 | ||||
| 	bl	.copy_and_flush	/* (dest, src, copy limit, start offset) */ | ||||
| 1:	/* assume normal blr return */ | ||||
| 
 | ||||
| 	/* release other cpus to the new kernel secondary start at 0x60 */ | ||||
| 	mflr	r5 | ||||
| 	li	r6,1 | ||||
| 	stw	r6,kexec_flag-1b(5) | ||||
| 	mr	r3,r25	# my phys cpu | ||||
| 	mr	r4,r30	# start, aka phys mem offset | ||||
| 	mtlr	4 | ||||
|  | ||||
| @ -427,14 +427,6 @@ static int __devinit of_pci_phb_probe(struct of_device *dev, | ||||
| 	/* Process "ranges" property */ | ||||
| 	pci_process_bridge_OF_ranges(phb, dev->node, 0); | ||||
| 
 | ||||
| 	/* Setup IO space. We use the non-dynamic version of that code here,
 | ||||
| 	 * which doesn't quite support unplugging. Next kernel release will | ||||
| 	 * have a better fix for this. | ||||
| 	 * Note also that we don't do ISA, this will also be fixed with a | ||||
| 	 * more massive rework. | ||||
| 	 */ | ||||
| 	pci_setup_phb_io(phb, pci_io_base == 0); | ||||
| 
 | ||||
| 	/* Init pci_dn data structures */ | ||||
| 	pci_devs_phb_init_dynamic(phb); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										454
									
								
								arch/powerpc/kernel/pci-common.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										454
									
								
								arch/powerpc/kernel/pci-common.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,454 @@ | ||||
| /*
 | ||||
|  * Contains common pci routines for ALL ppc platform | ||||
|  * (based on pci_32.c and pci_64.c) | ||||
|  * | ||||
|  * Port for PPC64 David Engebretsen, IBM Corp. | ||||
|  * Contains common pci routines for ppc64 platform, pSeries and iSeries brands. | ||||
|  * | ||||
|  * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | ||||
|  *   Rework, based on alpha PCI code. | ||||
|  * | ||||
|  * Common pmac/prep/chrp pci routines. -- Cort | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License | ||||
|  * as published by the Free Software Foundation; either version | ||||
|  * 2 of the License, or (at your option) any later version. | ||||
|  */ | ||||
| 
 | ||||
| #undef DEBUG | ||||
| 
 | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/pci.h> | ||||
| #include <linux/string.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/bootmem.h> | ||||
| #include <linux/mm.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/syscalls.h> | ||||
| #include <linux/irq.h> | ||||
| #include <linux/vmalloc.h> | ||||
| 
 | ||||
| #include <asm/processor.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/prom.h> | ||||
| #include <asm/pci-bridge.h> | ||||
| #include <asm/byteorder.h> | ||||
| #include <asm/machdep.h> | ||||
| #include <asm/ppc-pci.h> | ||||
| #include <asm/firmware.h> | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| #include <asm/udbg.h> | ||||
| #define DBG(fmt...) printk(fmt) | ||||
| #else | ||||
| #define DBG(fmt...) | ||||
| #endif | ||||
| 
 | ||||
| static DEFINE_SPINLOCK(hose_spinlock); | ||||
| 
 | ||||
| /* XXX kill that some day ... */ | ||||
| int global_phb_number;		/* Global phb counter */ | ||||
| 
 | ||||
| extern struct list_head hose_list; | ||||
| 
 | ||||
| /*
 | ||||
|  * pci_controller(phb) initialized common variables. | ||||
|  */ | ||||
| static void __devinit pci_setup_pci_controller(struct pci_controller *hose) | ||||
| { | ||||
| 	memset(hose, 0, sizeof(struct pci_controller)); | ||||
| 
 | ||||
| 	spin_lock(&hose_spinlock); | ||||
| 	hose->global_number = global_phb_number++; | ||||
| 	list_add_tail(&hose->list_node, &hose_list); | ||||
| 	spin_unlock(&hose_spinlock); | ||||
| } | ||||
| 
 | ||||
| struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | ||||
| { | ||||
| 	struct pci_controller *phb; | ||||
| 
 | ||||
| 	if (mem_init_done) | ||||
| 		phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | ||||
| 	else | ||||
| 		phb = alloc_bootmem(sizeof (struct pci_controller)); | ||||
| 	if (phb == NULL) | ||||
| 		return NULL; | ||||
| 	pci_setup_pci_controller(phb); | ||||
| 	phb->arch_data = dev; | ||||
| 	phb->is_dynamic = mem_init_done; | ||||
| #ifdef CONFIG_PPC64 | ||||
| 	if (dev) { | ||||
| 		int nid = of_node_to_nid(dev); | ||||
| 
 | ||||
| 		if (nid < 0 || !node_online(nid)) | ||||
| 			nid = -1; | ||||
| 
 | ||||
| 		PHB_SET_NODE(phb, nid); | ||||
| 	} | ||||
| #endif | ||||
| 	return phb; | ||||
| } | ||||
| 
 | ||||
| void pcibios_free_controller(struct pci_controller *phb) | ||||
| { | ||||
| 	spin_lock(&hose_spinlock); | ||||
| 	list_del(&phb->list_node); | ||||
| 	spin_unlock(&hose_spinlock); | ||||
| 
 | ||||
| 	if (phb->is_dynamic) | ||||
| 		kfree(phb); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Return the domain number for this bus. | ||||
|  */ | ||||
| int pci_domain_nr(struct pci_bus *bus) | ||||
| { | ||||
| 	if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||||
| 		return 0; | ||||
| 	else { | ||||
| 		struct pci_controller *hose = pci_bus_to_host(bus); | ||||
| 
 | ||||
| 		return hose->global_number; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| EXPORT_SYMBOL(pci_domain_nr); | ||||
| 
 | ||||
| #ifdef CONFIG_PPC_OF | ||||
| 
 | ||||
| /* This routine is meant to be used early during boot, when the
 | ||||
|  * PCI bus numbers have not yet been assigned, and you need to | ||||
|  * issue PCI config cycles to an OF device. | ||||
|  * It could also be used to "fix" RTAS config cycles if you want | ||||
|  * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||||
|  * config cycles. | ||||
|  */ | ||||
| struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||||
| { | ||||
| 	if (!have_of) | ||||
| 		return NULL; | ||||
| 	while(node) { | ||||
| 		struct pci_controller *hose, *tmp; | ||||
| 		list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||||
| 			if (hose->arch_data == node) | ||||
| 				return hose; | ||||
| 		node = node->parent; | ||||
| 	} | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pci_show_devspec(struct device *dev, | ||||
| 		struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct pci_dev *pdev; | ||||
| 	struct device_node *np; | ||||
| 
 | ||||
| 	pdev = to_pci_dev (dev); | ||||
| 	np = pci_device_to_OF_node(pdev); | ||||
| 	if (np == NULL || np->full_name == NULL) | ||||
| 		return 0; | ||||
| 	return sprintf(buf, "%s", np->full_name); | ||||
| } | ||||
| static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||||
| #endif /* CONFIG_PPC_OF */ | ||||
| 
 | ||||
| /* Add sysfs properties */ | ||||
| void pcibios_add_platform_entries(struct pci_dev *pdev) | ||||
| { | ||||
| #ifdef CONFIG_PPC_OF | ||||
| 	device_create_file(&pdev->dev, &dev_attr_devspec); | ||||
| #endif /* CONFIG_PPC_OF */ | ||||
| } | ||||
| 
 | ||||
| char __init *pcibios_setup(char *str) | ||||
| { | ||||
| 	return str; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Reads the interrupt pin to determine if interrupt is use by card. | ||||
|  * If the interrupt is used, then gets the interrupt line from the | ||||
|  * openfirmware and sets it in the pci_dev and pci_config line. | ||||
|  */ | ||||
| int pci_read_irq_line(struct pci_dev *pci_dev) | ||||
| { | ||||
| 	struct of_irq oirq; | ||||
| 	unsigned int virq; | ||||
| 
 | ||||
| 	DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| 	memset(&oirq, 0xff, sizeof(oirq)); | ||||
| #endif | ||||
| 	/* Try to get a mapping from the device-tree */ | ||||
| 	if (of_irq_map_pci(pci_dev, &oirq)) { | ||||
| 		u8 line, pin; | ||||
| 
 | ||||
| 		/* If that fails, lets fallback to what is in the config
 | ||||
| 		 * space and map that through the default controller. We | ||||
| 		 * also set the type to level low since that's what PCI | ||||
| 		 * interrupts are. If your platform does differently, then | ||||
| 		 * either provide a proper interrupt tree or don't use this | ||||
| 		 * function. | ||||
| 		 */ | ||||
| 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||||
| 			return -1; | ||||
| 		if (pin == 0) | ||||
| 			return -1; | ||||
| 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||||
| 		    line == 0xff) { | ||||
| 			return -1; | ||||
| 		} | ||||
| 		DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||||
| 
 | ||||
| 		virq = irq_create_mapping(NULL, line); | ||||
| 		if (virq != NO_IRQ) | ||||
| 			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||||
| 	} else { | ||||
| 		DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||||
| 		    oirq.size, oirq.specifier[0], oirq.specifier[1], | ||||
| 		    oirq.controller->full_name); | ||||
| 
 | ||||
| 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||||
| 					     oirq.size); | ||||
| 	} | ||||
| 	if(virq == NO_IRQ) { | ||||
| 		DBG(" -> failed to map !\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	DBG(" -> mapped to linux irq %d\n", virq); | ||||
| 
 | ||||
| 	pci_dev->irq = virq; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(pci_read_irq_line); | ||||
| 
 | ||||
| /*
 | ||||
|  * Platform support for /proc/bus/pci/X/Y mmap()s, | ||||
|  * modelled on the sparc64 implementation by Dave Miller. | ||||
|  *  -- paulus. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Adjust vm_pgoff of VMA such that it is the physical page offset | ||||
|  * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||||
|  * | ||||
|  * Basically, the user finds the base address for his device which he wishes | ||||
|  * to mmap.  They read the 32-bit value from the config space base register, | ||||
|  * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||||
|  * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||||
|  * | ||||
|  * Returns negative error code on failure, zero on success. | ||||
|  */ | ||||
| static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||||
| 					       resource_size_t *offset, | ||||
| 					       enum pci_mmap_state mmap_state) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||||
| 	unsigned long io_offset = 0; | ||||
| 	int i, res_bit; | ||||
| 
 | ||||
| 	if (hose == 0) | ||||
| 		return NULL;		/* should never happen */ | ||||
| 
 | ||||
| 	/* If memory, add on the PCI bridge address offset */ | ||||
| 	if (mmap_state == pci_mmap_mem) { | ||||
| #if 0 /* See comment in pci_resource_to_user() for why this is disabled */
 | ||||
| 		*offset += hose->pci_mem_offset; | ||||
| #endif | ||||
| 		res_bit = IORESOURCE_MEM; | ||||
| 	} else { | ||||
| 		io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 		*offset += io_offset; | ||||
| 		res_bit = IORESOURCE_IO; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Check that the offset requested corresponds to one of the | ||||
| 	 * resources of the device. | ||||
| 	 */ | ||||
| 	for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||||
| 		struct resource *rp = &dev->resource[i]; | ||||
| 		int flags = rp->flags; | ||||
| 
 | ||||
| 		/* treat ROM as memory (should be already) */ | ||||
| 		if (i == PCI_ROM_RESOURCE) | ||||
| 			flags |= IORESOURCE_MEM; | ||||
| 
 | ||||
| 		/* Active and same type? */ | ||||
| 		if ((flags & res_bit) == 0) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* In the range of this resource? */ | ||||
| 		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* found it! construct the final physical address */ | ||||
| 		if (mmap_state == pci_mmap_io) | ||||
| 			*offset += hose->io_base_phys - io_offset; | ||||
| 		return rp; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||||
|  * device mapping. | ||||
|  */ | ||||
| static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||||
| 				      pgprot_t protection, | ||||
| 				      enum pci_mmap_state mmap_state, | ||||
| 				      int write_combine) | ||||
| { | ||||
| 	unsigned long prot = pgprot_val(protection); | ||||
| 
 | ||||
| 	/* Write combine is always 0 on non-memory space mappings. On
 | ||||
| 	 * memory space, if the user didn't pass 1, we check for a | ||||
| 	 * "prefetchable" resource. This is a bit hackish, but we use | ||||
| 	 * this to workaround the inability of /sysfs to provide a write | ||||
| 	 * combine bit | ||||
| 	 */ | ||||
| 	if (mmap_state != pci_mmap_mem) | ||||
| 		write_combine = 0; | ||||
| 	else if (write_combine == 0) { | ||||
| 		if (rp->flags & IORESOURCE_PREFETCH) | ||||
| 			write_combine = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* XXX would be nice to have a way to ask for write-through */ | ||||
| 	prot |= _PAGE_NO_CACHE; | ||||
| 	if (write_combine) | ||||
| 		prot &= ~_PAGE_GUARDED; | ||||
| 	else | ||||
| 		prot |= _PAGE_GUARDED; | ||||
| 
 | ||||
| 	return __pgprot(prot); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This one is used by /dev/mem and fbdev who have no clue about the | ||||
|  * PCI device, it tries to find the PCI device first and calls the | ||||
|  * above routine | ||||
|  */ | ||||
| pgprot_t pci_phys_mem_access_prot(struct file *file, | ||||
| 				  unsigned long pfn, | ||||
| 				  unsigned long size, | ||||
| 				  pgprot_t protection) | ||||
| { | ||||
| 	struct pci_dev *pdev = NULL; | ||||
| 	struct resource *found = NULL; | ||||
| 	unsigned long prot = pgprot_val(protection); | ||||
| 	unsigned long offset = pfn << PAGE_SHIFT; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (page_is_ram(pfn)) | ||||
| 		return __pgprot(prot); | ||||
| 
 | ||||
| 	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||||
| 
 | ||||
| 	for_each_pci_dev(pdev) { | ||||
| 		for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||||
| 			struct resource *rp = &pdev->resource[i]; | ||||
| 			int flags = rp->flags; | ||||
| 
 | ||||
| 			/* Active and same type? */ | ||||
| 			if ((flags & IORESOURCE_MEM) == 0) | ||||
| 				continue; | ||||
| 			/* In the range of this resource? */ | ||||
| 			if (offset < (rp->start & PAGE_MASK) || | ||||
| 			    offset > rp->end) | ||||
| 				continue; | ||||
| 			found = rp; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (found) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (found) { | ||||
| 		if (found->flags & IORESOURCE_PREFETCH) | ||||
| 			prot &= ~_PAGE_GUARDED; | ||||
| 		pci_dev_put(pdev); | ||||
| 	} | ||||
| 
 | ||||
| 	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||||
| 
 | ||||
| 	return __pgprot(prot); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Perform the actual remap of the pages for a PCI device mapping, as | ||||
|  * appropriate for this architecture.  The region in the process to map | ||||
|  * is described by vm_start and vm_end members of VMA, the base physical | ||||
|  * address is found in vm_pgoff. | ||||
|  * The pci device structure is provided so that architectures may make mapping | ||||
|  * decisions on a per-device or per-bus basis. | ||||
|  * | ||||
|  * Returns a negative error code on failure, zero on success. | ||||
|  */ | ||||
| int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||||
| 			enum pci_mmap_state mmap_state, int write_combine) | ||||
| { | ||||
| 	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||||
| 	struct resource *rp; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||||
| 	if (rp == NULL) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	vma->vm_pgoff = offset >> PAGE_SHIFT; | ||||
| 	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||||
| 						  vma->vm_page_prot, | ||||
| 						  mmap_state, write_combine); | ||||
| 
 | ||||
| 	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||||
| 			       vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||||
| 			  const struct resource *rsrc, | ||||
| 			  resource_size_t *start, resource_size_t *end) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||||
| 	resource_size_t offset = 0; | ||||
| 
 | ||||
| 	if (hose == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (rsrc->flags & IORESOURCE_IO) | ||||
| 		offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 
 | ||||
| 	/* We pass a fully fixed up address to userland for MMIO instead of
 | ||||
| 	 * a BAR value because X is lame and expects to be able to use that | ||||
| 	 * to pass to /dev/mem ! | ||||
| 	 * | ||||
| 	 * That means that we'll have potentially 64 bits values where some | ||||
| 	 * userland apps only expect 32 (like X itself since it thinks only | ||||
| 	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||||
| 	 * 32 bits CHRPs :-( | ||||
| 	 * | ||||
| 	 * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||||
| 	 * has been fixed (and the fix spread enough), we can re-enable the | ||||
| 	 * 2 lines below and pass down a BAR value to userland. In that case | ||||
| 	 * we'll also have to re-enable the matching code in | ||||
| 	 * __pci_mmap_make_offset(). | ||||
| 	 * | ||||
| 	 * BenH. | ||||
| 	 */ | ||||
| #if 0 | ||||
| 	else if (rsrc->flags & IORESOURCE_MEM) | ||||
| 		offset = hose->pci_mem_offset; | ||||
| #endif | ||||
| 
 | ||||
| 	*start = rsrc->start - offset; | ||||
| 	*end = rsrc->end - offset; | ||||
| } | ||||
| @ -55,8 +55,7 @@ static u8* pci_to_OF_bus_map; | ||||
|  */ | ||||
| int pci_assign_all_buses; | ||||
| 
 | ||||
| struct pci_controller* hose_head; | ||||
| struct pci_controller** hose_tail = &hose_head; | ||||
| LIST_HEAD(hose_list); | ||||
| 
 | ||||
| static int pci_bus_count; | ||||
| 
 | ||||
| @ -573,58 +572,6 @@ pcibios_assign_resources(void) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| pcibios_enable_resources(struct pci_dev *dev, int mask) | ||||
| { | ||||
| 	u16 cmd, old_cmd; | ||||
| 	int idx; | ||||
| 	struct resource *r; | ||||
| 
 | ||||
| 	pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||||
| 	old_cmd = cmd; | ||||
| 	for (idx=0; idx<6; idx++) { | ||||
| 		/* Only set up the requested stuff */ | ||||
| 		if (!(mask & (1<<idx))) | ||||
| 			continue; | ||||
| 	 | ||||
| 		r = &dev->resource[idx]; | ||||
| 		if (r->flags & IORESOURCE_UNSET) { | ||||
| 			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (r->flags & IORESOURCE_IO) | ||||
| 			cmd |= PCI_COMMAND_IO; | ||||
| 		if (r->flags & IORESOURCE_MEM) | ||||
| 			cmd |= PCI_COMMAND_MEMORY; | ||||
| 	} | ||||
| 	if (dev->resource[PCI_ROM_RESOURCE].start) | ||||
| 		cmd |= PCI_COMMAND_MEMORY; | ||||
| 	if (cmd != old_cmd) { | ||||
| 		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); | ||||
| 		pci_write_config_word(dev, PCI_COMMAND, cmd); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int next_controller_index; | ||||
| 
 | ||||
| struct pci_controller * __init | ||||
| pcibios_alloc_controller(void) | ||||
| { | ||||
| 	struct pci_controller *hose; | ||||
| 
 | ||||
| 	hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); | ||||
| 	memset(hose, 0, sizeof(struct pci_controller)); | ||||
| 
 | ||||
| 	*hose_tail = hose; | ||||
| 	hose_tail = &hose->next; | ||||
| 
 | ||||
| 	hose->index = next_controller_index++; | ||||
| 
 | ||||
| 	return hose; | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PPC_OF | ||||
| /*
 | ||||
|  * Functions below are used on OpenFirmware machines. | ||||
| @ -670,7 +617,7 @@ void | ||||
| pcibios_make_OF_bus_map(void) | ||||
| { | ||||
| 	int i; | ||||
| 	struct pci_controller* hose; | ||||
| 	struct pci_controller *hose, *tmp; | ||||
| 	struct property *map_prop; | ||||
| 	struct device_node *dn; | ||||
| 
 | ||||
| @ -687,7 +634,7 @@ pcibios_make_OF_bus_map(void) | ||||
| 		pci_to_OF_bus_map[i] = 0xff; | ||||
| 
 | ||||
| 	/* For each hose, we begin searching bridges */ | ||||
| 	for(hose=hose_head; hose; hose=hose->next) { | ||||
| 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||||
| 		struct device_node* node;	 | ||||
| 		node = (struct device_node *)hose->arch_data; | ||||
| 		if (!node) | ||||
| @ -765,7 +712,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus) | ||||
| 
 | ||||
| 	/* Are we a root bus ? */ | ||||
| 	if (bus->self == NULL || bus->parent == NULL) { | ||||
| 		struct pci_controller *hose = pci_bus_to_hose(bus->number); | ||||
| 		struct pci_controller *hose = pci_bus_to_host(bus); | ||||
| 		if (hose == NULL) | ||||
| 			return NULL; | ||||
| 		return of_node_get(hose->arch_data); | ||||
| @ -818,27 +765,6 @@ pci_device_to_OF_node(struct pci_dev *dev) | ||||
| } | ||||
| EXPORT_SYMBOL(pci_device_to_OF_node); | ||||
| 
 | ||||
| /* This routine is meant to be used early during boot, when the
 | ||||
|  * PCI bus numbers have not yet been assigned, and you need to | ||||
|  * issue PCI config cycles to an OF device. | ||||
|  * It could also be used to "fix" RTAS config cycles if you want | ||||
|  * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||||
|  * config cycles. | ||||
|  */ | ||||
| struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||||
| { | ||||
| 	if (!have_of) | ||||
| 		return NULL; | ||||
| 	while(node) { | ||||
| 		struct pci_controller* hose; | ||||
| 		for (hose=hose_head;hose;hose=hose->next) | ||||
| 			if (hose->arch_data == node) | ||||
| 				return hose; | ||||
| 		node=node->parent; | ||||
| 	} | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| find_OF_pci_device_filter(struct device_node* node, void* data) | ||||
| { | ||||
| @ -1027,34 +953,12 @@ pci_create_OF_bus_map(void) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct pci_dev *pdev; | ||||
| 	struct device_node *np; | ||||
| 
 | ||||
| 	pdev = to_pci_dev (dev); | ||||
| 	np = pci_device_to_OF_node(pdev); | ||||
| 	if (np == NULL || np->full_name == NULL) | ||||
| 		return 0; | ||||
| 	return sprintf(buf, "%s", np->full_name); | ||||
| } | ||||
| static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||||
| 
 | ||||
| #else /* CONFIG_PPC_OF */ | ||||
| void pcibios_make_OF_bus_map(void) | ||||
| { | ||||
| } | ||||
| #endif /* CONFIG_PPC_OF */ | ||||
| 
 | ||||
| /* Add sysfs properties */ | ||||
| void pcibios_add_platform_entries(struct pci_dev *pdev) | ||||
| { | ||||
| #ifdef CONFIG_PPC_OF | ||||
| 	device_create_file(&pdev->dev, &dev_attr_devspec); | ||||
| #endif /* CONFIG_PPC_OF */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef CONFIG_PPC_PMAC | ||||
| /*
 | ||||
|  * This set of routines checks for PCI<->PCI bridges that have closed | ||||
| @ -1269,14 +1173,14 @@ pcibios_fixup_p2p_bridges(void) | ||||
| static int __init | ||||
| pcibios_init(void) | ||||
| { | ||||
| 	struct pci_controller *hose; | ||||
| 	struct pci_controller *hose, *tmp; | ||||
| 	struct pci_bus *bus; | ||||
| 	int next_busno; | ||||
| 	int next_busno = 0; | ||||
| 
 | ||||
| 	printk(KERN_INFO "PCI: Probing PCI hardware\n"); | ||||
| 
 | ||||
| 	/* Scan all of the recorded PCI controllers.  */ | ||||
| 	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { | ||||
| 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||||
| 		if (pci_assign_all_buses) | ||||
| 			hose->first_busno = next_busno; | ||||
| 		hose->last_busno = 0xff; | ||||
| @ -1319,12 +1223,6 @@ pcibios_init(void) | ||||
| 
 | ||||
| subsys_initcall(pcibios_init); | ||||
| 
 | ||||
| unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, | ||||
| 			     unsigned long start, unsigned long size) | ||||
| { | ||||
| 	return start; | ||||
| } | ||||
| 
 | ||||
| void __init pcibios_fixup_bus(struct pci_bus *bus) | ||||
| { | ||||
| 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata; | ||||
| @ -1342,7 +1240,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | ||||
| 		if (!res->flags) { | ||||
| 			if (io_offset) | ||||
| 				printk(KERN_ERR "I/O resource not set for host" | ||||
| 				       " bridge %d\n", hose->index); | ||||
| 				       " bridge %d\n", hose->global_number); | ||||
| 			res->start = 0; | ||||
| 			res->end = IO_SPACE_LIMIT; | ||||
| 			res->flags = IORESOURCE_IO; | ||||
| @ -1356,7 +1254,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | ||||
| 				if (i > 0) | ||||
| 					continue; | ||||
| 				printk(KERN_ERR "Memory resource not set for " | ||||
| 				       "host bridge %d\n", hose->index); | ||||
| 				       "host bridge %d\n", hose->global_number); | ||||
| 				res->start = hose->pci_mem_offset; | ||||
| 				res->end = ~0U; | ||||
| 				res->flags = IORESOURCE_MEM; | ||||
| @ -1370,7 +1268,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | ||||
| 		for (i = 0; i < 4; ++i) { | ||||
| 			if ((res = bus->resource[i]) == NULL) | ||||
| 				continue; | ||||
| 			if (!res->flags) | ||||
| 			if (!res->flags || bus->self->transparent) | ||||
| 				continue; | ||||
| 			if (io_offset && (res->flags & IORESOURCE_IO)) { | ||||
| 				res->start += io_offset; | ||||
| @ -1395,11 +1293,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| char __init *pcibios_setup(char *str) | ||||
| { | ||||
| 	return str; | ||||
| } | ||||
| 
 | ||||
| /* the next one is stolen from the alpha port... */ | ||||
| void __init | ||||
| pcibios_update_irq(struct pci_dev *dev, int irq) | ||||
| @ -1408,64 +1301,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq) | ||||
| 	/* XXX FIXME - update OF device tree node interrupt property */ | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PPC_MERGE | ||||
| /* XXX This is a copy of the ppc64 version. This is temporary until we start
 | ||||
|  * merging the 2 PCI layers | ||||
|  */ | ||||
| /*
 | ||||
|  * Reads the interrupt pin to determine if interrupt is use by card. | ||||
|  * If the interrupt is used, then gets the interrupt line from the | ||||
|  * openfirmware and sets it in the pci_dev and pci_config line. | ||||
|  */ | ||||
| int pci_read_irq_line(struct pci_dev *pci_dev) | ||||
| { | ||||
| 	struct of_irq oirq; | ||||
| 	unsigned int virq; | ||||
| 
 | ||||
| 	DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||||
| 
 | ||||
| 	/* Try to get a mapping from the device-tree */ | ||||
| 	if (of_irq_map_pci(pci_dev, &oirq)) { | ||||
| 		u8 line, pin; | ||||
| 
 | ||||
| 		/* If that fails, lets fallback to what is in the config
 | ||||
| 		 * space and map that through the default controller. We | ||||
| 		 * also set the type to level low since that's what PCI | ||||
| 		 * interrupts are. If your platform does differently, then | ||||
| 		 * either provide a proper interrupt tree or don't use this | ||||
| 		 * function. | ||||
| 		 */ | ||||
| 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||||
| 			return -1; | ||||
| 		if (pin == 0) | ||||
| 			return -1; | ||||
| 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||||
| 		    line == 0xff) { | ||||
| 			return -1; | ||||
| 		} | ||||
| 		DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||||
| 
 | ||||
| 		virq = irq_create_mapping(NULL, line); | ||||
| 		if (virq != NO_IRQ) | ||||
| 			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||||
| 	} else { | ||||
| 		DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", | ||||
| 		    oirq.size, oirq.specifier[0], oirq.controller->full_name); | ||||
| 
 | ||||
| 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||||
| 					     oirq.size); | ||||
| 	} | ||||
| 	if(virq == NO_IRQ) { | ||||
| 		DBG(" -> failed to map !\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	pci_dev->irq = virq; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(pci_read_irq_line); | ||||
| #endif /* CONFIG_PPC_MERGE */ | ||||
| 
 | ||||
| int pcibios_enable_device(struct pci_dev *dev, int mask) | ||||
| { | ||||
| 	u16 cmd, old_cmd; | ||||
| @ -1497,281 +1332,17 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| struct pci_controller* | ||||
| static struct pci_controller* | ||||
| pci_bus_to_hose(int bus) | ||||
| { | ||||
| 	struct pci_controller* hose = hose_head; | ||||
| 	struct pci_controller *hose, *tmp; | ||||
| 
 | ||||
| 	for (; hose; hose = hose->next) | ||||
| 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||||
| 		if (bus >= hose->first_busno && bus <= hose->last_busno) | ||||
| 			return hose; | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void __iomem * | ||||
| pci_bus_io_base(unsigned int bus) | ||||
| { | ||||
| 	struct pci_controller *hose; | ||||
| 
 | ||||
| 	hose = pci_bus_to_hose(bus); | ||||
| 	if (!hose) | ||||
| 		return NULL; | ||||
| 	return hose->io_base_virt; | ||||
| } | ||||
| 
 | ||||
| unsigned long | ||||
| pci_bus_io_base_phys(unsigned int bus) | ||||
| { | ||||
| 	struct pci_controller *hose; | ||||
| 
 | ||||
| 	hose = pci_bus_to_hose(bus); | ||||
| 	if (!hose) | ||||
| 		return 0; | ||||
| 	return hose->io_base_phys; | ||||
| } | ||||
| 
 | ||||
| unsigned long | ||||
| pci_bus_mem_base_phys(unsigned int bus) | ||||
| { | ||||
| 	struct pci_controller *hose; | ||||
| 
 | ||||
| 	hose = pci_bus_to_hose(bus); | ||||
| 	if (!hose) | ||||
| 		return 0; | ||||
| 	return hose->pci_mem_offset; | ||||
| } | ||||
| 
 | ||||
| unsigned long | ||||
| pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) | ||||
| { | ||||
| 	/* Hack alert again ! See comments in chrp_pci.c
 | ||||
| 	 */ | ||||
| 	struct pci_controller* hose = | ||||
| 		(struct pci_controller *)pdev->sysdata; | ||||
| 	if (hose && res->flags & IORESOURCE_MEM) | ||||
| 		return res->start - hose->pci_mem_offset; | ||||
| 	/* We may want to do something with IOs here... */ | ||||
| 	return res->start; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||||
| 					       resource_size_t *offset, | ||||
| 					       enum pci_mmap_state mmap_state) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||||
| 	unsigned long io_offset = 0; | ||||
| 	int i, res_bit; | ||||
| 
 | ||||
| 	if (hose == 0) | ||||
| 		return NULL;		/* should never happen */ | ||||
| 
 | ||||
| 	/* If memory, add on the PCI bridge address offset */ | ||||
| 	if (mmap_state == pci_mmap_mem) { | ||||
| #if 0 /* See comment in pci_resource_to_user() for why this is disabled */
 | ||||
| 		*offset += hose->pci_mem_offset; | ||||
| #endif | ||||
| 		res_bit = IORESOURCE_MEM; | ||||
| 	} else { | ||||
| 		io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; | ||||
| 		*offset += io_offset; | ||||
| 		res_bit = IORESOURCE_IO; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Check that the offset requested corresponds to one of the | ||||
| 	 * resources of the device. | ||||
| 	 */ | ||||
| 	for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||||
| 		struct resource *rp = &dev->resource[i]; | ||||
| 		int flags = rp->flags; | ||||
| 
 | ||||
| 		/* treat ROM as memory (should be already) */ | ||||
| 		if (i == PCI_ROM_RESOURCE) | ||||
| 			flags |= IORESOURCE_MEM; | ||||
| 
 | ||||
| 		/* Active and same type? */ | ||||
| 		if ((flags & res_bit) == 0) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* In the range of this resource? */ | ||||
| 		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* found it! construct the final physical address */ | ||||
| 		if (mmap_state == pci_mmap_io) | ||||
| 			*offset += hose->io_base_phys - io_offset; | ||||
| 		return rp; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||||
|  * device mapping. | ||||
|  */ | ||||
| static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||||
| 				      pgprot_t protection, | ||||
| 				      enum pci_mmap_state mmap_state, | ||||
| 				      int write_combine) | ||||
| { | ||||
| 	unsigned long prot = pgprot_val(protection); | ||||
| 
 | ||||
| 	/* Write combine is always 0 on non-memory space mappings. On
 | ||||
| 	 * memory space, if the user didn't pass 1, we check for a | ||||
| 	 * "prefetchable" resource. This is a bit hackish, but we use | ||||
| 	 * this to workaround the inability of /sysfs to provide a write | ||||
| 	 * combine bit | ||||
| 	 */ | ||||
| 	if (mmap_state != pci_mmap_mem) | ||||
| 		write_combine = 0; | ||||
| 	else if (write_combine == 0) { | ||||
| 		if (rp->flags & IORESOURCE_PREFETCH) | ||||
| 			write_combine = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* XXX would be nice to have a way to ask for write-through */ | ||||
| 	prot |= _PAGE_NO_CACHE; | ||||
| 	if (write_combine) | ||||
| 		prot &= ~_PAGE_GUARDED; | ||||
| 	else | ||||
| 		prot |= _PAGE_GUARDED; | ||||
| 
 | ||||
| 	return __pgprot(prot); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This one is used by /dev/mem and fbdev who have no clue about the | ||||
|  * PCI device, it tries to find the PCI device first and calls the | ||||
|  * above routine | ||||
|  */ | ||||
| pgprot_t pci_phys_mem_access_prot(struct file *file, | ||||
| 				  unsigned long pfn, | ||||
| 				  unsigned long size, | ||||
| 				  pgprot_t protection) | ||||
| { | ||||
| 	struct pci_dev *pdev = NULL; | ||||
| 	struct resource *found = NULL; | ||||
| 	unsigned long prot = pgprot_val(protection); | ||||
| 	unsigned long offset = pfn << PAGE_SHIFT; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (page_is_ram(pfn)) | ||||
| 		return __pgprot(prot); | ||||
| 
 | ||||
| 	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||||
| 
 | ||||
| 	for_each_pci_dev(pdev) { | ||||
| 		for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||||
| 			struct resource *rp = &pdev->resource[i]; | ||||
| 			int flags = rp->flags; | ||||
| 
 | ||||
| 			/* Active and same type? */ | ||||
| 			if ((flags & IORESOURCE_MEM) == 0) | ||||
| 				continue; | ||||
| 			/* In the range of this resource? */ | ||||
| 			if (offset < (rp->start & PAGE_MASK) || | ||||
| 			    offset > rp->end) | ||||
| 				continue; | ||||
| 			found = rp; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (found) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (found) { | ||||
| 		if (found->flags & IORESOURCE_PREFETCH) | ||||
| 			prot &= ~_PAGE_GUARDED; | ||||
| 		pci_dev_put(pdev); | ||||
| 	} | ||||
| 
 | ||||
| 	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||||
| 
 | ||||
| 	return __pgprot(prot); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Perform the actual remap of the pages for a PCI device mapping, as | ||||
|  * appropriate for this architecture.  The region in the process to map | ||||
|  * is described by vm_start and vm_end members of VMA, the base physical | ||||
|  * address is found in vm_pgoff. | ||||
|  * The pci device structure is provided so that architectures may make mapping | ||||
|  * decisions on a per-device or per-bus basis. | ||||
|  * | ||||
|  * Returns a negative error code on failure, zero on success. | ||||
|  */ | ||||
| int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||||
| 			enum pci_mmap_state mmap_state, | ||||
| 			int write_combine) | ||||
| { | ||||
| 	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||||
| 	struct resource *rp; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||||
| 	if (rp == NULL) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	vma->vm_pgoff = offset >> PAGE_SHIFT; | ||||
| 	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||||
| 						  vma->vm_page_prot, | ||||
| 						  mmap_state, write_combine); | ||||
| 
 | ||||
| 	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||||
| 			       vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* Obsolete functions. Should be removed once the symbios driver
 | ||||
|  * is fixed | ||||
|  */ | ||||
| unsigned long | ||||
| phys_to_bus(unsigned long pa) | ||||
| { | ||||
| 	struct pci_controller *hose; | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (hose = hose_head; hose; hose = hose->next) { | ||||
| 		for (i = 0; i < 3; ++i) { | ||||
| 			if (pa >= hose->mem_resources[i].start | ||||
| 			    && pa <= hose->mem_resources[i].end) { | ||||
| 				/*
 | ||||
| 				 * XXX the hose->pci_mem_offset really | ||||
| 				 * only applies to mem_resources[0]. | ||||
| 				 * We need a way to store an offset for | ||||
| 				 * the others.  -- paulus | ||||
| 				 */ | ||||
| 				if (i == 0) | ||||
| 					pa -= hose->pci_mem_offset; | ||||
| 				return pa; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	/* hmmm, didn't find it */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| unsigned long | ||||
| pci_phys_to_bus(unsigned long pa, int busnr) | ||||
| { | ||||
| 	struct pci_controller* hose = pci_bus_to_hose(busnr); | ||||
| 	if (!hose) | ||||
| 		return pa; | ||||
| 	return pa - hose->pci_mem_offset; | ||||
| } | ||||
| 
 | ||||
| unsigned long | ||||
| pci_bus_to_phys(unsigned int ba, int busnr) | ||||
| { | ||||
| 	struct pci_controller* hose = pci_bus_to_hose(busnr); | ||||
| 	if (!hose) | ||||
| 		return ba; | ||||
| 	return ba + hose->pci_mem_offset; | ||||
| } | ||||
| 
 | ||||
| /* Provide information on locations of various I/O regions in physical
 | ||||
|  * memory.  Do this on a per-card basis so that we choose the right | ||||
|  * root bridge. | ||||
| @ -1814,62 +1385,11 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||||
| 			  const struct resource *rsrc, | ||||
| 			  resource_size_t *start, resource_size_t *end) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||||
| 	resource_size_t offset = 0; | ||||
| 
 | ||||
| 	if (hose == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (rsrc->flags & IORESOURCE_IO) | ||||
| 		offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 
 | ||||
| 	/* We pass a fully fixed up address to userland for MMIO instead of
 | ||||
| 	 * a BAR value because X is lame and expects to be able to use that | ||||
| 	 * to pass to /dev/mem ! | ||||
| 	 * | ||||
| 	 * That means that we'll have potentially 64 bits values where some | ||||
| 	 * userland apps only expect 32 (like X itself since it thinks only | ||||
| 	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||||
| 	 * 32 bits CHRPs :-( | ||||
| 	 * | ||||
| 	 * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||||
| 	 * has been fixed (and the fix spread enough), we can re-enable the | ||||
| 	 * 2 lines below and pass down a BAR value to userland. In that case | ||||
| 	 * we'll also have to re-enable the matching code in | ||||
| 	 * __pci_mmap_make_offset(). | ||||
| 	 * | ||||
| 	 * BenH. | ||||
| 	 */ | ||||
| #if 0 | ||||
| 	else if (rsrc->flags & IORESOURCE_MEM) | ||||
| 		offset = hose->pci_mem_offset; | ||||
| #endif | ||||
| 
 | ||||
| 	*start = rsrc->start - offset; | ||||
| 	*end = rsrc->end - offset; | ||||
| } | ||||
| 
 | ||||
| void __init pci_init_resource(struct resource *res, resource_size_t start, | ||||
| 			      resource_size_t end, int flags, char *name) | ||||
| { | ||||
| 	res->start = start; | ||||
| 	res->end = end; | ||||
| 	res->flags = flags; | ||||
| 	res->name = name; | ||||
| 	res->parent = NULL; | ||||
| 	res->sibling = NULL; | ||||
| 	res->child = NULL; | ||||
| } | ||||
| 
 | ||||
| unsigned long pci_address_to_pio(phys_addr_t address) | ||||
| { | ||||
| 	struct pci_controller* hose = hose_head; | ||||
| 	struct pci_controller *hose, *tmp; | ||||
| 
 | ||||
| 	for (; hose; hose = hose->next) { | ||||
| 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||||
| 		unsigned int size = hose->io_resource.end - | ||||
| 			hose->io_resource.start + 1; | ||||
| 		if (address >= hose->io_base_phys && | ||||
|  | ||||
| @ -22,6 +22,7 @@ | ||||
| #include <linux/list.h> | ||||
| #include <linux/syscalls.h> | ||||
| #include <linux/irq.h> | ||||
| #include <linux/vmalloc.h> | ||||
| 
 | ||||
| #include <asm/processor.h> | ||||
| #include <asm/io.h> | ||||
| @ -41,35 +42,23 @@ | ||||
| 
 | ||||
| unsigned long pci_probe_only = 1; | ||||
| int pci_assign_all_buses = 0; | ||||
| static int pci_initial_scan_done; | ||||
| 
 | ||||
| static void fixup_resource(struct resource *res, struct pci_dev *dev); | ||||
| static void do_bus_setup(struct pci_bus *bus); | ||||
| static void phbs_remap_io(void); | ||||
| 
 | ||||
| /* pci_io_base -- the base address from which io bars are offsets.
 | ||||
|  * This is the lowest I/O base address (so bar values are always positive), | ||||
|  * and it *must* be the start of ISA space if an ISA bus exists because | ||||
|  * ISA drivers use hard coded offsets.  If no ISA bus exists a dummy | ||||
|  * page is mapped and isa_io_limit prevents access to it. | ||||
|  * ISA drivers use hard coded offsets.  If no ISA bus exists nothing | ||||
|  * is mapped on the first 64K of IO space | ||||
|  */ | ||||
| unsigned long isa_io_base;	/* NULL if no ISA bus */ | ||||
| EXPORT_SYMBOL(isa_io_base); | ||||
| unsigned long pci_io_base; | ||||
| unsigned long pci_io_base = ISA_IO_BASE; | ||||
| EXPORT_SYMBOL(pci_io_base); | ||||
| 
 | ||||
| void iSeries_pcibios_init(void); | ||||
| 
 | ||||
| LIST_HEAD(hose_list); | ||||
| 
 | ||||
| static struct dma_mapping_ops *pci_dma_ops; | ||||
| 
 | ||||
| int global_phb_number;		/* Global phb counter */ | ||||
| 
 | ||||
| /* Cached ISA bridge dev. */ | ||||
| struct pci_dev *ppc64_isabridge_dev = NULL; | ||||
| EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); | ||||
| 
 | ||||
| void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) | ||||
| { | ||||
| 	pci_dma_ops = dma_ops; | ||||
| @ -100,7 +89,7 @@ void  pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region | ||||
| 		return; | ||||
| 
 | ||||
| 	if (res->flags & IORESOURCE_IO) | ||||
| 	        offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 	        offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 
 | ||||
| 	if (res->flags & IORESOURCE_MEM) | ||||
| 		offset = hose->pci_mem_offset; | ||||
| @ -119,7 +108,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||||
| 		return; | ||||
| 
 | ||||
| 	if (res->flags & IORESOURCE_IO) | ||||
| 	        offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 	        offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 
 | ||||
| 	if (res->flags & IORESOURCE_MEM) | ||||
| 		offset = hose->pci_mem_offset; | ||||
| @ -156,7 +145,7 @@ void pcibios_align_resource(void *data, struct resource *res, | ||||
| 
 | ||||
| 	if (res->flags & IORESOURCE_IO) { | ||||
| 	        unsigned long offset = (unsigned long)hose->io_base_virt - | ||||
| 					pci_io_base; | ||||
| 					_IO_BASE; | ||||
| 		/* Make sure we start at our min on all hoses */ | ||||
| 		if (start - offset < PCIBIOS_MIN_IO) | ||||
| 			start = PCIBIOS_MIN_IO + offset; | ||||
| @ -180,55 +169,6 @@ void pcibios_align_resource(void *data, struct resource *res, | ||||
| 	res->start = start; | ||||
| } | ||||
| 
 | ||||
| static DEFINE_SPINLOCK(hose_spinlock); | ||||
| 
 | ||||
| /*
 | ||||
|  * pci_controller(phb) initialized common variables. | ||||
|  */ | ||||
| static void __devinit pci_setup_pci_controller(struct pci_controller *hose) | ||||
| { | ||||
| 	memset(hose, 0, sizeof(struct pci_controller)); | ||||
| 
 | ||||
| 	spin_lock(&hose_spinlock); | ||||
| 	hose->global_number = global_phb_number++; | ||||
| 	list_add_tail(&hose->list_node, &hose_list); | ||||
| 	spin_unlock(&hose_spinlock); | ||||
| } | ||||
| 
 | ||||
| struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | ||||
| { | ||||
| 	struct pci_controller *phb; | ||||
| 
 | ||||
| 	if (mem_init_done) | ||||
| 		phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | ||||
| 	else | ||||
| 		phb = alloc_bootmem(sizeof (struct pci_controller)); | ||||
| 	if (phb == NULL) | ||||
| 		return NULL; | ||||
| 	pci_setup_pci_controller(phb); | ||||
| 	phb->arch_data = dev; | ||||
| 	phb->is_dynamic = mem_init_done; | ||||
| 	if (dev) { | ||||
| 		int nid = of_node_to_nid(dev); | ||||
| 
 | ||||
| 		if (nid < 0 || !node_online(nid)) | ||||
| 			nid = -1; | ||||
| 
 | ||||
| 		PHB_SET_NODE(phb, nid); | ||||
| 	} | ||||
| 	return phb; | ||||
| } | ||||
| 
 | ||||
| void pcibios_free_controller(struct pci_controller *phb) | ||||
| { | ||||
| 	spin_lock(&hose_spinlock); | ||||
| 	list_del(&phb->list_node); | ||||
| 	spin_unlock(&hose_spinlock); | ||||
| 
 | ||||
| 	if (phb->is_dynamic) | ||||
| 		kfree(phb); | ||||
| } | ||||
| 
 | ||||
| void __devinit pcibios_claim_one_bus(struct pci_bus *b) | ||||
| { | ||||
| 	struct pci_dev *dev; | ||||
| @ -291,7 +231,6 @@ static unsigned int pci_parse_of_flags(u32 addr0) | ||||
| 	return flags; | ||||
| } | ||||
| 
 | ||||
| #define GET_64BIT(prop, i)	((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) | ||||
| 
 | ||||
| static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | ||||
| { | ||||
| @ -310,8 +249,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | ||||
| 		flags = pci_parse_of_flags(addrs[0]); | ||||
| 		if (!flags) | ||||
| 			continue; | ||||
| 		base = GET_64BIT(addrs, 1); | ||||
| 		size = GET_64BIT(addrs, 3); | ||||
| 		base = of_read_number(&addrs[1], 2); | ||||
| 		size = of_read_number(&addrs[3], 2); | ||||
| 		if (!size) | ||||
| 			continue; | ||||
| 		i = addrs[0] & 0xff; | ||||
| @ -477,7 +416,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | ||||
| 	i = 1; | ||||
| 	for (; len >= 32; len -= 32, ranges += 8) { | ||||
| 		flags = pci_parse_of_flags(ranges[0]); | ||||
| 		size = GET_64BIT(ranges, 6); | ||||
| 		size = of_read_number(&ranges[6], 2); | ||||
| 		if (flags == 0 || size == 0) | ||||
| 			continue; | ||||
| 		if (flags & IORESOURCE_IO) { | ||||
| @ -496,7 +435,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | ||||
| 			res = bus->resource[i]; | ||||
| 			++i; | ||||
| 		} | ||||
| 		res->start = GET_64BIT(ranges, 1); | ||||
| 		res->start = of_read_number(&ranges[1], 2); | ||||
| 		res->end = res->start + size - 1; | ||||
| 		res->flags = flags; | ||||
| 		fixup_resource(res, dev); | ||||
| @ -535,10 +474,16 @@ void __devinit scan_phb(struct pci_controller *hose) | ||||
| 	bus->secondary = hose->first_busno; | ||||
| 	hose->bus = bus; | ||||
| 
 | ||||
| 	if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||||
| 		pcibios_map_io_space(bus); | ||||
| 
 | ||||
| 	bus->resource[0] = res = &hose->io_resource; | ||||
| 	if (res->flags && request_resource(&ioport_resource, res)) | ||||
| 	if (res->flags && request_resource(&ioport_resource, res)) { | ||||
| 		printk(KERN_ERR "Failed to request PCI IO region " | ||||
| 		       "on PCI domain %04x\n", hose->global_number); | ||||
| 		DBG("res->start = 0x%016lx, res->end = 0x%016lx\n", | ||||
| 		    res->start, res->end); | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < 3; ++i) { | ||||
| 		res = &hose->mem_resources[i]; | ||||
| @ -596,17 +541,6 @@ static int __init pcibios_init(void) | ||||
| 	if (ppc_md.pcibios_fixup) | ||||
| 		ppc_md.pcibios_fixup(); | ||||
| 
 | ||||
| 	/* Cache the location of the ISA bridge (if we have one) */ | ||||
| 	ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); | ||||
| 	if (ppc64_isabridge_dev != NULL) | ||||
| 		printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | ||||
| 
 | ||||
| 	if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||||
| 		/* map in PCI I/O space */ | ||||
| 		phbs_remap_io(); | ||||
| 
 | ||||
| 	pci_initial_scan_done = 1; | ||||
| 
 | ||||
| 	printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); | ||||
| 
 | ||||
| 	return 0; | ||||
| @ -614,11 +548,6 @@ static int __init pcibios_init(void) | ||||
| 
 | ||||
| subsys_initcall(pcibios_init); | ||||
| 
 | ||||
| char __init *pcibios_setup(char *str) | ||||
| { | ||||
| 	return str; | ||||
| } | ||||
| 
 | ||||
| int pcibios_enable_device(struct pci_dev *dev, int mask) | ||||
| { | ||||
| 	u16 cmd, oldcmd; | ||||
| @ -649,22 +578,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Return the domain number for this bus. | ||||
|  */ | ||||
| int pci_domain_nr(struct pci_bus *bus) | ||||
| { | ||||
| 	if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||||
| 		return 0; | ||||
| 	else { | ||||
| 		struct pci_controller *hose = pci_bus_to_host(bus); | ||||
| 
 | ||||
| 		return hose->global_number; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| EXPORT_SYMBOL(pci_domain_nr); | ||||
| 
 | ||||
| /* Decide whether to display the domain number in /proc */ | ||||
| int pci_proc_domain(struct pci_bus *bus) | ||||
| { | ||||
| @ -676,281 +589,6 @@ int pci_proc_domain(struct pci_bus *bus) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Platform support for /proc/bus/pci/X/Y mmap()s, | ||||
|  * modelled on the sparc64 implementation by Dave Miller. | ||||
|  *  -- paulus. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Adjust vm_pgoff of VMA such that it is the physical page offset | ||||
|  * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||||
|  * | ||||
|  * Basically, the user finds the base address for his device which he wishes | ||||
|  * to mmap.  They read the 32-bit value from the config space base register, | ||||
|  * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||||
|  * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||||
|  * | ||||
|  * Returns negative error code on failure, zero on success. | ||||
|  */ | ||||
| static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||||
| 					       resource_size_t *offset, | ||||
| 					       enum pci_mmap_state mmap_state) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||||
| 	unsigned long io_offset = 0; | ||||
| 	int i, res_bit; | ||||
| 
 | ||||
| 	if (hose == 0) | ||||
| 		return NULL;		/* should never happen */ | ||||
| 
 | ||||
| 	/* If memory, add on the PCI bridge address offset */ | ||||
| 	if (mmap_state == pci_mmap_mem) { | ||||
| #if 0 /* See comment in pci_resource_to_user() for why this is disabled */
 | ||||
| 		*offset += hose->pci_mem_offset; | ||||
| #endif | ||||
| 		res_bit = IORESOURCE_MEM; | ||||
| 	} else { | ||||
| 		io_offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 		*offset += io_offset; | ||||
| 		res_bit = IORESOURCE_IO; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Check that the offset requested corresponds to one of the | ||||
| 	 * resources of the device. | ||||
| 	 */ | ||||
| 	for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||||
| 		struct resource *rp = &dev->resource[i]; | ||||
| 		int flags = rp->flags; | ||||
| 
 | ||||
| 		/* treat ROM as memory (should be already) */ | ||||
| 		if (i == PCI_ROM_RESOURCE) | ||||
| 			flags |= IORESOURCE_MEM; | ||||
| 
 | ||||
| 		/* Active and same type? */ | ||||
| 		if ((flags & res_bit) == 0) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* In the range of this resource? */ | ||||
| 		if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* found it! construct the final physical address */ | ||||
| 		if (mmap_state == pci_mmap_io) | ||||
| 		       	*offset += hose->io_base_phys - io_offset; | ||||
| 		return rp; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||||
|  * device mapping. | ||||
|  */ | ||||
| static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||||
| 				      pgprot_t protection, | ||||
| 				      enum pci_mmap_state mmap_state, | ||||
| 				      int write_combine) | ||||
| { | ||||
| 	unsigned long prot = pgprot_val(protection); | ||||
| 
 | ||||
| 	/* Write combine is always 0 on non-memory space mappings. On
 | ||||
| 	 * memory space, if the user didn't pass 1, we check for a | ||||
| 	 * "prefetchable" resource. This is a bit hackish, but we use | ||||
| 	 * this to workaround the inability of /sysfs to provide a write | ||||
| 	 * combine bit | ||||
| 	 */ | ||||
| 	if (mmap_state != pci_mmap_mem) | ||||
| 		write_combine = 0; | ||||
| 	else if (write_combine == 0) { | ||||
| 		if (rp->flags & IORESOURCE_PREFETCH) | ||||
| 			write_combine = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* XXX would be nice to have a way to ask for write-through */ | ||||
| 	prot |= _PAGE_NO_CACHE; | ||||
| 	if (write_combine) | ||||
| 		prot &= ~_PAGE_GUARDED; | ||||
| 	else | ||||
| 		prot |= _PAGE_GUARDED; | ||||
| 
 | ||||
| 	return __pgprot(prot); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This one is used by /dev/mem and fbdev who have no clue about the | ||||
|  * PCI device, it tries to find the PCI device first and calls the | ||||
|  * above routine | ||||
|  */ | ||||
| pgprot_t pci_phys_mem_access_prot(struct file *file, | ||||
| 				  unsigned long pfn, | ||||
| 				  unsigned long size, | ||||
| 				  pgprot_t protection) | ||||
| { | ||||
| 	struct pci_dev *pdev = NULL; | ||||
| 	struct resource *found = NULL; | ||||
| 	unsigned long prot = pgprot_val(protection); | ||||
| 	unsigned long offset = pfn << PAGE_SHIFT; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (page_is_ram(pfn)) | ||||
| 		return __pgprot(prot); | ||||
| 
 | ||||
| 	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||||
| 
 | ||||
| 	for_each_pci_dev(pdev) { | ||||
| 		for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||||
| 			struct resource *rp = &pdev->resource[i]; | ||||
| 			int flags = rp->flags; | ||||
| 
 | ||||
| 			/* Active and same type? */ | ||||
| 			if ((flags & IORESOURCE_MEM) == 0) | ||||
| 				continue; | ||||
| 			/* In the range of this resource? */ | ||||
| 			if (offset < (rp->start & PAGE_MASK) || | ||||
| 			    offset > rp->end) | ||||
| 				continue; | ||||
| 			found = rp; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (found) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (found) { | ||||
| 		if (found->flags & IORESOURCE_PREFETCH) | ||||
| 			prot &= ~_PAGE_GUARDED; | ||||
| 		pci_dev_put(pdev); | ||||
| 	} | ||||
| 
 | ||||
| 	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||||
| 
 | ||||
| 	return __pgprot(prot); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Perform the actual remap of the pages for a PCI device mapping, as | ||||
|  * appropriate for this architecture.  The region in the process to map | ||||
|  * is described by vm_start and vm_end members of VMA, the base physical | ||||
|  * address is found in vm_pgoff. | ||||
|  * The pci device structure is provided so that architectures may make mapping | ||||
|  * decisions on a per-device or per-bus basis. | ||||
|  * | ||||
|  * Returns a negative error code on failure, zero on success. | ||||
|  */ | ||||
| int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||||
| 			enum pci_mmap_state mmap_state, int write_combine) | ||||
| { | ||||
| 	resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||||
| 	struct resource *rp; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||||
| 	if (rp == NULL) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	vma->vm_pgoff = offset >> PAGE_SHIFT; | ||||
| 	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||||
| 						  vma->vm_page_prot, | ||||
| 						  mmap_state, write_combine); | ||||
| 
 | ||||
| 	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||||
| 			       vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pci_show_devspec(struct device *dev, | ||||
| 		struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct pci_dev *pdev; | ||||
| 	struct device_node *np; | ||||
| 
 | ||||
| 	pdev = to_pci_dev (dev); | ||||
| 	np = pci_device_to_OF_node(pdev); | ||||
| 	if (np == NULL || np->full_name == NULL) | ||||
| 		return 0; | ||||
| 	return sprintf(buf, "%s", np->full_name); | ||||
| } | ||||
| static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||||
| 
 | ||||
| void pcibios_add_platform_entries(struct pci_dev *pdev) | ||||
| { | ||||
| 	device_create_file(&pdev->dev, &dev_attr_devspec); | ||||
| } | ||||
| 
 | ||||
| #define ISA_SPACE_MASK 0x1 | ||||
| #define ISA_SPACE_IO 0x1 | ||||
| 
 | ||||
| static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, | ||||
| 				      unsigned long phb_io_base_phys, | ||||
| 				      void __iomem * phb_io_base_virt) | ||||
| { | ||||
| 	/* Remove these asap */ | ||||
| 
 | ||||
| 	struct pci_address { | ||||
| 		u32 a_hi; | ||||
| 		u32 a_mid; | ||||
| 		u32 a_lo; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct isa_address { | ||||
| 		u32 a_hi; | ||||
| 		u32 a_lo; | ||||
| 	}; | ||||
| 
 | ||||
| 	struct isa_range { | ||||
| 		struct isa_address isa_addr; | ||||
| 		struct pci_address pci_addr; | ||||
| 		unsigned int size; | ||||
| 	}; | ||||
| 
 | ||||
| 	const struct isa_range *range; | ||||
| 	unsigned long pci_addr; | ||||
| 	unsigned int isa_addr; | ||||
| 	unsigned int size; | ||||
| 	int rlen = 0; | ||||
| 
 | ||||
| 	range = of_get_property(isa_node, "ranges", &rlen); | ||||
| 	if (range == NULL || (rlen < sizeof(struct isa_range))) { | ||||
| 		printk(KERN_ERR "no ISA ranges or unexpected isa range size," | ||||
| 		       "mapping 64k\n"); | ||||
| 		__ioremap_explicit(phb_io_base_phys, | ||||
| 				   (unsigned long)phb_io_base_virt, | ||||
| 				   0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED); | ||||
| 		return;	 | ||||
| 	} | ||||
| 	 | ||||
| 	/* From "ISA Binding to 1275"
 | ||||
| 	 * The ranges property is laid out as an array of elements, | ||||
| 	 * each of which comprises: | ||||
| 	 *   cells 0 - 1:	an ISA address | ||||
| 	 *   cells 2 - 4:	a PCI address  | ||||
| 	 *			(size depending on dev->n_addr_cells) | ||||
| 	 *   cell 5:		the size of the range | ||||
| 	 */ | ||||
| 	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) { | ||||
| 		isa_addr = range->isa_addr.a_lo; | ||||
| 		pci_addr = (unsigned long) range->pci_addr.a_mid << 32 |  | ||||
| 			range->pci_addr.a_lo; | ||||
| 
 | ||||
| 		/* Assume these are both zero */ | ||||
| 		if ((pci_addr != 0) || (isa_addr != 0)) { | ||||
| 			printk(KERN_ERR "unexpected isa to pci mapping: %s\n", | ||||
| 					__FUNCTION__); | ||||
| 			return; | ||||
| 		} | ||||
| 		 | ||||
| 		size = PAGE_ALIGN(range->size); | ||||
| 
 | ||||
| 		__ioremap_explicit(phb_io_base_phys,  | ||||
| 				   (unsigned long) phb_io_base_virt,  | ||||
| 				   size, _PAGE_NO_CACHE | _PAGE_GUARDED); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | ||||
| 					    struct device_node *dev, int prim) | ||||
| { | ||||
| @ -1045,155 +683,122 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary) | ||||
| #ifdef CONFIG_HOTPLUG | ||||
| 
 | ||||
| int pcibios_unmap_io_space(struct pci_bus *bus) | ||||
| { | ||||
| 	unsigned long size = hose->pci_io_size; | ||||
| 	unsigned long io_virt_offset; | ||||
| 	struct resource *res; | ||||
| 	struct device_node *isa_dn; | ||||
| 	struct pci_controller *hose; | ||||
| 
 | ||||
| 	if (size == 0) | ||||
| 		return; | ||||
| 	WARN_ON(bus == NULL); | ||||
| 
 | ||||
| 	hose->io_base_virt = reserve_phb_iospace(size); | ||||
| 	DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", | ||||
| 		hose->global_number, hose->io_base_phys, | ||||
| 		(unsigned long) hose->io_base_virt); | ||||
| 
 | ||||
| 	if (primary) { | ||||
| 		pci_io_base = (unsigned long)hose->io_base_virt; | ||||
| 		isa_dn = of_find_node_by_type(NULL, "isa"); | ||||
| 		if (isa_dn) { | ||||
| 			isa_io_base = pci_io_base; | ||||
| 			pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, | ||||
| 						hose->io_base_virt); | ||||
| 			of_node_put(isa_dn); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 	res = &hose->io_resource; | ||||
| 	res->start += io_virt_offset; | ||||
| 	res->end += io_virt_offset; | ||||
| 
 | ||||
| 	/* If this is called after the initial PCI scan, then we need to
 | ||||
| 	 * proceed to IO mappings now | ||||
| 	/* If this is not a PHB, we only flush the hash table over
 | ||||
| 	 * the area mapped by this bridge. We don't play with the PTE | ||||
| 	 * mappings since we might have to deal with sub-page alignemnts | ||||
| 	 * so flushing the hash table is the only sane way to make sure | ||||
| 	 * that no hash entries are covering that removed bridge area | ||||
| 	 * while still allowing other busses overlapping those pages | ||||
| 	 */ | ||||
| 	if (pci_initial_scan_done) | ||||
| 		__ioremap_explicit(hose->io_base_phys, | ||||
| 				   (unsigned long)hose->io_base_virt, | ||||
| 				   hose->pci_io_size, | ||||
| 				   _PAGE_NO_CACHE | _PAGE_GUARDED); | ||||
| } | ||||
| 	if (bus->self) { | ||||
| 		struct resource *res = bus->resource[0]; | ||||
| 
 | ||||
| void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose, | ||||
| 					int primary) | ||||
| 		DBG("IO unmapping for PCI-PCI bridge %s\n", | ||||
| 		    pci_name(bus->self)); | ||||
| 
 | ||||
| 		__flush_hash_table_range(&init_mm, res->start + _IO_BASE, | ||||
| 					 res->end - res->start + 1); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Get the host bridge */ | ||||
| 	hose = pci_bus_to_host(bus); | ||||
| 
 | ||||
| 	/* Check if we have IOs allocated */ | ||||
| 	if (hose->io_base_alloc == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	DBG("IO unmapping for PHB %s\n", | ||||
| 	    ((struct device_node *)hose->arch_data)->full_name); | ||||
| 	DBG("  alloc=0x%p\n", hose->io_base_alloc); | ||||
| 
 | ||||
| 	/* This is a PHB, we fully unmap the IO area */ | ||||
| 	vunmap(hose->io_base_alloc); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(pcibios_unmap_io_space); | ||||
| 
 | ||||
| #endif /* CONFIG_HOTPLUG */ | ||||
| 
 | ||||
| int __devinit pcibios_map_io_space(struct pci_bus *bus) | ||||
| { | ||||
| 	unsigned long size = hose->pci_io_size; | ||||
| 	struct vm_struct *area; | ||||
| 	unsigned long phys_page; | ||||
| 	unsigned long size_page; | ||||
| 	unsigned long io_virt_offset; | ||||
| 	struct resource *res; | ||||
| 	struct pci_controller *hose; | ||||
| 
 | ||||
| 	if (size == 0) | ||||
| 		return; | ||||
| 	WARN_ON(bus == NULL); | ||||
| 
 | ||||
| 	hose->io_base_virt = __ioremap(hose->io_base_phys, size, | ||||
| 					_PAGE_NO_CACHE | _PAGE_GUARDED); | ||||
| 	DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", | ||||
| 		hose->global_number, hose->io_base_phys, | ||||
| 		(unsigned long) hose->io_base_virt); | ||||
| 
 | ||||
| 	if (primary) | ||||
| 		pci_io_base = (unsigned long)hose->io_base_virt; | ||||
| 
 | ||||
| 	io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 	res = &hose->io_resource; | ||||
| 	res->start += io_virt_offset; | ||||
| 	res->end += io_virt_offset; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, | ||||
| 				unsigned long *start_virt, unsigned long *size) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_host(bus); | ||||
| 	struct resource *res; | ||||
| 
 | ||||
| 	if (bus->self) | ||||
| 		res = bus->resource[0]; | ||||
| 	else | ||||
| 		/* Root Bus */ | ||||
| 		res = &hose->io_resource; | ||||
| 
 | ||||
| 	if (res->end == 0 && res->start == 0) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	*start_virt = pci_io_base + res->start; | ||||
| 	*start_phys = *start_virt + hose->io_base_phys | ||||
| 		- (unsigned long) hose->io_base_virt; | ||||
| 
 | ||||
| 	if (res->end > res->start) | ||||
| 		*size = res->end - res->start + 1; | ||||
| 	else { | ||||
| 		printk("%s(): unexpected region 0x%lx->0x%lx\n", | ||||
| 		       __FUNCTION__, res->start, res->end); | ||||
| 		return 1; | ||||
| 	/* If this not a PHB, nothing to do, page tables still exist and
 | ||||
| 	 * thus HPTEs will be faulted in when needed | ||||
| 	 */ | ||||
| 	if (bus->self) { | ||||
| 		DBG("IO mapping for PCI-PCI bridge %s\n", | ||||
| 		    pci_name(bus->self)); | ||||
| 		DBG("  virt=0x%016lx...0x%016lx\n", | ||||
| 		    bus->resource[0]->start + _IO_BASE, | ||||
| 		    bus->resource[0]->end + _IO_BASE); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Get the host bridge */ | ||||
| 	hose = pci_bus_to_host(bus); | ||||
| 	phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE); | ||||
| 	size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE); | ||||
| 
 | ||||
| 	/* Make sure IO area address is clear */ | ||||
| 	hose->io_base_alloc = NULL; | ||||
| 
 | ||||
| 	/* If there's no IO to map on that bus, get away too */ | ||||
| 	if (hose->pci_io_size == 0 || hose->io_base_phys == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* Let's allocate some IO space for that guy. We don't pass
 | ||||
| 	 * VM_IOREMAP because we don't care about alignment tricks that | ||||
| 	 * the core does in that case. Maybe we should due to stupid card | ||||
| 	 * with incomplete address decoding but I'd rather not deal with | ||||
| 	 * those outside of the reserved 64K legacy region. | ||||
| 	 */ | ||||
| 	area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END); | ||||
| 	if (area == NULL) | ||||
| 		return -ENOMEM; | ||||
| 	hose->io_base_alloc = area->addr; | ||||
| 	hose->io_base_virt = (void __iomem *)(area->addr + | ||||
| 					      hose->io_base_phys - phys_page); | ||||
| 
 | ||||
| 	DBG("IO mapping for PHB %s\n", | ||||
| 	    ((struct device_node *)hose->arch_data)->full_name); | ||||
| 	DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n", | ||||
| 	    hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc); | ||||
| 	DBG("  size=0x%016lx (alloc=0x%016lx)\n", | ||||
| 	    hose->pci_io_size, size_page); | ||||
| 
 | ||||
| 	/* Establish the mapping */ | ||||
| 	if (__ioremap_at(phys_page, area->addr, size_page, | ||||
| 			 _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	/* Fixup hose IO resource */ | ||||
| 	io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 	hose->io_resource.start += io_virt_offset; | ||||
| 	hose->io_resource.end += io_virt_offset; | ||||
| 
 | ||||
| 	DBG("  hose->io_resource=0x%016lx...0x%016lx\n", | ||||
| 	    hose->io_resource.start, hose->io_resource.end); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int unmap_bus_range(struct pci_bus *bus) | ||||
| { | ||||
| 	unsigned long start_phys; | ||||
| 	unsigned long start_virt; | ||||
| 	unsigned long size; | ||||
| 
 | ||||
| 	if (!bus) { | ||||
| 		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	 | ||||
| 	if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | ||||
| 		return 1; | ||||
| 	if (__iounmap_explicit((void __iomem *) start_virt, size)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(unmap_bus_range); | ||||
| 
 | ||||
| int remap_bus_range(struct pci_bus *bus) | ||||
| { | ||||
| 	unsigned long start_phys; | ||||
| 	unsigned long start_virt; | ||||
| 	unsigned long size; | ||||
| 
 | ||||
| 	if (!bus) { | ||||
| 		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | ||||
| 		return 1; | ||||
| 	if (start_phys == 0) | ||||
| 		return 1; | ||||
| 	printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); | ||||
| 	if (__ioremap_explicit(start_phys, start_virt, size, | ||||
| 			       _PAGE_NO_CACHE | _PAGE_GUARDED)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(remap_bus_range); | ||||
| 
 | ||||
| static void phbs_remap_io(void) | ||||
| { | ||||
| 	struct pci_controller *hose, *tmp; | ||||
| 
 | ||||
| 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||||
| 		remap_bus_range(hose->bus); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(pcibios_map_io_space); | ||||
| 
 | ||||
| static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | ||||
| { | ||||
| @ -1201,8 +806,7 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | ||||
| 	unsigned long offset; | ||||
| 
 | ||||
| 	if (res->flags & IORESOURCE_IO) { | ||||
| 		offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 
 | ||||
| 		offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 		res->start += offset; | ||||
| 		res->end += offset; | ||||
| 	} else if (res->flags & IORESOURCE_MEM) { | ||||
| @ -1217,9 +821,20 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | ||||
| 	/* Update device resources.  */ | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < PCI_NUM_RESOURCES; i++) | ||||
| 		if (dev->resource[i].flags) | ||||
| 			fixup_resource(&dev->resource[i], dev); | ||||
| 	DBG("%s: Fixup resources:\n", pci_name(dev)); | ||||
| 	for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||||
| 		struct resource *res = &dev->resource[i]; | ||||
| 		if (!res->flags) | ||||
| 			continue; | ||||
| 
 | ||||
| 		DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n", | ||||
| 		    i, res->flags, res->start, res->end); | ||||
| 
 | ||||
| 		fixup_resource(res, dev); | ||||
| 
 | ||||
| 		DBG("       > %08lx:0x%016lx...0x%016lx\n", | ||||
| 		    res->flags, res->start, res->end); | ||||
| 	} | ||||
| } | ||||
| EXPORT_SYMBOL(pcibios_fixup_device_resources); | ||||
| 
 | ||||
| @ -1289,119 +904,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | ||||
| } | ||||
| EXPORT_SYMBOL(pcibios_fixup_bus); | ||||
| 
 | ||||
| /*
 | ||||
|  * Reads the interrupt pin to determine if interrupt is use by card. | ||||
|  * If the interrupt is used, then gets the interrupt line from the  | ||||
|  * openfirmware and sets it in the pci_dev and pci_config line. | ||||
|  */ | ||||
| int pci_read_irq_line(struct pci_dev *pci_dev) | ||||
| { | ||||
| 	struct of_irq oirq; | ||||
| 	unsigned int virq; | ||||
| 
 | ||||
| 	DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| 	memset(&oirq, 0xff, sizeof(oirq)); | ||||
| #endif | ||||
| 	/* Try to get a mapping from the device-tree */ | ||||
| 	if (of_irq_map_pci(pci_dev, &oirq)) { | ||||
| 		u8 line, pin; | ||||
| 
 | ||||
| 		/* If that fails, lets fallback to what is in the config
 | ||||
| 		 * space and map that through the default controller. We | ||||
| 		 * also set the type to level low since that's what PCI | ||||
| 		 * interrupts are. If your platform does differently, then | ||||
| 		 * either provide a proper interrupt tree or don't use this | ||||
| 		 * function. | ||||
| 		 */ | ||||
| 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||||
| 			return -1; | ||||
| 		if (pin == 0) | ||||
| 			return -1; | ||||
| 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||||
| 		    line == 0xff) { | ||||
| 			return -1; | ||||
| 		} | ||||
| 		DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||||
| 
 | ||||
| 		virq = irq_create_mapping(NULL, line); | ||||
| 		if (virq != NO_IRQ) | ||||
| 			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||||
| 	} else { | ||||
| 		DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||||
| 		    oirq.size, oirq.specifier[0], oirq.specifier[1], | ||||
| 		    oirq.controller->full_name); | ||||
| 
 | ||||
| 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||||
| 					     oirq.size); | ||||
| 	} | ||||
| 	if(virq == NO_IRQ) { | ||||
| 		DBG(" -> failed to map !\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	DBG(" -> mapped to linux irq %d\n", virq); | ||||
| 
 | ||||
| 	pci_dev->irq = virq; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(pci_read_irq_line); | ||||
| 
 | ||||
| void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||||
| 			  const struct resource *rsrc, | ||||
| 			  resource_size_t *start, resource_size_t *end) | ||||
| { | ||||
| 	struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||||
| 	resource_size_t offset = 0; | ||||
| 
 | ||||
| 	if (hose == NULL) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (rsrc->flags & IORESOURCE_IO) | ||||
| 		offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 
 | ||||
| 	/* We pass a fully fixed up address to userland for MMIO instead of
 | ||||
| 	 * a BAR value because X is lame and expects to be able to use that | ||||
| 	 * to pass to /dev/mem ! | ||||
| 	 * | ||||
| 	 * That means that we'll have potentially 64 bits values where some | ||||
| 	 * userland apps only expect 32 (like X itself since it thinks only | ||||
| 	 * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||||
| 	 * 32 bits CHRPs :-( | ||||
| 	 * | ||||
| 	 * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||||
| 	 * has been fixed (and the fix spread enough), we can re-enable the | ||||
| 	 * 2 lines below and pass down a BAR value to userland. In that case | ||||
| 	 * we'll also have to re-enable the matching code in | ||||
| 	 * __pci_mmap_make_offset(). | ||||
| 	 * | ||||
| 	 * BenH. | ||||
| 	 */ | ||||
| #if 0 | ||||
| 	else if (rsrc->flags & IORESOURCE_MEM) | ||||
| 		offset = hose->pci_mem_offset; | ||||
| #endif | ||||
| 
 | ||||
| 	*start = rsrc->start - offset; | ||||
| 	*end = rsrc->end - offset; | ||||
| } | ||||
| 
 | ||||
| struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||||
| { | ||||
| 	if (!have_of) | ||||
| 		return NULL; | ||||
| 	while(node) { | ||||
| 		struct pci_controller *hose, *tmp; | ||||
| 		list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||||
| 			if (hose->arch_data == node) | ||||
| 				return hose; | ||||
| 		node = node->parent; | ||||
| 	} | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| unsigned long pci_address_to_pio(phys_addr_t address) | ||||
| { | ||||
| 	struct pci_controller *hose, *tmp; | ||||
| @ -1410,7 +912,7 @@ unsigned long pci_address_to_pio(phys_addr_t address) | ||||
| 		if (address >= hose->io_base_phys && | ||||
| 		    address < (hose->io_base_phys + hose->pci_io_size)) { | ||||
| 			unsigned long base = | ||||
| 				(unsigned long)hose->io_base_virt - pci_io_base; | ||||
| 				(unsigned long)hose->io_base_virt - _IO_BASE; | ||||
| 			return base + (address - hose->io_base_phys); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -67,7 +67,6 @@ EXPORT_SYMBOL(ISA_DMA_THRESHOLD); | ||||
| EXPORT_SYMBOL(DMA_MODE_READ); | ||||
| EXPORT_SYMBOL(DMA_MODE_WRITE); | ||||
| 
 | ||||
| EXPORT_SYMBOL(do_signal); | ||||
| EXPORT_SYMBOL(transfer_to_handler); | ||||
| EXPORT_SYMBOL(do_IRQ); | ||||
| EXPORT_SYMBOL(machine_check_exception); | ||||
| @ -106,10 +105,6 @@ EXPORT_SYMBOL(isa_mem_base); | ||||
| EXPORT_SYMBOL(pci_dram_offset); | ||||
| EXPORT_SYMBOL(pci_alloc_consistent); | ||||
| EXPORT_SYMBOL(pci_free_consistent); | ||||
| EXPORT_SYMBOL(pci_bus_io_base); | ||||
| EXPORT_SYMBOL(pci_bus_io_base_phys); | ||||
| EXPORT_SYMBOL(pci_bus_mem_base_phys); | ||||
| EXPORT_SYMBOL(pci_bus_to_hose); | ||||
| #endif /* CONFIG_PCI */ | ||||
| 
 | ||||
| EXPORT_SYMBOL(start_thread); | ||||
|  | ||||
| @ -219,22 +219,26 @@ void discard_lazy_cpu_state(void) | ||||
| } | ||||
| #endif /* CONFIG_SMP */ | ||||
| 
 | ||||
| #ifdef CONFIG_PPC_MERGE		/* XXX for now */ | ||||
| int set_dabr(unsigned long dabr) | ||||
| { | ||||
| #ifdef CONFIG_PPC_MERGE		/* XXX for now */ | ||||
| 	if (ppc_md.set_dabr) | ||||
| 		return ppc_md.set_dabr(dabr); | ||||
| #endif | ||||
| 
 | ||||
| 	/* XXX should we have a CPU_FTR_HAS_DABR ? */ | ||||
| #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) | ||||
| 	mtspr(SPRN_DABR, dabr); | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64 | ||||
| DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); | ||||
| static DEFINE_PER_CPU(unsigned long, current_dabr); | ||||
| #endif | ||||
| 
 | ||||
| static DEFINE_PER_CPU(unsigned long, current_dabr); | ||||
| 
 | ||||
| struct task_struct *__switch_to(struct task_struct *prev, | ||||
| 	struct task_struct *new) | ||||
| { | ||||
| @ -299,12 +303,10 @@ struct task_struct *__switch_to(struct task_struct *prev, | ||||
| 
 | ||||
| #endif /* CONFIG_SMP */ | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64	/* for now */ | ||||
| 	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { | ||||
| 		set_dabr(new->thread.dabr); | ||||
| 		__get_cpu_var(current_dabr) = new->thread.dabr; | ||||
| 	} | ||||
| #endif /* CONFIG_PPC64 */ | ||||
| 
 | ||||
| 	new_thread = &new->thread; | ||||
| 	old_thread = ¤t->thread; | ||||
| @ -473,12 +475,10 @@ void flush_thread(void) | ||||
| 
 | ||||
| 	discard_lazy_cpu_state(); | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64	/* for now */ | ||||
| 	if (current->thread.dabr) { | ||||
| 		current->thread.dabr = 0; | ||||
| 		set_dabr(0); | ||||
| 	} | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void | ||||
|  | ||||
| @ -52,6 +52,7 @@ | ||||
| #include <asm/pSeries_reconfig.h> | ||||
| #include <asm/pci-bridge.h> | ||||
| #include <asm/kexec.h> | ||||
| #include <asm/system.h> | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| #define DBG(fmt...) printk(KERN_ERR fmt) | ||||
| @ -1005,7 +1006,7 @@ static void __init early_reserve_mem(void) | ||||
| 
 | ||||
| void __init early_init_devtree(void *params) | ||||
| { | ||||
| 	DBG(" -> early_init_devtree()\n"); | ||||
| 	DBG(" -> early_init_devtree(%p)\n", params); | ||||
| 
 | ||||
| 	/* Setup flat device-tree pointer */ | ||||
| 	initial_boot_params = params; | ||||
| @ -1055,8 +1056,6 @@ void __init early_init_devtree(void *params) | ||||
| 	DBG(" <- early_init_devtree()\n"); | ||||
| } | ||||
| 
 | ||||
| #undef printk | ||||
| 
 | ||||
| int of_n_addr_cells(struct device_node* np) | ||||
| { | ||||
| 	const int *ip; | ||||
| @ -1375,8 +1374,17 @@ static void of_node_release(struct kref *kref) | ||||
| 	struct device_node *node = kref_to_device_node(kref); | ||||
| 	struct property *prop = node->properties; | ||||
| 
 | ||||
| 	if (!OF_IS_DYNAMIC(node)) | ||||
| 	/* We should never be releasing nodes that haven't been detached. */ | ||||
| 	if (!of_node_check_flag(node, OF_DETACHED)) { | ||||
| 		printk("WARNING: Bad of_node_put() on %s\n", node->full_name); | ||||
| 		dump_stack(); | ||||
| 		kref_init(&node->kref); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!of_node_check_flag(node, OF_DYNAMIC)) | ||||
| 		return; | ||||
| 
 | ||||
| 	while (prop) { | ||||
| 		struct property *next = prop->next; | ||||
| 		kfree(prop->name); | ||||
| @ -1432,6 +1440,8 @@ void of_detach_node(const struct device_node *np) | ||||
| 	write_lock(&devtree_lock); | ||||
| 
 | ||||
| 	parent = np->parent; | ||||
| 	if (!parent) | ||||
| 		goto out_unlock; | ||||
| 
 | ||||
| 	if (allnodes == np) | ||||
| 		allnodes = np->allnext; | ||||
| @ -1455,6 +1465,9 @@ void of_detach_node(const struct device_node *np) | ||||
| 		prevsib->sibling = np->sibling; | ||||
| 	} | ||||
| 
 | ||||
| 	of_node_set_flag(np, OF_DETACHED); | ||||
| 
 | ||||
| out_unlock: | ||||
| 	write_unlock(&devtree_lock); | ||||
| } | ||||
| 
 | ||||
| @ -1716,22 +1729,18 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | ||||
| } | ||||
| EXPORT_SYMBOL(of_get_cpu_node); | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) | ||||
| static struct debugfs_blob_wrapper flat_dt_blob; | ||||
| 
 | ||||
| static int __init export_flat_device_tree(void) | ||||
| { | ||||
| 	struct dentry *d; | ||||
| 
 | ||||
| 	d = debugfs_create_dir("powerpc", NULL); | ||||
| 	if (!d) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	flat_dt_blob.data = initial_boot_params; | ||||
| 	flat_dt_blob.size = initial_boot_params->totalsize; | ||||
| 
 | ||||
| 	d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, | ||||
| 				d, &flat_dt_blob); | ||||
| 				powerpc_debugfs_root, &flat_dt_blob); | ||||
| 	if (!d) | ||||
| 		return 1; | ||||
| 
 | ||||
|  | ||||
| @ -635,6 +635,7 @@ static void __init early_cmdline_parse(void) | ||||
| /* ibm,dynamic-reconfiguration-memory property supported */ | ||||
| #define OV5_DRCONF_MEMORY	0x20 | ||||
| #define OV5_LARGE_PAGES		0x10	/* large pages supported */ | ||||
| #define OV5_DONATE_DEDICATE_CPU 0x02	/* donate dedicated CPU support */ | ||||
| /* PCIe/MSI support.  Without MSI full PCIe is not supported */ | ||||
| #ifdef CONFIG_PCI_MSI | ||||
| #define OV5_MSI			0x01	/* PCIe/MSI support */ | ||||
| @ -685,7 +686,8 @@ static unsigned char ibm_architecture_vec[] = { | ||||
| 	/* option vector 5: PAPR/OF options */ | ||||
| 	3 - 2,				/* length */ | ||||
| 	0,				/* don't ignore, don't halt */ | ||||
| 	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI, | ||||
| 	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | | ||||
| 	OV5_DONATE_DEDICATE_CPU | OV5_MSI, | ||||
| }; | ||||
| 
 | ||||
| /* Old method - ELF header with PT_NOTE sections */ | ||||
|  | ||||
| @ -1,161 +0,0 @@ | ||||
| /*
 | ||||
|  *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration | ||||
|  *    Extracted from ptrace.c and ptrace32.c | ||||
|  * | ||||
|  * This file is subject to the terms and conditions of the GNU General | ||||
|  * Public License.  See the file README.legal in the main directory of | ||||
|  * this archive for more details. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _PPC64_PTRACE_COMMON_H | ||||
| #define _PPC64_PTRACE_COMMON_H | ||||
| 
 | ||||
| #include <asm/system.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Set of msr bits that gdb can change on behalf of a process. | ||||
|  */ | ||||
| #define MSR_DEBUGCHANGE	(MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) | ||||
| 
 | ||||
| /*
 | ||||
|  * Get contents of register REGNO in task TASK. | ||||
|  */ | ||||
| static inline unsigned long get_reg(struct task_struct *task, int regno) | ||||
| { | ||||
| 	unsigned long tmp = 0; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Put the correct FP bits in, they might be wrong as a result | ||||
| 	 * of our lazy FP restore. | ||||
| 	 */ | ||||
| 	if (regno == PT_MSR) { | ||||
| 		tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | ||||
| 		tmp |= task->thread.fpexc_mode; | ||||
| 	} else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { | ||||
| 		tmp = ((unsigned long *)task->thread.regs)[regno]; | ||||
| 	} | ||||
| 
 | ||||
| 	return tmp; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Write contents of register REGNO in task TASK. | ||||
|  */ | ||||
| static inline int put_reg(struct task_struct *task, int regno, | ||||
| 			  unsigned long data) | ||||
| { | ||||
| 	if (regno < PT_SOFTE) { | ||||
| 		if (regno == PT_MSR) | ||||
| 			data = (data & MSR_DEBUGCHANGE) | ||||
| 				| (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||||
| 		((unsigned long *)task->thread.regs)[regno] = data; | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return -EIO; | ||||
| } | ||||
| 
 | ||||
| static inline void set_single_step(struct task_struct *task) | ||||
| { | ||||
| 	struct pt_regs *regs = task->thread.regs; | ||||
| 	if (regs != NULL) | ||||
| 		regs->msr |= MSR_SE; | ||||
| 	set_tsk_thread_flag(task, TIF_SINGLESTEP); | ||||
| } | ||||
| 
 | ||||
| static inline void clear_single_step(struct task_struct *task) | ||||
| { | ||||
| 	struct pt_regs *regs = task->thread.regs; | ||||
| 	if (regs != NULL) | ||||
| 		regs->msr &= ~MSR_SE; | ||||
| 	clear_tsk_thread_flag(task, TIF_SINGLESTEP); | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_ALTIVEC | ||||
| /*
 | ||||
|  * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. | ||||
|  * The transfer totals 34 quadword.  Quadwords 0-31 contain the | ||||
|  * corresponding vector registers.  Quadword 32 contains the vscr as the | ||||
|  * last word (offset 12) within that quadword.  Quadword 33 contains the | ||||
|  * vrsave as the first word (offset 0) within the quadword. | ||||
|  * | ||||
|  * This definition of the VMX state is compatible with the current PPC32 | ||||
|  * ptrace interface.  This allows signal handling and ptrace to use the | ||||
|  * same structures.  This also simplifies the implementation of a bi-arch | ||||
|  * (combined (32- and 64-bit) gdb. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Get contents of AltiVec register state in task TASK | ||||
|  */ | ||||
| static inline int get_vrregs(unsigned long __user *data, | ||||
| 			     struct task_struct *task) | ||||
| { | ||||
| 	unsigned long regsize; | ||||
| 
 | ||||
| 	/* copy AltiVec registers VR[0] .. VR[31] */ | ||||
| 	regsize = 32 * sizeof(vector128); | ||||
| 	if (copy_to_user(data, task->thread.vr, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
| 	/* copy VSCR */ | ||||
| 	regsize = 1 * sizeof(vector128); | ||||
| 	if (copy_to_user(data, &task->thread.vscr, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
| 	/* copy VRSAVE */ | ||||
| 	if (put_user(task->thread.vrsave, (u32 __user *)data)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Write contents of AltiVec register state into task TASK. | ||||
|  */ | ||||
| static inline int set_vrregs(struct task_struct *task, | ||||
| 			     unsigned long __user *data) | ||||
| { | ||||
| 	unsigned long regsize; | ||||
| 
 | ||||
| 	/* copy AltiVec registers VR[0] .. VR[31] */ | ||||
| 	regsize = 32 * sizeof(vector128); | ||||
| 	if (copy_from_user(task->thread.vr, data, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
| 	/* copy VSCR */ | ||||
| 	regsize = 1 * sizeof(vector128); | ||||
| 	if (copy_from_user(&task->thread.vscr, data, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
| 	/* copy VRSAVE */ | ||||
| 	if (get_user(task->thread.vrsave, (u32 __user *)data)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static inline int ptrace_set_debugreg(struct task_struct *task, | ||||
| 				      unsigned long addr, unsigned long data) | ||||
| { | ||||
| 	/* We only support one DABR and no IABRS at the moment */ | ||||
| 	if (addr > 0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* The bottom 3 bits are flags */ | ||||
| 	if ((data & ~0x7UL) >= TASK_SIZE) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	/* Ensure translation is on */ | ||||
| 	if (data && !(data & DABR_TRANSLATION)) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	task->thread.dabr = data; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #endif /* _PPC64_PTRACE_COMMON_H */ | ||||
| @ -35,11 +35,11 @@ | ||||
| #include <asm/pgtable.h> | ||||
| #include <asm/system.h> | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64 | ||||
| #include "ptrace-common.h" | ||||
| #endif | ||||
| /*
 | ||||
|  * does not yet catch signals sent when the child dies. | ||||
|  * in exit.c or in signal.c. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef CONFIG_PPC32 | ||||
| /*
 | ||||
|  * Set of msr bits that gdb can change on behalf of a process. | ||||
|  */ | ||||
| @ -48,65 +48,117 @@ | ||||
| #else | ||||
| #define MSR_DEBUGCHANGE	(MSR_SE | MSR_BE) | ||||
| #endif | ||||
| #endif /* CONFIG_PPC32 */ | ||||
| 
 | ||||
| /*
 | ||||
|  * does not yet catch signals sent when the child dies. | ||||
|  * in exit.c or in signal.c. | ||||
|  * Max register writeable via put_reg | ||||
|  */ | ||||
| 
 | ||||
| #ifdef CONFIG_PPC32 | ||||
| #define PT_MAX_PUT_REG	PT_MQ | ||||
| #else | ||||
| #define PT_MAX_PUT_REG	PT_CCR | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * Get contents of register REGNO in task TASK. | ||||
|  */ | ||||
| static inline unsigned long get_reg(struct task_struct *task, int regno) | ||||
| unsigned long ptrace_get_reg(struct task_struct *task, int regno) | ||||
| { | ||||
| 	if (regno < sizeof(struct pt_regs) / sizeof(unsigned long) | ||||
| 	    && task->thread.regs != NULL) | ||||
| 	unsigned long tmp = 0; | ||||
| 
 | ||||
| 	if (task->thread.regs == NULL) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	if (regno == PT_MSR) { | ||||
| 		tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | ||||
| 		return tmp | task->thread.fpexc_mode; | ||||
| 	} | ||||
| 
 | ||||
| 	if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) | ||||
| 		return ((unsigned long *)task->thread.regs)[regno]; | ||||
| 	return (0); | ||||
| 
 | ||||
| 	return -EIO; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Write contents of register REGNO in task TASK. | ||||
|  */ | ||||
| static inline int put_reg(struct task_struct *task, int regno, | ||||
| 			  unsigned long data) | ||||
| int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) | ||||
| { | ||||
| 	if (regno <= PT_MQ && task->thread.regs != NULL) { | ||||
| 	if (task->thread.regs == NULL) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) { | ||||
| 		if (regno == PT_MSR) | ||||
| 			data = (data & MSR_DEBUGCHANGE) | ||||
| 				| (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||||
| 		/* We prevent mucking around with the reserved area of trap
 | ||||
| 		 * which are used internally by the kernel | ||||
| 		 */ | ||||
| 		if (regno == PT_TRAP) | ||||
| 			data &= 0xfff0; | ||||
| 		((unsigned long *)task->thread.regs)[regno] = data; | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return -EIO; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int get_fpregs(void __user *data, struct task_struct *task, | ||||
| 		      int has_fpscr) | ||||
| { | ||||
| 	unsigned int count = has_fpscr ? 33 : 32; | ||||
| 
 | ||||
| 	if (copy_to_user(data, task->thread.fpr, count * sizeof(double))) | ||||
| 		return -EFAULT; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int set_fpregs(void __user *data, struct task_struct *task, | ||||
| 		      int has_fpscr) | ||||
| { | ||||
| 	unsigned int count = has_fpscr ? 33 : 32; | ||||
| 
 | ||||
| 	if (copy_from_user(task->thread.fpr, data, count * sizeof(double))) | ||||
| 		return -EFAULT; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef CONFIG_ALTIVEC | ||||
| /*
 | ||||
|  * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. | ||||
|  * The transfer totals 34 quadword.  Quadwords 0-31 contain the | ||||
|  * corresponding vector registers.  Quadword 32 contains the vscr as the | ||||
|  * last word (offset 12) within that quadword.  Quadword 33 contains the | ||||
|  * vrsave as the first word (offset 0) within the quadword. | ||||
|  * | ||||
|  * This definition of the VMX state is compatible with the current PPC32 | ||||
|  * ptrace interface.  This allows signal handling and ptrace to use the | ||||
|  * same structures.  This also simplifies the implementation of a bi-arch | ||||
|  * (combined (32- and 64-bit) gdb. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Get contents of AltiVec register state in task TASK | ||||
|  */ | ||||
| static inline int get_vrregs(unsigned long __user *data, struct task_struct *task) | ||||
| static int get_vrregs(unsigned long __user *data, struct task_struct *task) | ||||
| { | ||||
| 	int i, j; | ||||
| 
 | ||||
| 	if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long))) | ||||
| 		return -EFAULT; | ||||
| 	unsigned long regsize; | ||||
| 
 | ||||
| 	/* copy AltiVec registers VR[0] .. VR[31] */ | ||||
| 	for (i = 0; i < 32; i++) | ||||
| 		for (j = 0; j < 4; j++, data++) | ||||
| 			if (__put_user(task->thread.vr[i].u[j], data)) | ||||
| 				return -EFAULT; | ||||
| 	regsize = 32 * sizeof(vector128); | ||||
| 	if (copy_to_user(data, task->thread.vr, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
| 	/* copy VSCR */ | ||||
| 	for (i = 0; i < 4; i++, data++) | ||||
| 		if (__put_user(task->thread.vscr.u[i], data)) | ||||
| 			return -EFAULT; | ||||
| 	regsize = 1 * sizeof(vector128); | ||||
| 	if (copy_to_user(data, &task->thread.vscr, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
|         /* copy VRSAVE */ | ||||
| 	if (__put_user(task->thread.vrsave, data)) | ||||
| 	/* copy VRSAVE */ | ||||
| 	if (put_user(task->thread.vrsave, (u32 __user *)data)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return 0; | ||||
| @ -115,31 +167,29 @@ static inline int get_vrregs(unsigned long __user *data, struct task_struct *tas | ||||
| /*
 | ||||
|  * Write contents of AltiVec register state into task TASK. | ||||
|  */ | ||||
| static inline int set_vrregs(struct task_struct *task, unsigned long __user *data) | ||||
| static int set_vrregs(struct task_struct *task, unsigned long __user *data) | ||||
| { | ||||
| 	int i, j; | ||||
| 
 | ||||
| 	if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long))) | ||||
| 		return -EFAULT; | ||||
| 	unsigned long regsize; | ||||
| 
 | ||||
| 	/* copy AltiVec registers VR[0] .. VR[31] */ | ||||
| 	for (i = 0; i < 32; i++) | ||||
| 		for (j = 0; j < 4; j++, data++) | ||||
| 			if (__get_user(task->thread.vr[i].u[j], data)) | ||||
| 				return -EFAULT; | ||||
| 	regsize = 32 * sizeof(vector128); | ||||
| 	if (copy_from_user(task->thread.vr, data, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
| 	/* copy VSCR */ | ||||
| 	for (i = 0; i < 4; i++, data++) | ||||
| 		if (__get_user(task->thread.vscr.u[i], data)) | ||||
| 			return -EFAULT; | ||||
| 	regsize = 1 * sizeof(vector128); | ||||
| 	if (copy_from_user(&task->thread.vscr, data, regsize)) | ||||
| 		return -EFAULT; | ||||
| 	data += (regsize / sizeof(unsigned long)); | ||||
| 
 | ||||
| 	/* copy VRSAVE */ | ||||
| 	if (__get_user(task->thread.vrsave, data)) | ||||
| 	if (get_user(task->thread.vrsave, (u32 __user *)data)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
| #endif /* CONFIG_ALTIVEC */ | ||||
| 
 | ||||
| #ifdef CONFIG_SPE | ||||
| 
 | ||||
| @ -156,7 +206,7 @@ static inline int set_vrregs(struct task_struct *task, unsigned long __user *dat | ||||
| /*
 | ||||
|  * Get contents of SPE register state in task TASK. | ||||
|  */ | ||||
| static inline int get_evrregs(unsigned long *data, struct task_struct *task) | ||||
| static int get_evrregs(unsigned long *data, struct task_struct *task) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| @ -182,7 +232,7 @@ static inline int get_evrregs(unsigned long *data, struct task_struct *task) | ||||
| /*
 | ||||
|  * Write contents of SPE register state into task TASK. | ||||
|  */ | ||||
| static inline int set_evrregs(struct task_struct *task, unsigned long *data) | ||||
| static int set_evrregs(struct task_struct *task, unsigned long *data) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| @ -205,8 +255,8 @@ static inline int set_evrregs(struct task_struct *task, unsigned long *data) | ||||
| } | ||||
| #endif /* CONFIG_SPE */ | ||||
| 
 | ||||
| static inline void | ||||
| set_single_step(struct task_struct *task) | ||||
| 
 | ||||
| static void set_single_step(struct task_struct *task) | ||||
| { | ||||
| 	struct pt_regs *regs = task->thread.regs; | ||||
| 
 | ||||
| @ -221,8 +271,7 @@ set_single_step(struct task_struct *task) | ||||
| 	set_tsk_thread_flag(task, TIF_SINGLESTEP); | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| clear_single_step(struct task_struct *task) | ||||
| static void clear_single_step(struct task_struct *task) | ||||
| { | ||||
| 	struct pt_regs *regs = task->thread.regs; | ||||
| 
 | ||||
| @ -236,7 +285,25 @@ clear_single_step(struct task_struct *task) | ||||
| 	} | ||||
| 	clear_tsk_thread_flag(task, TIF_SINGLESTEP); | ||||
| } | ||||
| #endif /* CONFIG_PPC32 */ | ||||
| 
 | ||||
| static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | ||||
| 			       unsigned long data) | ||||
| { | ||||
| 	/* We only support one DABR and no IABRS at the moment */ | ||||
| 	if (addr > 0) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* The bottom 3 bits are flags */ | ||||
| 	if ((data & ~0x7UL) >= TASK_SIZE) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	/* Ensure translation is on */ | ||||
| 	if (data && !(data & DABR_TRANSLATION)) | ||||
| 		return -EIO; | ||||
| 
 | ||||
| 	task->thread.dabr = data; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Called by kernel/ptrace.c when detaching.. | ||||
| @ -249,6 +316,62 @@ void ptrace_disable(struct task_struct *child) | ||||
| 	clear_single_step(child); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, | ||||
|  * we mark them as obsolete now, they will be removed in a future version | ||||
|  */ | ||||
| static long arch_ptrace_old(struct task_struct *child, long request, long addr, | ||||
| 			    long data) | ||||
| { | ||||
| 	int ret = -EPERM; | ||||
| 
 | ||||
| 	switch(request) { | ||||
| 	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned long __user *tmp = (unsigned long __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = put_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned long __user *tmp = (unsigned long __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = get_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | ||||
| 		flush_fp_to_thread(child); | ||||
| 		ret = get_fpregs((void __user *)addr, child, 0); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||||
| 		flush_fp_to_thread(child); | ||||
| 		ret = set_fpregs((void __user *)addr, child, 0); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| long arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||||
| { | ||||
| 	int ret = -EPERM; | ||||
| @ -284,11 +407,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||||
| #endif | ||||
| 			break; | ||||
| 
 | ||||
| #ifdef CONFIG_PPC32 | ||||
| 		CHECK_FULL_REGS(child->thread.regs); | ||||
| #endif | ||||
| 		if (index < PT_FPR0) { | ||||
| 			tmp = get_reg(child, (int) index); | ||||
| 			tmp = ptrace_get_reg(child, (int) index); | ||||
| 		} else { | ||||
| 			flush_fp_to_thread(child); | ||||
| 			tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; | ||||
| @ -323,13 +444,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||||
| #endif | ||||
| 			break; | ||||
| 
 | ||||
| #ifdef CONFIG_PPC32 | ||||
| 		CHECK_FULL_REGS(child->thread.regs); | ||||
| #endif | ||||
| 		if (index == PT_ORIG_R3) | ||||
| 			break; | ||||
| 		if (index < PT_FPR0) { | ||||
| 			ret = put_reg(child, index, data); | ||||
| 			ret = ptrace_put_reg(child, index, data); | ||||
| 		} else { | ||||
| 			flush_fp_to_thread(child); | ||||
| 			((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; | ||||
| @ -384,7 +501,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64 | ||||
| 	case PTRACE_GET_DEBUGREG: { | ||||
| 		ret = -EINVAL; | ||||
| 		/* We only support one DABR and no IABRS at the moment */ | ||||
| @ -398,73 +514,61 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||||
| 	case PTRACE_SET_DEBUGREG: | ||||
| 		ret = ptrace_set_debugreg(child, addr, data); | ||||
| 		break; | ||||
| #endif | ||||
| 
 | ||||
| 	case PTRACE_DETACH: | ||||
| 		ret = ptrace_detach(child, data); | ||||
| 		break; | ||||
| 
 | ||||
| 	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned long __user *tmp = (unsigned long __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = put_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| #ifdef CONFIG_PPC64 | ||||
| 	case PTRACE_GETREGS64: | ||||
| #endif | ||||
| 	case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ | ||||
| 		int ui; | ||||
| 	  	if (!access_ok(VERIFY_WRITE, (void __user *)data, | ||||
| 			       sizeof(struct pt_regs))) { | ||||
| 			ret = -EIO; | ||||
| 			break; | ||||
| 		} | ||||
| 		ret = 0; | ||||
| 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||||
| 			ret |= __put_user(ptrace_get_reg(child, ui), | ||||
| 					  (unsigned long __user *) data); | ||||
| 			data += sizeof(long); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned long __user *tmp = (unsigned long __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = get_user(*reg, tmp); | ||||
| #ifdef CONFIG_PPC64 | ||||
| 	case PTRACE_SETREGS64: | ||||
| #endif | ||||
| 	case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | ||||
| 		unsigned long tmp; | ||||
| 		int ui; | ||||
| 	  	if (!access_ok(VERIFY_READ, (void __user *)data, | ||||
| 			       sizeof(struct pt_regs))) { | ||||
| 			ret = -EIO; | ||||
| 			break; | ||||
| 		} | ||||
| 		ret = 0; | ||||
| 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||||
| 			ret = __get_user(tmp, (unsigned long __user *) data); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 			ptrace_put_reg(child, ui, tmp); | ||||
| 			data += sizeof(long); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||||
| 		unsigned long __user *tmp = (unsigned long __user *)addr; | ||||
| 
 | ||||
| 	case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */ | ||||
| 		flush_fp_to_thread(child); | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = put_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		ret = get_fpregs((void __user *)data, child, 1); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||||
| 		unsigned long __user *tmp = (unsigned long __user *)addr; | ||||
| 
 | ||||
| 	case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */ | ||||
| 		flush_fp_to_thread(child); | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = get_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		ret = set_fpregs((void __user *)data, child, 1); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| @ -499,11 +603,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||||
| 		break; | ||||
| #endif | ||||
| 
 | ||||
| 	/* Old reverse args ptrace callss */ | ||||
| 	case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | ||||
| 	case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ | ||||
| 	case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ | ||||
| 	case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */ | ||||
| 		ret = arch_ptrace_old(child, request, addr, data); | ||||
| 		break; | ||||
| 
 | ||||
| 	default: | ||||
| 		ret = ptrace_request(child, request, addr, data); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -33,13 +33,55 @@ | ||||
| #include <asm/pgtable.h> | ||||
| #include <asm/system.h> | ||||
| 
 | ||||
| #include "ptrace-common.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * does not yet catch signals sent when the child dies. | ||||
|  * in exit.c or in signal.c. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, | ||||
|  * we mark them as obsolete now, they will be removed in a future version | ||||
|  */ | ||||
| static long compat_ptrace_old(struct task_struct *child, long request, | ||||
| 			      long addr, long data) | ||||
| { | ||||
| 	int ret = -EPERM; | ||||
| 
 | ||||
| 	switch(request) { | ||||
| 	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned int __user *tmp = (unsigned int __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = put_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned int __user *tmp = (unsigned int __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = get_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| long compat_sys_ptrace(int request, int pid, unsigned long addr, | ||||
| 		       unsigned long data) | ||||
| { | ||||
| @ -123,7 +165,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | ||||
| 			break; | ||||
| 
 | ||||
| 		if (index < PT_FPR0) { | ||||
| 			tmp = get_reg(child, index); | ||||
| 			tmp = ptrace_get_reg(child, index); | ||||
| 		} else { | ||||
| 			flush_fp_to_thread(child); | ||||
| 			/*
 | ||||
| @ -162,7 +204,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | ||||
| 		else | ||||
| 			part = 0;  /* want the 1st half of the register (left-most). */ | ||||
| 
 | ||||
| 		/* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ | ||||
| 		/* Validate the input - check to see if address is on the wrong boundary
 | ||||
| 		 * or beyond the end of the user area | ||||
| 		 */ | ||||
| 		if ((addr & 3) || numReg > PT_FPSCR) | ||||
| 			break; | ||||
| 
 | ||||
| @ -170,7 +214,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | ||||
| 			flush_fp_to_thread(child); | ||||
| 			tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; | ||||
| 		} else { /* register within PT_REGS struct */ | ||||
| 			tmp = get_reg(child, numReg); | ||||
| 			tmp = ptrace_get_reg(child, numReg); | ||||
| 		}  | ||||
| 		reg32bits = ((u32*)&tmp)[part]; | ||||
| 		ret = put_user(reg32bits, (u32 __user *)data); | ||||
| @ -226,10 +270,8 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | ||||
| 		if ((addr & 3) || (index > PT_FPSCR32)) | ||||
| 			break; | ||||
| 
 | ||||
| 		if (index == PT_ORIG_R3) | ||||
| 			break; | ||||
| 		if (index < PT_FPR0) { | ||||
| 			ret = put_reg(child, index, data); | ||||
| 			ret = ptrace_put_reg(child, index, data); | ||||
| 		} else { | ||||
| 			flush_fp_to_thread(child); | ||||
| 			/*
 | ||||
| @ -258,70 +300,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | ||||
| 		/* Determine which register the user wants */ | ||||
| 		index = (u64)addr >> 2; | ||||
| 		numReg = index / 2; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Validate the input - check to see if address is on the | ||||
| 		 * wrong boundary or beyond the end of the user area | ||||
| 		 */ | ||||
| 		if ((addr & 3) || (numReg > PT_FPSCR)) | ||||
| 			break; | ||||
| 		/* Insure it is a register we let them change */ | ||||
| 		if ((numReg == PT_ORIG_R3) | ||||
| 				|| ((numReg > PT_CCR) && (numReg < PT_FPR0))) | ||||
| 			break; | ||||
| 		if (numReg >= PT_FPR0) { | ||||
| 		if (numReg < PT_FPR0) { | ||||
| 			unsigned long freg = ptrace_get_reg(child, numReg); | ||||
| 			if (index % 2) | ||||
| 				freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); | ||||
| 			else | ||||
| 				freg = (freg & 0xfffffffful) | (data << 32); | ||||
| 			ret = ptrace_put_reg(child, numReg, freg); | ||||
| 		} else { | ||||
| 			flush_fp_to_thread(child); | ||||
| 			((unsigned int *)child->thread.regs)[index] = data; | ||||
| 			ret = 0; | ||||
| 		} | ||||
| 		if (numReg == PT_MSR) | ||||
| 			data = (data & MSR_DEBUGCHANGE) | ||||
| 				| (child->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||||
| 		((u32*)child->thread.regs)[index] = data; | ||||
| 		ret = 0; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||||
| 	case PTRACE_CONT: { /* restart after signal. */ | ||||
| 		ret = -EIO; | ||||
| 		if (!valid_signal(data)) | ||||
| 			break; | ||||
| 		if (request == PTRACE_SYSCALL) | ||||
| 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||||
| 		else | ||||
| 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||||
| 		child->exit_code = data; | ||||
| 		/* make sure the single step bit is not set. */ | ||||
| 		clear_single_step(child); | ||||
| 		wake_up_process(child); | ||||
| 		ret = 0; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * make the child exit.  Best I can do is send it a sigkill. | ||||
| 	 * perhaps it should be put in the status that it wants to | ||||
| 	 * exit. | ||||
| 	 */ | ||||
| 	case PTRACE_KILL: { | ||||
| 		ret = 0; | ||||
| 		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */ | ||||
| 			break; | ||||
| 		child->exit_code = SIGKILL; | ||||
| 		/* make sure the single step bit is not set. */ | ||||
| 		clear_single_step(child); | ||||
| 		wake_up_process(child); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */ | ||||
| 		ret = -EIO; | ||||
| 		if (!valid_signal(data)) | ||||
| 			break; | ||||
| 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||||
| 		set_single_step(child); | ||||
| 		child->exit_code = data; | ||||
| 		/* give it a chance to run. */ | ||||
| 		wake_up_process(child); | ||||
| 		ret = 0; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| @ -334,95 +331,67 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PTRACE_SET_DEBUGREG: | ||||
| 		ret = ptrace_set_debugreg(child, addr, data); | ||||
| 		break; | ||||
| 
 | ||||
| 	case PTRACE_DETACH: | ||||
| 		ret = ptrace_detach(child, data); | ||||
| 		break; | ||||
| 
 | ||||
| 	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned int __user *tmp = (unsigned int __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = put_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||||
| 		unsigned int __user *tmp = (unsigned int __user *)addr; | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = get_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||||
| 		unsigned int __user *tmp = (unsigned int __user *)addr; | ||||
| 
 | ||||
| 		flush_fp_to_thread(child); | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = put_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||||
| 		int i; | ||||
| 		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||||
| 		unsigned int __user *tmp = (unsigned int __user *)addr; | ||||
| 
 | ||||
| 		flush_fp_to_thread(child); | ||||
| 
 | ||||
| 		for (i = 0; i < 32; i++) { | ||||
| 			ret = get_user(*reg, tmp); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			reg++; | ||||
| 			tmp++; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PTRACE_GETEVENTMSG: | ||||
| 		ret = put_user(child->ptrace_message, (unsigned int __user *) data); | ||||
| 		break; | ||||
| 
 | ||||
| #ifdef CONFIG_ALTIVEC | ||||
| 	case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ | ||||
| 		int ui; | ||||
| 	  	if (!access_ok(VERIFY_WRITE, (void __user *)data, | ||||
| 			       PT_REGS_COUNT * sizeof(int))) { | ||||
| 			ret = -EIO; | ||||
| 			break; | ||||
| 		} | ||||
| 		ret = 0; | ||||
| 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||||
| 			ret |= __put_user(ptrace_get_reg(child, ui), | ||||
| 					  (unsigned int __user *) data); | ||||
| 			data += sizeof(int); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | ||||
| 		unsigned long tmp; | ||||
| 		int ui; | ||||
| 	  	if (!access_ok(VERIFY_READ, (void __user *)data, | ||||
| 			       PT_REGS_COUNT * sizeof(int))) { | ||||
| 			ret = -EIO; | ||||
| 			break; | ||||
| 		} | ||||
| 		ret = 0; | ||||
| 		for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||||
| 			ret = __get_user(tmp, (unsigned int __user *) data); | ||||
| 			if (ret) | ||||
| 				break; | ||||
| 			ptrace_put_reg(child, ui, tmp); | ||||
| 			data += sizeof(int); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	case PTRACE_GETFPREGS: | ||||
| 	case PTRACE_SETFPREGS: | ||||
| 	case PTRACE_GETVRREGS: | ||||
| 		/* Get the child altivec register state. */ | ||||
| 		flush_altivec_to_thread(child); | ||||
| 		ret = get_vrregs((unsigned long __user *)data, child); | ||||
| 	case PTRACE_SETVRREGS: | ||||
| 	case PTRACE_GETREGS64: | ||||
| 	case PTRACE_SETREGS64: | ||||
| 	case PPC_PTRACE_GETFPREGS: | ||||
| 	case PPC_PTRACE_SETFPREGS: | ||||
| 	case PTRACE_KILL: | ||||
| 	case PTRACE_SINGLESTEP: | ||||
| 	case PTRACE_DETACH: | ||||
| 	case PTRACE_SET_DEBUGREG: | ||||
| 	case PTRACE_SYSCALL: | ||||
| 	case PTRACE_CONT: | ||||
| 		ret = arch_ptrace(child, request, addr, data); | ||||
| 		break; | ||||
| 
 | ||||
| 	case PTRACE_SETVRREGS: | ||||
| 		/* Set the child altivec register state. */ | ||||
| 		flush_altivec_to_thread(child); | ||||
| 		ret = set_vrregs(child, (unsigned long __user *)data); | ||||
| 	/* Old reverse args ptrace callss */ | ||||
| 	case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | ||||
| 	case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ | ||||
| 		ret = compat_ptrace_old(child, request, addr, data); | ||||
| 		break; | ||||
| #endif | ||||
| 
 | ||||
| 	default: | ||||
| 		ret = ptrace_request(child, request, addr, data); | ||||
|  | ||||
| @ -278,10 +278,8 @@ void __init find_and_init_phbs(void) | ||||
| { | ||||
| 	struct device_node *node; | ||||
| 	struct pci_controller *phb; | ||||
| 	unsigned int index; | ||||
| 	struct device_node *root = of_find_node_by_path("/"); | ||||
| 
 | ||||
| 	index = 0; | ||||
| 	for (node = of_get_next_child(root, NULL); | ||||
| 	     node != NULL; | ||||
| 	     node = of_get_next_child(root, node)) { | ||||
| @ -295,8 +293,7 @@ void __init find_and_init_phbs(void) | ||||
| 			continue; | ||||
| 		rtas_setup_phb(phb); | ||||
| 		pci_process_bridge_OF_ranges(phb, node, 0); | ||||
| 		pci_setup_phb_io(phb, index == 0); | ||||
| 		index++; | ||||
| 		isa_bridge_find_early(phb); | ||||
| 	} | ||||
| 
 | ||||
| 	of_node_put(root); | ||||
| @ -335,7 +332,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb) | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	rc = unmap_bus_range(b); | ||||
| 	rc = pcibios_unmap_io_space(b); | ||||
| 	if (rc) { | ||||
| 		printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", | ||||
| 			__FUNCTION__, b->name); | ||||
|  | ||||
| @ -32,6 +32,7 @@ | ||||
| #include <linux/unistd.h> | ||||
| #include <linux/serial.h> | ||||
| #include <linux/serial_8250.h> | ||||
| #include <linux/debugfs.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/prom.h> | ||||
| #include <asm/processor.h> | ||||
| @ -486,6 +487,14 @@ int check_legacy_ioport(unsigned long base_port) | ||||
| 
 | ||||
| 	switch(base_port) { | ||||
| 	case I8042_DATA_REG: | ||||
| 		if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303"))) | ||||
| 			np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03"); | ||||
| 		if (np) { | ||||
| 			parent = of_get_parent(np); | ||||
| 			of_node_put(np); | ||||
| 			np = parent; | ||||
| 			break; | ||||
| 		} | ||||
| 		np = of_find_node_by_type(NULL, "8042"); | ||||
| 		break; | ||||
| 	case FDC_BASE: /* FDC1 */ | ||||
| @ -571,3 +580,15 @@ static int __init check_cache_coherency(void) | ||||
| 
 | ||||
| late_initcall(check_cache_coherency); | ||||
| #endif /* CONFIG_CHECK_CACHE_COHERENCY */ | ||||
| 
 | ||||
| #ifdef CONFIG_DEBUG_FS | ||||
| struct dentry *powerpc_debugfs_root; | ||||
| 
 | ||||
| static int powerpc_debugfs_init(void) | ||||
| { | ||||
| 	powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL); | ||||
| 
 | ||||
| 	return powerpc_debugfs_root == NULL; | ||||
| } | ||||
| arch_initcall(powerpc_debugfs_init); | ||||
| #endif | ||||
|  | ||||
| @ -262,13 +262,11 @@ void __init setup_arch(char **cmdline_p) | ||||
| 	 * Systems with OF can look in the properties on the cpu node(s) | ||||
| 	 * for a possibly more accurate value. | ||||
| 	 */ | ||||
| 	if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { | ||||
| 		dcache_bsize = cur_cpu_spec->dcache_bsize; | ||||
| 		icache_bsize = cur_cpu_spec->icache_bsize; | ||||
| 		ucache_bsize = 0; | ||||
| 	} else | ||||
| 		ucache_bsize = dcache_bsize = icache_bsize | ||||
| 			= cur_cpu_spec->dcache_bsize; | ||||
| 	dcache_bsize = cur_cpu_spec->dcache_bsize; | ||||
| 	icache_bsize = cur_cpu_spec->icache_bsize; | ||||
| 	ucache_bsize = 0; | ||||
| 	if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) | ||||
| 		ucache_bsize = icache_bsize = dcache_bsize; | ||||
| 
 | ||||
| 	/* reboot on panic */ | ||||
| 	panic_timeout = 180; | ||||
|  | ||||
| @ -350,13 +350,11 @@ void __init setup_system(void) | ||||
| { | ||||
| 	DBG(" -> setup_system()\n"); | ||||
| 
 | ||||
| 	/* Apply the CPUs-specific and firmware specific fixups to kernel
 | ||||
| 	 * text (nop out sections not relevant to this CPU or this firmware) | ||||
| 	/* Apply CPUs-specific fixups to kernel text (nop out sections
 | ||||
| 	 * not relevant to this CPU) | ||||
| 	 */ | ||||
| 	do_feature_fixups(cur_cpu_spec->cpu_features, | ||||
| 			  &__start___ftr_fixup, &__stop___ftr_fixup); | ||||
| 	do_feature_fixups(powerpc_firmware_features, | ||||
| 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Unflatten the device-tree passed by prom_init or kexec | ||||
| @ -394,6 +392,12 @@ void __init setup_system(void) | ||||
| 	if (ppc_md.init_early) | ||||
| 		ppc_md.init_early(); | ||||
| 
 | ||||
| 	/* Apply firmware specific fixups to kernel text (nop out
 | ||||
| 	 * sections not relevant to this firmware) | ||||
| 	 */ | ||||
| 	do_feature_fixups(powerpc_firmware_features, | ||||
| 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); | ||||
| 
 | ||||
|  	/*
 | ||||
| 	 * We can discover serial ports now since the above did setup the | ||||
| 	 * hash table management for us, thus ioremap works. We do that early | ||||
|  | ||||
							
								
								
									
										180
									
								
								arch/powerpc/kernel/signal.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								arch/powerpc/kernel/signal.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,180 @@ | ||||
| /*
 | ||||
|  * Common signal handling code for both 32 and 64 bits | ||||
|  * | ||||
|  *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration | ||||
|  *    Extracted from signal_32.c and signal_64.c | ||||
|  * | ||||
|  * This file is subject to the terms and conditions of the GNU General | ||||
|  * Public License.  See the file README.legal in the main directory of | ||||
|  * this archive for more details. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/ptrace.h> | ||||
| #include <linux/signal.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <asm/unistd.h> | ||||
| 
 | ||||
| #include "signal.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * Allocate space for the signal frame | ||||
|  */ | ||||
| void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||||
| 			   size_t frame_size) | ||||
| { | ||||
|         unsigned long oldsp, newsp; | ||||
| 
 | ||||
|         /* Default to using normal stack */ | ||||
|         oldsp = regs->gpr[1]; | ||||
| 
 | ||||
| 	/* Check for alt stack */ | ||||
| 	if ((ka->sa.sa_flags & SA_ONSTACK) && | ||||
| 	    current->sas_ss_size && !on_sig_stack(oldsp)) | ||||
| 		oldsp = (current->sas_ss_sp + current->sas_ss_size); | ||||
| 
 | ||||
| 	/* Get aligned frame */ | ||||
| 	newsp = (oldsp - frame_size) & ~0xFUL; | ||||
| 
 | ||||
| 	/* Check access */ | ||||
| 	if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp)) | ||||
| 		return NULL; | ||||
| 
 | ||||
|         return (void __user *)newsp; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Restore the user process's signal mask | ||||
|  */ | ||||
| void restore_sigmask(sigset_t *set) | ||||
| { | ||||
| 	sigdelsetmask(set, ~_BLOCKABLE); | ||||
| 	spin_lock_irq(¤t->sighand->siglock); | ||||
| 	current->blocked = *set; | ||||
| 	recalc_sigpending(); | ||||
| 	spin_unlock_irq(¤t->sighand->siglock); | ||||
| } | ||||
| 
 | ||||
| static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | ||||
| 				  int has_handler) | ||||
| { | ||||
| 	unsigned long ret = regs->gpr[3]; | ||||
| 	int restart = 1; | ||||
| 
 | ||||
| 	/* syscall ? */ | ||||
| 	if (TRAP(regs) != 0x0C00) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* error signalled ? */ | ||||
| 	if (!(regs->ccr & 0x10000000)) | ||||
| 		return; | ||||
| 
 | ||||
| 	switch (ret) { | ||||
| 	case ERESTART_RESTARTBLOCK: | ||||
| 	case ERESTARTNOHAND: | ||||
| 		/* ERESTARTNOHAND means that the syscall should only be
 | ||||
| 		 * restarted if there was no handler for the signal, and since | ||||
| 		 * we only get here if there is a handler, we dont restart. | ||||
| 		 */ | ||||
| 		restart = !has_handler; | ||||
| 		break; | ||||
| 	case ERESTARTSYS: | ||||
| 		/* ERESTARTSYS means to restart the syscall if there is no
 | ||||
| 		 * handler or the handler was registered with SA_RESTART | ||||
| 		 */ | ||||
| 		restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0; | ||||
| 		break; | ||||
| 	case ERESTARTNOINTR: | ||||
| 		/* ERESTARTNOINTR means that the syscall should be
 | ||||
| 		 * called again after the signal handler returns. | ||||
| 		 */ | ||||
| 		break; | ||||
| 	default: | ||||
| 		return; | ||||
| 	} | ||||
| 	if (restart) { | ||||
| 		if (ret == ERESTART_RESTARTBLOCK) | ||||
| 			regs->gpr[0] = __NR_restart_syscall; | ||||
| 		else | ||||
| 			regs->gpr[3] = regs->orig_gpr3; | ||||
| 		regs->nip -= 4; | ||||
| 		regs->result = 0; | ||||
| 	} else { | ||||
| 		regs->result = -EINTR; | ||||
| 		regs->gpr[3] = EINTR; | ||||
| 		regs->ccr |= 0x10000000; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||||
| { | ||||
| 	siginfo_t info; | ||||
| 	int signr; | ||||
| 	struct k_sigaction ka; | ||||
| 	int ret; | ||||
| 	int is32 = is_32bit_task(); | ||||
| 
 | ||||
| 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||||
| 		oldset = ¤t->saved_sigmask; | ||||
| 	else if (!oldset) | ||||
| 		oldset = ¤t->blocked; | ||||
| 
 | ||||
| 	signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||||
| 
 | ||||
| 	/* Is there any syscall restart business here ? */ | ||||
| 	check_syscall_restart(regs, &ka, signr > 0); | ||||
| 
 | ||||
| 	if (signr <= 0) { | ||||
| 		/* No signal to deliver -- put the saved sigmask back */ | ||||
| 		if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||||
| 			clear_thread_flag(TIF_RESTORE_SIGMASK); | ||||
| 			sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||||
| 		} | ||||
| 		return 0;               /* no signals delivered */ | ||||
| 	} | ||||
| 
 | ||||
|         /*
 | ||||
| 	 * Reenable the DABR before delivering the signal to | ||||
| 	 * user space. The DABR will have been cleared if it | ||||
| 	 * triggered inside the kernel. | ||||
| 	 */ | ||||
| 	if (current->thread.dabr) | ||||
| 		set_dabr(current->thread.dabr); | ||||
| 
 | ||||
| 	if (is32) { | ||||
|         	if (ka.sa.sa_flags & SA_SIGINFO) | ||||
| 			ret = handle_rt_signal32(signr, &ka, &info, oldset, | ||||
| 					regs); | ||||
| 		else | ||||
| 			ret = handle_signal32(signr, &ka, &info, oldset, | ||||
| 					regs); | ||||
| 	} else { | ||||
| 		ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); | ||||
| 	} | ||||
| 
 | ||||
| 	if (ret) { | ||||
| 		spin_lock_irq(¤t->sighand->siglock); | ||||
| 		sigorsets(¤t->blocked, ¤t->blocked, | ||||
| 			  &ka.sa.sa_mask); | ||||
| 		if (!(ka.sa.sa_flags & SA_NODEFER)) | ||||
| 			sigaddset(¤t->blocked, signr); | ||||
| 		recalc_sigpending(); | ||||
| 		spin_unlock_irq(¤t->sighand->siglock); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * A signal was successfully delivered; the saved sigmask is in | ||||
| 		 * its frame, and we can clear the TIF_RESTORE_SIGMASK flag. | ||||
| 		 */ | ||||
| 		if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||||
| 			clear_thread_flag(TIF_RESTORE_SIGMASK); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||||
| 		unsigned long r5, unsigned long r6, unsigned long r7, | ||||
| 		unsigned long r8, struct pt_regs *regs) | ||||
| { | ||||
| 	return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||||
| } | ||||
							
								
								
									
										55
									
								
								arch/powerpc/kernel/signal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								arch/powerpc/kernel/signal.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| /*
 | ||||
|  *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration | ||||
|  *    Extracted from signal_32.c and signal_64.c | ||||
|  * | ||||
|  * This file is subject to the terms and conditions of the GNU General | ||||
|  * Public License.  See the file README.legal in the main directory of | ||||
|  * this archive for more details. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _POWERPC_ARCH_SIGNAL_H | ||||
| #define _POWERPC_ARCH_SIGNAL_H | ||||
| 
 | ||||
| #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||||
| 
 | ||||
| extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||||
| 				  size_t frame_size); | ||||
| extern void restore_sigmask(sigset_t *set); | ||||
| 
 | ||||
| extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, | ||||
| 			   siginfo_t *info, sigset_t *oldset, | ||||
| 			   struct pt_regs *regs); | ||||
| 
 | ||||
| extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | ||||
| 			      siginfo_t *info, sigset_t *oldset, | ||||
| 			      struct pt_regs *regs); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64 | ||||
| 
 | ||||
| static inline int is_32bit_task(void) | ||||
| { | ||||
| 	return test_thread_flag(TIF_32BIT); | ||||
| } | ||||
| 
 | ||||
| extern int handle_rt_signal64(int signr, struct k_sigaction *ka, | ||||
| 			      siginfo_t *info, sigset_t *set, | ||||
| 			      struct pt_regs *regs); | ||||
| 
 | ||||
| #else /* CONFIG_PPC64 */ | ||||
| 
 | ||||
| static inline int is_32bit_task(void) | ||||
| { | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, | ||||
| 				     siginfo_t *info, sigset_t *set, | ||||
| 				     struct pt_regs *regs) | ||||
| { | ||||
| 	return -EFAULT; | ||||
| } | ||||
| 
 | ||||
| #endif /* !defined(CONFIG_PPC64) */ | ||||
| 
 | ||||
| #endif  /* _POWERPC_ARCH_SIGNAL_H */ | ||||
| @ -51,12 +51,11 @@ | ||||
| #include <asm/pgtable.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "signal.h" | ||||
| 
 | ||||
| #undef DEBUG_SIG | ||||
| 
 | ||||
| #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64 | ||||
| #define do_signal	do_signal32 | ||||
| #define sys_sigsuspend	compat_sys_sigsuspend | ||||
| #define sys_rt_sigsuspend	compat_sys_rt_sigsuspend | ||||
| #define sys_rt_sigreturn	compat_sys_rt_sigreturn | ||||
| @ -231,8 +230,6 @@ static inline int restore_general_regs(struct pt_regs *regs, | ||||
| 
 | ||||
| #endif /* CONFIG_PPC64 */ | ||||
| 
 | ||||
| int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||||
| 
 | ||||
| /*
 | ||||
|  * Atomically swap in the new signal mask, and wait for a signal. | ||||
|  */ | ||||
| @ -251,14 +248,6 @@ long sys_sigsuspend(old_sigset_t mask) | ||||
|  	return -ERESTARTNOHAND; | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PPC32 | ||||
| long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5, | ||||
| 		int r6, int r7, int r8, struct pt_regs *regs) | ||||
| { | ||||
| 	return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| long sys_sigaction(int sig, struct old_sigaction __user *act, | ||||
| 		struct old_sigaction __user *oact) | ||||
| { | ||||
| @ -293,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act, | ||||
| /*
 | ||||
|  * When we have signals to deliver, we set up on the | ||||
|  * user stack, going down from the original stack pointer: | ||||
|  *	a sigregs struct | ||||
|  *	an ABI gap of 56 words | ||||
|  *	an mcontext struct | ||||
|  *	a sigcontext struct | ||||
|  *	a gap of __SIGNAL_FRAMESIZE bytes | ||||
|  * | ||||
|  * Each of these things must be a multiple of 16 bytes in size. | ||||
|  * Each of these things must be a multiple of 16 bytes in size. The following | ||||
|  * structure represent all of this except the __SIGNAL_FRAMESIZE gap | ||||
|  * | ||||
|  */ | ||||
| struct sigregs { | ||||
| struct sigframe { | ||||
| 	struct sigcontext sctx;		/* the sigcontext */ | ||||
| 	struct mcontext	mctx;		/* all the register values */ | ||||
| 	/*
 | ||||
| 	 * Programs using the rs6000/xcoff abi can save up to 19 gp | ||||
| @ -703,44 +695,22 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, | ||||
| } | ||||
| #endif /* CONFIG_PPC64 */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Restore the user process's signal mask | ||||
|  */ | ||||
| #ifdef CONFIG_PPC64 | ||||
| extern void restore_sigmask(sigset_t *set); | ||||
| #else /* CONFIG_PPC64 */ | ||||
| static void restore_sigmask(sigset_t *set) | ||||
| { | ||||
| 	sigdelsetmask(set, ~_BLOCKABLE); | ||||
| 	spin_lock_irq(¤t->sighand->siglock); | ||||
| 	current->blocked = *set; | ||||
| 	recalc_sigpending(); | ||||
| 	spin_unlock_irq(¤t->sighand->siglock); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * Set up a signal frame for a "real-time" signal handler | ||||
|  * (one which gets siginfo). | ||||
|  */ | ||||
| static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | ||||
| int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | ||||
| 		siginfo_t *info, sigset_t *oldset, | ||||
| 		struct pt_regs *regs, unsigned long newsp) | ||||
| 		struct pt_regs *regs) | ||||
| { | ||||
| 	struct rt_sigframe __user *rt_sf; | ||||
| 	struct mcontext __user *frame; | ||||
| 	unsigned long origsp = newsp; | ||||
| 	unsigned long newsp = 0; | ||||
| 
 | ||||
| 	/* Set up Signal Frame */ | ||||
| 	/* Put a Real Time Context onto stack */ | ||||
| 	newsp -= sizeof(*rt_sf); | ||||
| 	rt_sf = (struct rt_sigframe __user *)newsp; | ||||
| 
 | ||||
| 	/* create a stack frame for the caller of the handler */ | ||||
| 	newsp -= __SIGNAL_FRAMESIZE + 16; | ||||
| 
 | ||||
| 	if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) | ||||
| 	rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); | ||||
| 	if (unlikely(rt_sf == NULL)) | ||||
| 		goto badframe; | ||||
| 
 | ||||
| 	/* Put the siginfo & fill in most of the ucontext */ | ||||
| @ -770,8 +740,12 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | ||||
| 
 | ||||
| 	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */ | ||||
| 
 | ||||
| 	/* create a stack frame for the caller of the handler */ | ||||
| 	newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); | ||||
| 	if (put_user(regs->gpr[1], (u32 __user *)newsp)) | ||||
| 		goto badframe; | ||||
| 
 | ||||
| 	/* Fill registers for signal handler */ | ||||
| 	regs->gpr[1] = newsp; | ||||
| 	regs->gpr[3] = sig; | ||||
| 	regs->gpr[4] = (unsigned long) &rt_sf->info; | ||||
| @ -1015,27 +989,18 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | ||||
| /*
 | ||||
|  * OK, we're invoking a handler | ||||
|  */ | ||||
| static int handle_signal(unsigned long sig, struct k_sigaction *ka, | ||||
| 		siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, | ||||
| 		unsigned long newsp) | ||||
| int handle_signal32(unsigned long sig, struct k_sigaction *ka, | ||||
| 		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | ||||
| { | ||||
| 	struct sigcontext __user *sc; | ||||
| 	struct sigregs __user *frame; | ||||
| 	unsigned long origsp = newsp; | ||||
| 	struct sigframe __user *frame; | ||||
| 	unsigned long newsp = 0; | ||||
| 
 | ||||
| 	/* Set up Signal Frame */ | ||||
| 	newsp -= sizeof(struct sigregs); | ||||
| 	frame = (struct sigregs __user *) newsp; | ||||
| 
 | ||||
| 	/* Put a sigcontext on the stack */ | ||||
| 	newsp -= sizeof(*sc); | ||||
| 	sc = (struct sigcontext __user *) newsp; | ||||
| 
 | ||||
| 	/* create a stack frame for the caller of the handler */ | ||||
| 	newsp -= __SIGNAL_FRAMESIZE; | ||||
| 
 | ||||
| 	if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) | ||||
| 	frame = get_sigframe(ka, regs, sizeof(*frame)); | ||||
| 	if (unlikely(frame == NULL)) | ||||
| 		goto badframe; | ||||
| 	sc = (struct sigcontext __user *) &frame->sctx; | ||||
| 
 | ||||
| #if _NSIG != 64 | ||||
| #error "Please adjust handle_signal()" | ||||
| @ -1047,7 +1012,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | ||||
| #else | ||||
| 	    || __put_user(oldset->sig[1], &sc->_unused[3]) | ||||
| #endif | ||||
| 	    || __put_user(to_user_ptr(frame), &sc->regs) | ||||
| 	    || __put_user(to_user_ptr(&frame->mctx), &sc->regs) | ||||
| 	    || __put_user(sig, &sc->signal)) | ||||
| 		goto badframe; | ||||
| 
 | ||||
| @ -1063,8 +1028,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | ||||
| 
 | ||||
| 	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */ | ||||
| 
 | ||||
| 	/* create a stack frame for the caller of the handler */ | ||||
| 	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; | ||||
| 	if (put_user(regs->gpr[1], (u32 __user *)newsp)) | ||||
| 		goto badframe; | ||||
| 
 | ||||
| 	regs->gpr[1] = newsp; | ||||
| 	regs->gpr[3] = sig; | ||||
| 	regs->gpr[4] = (unsigned long) sc; | ||||
| @ -1126,106 +1094,3 @@ badframe: | ||||
| 	force_sig(SIGSEGV, current); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Note that 'init' is a special process: it doesn't get signals it doesn't | ||||
|  * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||||
|  * mistake. | ||||
|  */ | ||||
| int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||||
| { | ||||
| 	siginfo_t info; | ||||
| 	struct k_sigaction ka; | ||||
| 	unsigned int newsp; | ||||
| 	int signr, ret; | ||||
| 
 | ||||
| #ifdef CONFIG_PPC32 | ||||
| 	if (try_to_freeze()) { | ||||
| 		signr = 0; | ||||
| 		if (!signal_pending(current)) | ||||
| 			goto no_signal; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||||
| 		oldset = ¤t->saved_sigmask; | ||||
| 	else if (!oldset) | ||||
| 		oldset = ¤t->blocked; | ||||
| 
 | ||||
| 	signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||||
| #ifdef CONFIG_PPC32 | ||||
| no_signal: | ||||
| #endif | ||||
| 	if (TRAP(regs) == 0x0C00		/* System Call! */ | ||||
| 	    && regs->ccr & 0x10000000		/* error signalled */ | ||||
| 	    && ((ret = regs->gpr[3]) == ERESTARTSYS | ||||
| 		|| ret == ERESTARTNOHAND || ret == ERESTARTNOINTR | ||||
| 		|| ret == ERESTART_RESTARTBLOCK)) { | ||||
| 
 | ||||
| 		if (signr > 0 | ||||
| 		    && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK | ||||
| 			|| (ret == ERESTARTSYS | ||||
| 			    && !(ka.sa.sa_flags & SA_RESTART)))) { | ||||
| 			/* make the system call return an EINTR error */ | ||||
| 			regs->result = -EINTR; | ||||
| 			regs->gpr[3] = EINTR; | ||||
| 			/* note that the cr0.SO bit is already set */ | ||||
| 		} else { | ||||
| 			regs->nip -= 4;	/* Back up & retry system call */ | ||||
| 			regs->result = 0; | ||||
| 			regs->trap = 0; | ||||
| 			if (ret == ERESTART_RESTARTBLOCK) | ||||
| 				regs->gpr[0] = __NR_restart_syscall; | ||||
| 			else | ||||
| 				regs->gpr[3] = regs->orig_gpr3; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (signr == 0) { | ||||
| 		/* No signal to deliver -- put the saved sigmask back */ | ||||
| 		if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||||
| 			clear_thread_flag(TIF_RESTORE_SIGMASK); | ||||
| 			sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||||
| 		} | ||||
| 		return 0;		/* no signals delivered */ | ||||
| 	} | ||||
| 
 | ||||
| 	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size | ||||
| 	    && !on_sig_stack(regs->gpr[1])) | ||||
| 		newsp = current->sas_ss_sp + current->sas_ss_size; | ||||
| 	else | ||||
| 		newsp = regs->gpr[1]; | ||||
| 	newsp &= ~0xfUL; | ||||
| 
 | ||||
| #ifdef CONFIG_PPC64 | ||||
| 	/*
 | ||||
| 	 * Reenable the DABR before delivering the signal to | ||||
| 	 * user space. The DABR will have been cleared if it | ||||
| 	 * triggered inside the kernel. | ||||
| 	 */ | ||||
| 	if (current->thread.dabr) | ||||
| 		set_dabr(current->thread.dabr); | ||||
| #endif | ||||
| 
 | ||||
| 	/* Whee!  Actually deliver the signal.  */ | ||||
| 	if (ka.sa.sa_flags & SA_SIGINFO) | ||||
| 		ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp); | ||||
| 	else | ||||
| 		ret = handle_signal(signr, &ka, &info, oldset, regs, newsp); | ||||
| 
 | ||||
| 	if (ret) { | ||||
| 		spin_lock_irq(¤t->sighand->siglock); | ||||
| 		sigorsets(¤t->blocked, ¤t->blocked, | ||||
| 			  &ka.sa.sa_mask); | ||||
| 		if (!(ka.sa.sa_flags & SA_NODEFER)) | ||||
| 			sigaddset(¤t->blocked, signr); | ||||
| 		recalc_sigpending(); | ||||
| 		spin_unlock_irq(¤t->sighand->siglock); | ||||
| 		/* A signal was successfully delivered; the saved sigmask is in
 | ||||
| 		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||||
| 		if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||||
| 			clear_thread_flag(TIF_RESTORE_SIGMASK); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| @ -34,9 +34,9 @@ | ||||
| #include <asm/syscalls.h> | ||||
| #include <asm/vdso.h> | ||||
| 
 | ||||
| #define DEBUG_SIG 0 | ||||
| #include "signal.h" | ||||
| 
 | ||||
| #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||||
| #define DEBUG_SIG 0 | ||||
| 
 | ||||
| #define GP_REGS_SIZE	min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) | ||||
| #define FP_REGS_SIZE	sizeof(elf_fpregset_t) | ||||
| @ -64,14 +64,6 @@ struct rt_sigframe { | ||||
| 	char abigap[288]; | ||||
| } __attribute__ ((aligned (16))); | ||||
| 
 | ||||
| long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, | ||||
| 		     unsigned long r6, unsigned long r7, unsigned long r8, | ||||
| 		     struct pt_regs *regs) | ||||
| { | ||||
| 	return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Set up the sigcontext for the signal frame. | ||||
|  */ | ||||
| @ -207,25 +199,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Allocate space for the signal frame | ||||
|  */ | ||||
| static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||||
| 				  size_t frame_size) | ||||
| { | ||||
|         unsigned long newsp; | ||||
| 
 | ||||
|         /* Default to using normal stack */ | ||||
|         newsp = regs->gpr[1]; | ||||
| 
 | ||||
| 	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) { | ||||
| 		if (! on_sig_stack(regs->gpr[1])) | ||||
| 			newsp = (current->sas_ss_sp + current->sas_ss_size); | ||||
| 	} | ||||
| 
 | ||||
|         return (void __user *)((newsp - frame_size) & -16ul); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Setup the trampoline code on the stack | ||||
|  */ | ||||
| @ -252,19 +225,6 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Restore the user process's signal mask (also used by signal32.c) | ||||
|  */ | ||||
| void restore_sigmask(sigset_t *set) | ||||
| { | ||||
| 	sigdelsetmask(set, ~_BLOCKABLE); | ||||
| 	spin_lock_irq(¤t->sighand->siglock); | ||||
| 	current->blocked = *set; | ||||
| 	recalc_sigpending(); | ||||
| 	spin_unlock_irq(¤t->sighand->siglock); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Handle {get,set,swap}_context operations | ||||
|  */ | ||||
| @ -359,7 +319,7 @@ badframe: | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | ||||
| int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | ||||
| 		sigset_t *set, struct pt_regs *regs) | ||||
| { | ||||
| 	/* Handler is *really* a pointer to the function descriptor for
 | ||||
| @ -373,8 +333,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | ||||
| 	long err = 0; | ||||
| 
 | ||||
| 	frame = get_sigframe(ka, regs, sizeof(*frame)); | ||||
| 
 | ||||
| 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||||
| 	if (unlikely(frame == NULL)) | ||||
| 		goto badframe; | ||||
| 
 | ||||
| 	err |= __put_user(&frame->info, &frame->pinfo); | ||||
| @ -411,7 +370,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | ||||
| 	funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; | ||||
| 
 | ||||
| 	/* Allocate a dummy caller frame for the signal handler. */ | ||||
| 	newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; | ||||
| 	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; | ||||
| 	err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); | ||||
| 
 | ||||
| 	/* Set up "regs" so we "return" to the signal handler. */ | ||||
| @ -442,134 +401,3 @@ badframe: | ||||
| 	force_sigsegv(signr, current); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * OK, we're invoking a handler | ||||
|  */ | ||||
| static int handle_signal(unsigned long sig, struct k_sigaction *ka, | ||||
| 			 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/* Set up Signal Frame */ | ||||
| 	ret = setup_rt_frame(sig, ka, info, oldset, regs); | ||||
| 
 | ||||
| 	if (ret) { | ||||
| 		spin_lock_irq(¤t->sighand->siglock); | ||||
| 		sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||||
| 		if (!(ka->sa.sa_flags & SA_NODEFER)) | ||||
| 			sigaddset(¤t->blocked,sig); | ||||
| 		recalc_sigpending(); | ||||
| 		spin_unlock_irq(¤t->sighand->siglock); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | ||||
| { | ||||
| 	switch ((int)regs->result) { | ||||
| 	case -ERESTART_RESTARTBLOCK: | ||||
| 	case -ERESTARTNOHAND: | ||||
| 		/* ERESTARTNOHAND means that the syscall should only be
 | ||||
| 		 * restarted if there was no handler for the signal, and since | ||||
| 		 * we only get here if there is a handler, we dont restart. | ||||
| 		 */ | ||||
| 		regs->result = -EINTR; | ||||
| 		regs->gpr[3] = EINTR; | ||||
| 		regs->ccr |= 0x10000000; | ||||
| 		break; | ||||
| 	case -ERESTARTSYS: | ||||
| 		/* ERESTARTSYS means to restart the syscall if there is no
 | ||||
| 		 * handler or the handler was registered with SA_RESTART | ||||
| 		 */ | ||||
| 		if (!(ka->sa.sa_flags & SA_RESTART)) { | ||||
| 			regs->result = -EINTR; | ||||
| 			regs->gpr[3] = EINTR; | ||||
| 			regs->ccr |= 0x10000000; | ||||
| 			break; | ||||
| 		} | ||||
| 		/* fallthrough */ | ||||
| 	case -ERESTARTNOINTR: | ||||
| 		/* ERESTARTNOINTR means that the syscall should be
 | ||||
| 		 * called again after the signal handler returns. | ||||
| 		 */ | ||||
| 		regs->gpr[3] = regs->orig_gpr3; | ||||
| 		regs->nip -= 4; | ||||
| 		regs->result = 0; | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Note that 'init' is a special process: it doesn't get signals it doesn't | ||||
|  * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||||
|  * mistake. | ||||
|  */ | ||||
| int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||||
| { | ||||
| 	siginfo_t info; | ||||
| 	int signr; | ||||
| 	struct k_sigaction ka; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If the current thread is 32 bit - invoke the | ||||
| 	 * 32 bit signal handling code | ||||
| 	 */ | ||||
| 	if (test_thread_flag(TIF_32BIT)) | ||||
| 		return do_signal32(oldset, regs); | ||||
| 
 | ||||
| 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||||
| 		oldset = ¤t->saved_sigmask; | ||||
| 	else if (!oldset) | ||||
| 		oldset = ¤t->blocked; | ||||
| 
 | ||||
| 	signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||||
| 	if (signr > 0) { | ||||
| 		int ret; | ||||
| 
 | ||||
| 		/* Whee!  Actually deliver the signal.  */ | ||||
| 		if (TRAP(regs) == 0x0C00) | ||||
| 			syscall_restart(regs, &ka); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Reenable the DABR before delivering the signal to | ||||
| 		 * user space. The DABR will have been cleared if it | ||||
| 		 * triggered inside the kernel. | ||||
| 		 */ | ||||
| 		if (current->thread.dabr) | ||||
| 			set_dabr(current->thread.dabr); | ||||
| 
 | ||||
| 		ret = handle_signal(signr, &ka, &info, oldset, regs); | ||||
| 
 | ||||
| 		/* If a signal was successfully delivered, the saved sigmask is in
 | ||||
| 		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||||
| 		if (ret && test_thread_flag(TIF_RESTORE_SIGMASK)) | ||||
| 			clear_thread_flag(TIF_RESTORE_SIGMASK); | ||||
| 
 | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	if (TRAP(regs) == 0x0C00) {	/* System Call! */ | ||||
| 		if ((int)regs->result == -ERESTARTNOHAND || | ||||
| 		    (int)regs->result == -ERESTARTSYS || | ||||
| 		    (int)regs->result == -ERESTARTNOINTR) { | ||||
| 			regs->gpr[3] = regs->orig_gpr3; | ||||
| 			regs->nip -= 4; /* Back up & retry system call */ | ||||
| 			regs->result = 0; | ||||
| 		} else if ((int)regs->result == -ERESTART_RESTARTBLOCK) { | ||||
| 			regs->gpr[0] = __NR_restart_syscall; | ||||
| 			regs->nip -= 4; | ||||
| 			regs->result = 0; | ||||
| 		} | ||||
| 	} | ||||
| 	/* No signal to deliver -- put the saved sigmask back */ | ||||
| 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||||
| 		clear_thread_flag(TIF_RESTORE_SIGMASK); | ||||
| 		sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(do_signal); | ||||
|  | ||||
| @ -442,12 +442,14 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid) | ||||
| 	return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, | ||||
| 			kobject_name(&dev->kobj)); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); | ||||
| 
 | ||||
| void sysfs_remove_device_from_node(struct sys_device *dev, int nid) | ||||
| { | ||||
| 	struct node *node = &node_devices[nid]; | ||||
| 	sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); | ||||
| 
 | ||||
| #else | ||||
| static void register_nodes(void) | ||||
| @ -457,9 +459,6 @@ static void register_nodes(void) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); | ||||
| EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); | ||||
| 
 | ||||
| /* Only valid if CPU is present. */ | ||||
| static ssize_t show_physical_id(struct sys_device *dev, char *buf) | ||||
| { | ||||
|  | ||||
| @ -77,9 +77,8 @@ | ||||
| /* keep track of when we need to update the rtc */ | ||||
| time_t last_rtc_update; | ||||
| #ifdef CONFIG_PPC_ISERIES | ||||
| unsigned long iSeries_recal_titan = 0; | ||||
| unsigned long iSeries_recal_tb = 0;  | ||||
| static unsigned long first_settimeofday = 1; | ||||
| static unsigned long __initdata iSeries_recal_titan; | ||||
| static signed long __initdata iSeries_recal_tb; | ||||
| #endif | ||||
| 
 | ||||
| /* The decrementer counts down by 128 every 128ns on a 601. */ | ||||
| @ -113,8 +112,9 @@ u64 ticklen_to_xs;	/* 0.64 fraction */ | ||||
| DEFINE_SPINLOCK(rtc_lock); | ||||
| EXPORT_SYMBOL_GPL(rtc_lock); | ||||
| 
 | ||||
| u64 tb_to_ns_scale; | ||||
| unsigned tb_to_ns_shift; | ||||
| static u64 tb_to_ns_scale __read_mostly; | ||||
| static unsigned tb_to_ns_shift __read_mostly; | ||||
| static unsigned long boot_tb __read_mostly; | ||||
| 
 | ||||
| struct gettimeofday_struct do_gtod; | ||||
| 
 | ||||
| @ -214,7 +214,6 @@ static void account_process_time(struct pt_regs *regs) | ||||
|  	run_posix_cpu_timers(current); | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PPC_SPLPAR | ||||
| /*
 | ||||
|  * Stuff for accounting stolen time. | ||||
|  */ | ||||
| @ -222,19 +221,28 @@ struct cpu_purr_data { | ||||
| 	int	initialized;			/* thread is running */ | ||||
| 	u64	tb;			/* last TB value read */ | ||||
| 	u64	purr;			/* last PURR value read */ | ||||
| 	spinlock_t lock; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Each entry in the cpu_purr_data array is manipulated only by its | ||||
|  * "owner" cpu -- usually in the timer interrupt but also occasionally | ||||
|  * in process context for cpu online.  As long as cpus do not touch | ||||
|  * each others' cpu_purr_data, disabling local interrupts is | ||||
|  * sufficient to serialize accesses. | ||||
|  */ | ||||
| static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); | ||||
| 
 | ||||
| static void snapshot_tb_and_purr(void *data) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | ||||
| 
 | ||||
| 	local_irq_save(flags); | ||||
| 	p->tb = mftb(); | ||||
| 	p->purr = mfspr(SPRN_PURR); | ||||
| 	wmb(); | ||||
| 	p->initialized = 1; | ||||
| 	local_irq_restore(flags); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -242,15 +250,14 @@ static void snapshot_tb_and_purr(void *data) | ||||
|  */ | ||||
| void snapshot_timebases(void) | ||||
| { | ||||
| 	int cpu; | ||||
| 
 | ||||
| 	if (!cpu_has_feature(CPU_FTR_PURR)) | ||||
| 		return; | ||||
| 	for_each_possible_cpu(cpu) | ||||
| 		spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); | ||||
| 	on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Must be called with interrupts disabled. | ||||
|  */ | ||||
| void calculate_steal_time(void) | ||||
| { | ||||
| 	u64 tb, purr; | ||||
| @ -262,7 +269,6 @@ void calculate_steal_time(void) | ||||
| 	pme = &per_cpu(cpu_purr_data, smp_processor_id()); | ||||
| 	if (!pme->initialized) | ||||
| 		return;		/* this can happen in early boot */ | ||||
| 	spin_lock(&pme->lock); | ||||
| 	tb = mftb(); | ||||
| 	purr = mfspr(SPRN_PURR); | ||||
| 	stolen = (tb - pme->tb) - (purr - pme->purr); | ||||
| @ -270,9 +276,9 @@ void calculate_steal_time(void) | ||||
| 		account_steal_time(current, stolen); | ||||
| 	pme->tb = tb; | ||||
| 	pme->purr = purr; | ||||
| 	spin_unlock(&pme->lock); | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PPC_SPLPAR | ||||
| /*
 | ||||
|  * Must be called before the cpu is added to the online map when | ||||
|  * a cpu is being brought up at runtime. | ||||
| @ -284,12 +290,12 @@ static void snapshot_purr(void) | ||||
| 
 | ||||
| 	if (!cpu_has_feature(CPU_FTR_PURR)) | ||||
| 		return; | ||||
| 	local_irq_save(flags); | ||||
| 	pme = &per_cpu(cpu_purr_data, smp_processor_id()); | ||||
| 	spin_lock_irqsave(&pme->lock, flags); | ||||
| 	pme->tb = mftb(); | ||||
| 	pme->purr = mfspr(SPRN_PURR); | ||||
| 	pme->initialized = 1; | ||||
| 	spin_unlock_irqrestore(&pme->lock, flags); | ||||
| 	local_irq_restore(flags); | ||||
| } | ||||
| 
 | ||||
| #endif /* CONFIG_PPC_SPLPAR */ | ||||
| @ -550,10 +556,15 @@ EXPORT_SYMBOL(profile_pc); | ||||
|  * returned by the service processor for the timebase frequency.   | ||||
|  */ | ||||
| 
 | ||||
| static void iSeries_tb_recal(void) | ||||
| static int __init iSeries_tb_recal(void) | ||||
| { | ||||
| 	struct div_result divres; | ||||
| 	unsigned long titan, tb; | ||||
| 
 | ||||
| 	/* Make sure we only run on iSeries */ | ||||
| 	if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	tb = get_tb(); | ||||
| 	titan = HvCallXm_loadTod(); | ||||
| 	if ( iSeries_recal_titan ) { | ||||
| @ -594,8 +605,18 @@ static void iSeries_tb_recal(void) | ||||
| 	} | ||||
| 	iSeries_recal_titan = titan; | ||||
| 	iSeries_recal_tb = tb; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
| late_initcall(iSeries_tb_recal); | ||||
| 
 | ||||
| /* Called from platform early init */ | ||||
| void __init iSeries_time_init_early(void) | ||||
| { | ||||
| 	iSeries_recal_tb = get_tb(); | ||||
| 	iSeries_recal_titan = HvCallXm_loadTod(); | ||||
| } | ||||
| #endif /* CONFIG_PPC_ISERIES */ | ||||
| 
 | ||||
| /*
 | ||||
|  * For iSeries shared processors, we have to let the hypervisor | ||||
| @ -735,7 +756,7 @@ unsigned long long sched_clock(void) | ||||
| { | ||||
| 	if (__USE_RTC()) | ||||
| 		return get_rtc(); | ||||
| 	return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; | ||||
| 	return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift; | ||||
| } | ||||
| 
 | ||||
| int do_settimeofday(struct timespec *tv) | ||||
| @ -759,12 +780,6 @@ int do_settimeofday(struct timespec *tv) | ||||
| 	 * to the RTC again, or write to the RTC but then they don't call | ||||
| 	 * settimeofday to perform this operation. | ||||
| 	 */ | ||||
| #ifdef CONFIG_PPC_ISERIES | ||||
| 	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) { | ||||
| 		iSeries_tb_recal(); | ||||
| 		first_settimeofday = 0; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	/* Make userspace gettimeofday spin until we're done. */ | ||||
| 	++vdso_data->tb_update_count; | ||||
| @ -960,6 +975,8 @@ void __init time_init(void) | ||||
| 	} | ||||
| 	tb_to_ns_scale = scale; | ||||
| 	tb_to_ns_shift = shift; | ||||
| 	/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ | ||||
| 	boot_tb = get_tb(); | ||||
| 
 | ||||
| 	tm = get_boot_time(); | ||||
| 
 | ||||
|  | ||||
| @ -670,7 +670,7 @@ static int __init vdso_init(void) | ||||
| 	/*
 | ||||
| 	 * Fill up the "systemcfg" stuff for backward compatiblity | ||||
| 	 */ | ||||
| 	strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); | ||||
| 	strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); | ||||
| 	vdso_data->version.major = SYSTEMCFG_MAJOR; | ||||
| 	vdso_data->version.minor = SYSTEMCFG_MINOR; | ||||
| 	vdso_data->processor = mfspr(SPRN_PVR); | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| #define PROVIDE32(x)	PROVIDE(x) | ||||
| #endif | ||||
| #include <asm-generic/vmlinux.lds.h> | ||||
| #include <asm/cache.h> | ||||
| 
 | ||||
| ENTRY(_stext) | ||||
| 
 | ||||
| @ -211,6 +212,11 @@ SECTIONS | ||||
| 		*(.data.cacheline_aligned) | ||||
| 	} | ||||
| 
 | ||||
| 	. = ALIGN(L1_CACHE_BYTES);
 | ||||
| 	.data.read_mostly : { | ||||
| 		*(.data.read_mostly) | ||||
| 	} | ||||
| 
 | ||||
| 	. = ALIGN(PAGE_SIZE);
 | ||||
| 	__data_nosave : { | ||||
| 		__nosave_begin = .;
 | ||||
|  | ||||
| @ -12,7 +12,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
|  | ||||
| @ -9,7 +9,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
|  | ||||
| @ -11,8 +11,7 @@ obj-$(CONFIG_PPC32)		+= init_32.o pgtable_32.o mmu_context_32.o | ||||
| hash-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o | ||||
| obj-$(CONFIG_PPC64)		+= init_64.o pgtable_64.o mmu_context_64.o \
 | ||||
| 				   hash_utils_64.o hash_low_64.o tlb_64.o \
 | ||||
| 				   slb_low.o slb.o stab.o mmap.o imalloc.o \
 | ||||
| 				   $(hash-y) | ||||
| 				   slb_low.o slb.o stab.o mmap.o $(hash-y) | ||||
| obj-$(CONFIG_PPC_STD_MMU_32)	+= ppc_mmu_32.o hash_low_32.o tlb_32.o | ||||
| obj-$(CONFIG_40x)		+= 4xx_mmu.o | ||||
| obj-$(CONFIG_44x)		+= 44x_mmu.o | ||||
|  | ||||
| @ -380,7 +380,7 @@ out_of_memory: | ||||
| 	} | ||||
| 	printk("VM: killing process %s\n", current->comm); | ||||
| 	if (user_mode(regs)) | ||||
| 		do_exit(SIGKILL); | ||||
| 		do_group_exit(SIGKILL); | ||||
| 	return SIGKILL; | ||||
| 
 | ||||
| do_sigbus: | ||||
|  | ||||
| @ -14,7 +14,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
|  | ||||
| @ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local) | ||||
| 		spin_unlock(&native_tlbie_lock); | ||||
| } | ||||
| 
 | ||||
| static inline void native_lock_hpte(hpte_t *hptep) | ||||
| static inline void native_lock_hpte(struct hash_pte *hptep) | ||||
| { | ||||
| 	unsigned long *word = &hptep->v; | ||||
| 
 | ||||
| @ -116,7 +116,7 @@ static inline void native_lock_hpte(hpte_t *hptep) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline void native_unlock_hpte(hpte_t *hptep) | ||||
| static inline void native_unlock_hpte(struct hash_pte *hptep) | ||||
| { | ||||
| 	unsigned long *word = &hptep->v; | ||||
| 
 | ||||
| @ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | ||||
| 			unsigned long pa, unsigned long rflags, | ||||
| 			unsigned long vflags, int psize) | ||||
| { | ||||
| 	hpte_t *hptep = htab_address + hpte_group; | ||||
| 	struct hash_pte *hptep = htab_address + hpte_group; | ||||
| 	unsigned long hpte_v, hpte_r; | ||||
| 	int i; | ||||
| 
 | ||||
| @ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | ||||
| 
 | ||||
| 	hptep->r = hpte_r; | ||||
| 	/* Guarantee the second dword is visible before the valid bit */ | ||||
| 	__asm__ __volatile__ ("eieio" : : : "memory"); | ||||
| 	eieio(); | ||||
| 	/*
 | ||||
| 	 * Now set the first dword including the valid bit | ||||
| 	 * NOTE: this also unlocks the hpte | ||||
| @ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | ||||
| 
 | ||||
| static long native_hpte_remove(unsigned long hpte_group) | ||||
| { | ||||
| 	hpte_t *hptep; | ||||
| 	struct hash_pte *hptep; | ||||
| 	int i; | ||||
| 	int slot_offset; | ||||
| 	unsigned long hpte_v; | ||||
| @ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group) | ||||
| static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | ||||
| 				 unsigned long va, int psize, int local) | ||||
| { | ||||
| 	hpte_t *hptep = htab_address + slot; | ||||
| 	struct hash_pte *hptep = htab_address + slot; | ||||
| 	unsigned long hpte_v, want_v; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| @ -233,15 +233,14 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | ||||
| 	/* Even if we miss, we need to invalidate the TLB */ | ||||
| 	if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { | ||||
| 		DBG_LOW(" -> miss\n"); | ||||
| 		native_unlock_hpte(hptep); | ||||
| 		ret = -1; | ||||
| 	} else { | ||||
| 		DBG_LOW(" -> hit\n"); | ||||
| 		/* Update the HPTE */ | ||||
| 		hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | | ||||
| 			(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); | ||||
| 		native_unlock_hpte(hptep); | ||||
| 	} | ||||
| 	native_unlock_hpte(hptep); | ||||
| 
 | ||||
| 	/* Ensure it is out of the tlb too. */ | ||||
| 	tlbie(va, psize, local); | ||||
| @ -251,7 +250,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | ||||
| 
 | ||||
| static long native_hpte_find(unsigned long va, int psize) | ||||
| { | ||||
| 	hpte_t *hptep; | ||||
| 	struct hash_pte *hptep; | ||||
| 	unsigned long hash; | ||||
| 	unsigned long i, j; | ||||
| 	long slot; | ||||
| @ -294,7 +293,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | ||||
| { | ||||
| 	unsigned long vsid, va; | ||||
| 	long slot; | ||||
| 	hpte_t *hptep; | ||||
| 	struct hash_pte *hptep; | ||||
| 
 | ||||
| 	vsid = get_kernel_vsid(ea); | ||||
| 	va = (vsid << 28) | (ea & 0x0fffffff); | ||||
| @ -315,7 +314,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | ||||
| static void native_hpte_invalidate(unsigned long slot, unsigned long va, | ||||
| 				   int psize, int local) | ||||
| { | ||||
| 	hpte_t *hptep = htab_address + slot; | ||||
| 	struct hash_pte *hptep = htab_address + slot; | ||||
| 	unsigned long hpte_v; | ||||
| 	unsigned long want_v; | ||||
| 	unsigned long flags; | ||||
| @ -345,7 +344,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, | ||||
| #define LP_BITS		8 | ||||
| #define LP_MASK(i)	((0xFF >> (i)) << LP_SHIFT) | ||||
| 
 | ||||
| static void hpte_decode(hpte_t *hpte, unsigned long slot, | ||||
| static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | ||||
| 			int *psize, unsigned long *va) | ||||
| { | ||||
| 	unsigned long hpte_r = hpte->r; | ||||
| @ -415,7 +414,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot, | ||||
| static void native_hpte_clear(void) | ||||
| { | ||||
| 	unsigned long slot, slots, flags; | ||||
| 	hpte_t *hptep = htab_address; | ||||
| 	struct hash_pte *hptep = htab_address; | ||||
| 	unsigned long hpte_v, va; | ||||
| 	unsigned long pteg_count; | ||||
| 	int psize; | ||||
| @ -462,7 +461,7 @@ static void native_hpte_clear(void) | ||||
| static void native_flush_hash_range(unsigned long number, int local) | ||||
| { | ||||
| 	unsigned long va, hash, index, hidx, shift, slot; | ||||
| 	hpte_t *hptep; | ||||
| 	struct hash_pte *hptep; | ||||
| 	unsigned long hpte_v; | ||||
| 	unsigned long want_v; | ||||
| 	unsigned long flags; | ||||
|  | ||||
| @ -87,7 +87,7 @@ extern unsigned long dart_tablebase; | ||||
| static unsigned long _SDR1; | ||||
| struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | ||||
| 
 | ||||
| hpte_t *htab_address; | ||||
| struct hash_pte *htab_address; | ||||
| unsigned long htab_size_bytes; | ||||
| unsigned long htab_hash_mask; | ||||
| int mmu_linear_psize = MMU_PAGE_4K; | ||||
|  | ||||
| @ -1,313 +0,0 @@ | ||||
| /*
 | ||||
|  * c 2001 PPC 64 Team, IBM Corp | ||||
|  *  | ||||
|  *      This program is free software; you can redistribute it and/or | ||||
|  *      modify it under the terms of the GNU General Public License | ||||
|  *      as published by the Free Software Foundation; either version | ||||
|  *      2 of the License, or (at your option) any later version. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/slab.h> | ||||
| #include <linux/vmalloc.h> | ||||
| 
 | ||||
| #include <asm/uaccess.h> | ||||
| #include <asm/pgalloc.h> | ||||
| #include <asm/pgtable.h> | ||||
| #include <linux/mutex.h> | ||||
| #include <asm/cacheflush.h> | ||||
| 
 | ||||
| #include "mmu_decl.h" | ||||
| 
 | ||||
| static DEFINE_MUTEX(imlist_mutex); | ||||
| struct vm_struct * imlist = NULL; | ||||
| 
 | ||||
| static int get_free_im_addr(unsigned long size, unsigned long *im_addr) | ||||
| { | ||||
| 	unsigned long addr; | ||||
| 	struct vm_struct **p, *tmp; | ||||
| 
 | ||||
| 	addr = ioremap_bot; | ||||
| 	for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||||
| 		if (size + addr < (unsigned long) tmp->addr) | ||||
| 			break; | ||||
| 		if ((unsigned long)tmp->addr >= ioremap_bot) | ||||
| 			addr = tmp->size + (unsigned long) tmp->addr; | ||||
| 		if (addr >= IMALLOC_END-size) | ||||
| 			return 1; | ||||
| 	} | ||||
| 	*im_addr = addr; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Return whether the region described by v_addr and size is a subset
 | ||||
|  * of the region described by parent | ||||
|  */ | ||||
| static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, | ||||
| 			struct vm_struct *parent) | ||||
| { | ||||
| 	return (int) (v_addr >= (unsigned long) parent->addr && | ||||
| 	              v_addr < (unsigned long) parent->addr + parent->size && | ||||
| 	    	      size < parent->size); | ||||
| } | ||||
| 
 | ||||
| /* Return whether the region described by v_addr and size is a superset
 | ||||
|  * of the region described by child | ||||
|  */ | ||||
| static int im_region_is_superset(unsigned long v_addr, unsigned long size, | ||||
| 		struct vm_struct *child) | ||||
| { | ||||
| 	struct vm_struct parent; | ||||
| 
 | ||||
| 	parent.addr = (void *) v_addr; | ||||
| 	parent.size = size; | ||||
| 
 | ||||
| 	return im_region_is_subset((unsigned long) child->addr, child->size, | ||||
| 			&parent); | ||||
| } | ||||
| 
 | ||||
| /* Return whether the region described by v_addr and size overlaps
 | ||||
|  * the region described by vm.  Overlapping regions meet the | ||||
|  * following conditions: | ||||
|  * 1) The regions share some part of the address space | ||||
|  * 2) The regions aren't identical | ||||
|  * 3) Neither region is a subset of the other | ||||
|  */ | ||||
| static int im_region_overlaps(unsigned long v_addr, unsigned long size, | ||||
| 		     struct vm_struct *vm) | ||||
| { | ||||
| 	if (im_region_is_superset(v_addr, size, vm)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return (v_addr + size > (unsigned long) vm->addr + vm->size && | ||||
| 		v_addr < (unsigned long) vm->addr + vm->size) || | ||||
| 	       (v_addr < (unsigned long) vm->addr && | ||||
| 		v_addr + size > (unsigned long) vm->addr); | ||||
| } | ||||
| 
 | ||||
| /* Determine imalloc status of region described by v_addr and size.
 | ||||
|  * Can return one of the following: | ||||
|  * IM_REGION_UNUSED   -  Entire region is unallocated in imalloc space. | ||||
|  * IM_REGION_SUBSET -    Region is a subset of a region that is already | ||||
|  * 			 allocated in imalloc space. | ||||
|  * 		         vm will be assigned to a ptr to the parent region. | ||||
|  * IM_REGION_EXISTS -    Exact region already allocated in imalloc space. | ||||
|  *                       vm will be assigned to a ptr to the existing imlist | ||||
|  *                       member. | ||||
|  * IM_REGION_OVERLAPS -  Region overlaps an allocated region in imalloc space. | ||||
|  * IM_REGION_SUPERSET -  Region is a superset of a region that is already | ||||
|  *                       allocated in imalloc space. | ||||
|  */ | ||||
| static int im_region_status(unsigned long v_addr, unsigned long size, | ||||
| 		    struct vm_struct **vm) | ||||
| { | ||||
| 	struct vm_struct *tmp; | ||||
| 
 | ||||
| 	for (tmp = imlist; tmp; tmp = tmp->next) | ||||
| 		if (v_addr < (unsigned long) tmp->addr + tmp->size) | ||||
| 			break; | ||||
| 
 | ||||
| 	*vm = NULL; | ||||
| 	if (tmp) { | ||||
| 		if (im_region_overlaps(v_addr, size, tmp)) | ||||
| 			return IM_REGION_OVERLAP; | ||||
| 
 | ||||
| 		*vm = tmp; | ||||
| 		if (im_region_is_subset(v_addr, size, tmp)) { | ||||
| 			/* Return with tmp pointing to superset */ | ||||
| 			return IM_REGION_SUBSET; | ||||
| 		} | ||||
| 		if (im_region_is_superset(v_addr, size, tmp)) { | ||||
| 			/* Return with tmp pointing to first subset */ | ||||
| 			return IM_REGION_SUPERSET; | ||||
| 		} | ||||
| 		else if (v_addr == (unsigned long) tmp->addr && | ||||
| 		 	 size == tmp->size) { | ||||
| 			/* Return with tmp pointing to exact region */ | ||||
| 			return IM_REGION_EXISTS; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return IM_REGION_UNUSED; | ||||
| } | ||||
| 
 | ||||
| static struct vm_struct * split_im_region(unsigned long v_addr,  | ||||
| 		unsigned long size, struct vm_struct *parent) | ||||
| { | ||||
| 	struct vm_struct *vm1 = NULL; | ||||
| 	struct vm_struct *vm2 = NULL; | ||||
| 	struct vm_struct *new_vm = NULL; | ||||
| 	 | ||||
| 	vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL); | ||||
| 	if (vm1	== NULL) { | ||||
| 		printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (v_addr == (unsigned long) parent->addr) { | ||||
| 	        /* Use existing parent vm_struct to represent child, allocate
 | ||||
| 		 * new one for the remainder of parent range | ||||
| 		 */ | ||||
| 		vm1->size = parent->size - size; | ||||
| 		vm1->addr = (void *) (v_addr + size); | ||||
| 		vm1->next = parent->next; | ||||
| 
 | ||||
| 		parent->size = size; | ||||
| 		parent->next = vm1; | ||||
| 		new_vm = parent; | ||||
| 	} else if (v_addr + size == (unsigned long) parent->addr +  | ||||
| 			parent->size) { | ||||
| 		/* Allocate new vm_struct to represent child, use existing
 | ||||
| 		 * parent one for remainder of parent range | ||||
| 		 */ | ||||
| 		vm1->size = size; | ||||
| 		vm1->addr = (void *) v_addr; | ||||
| 		vm1->next = parent->next; | ||||
| 		new_vm = vm1; | ||||
| 
 | ||||
| 		parent->size -= size; | ||||
| 		parent->next = vm1; | ||||
| 	} else { | ||||
| 	        /* Allocate two new vm_structs for the new child and 
 | ||||
| 		 * uppermost remainder, and use existing parent one for the | ||||
| 		 * lower remainder of parent range | ||||
| 		 */ | ||||
| 		vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL); | ||||
| 		if (vm2 == NULL) { | ||||
| 			printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||||
| 			kfree(vm1); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 
 | ||||
| 		vm1->size = size; | ||||
| 		vm1->addr = (void *) v_addr; | ||||
| 		vm1->next = vm2; | ||||
| 		new_vm = vm1; | ||||
| 
 | ||||
| 		vm2->size = ((unsigned long) parent->addr + parent->size) -  | ||||
| 				(v_addr + size); | ||||
| 		vm2->addr = (void *) v_addr + size; | ||||
| 		vm2->next = parent->next; | ||||
| 
 | ||||
| 		parent->size = v_addr - (unsigned long) parent->addr; | ||||
| 		parent->next = vm1; | ||||
| 	} | ||||
| 
 | ||||
| 	return new_vm; | ||||
| } | ||||
| 
 | ||||
| static struct vm_struct * __add_new_im_area(unsigned long req_addr,  | ||||
| 					    unsigned long size) | ||||
| { | ||||
| 	struct vm_struct **p, *tmp, *area; | ||||
| 		 | ||||
| 	for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||||
| 		if (req_addr + size <= (unsigned long)tmp->addr) | ||||
| 			break; | ||||
| 	} | ||||
| 	 | ||||
| 	area = kmalloc(sizeof(*area), GFP_KERNEL); | ||||
| 	if (!area) | ||||
| 		return NULL; | ||||
| 	area->flags = 0; | ||||
| 	area->addr = (void *)req_addr; | ||||
| 	area->size = size; | ||||
| 	area->next = *p; | ||||
| 	*p = area; | ||||
| 
 | ||||
| 	return area; | ||||
| } | ||||
| 
 | ||||
| static struct vm_struct * __im_get_area(unsigned long req_addr,  | ||||
| 					unsigned long size, | ||||
| 					int criteria) | ||||
| { | ||||
| 	struct vm_struct *tmp; | ||||
| 	int status; | ||||
| 
 | ||||
| 	status = im_region_status(req_addr, size, &tmp); | ||||
| 	if ((criteria & status) == 0) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	 | ||||
| 	switch (status) { | ||||
| 	case IM_REGION_UNUSED: | ||||
| 		tmp = __add_new_im_area(req_addr, size); | ||||
| 		break; | ||||
| 	case IM_REGION_SUBSET: | ||||
| 		tmp = split_im_region(req_addr, size, tmp); | ||||
| 		break; | ||||
| 	case IM_REGION_EXISTS: | ||||
| 		/* Return requested region */ | ||||
| 		break; | ||||
| 	case IM_REGION_SUPERSET: | ||||
| 		/* Return first existing subset of requested region */ | ||||
| 		break; | ||||
| 	default: | ||||
| 		printk(KERN_ERR "%s() unexpected imalloc region status\n", | ||||
| 				__FUNCTION__); | ||||
| 		tmp = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return tmp; | ||||
| } | ||||
| 
 | ||||
| struct vm_struct * im_get_free_area(unsigned long size) | ||||
| { | ||||
| 	struct vm_struct *area; | ||||
| 	unsigned long addr; | ||||
| 	 | ||||
| 	mutex_lock(&imlist_mutex); | ||||
| 	if (get_free_im_addr(size, &addr)) { | ||||
| 		printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", | ||||
| 				__FUNCTION__, size); | ||||
| 		area = NULL; | ||||
| 		goto next_im_done; | ||||
| 	} | ||||
| 
 | ||||
| 	area = __im_get_area(addr, size, IM_REGION_UNUSED); | ||||
| 	if (area == NULL) { | ||||
| 		printk(KERN_ERR  | ||||
| 		       "%s() cannot obtain area for addr 0x%lx size 0x%lx\n", | ||||
| 			__FUNCTION__, addr, size); | ||||
| 	} | ||||
| next_im_done: | ||||
| 	mutex_unlock(&imlist_mutex); | ||||
| 	return area; | ||||
| } | ||||
| 
 | ||||
| struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||||
| 		int criteria) | ||||
| { | ||||
| 	struct vm_struct *area; | ||||
| 
 | ||||
| 	mutex_lock(&imlist_mutex); | ||||
| 	area = __im_get_area(v_addr, size, criteria); | ||||
| 	mutex_unlock(&imlist_mutex); | ||||
| 	return area; | ||||
| } | ||||
| 
 | ||||
| void im_free(void * addr) | ||||
| { | ||||
| 	struct vm_struct **p, *tmp; | ||||
|    | ||||
| 	if (!addr) | ||||
| 		return; | ||||
| 	if ((unsigned long) addr & ~PAGE_MASK) { | ||||
| 		printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__,			addr); | ||||
| 		return; | ||||
| 	} | ||||
| 	mutex_lock(&imlist_mutex); | ||||
| 	for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { | ||||
| 		if (tmp->addr == addr) { | ||||
| 			*p = tmp->next; | ||||
| 			unmap_vm_area(tmp); | ||||
| 			kfree(tmp); | ||||
| 			mutex_unlock(&imlist_mutex); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 	mutex_unlock(&imlist_mutex); | ||||
| 	printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, | ||||
| 			addr); | ||||
| } | ||||
| @ -5,7 +5,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  | ||||
| @ -5,7 +5,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
|  | ||||
| @ -5,7 +5,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  *  PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
| @ -129,8 +128,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) | ||||
| 	zone = pgdata->node_zones; | ||||
| 
 | ||||
| 	return __add_pages(zone, start_pfn, nr_pages); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -11,7 +11,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
|  | ||||
| @ -8,7 +8,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
| @ -40,8 +39,8 @@ extern int __map_without_bats; | ||||
| extern unsigned long ioremap_base; | ||||
| extern unsigned int rtas_data, rtas_size; | ||||
| 
 | ||||
| struct _PTE; | ||||
| extern struct _PTE *Hash, *Hash_end; | ||||
| struct hash_pte; | ||||
| extern struct hash_pte *Hash, *Hash_end; | ||||
| extern unsigned long Hash_size, Hash_mask; | ||||
| 
 | ||||
| extern unsigned int num_tlbcam_entries; | ||||
| @ -90,16 +89,4 @@ static inline void flush_HPTE(unsigned context, unsigned long va, | ||||
| 	else | ||||
| 		_tlbie(va); | ||||
| } | ||||
| #else /* CONFIG_PPC64 */ | ||||
| /* imalloc region types */ | ||||
| #define IM_REGION_UNUSED	0x1 | ||||
| #define IM_REGION_SUBSET	0x2 | ||||
| #define IM_REGION_EXISTS	0x4 | ||||
| #define IM_REGION_OVERLAP	0x8 | ||||
| #define IM_REGION_SUPERSET	0x10 | ||||
| 
 | ||||
| extern struct vm_struct * im_get_free_area(unsigned long size); | ||||
| extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||||
| 				      int region_type); | ||||
| extern void im_free(void *addr); | ||||
| #endif | ||||
|  | ||||
| @ -8,7 +8,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
| @ -37,7 +36,6 @@ | ||||
| unsigned long ioremap_base; | ||||
| unsigned long ioremap_bot; | ||||
| EXPORT_SYMBOL(ioremap_bot);	/* aka VMALLOC_END */ | ||||
| int io_bat_index; | ||||
| 
 | ||||
| #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) | ||||
| #define HAVE_BATS	1 | ||||
| @ -300,51 +298,6 @@ void __init mapin_ram(void) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* is x a power of 4? */ | ||||
| #define is_power_of_4(x)	is_power_of_2(x) && (ffs(x) & 1) | ||||
| 
 | ||||
| /*
 | ||||
|  * Set up a mapping for a block of I/O. | ||||
|  * virt, phys, size must all be page-aligned. | ||||
|  * This should only be called before ioremap is called. | ||||
|  */ | ||||
| void __init io_block_mapping(unsigned long virt, phys_addr_t phys, | ||||
| 			     unsigned int size, int flags) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (virt > KERNELBASE && virt < ioremap_bot) | ||||
| 		ioremap_bot = ioremap_base = virt; | ||||
| 
 | ||||
| #ifdef HAVE_BATS | ||||
| 	/*
 | ||||
| 	 * Use a BAT for this if possible... | ||||
| 	 */ | ||||
| 	if (io_bat_index < 2 && is_power_of_2(size) | ||||
| 	    && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { | ||||
| 		setbat(io_bat_index, virt, phys, size, flags); | ||||
| 		++io_bat_index; | ||||
| 		return; | ||||
| 	} | ||||
| #endif /* HAVE_BATS */ | ||||
| 
 | ||||
| #ifdef HAVE_TLBCAM | ||||
| 	/*
 | ||||
| 	 * Use a CAM for this if possible... | ||||
| 	 */ | ||||
| 	if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size) | ||||
| 	    && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { | ||||
| 		settlbcam(tlbcam_index, virt, phys, size, flags, 0); | ||||
| 		++tlbcam_index; | ||||
| 		return; | ||||
| 	} | ||||
| #endif /* HAVE_TLBCAM */ | ||||
| 
 | ||||
| 	/* No BATs available, put it in the page tables. */ | ||||
| 	for (i = 0; i < size; i += PAGE_SIZE) | ||||
| 		map_page(virt + i, phys + i, flags); | ||||
| } | ||||
| 
 | ||||
| /* Scan the real Linux page tables and return a PTE pointer for
 | ||||
|  * a virtual address in a context. | ||||
|  * Returns true (1) if PTE was found, zero otherwise.  The pointer to | ||||
| @ -379,82 +332,6 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) | ||||
|         return(retval); | ||||
| } | ||||
| 
 | ||||
| /* Find physical address for this virtual address.  Normally used by
 | ||||
|  * I/O functions, but anyone can call it. | ||||
|  */ | ||||
| unsigned long iopa(unsigned long addr) | ||||
| { | ||||
| 	unsigned long pa; | ||||
| 
 | ||||
| 	/* I don't know why this won't work on PMacs or CHRP.  It
 | ||||
| 	 * appears there is some bug, or there is some implicit | ||||
| 	 * mapping done not properly represented by BATs or in page | ||||
| 	 * tables.......I am actively working on resolving this, but | ||||
| 	 * can't hold up other stuff.  -- Dan | ||||
| 	 */ | ||||
| 	pte_t *pte; | ||||
| 	struct mm_struct *mm; | ||||
| 
 | ||||
| 	/* Check the BATs */ | ||||
| 	pa = v_mapped_by_bats(addr); | ||||
| 	if (pa) | ||||
| 		return pa; | ||||
| 
 | ||||
| 	/* Allow mapping of user addresses (within the thread)
 | ||||
| 	 * for DMA if necessary. | ||||
| 	 */ | ||||
| 	if (addr < TASK_SIZE) | ||||
| 		mm = current->mm; | ||||
| 	else | ||||
| 		mm = &init_mm; | ||||
| 
 | ||||
| 	pa = 0; | ||||
| 	if (get_pteptr(mm, addr, &pte, NULL)) { | ||||
| 		pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); | ||||
| 		pte_unmap(pte); | ||||
| 	} | ||||
| 
 | ||||
| 	return(pa); | ||||
| } | ||||
| 
 | ||||
| /* This is will find the virtual address for a physical one....
 | ||||
|  * Swiped from APUS, could be dangerous :-). | ||||
|  * This is only a placeholder until I really find a way to make this | ||||
|  * work.  -- Dan | ||||
|  */ | ||||
| unsigned long | ||||
| mm_ptov (unsigned long paddr) | ||||
| { | ||||
| 	unsigned long ret; | ||||
| #if 0 | ||||
| 	if (paddr < 16*1024*1024) | ||||
| 		ret = ZTWO_VADDR(paddr); | ||||
| 	else { | ||||
| 		int i; | ||||
| 
 | ||||
| 		for (i = 0; i < kmap_chunk_count;){ | ||||
| 			unsigned long phys = kmap_chunks[i++]; | ||||
| 			unsigned long size = kmap_chunks[i++]; | ||||
| 			unsigned long virt = kmap_chunks[i++]; | ||||
| 			if (paddr >= phys | ||||
| 			    && paddr < (phys + size)){ | ||||
| 				ret = virt + paddr - phys; | ||||
| 				goto exit; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 		ret = (unsigned long) __va(paddr); | ||||
| 	} | ||||
| exit: | ||||
| #ifdef DEBUGPV | ||||
| 	printk ("PTOV(%lx)=%lx\n", paddr, ret); | ||||
| #endif | ||||
| #else | ||||
| 	ret = (unsigned long)paddr + KERNELBASE; | ||||
| #endif | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_DEBUG_PAGEALLOC | ||||
| 
 | ||||
| static int __change_page_attr(struct page *page, pgprot_t prot) | ||||
|  | ||||
| @ -7,7 +7,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
| @ -34,41 +33,27 @@ | ||||
| #include <linux/stddef.h> | ||||
| #include <linux/vmalloc.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/bootmem.h> | ||||
| #include <linux/highmem.h> | ||||
| #include <linux/idr.h> | ||||
| #include <linux/nodemask.h> | ||||
| #include <linux/module.h> | ||||
| 
 | ||||
| #include <asm/pgalloc.h> | ||||
| #include <asm/page.h> | ||||
| #include <asm/prom.h> | ||||
| #include <asm/lmb.h> | ||||
| #include <asm/rtas.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/mmu_context.h> | ||||
| #include <asm/pgtable.h> | ||||
| #include <asm/mmu.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <asm/smp.h> | ||||
| #include <asm/machdep.h> | ||||
| #include <asm/tlb.h> | ||||
| #include <asm/eeh.h> | ||||
| #include <asm/processor.h> | ||||
| #include <asm/mmzone.h> | ||||
| #include <asm/cputable.h> | ||||
| #include <asm/sections.h> | ||||
| #include <asm/system.h> | ||||
| #include <asm/iommu.h> | ||||
| #include <asm/abs_addr.h> | ||||
| #include <asm/vdso.h> | ||||
| #include <asm/firmware.h> | ||||
| 
 | ||||
| #include "mmu_decl.h" | ||||
| 
 | ||||
| unsigned long ioremap_bot = IMALLOC_BASE; | ||||
| static unsigned long phbs_io_bot = PHBS_IO_BASE; | ||||
| unsigned long ioremap_bot = IOREMAP_BASE; | ||||
| 
 | ||||
| /*
 | ||||
|  * map_io_page currently only called by __ioremap | ||||
| @ -102,8 +87,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | ||||
| 		 * entry in the hardware page table. | ||||
| 		 * | ||||
| 		 */ | ||||
| 		if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | ||||
| 				      mmu_io_psize)) { | ||||
| 		if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE, | ||||
| 				      pa, flags, mmu_io_psize)) { | ||||
| 			printk(KERN_ERR "Failed to do bolted mapping IO " | ||||
| 			       "memory at %016lx !\n", pa); | ||||
| 			return -ENOMEM; | ||||
| @ -113,8 +98,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | ||||
| 			    unsigned long ea, unsigned long size, | ||||
| /**
 | ||||
|  * __ioremap_at - Low level function to establish the page tables | ||||
|  *                for an IO mapping | ||||
|  */ | ||||
| void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, | ||||
| 			    unsigned long flags) | ||||
| { | ||||
| 	unsigned long i; | ||||
| @ -122,17 +110,35 @@ static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | ||||
| 	if ((flags & _PAGE_PRESENT) == 0) | ||||
| 		flags |= pgprot_val(PAGE_KERNEL); | ||||
| 
 | ||||
| 	WARN_ON(pa & ~PAGE_MASK); | ||||
| 	WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||||
| 	WARN_ON(size & ~PAGE_MASK); | ||||
| 
 | ||||
| 	for (i = 0; i < size; i += PAGE_SIZE) | ||||
| 		if (map_io_page(ea+i, pa+i, flags)) | ||||
| 		if (map_io_page((unsigned long)ea+i, pa+i, flags)) | ||||
| 			return NULL; | ||||
| 
 | ||||
| 	return (void __iomem *) (ea + (addr & ~PAGE_MASK)); | ||||
| 	return (void __iomem *)ea; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * __iounmap_from - Low level function to tear down the page tables | ||||
|  *                  for an IO mapping. This is used for mappings that | ||||
|  *                  are manipulated manually, like partial unmapping of | ||||
|  *                  PCI IOs or ISA space. | ||||
|  */ | ||||
| void __iounmap_at(void *ea, unsigned long size) | ||||
| { | ||||
| 	WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||||
| 	WARN_ON(size & ~PAGE_MASK); | ||||
| 
 | ||||
| 	unmap_kernel_range((unsigned long)ea, size); | ||||
| } | ||||
| 
 | ||||
| void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | ||||
| 			 unsigned long flags) | ||||
| { | ||||
| 	unsigned long pa, ea; | ||||
| 	phys_addr_t paligned; | ||||
| 	void __iomem *ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -144,27 +150,30 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | ||||
| 	 * IMALLOC_END | ||||
| 	 *  | ||||
| 	 */ | ||||
| 	pa = addr & PAGE_MASK; | ||||
| 	size = PAGE_ALIGN(addr + size) - pa; | ||||
| 	paligned = addr & PAGE_MASK; | ||||
| 	size = PAGE_ALIGN(addr + size) - paligned; | ||||
| 
 | ||||
| 	if ((size == 0) || (pa == 0)) | ||||
| 	if ((size == 0) || (paligned == 0)) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if (mem_init_done) { | ||||
| 		struct vm_struct *area; | ||||
| 		area = im_get_free_area(size); | ||||
| 
 | ||||
| 		area = __get_vm_area(size, VM_IOREMAP, | ||||
| 				     ioremap_bot, IOREMAP_END); | ||||
| 		if (area == NULL) | ||||
| 			return NULL; | ||||
| 		ea = (unsigned long)(area->addr); | ||||
| 		ret = __ioremap_com(addr, pa, ea, size, flags); | ||||
| 		ret = __ioremap_at(paligned, area->addr, size, flags); | ||||
| 		if (!ret) | ||||
| 			im_free(area->addr); | ||||
| 			vunmap(area->addr); | ||||
| 	} else { | ||||
| 		ea = ioremap_bot; | ||||
| 		ret = __ioremap_com(addr, pa, ea, size, flags); | ||||
| 		ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); | ||||
| 		if (ret) | ||||
| 			ioremap_bot += size; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ret) | ||||
| 		ret += addr & ~PAGE_MASK; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| @ -187,62 +196,9 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) | ||||
| 
 | ||||
| int __ioremap_explicit(phys_addr_t pa, unsigned long ea, | ||||
| 		       unsigned long size, unsigned long flags) | ||||
| { | ||||
| 	struct vm_struct *area; | ||||
| 	void __iomem *ret; | ||||
| 	 | ||||
| 	/* For now, require page-aligned values for pa, ea, and size */ | ||||
| 	if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || | ||||
| 	    !IS_PAGE_ALIGNED(size)) { | ||||
| 		printk(KERN_ERR	"unaligned value in %s\n", __FUNCTION__); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	 | ||||
| 	if (!mem_init_done) { | ||||
| 		/* Two things to consider in this case:
 | ||||
| 		 * 1) No records will be kept (imalloc, etc) that the region | ||||
| 		 *    has been remapped | ||||
| 		 * 2) It won't be easy to iounmap() the region later (because | ||||
| 		 *    of 1) | ||||
| 		 */ | ||||
| 		; | ||||
| 	} else { | ||||
| 		area = im_get_area(ea, size, | ||||
| 			IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS); | ||||
| 		if (area == NULL) { | ||||
| 			/* Expected when PHB-dlpar is in play */ | ||||
| 			return 1; | ||||
| 		} | ||||
| 		if (ea != (unsigned long) area->addr) { | ||||
| 			printk(KERN_ERR "unexpected addr return from " | ||||
| 			       "im_get_area\n"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	ret = __ioremap_com(pa, pa, ea, size, flags); | ||||
| 	if (ret == NULL) { | ||||
| 		printk(KERN_ERR "ioremap_explicit() allocation failure !\n"); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	if (ret != (void *) ea) { | ||||
| 		printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*  
 | ||||
|  * Unmap an IO region and remove it from imalloc'd list. | ||||
|  * Access to IO memory should be serialized by driver. | ||||
|  * This code is modeled after vmalloc code - unmap_vm_area() | ||||
|  * | ||||
|  * XXX	what about calls before mem_init_done (ie python_countermeasures()) | ||||
|  */ | ||||
| void __iounmap(volatile void __iomem *token) | ||||
| { | ||||
| @ -251,9 +207,14 @@ void __iounmap(volatile void __iomem *token) | ||||
| 	if (!mem_init_done) | ||||
| 		return; | ||||
| 	 | ||||
| 	addr = (void *) ((unsigned long __force) token & PAGE_MASK); | ||||
| 
 | ||||
| 	im_free(addr); | ||||
| 	addr = (void *) ((unsigned long __force) | ||||
| 			 PCI_FIX_ADDR(token) & PAGE_MASK); | ||||
| 	if ((unsigned long)addr < ioremap_bot) { | ||||
| 		printk(KERN_WARNING "Attempt to iounmap early bolted mapping" | ||||
| 		       " at 0x%p\n", addr); | ||||
| 		return; | ||||
| 	} | ||||
| 	vunmap(addr); | ||||
| } | ||||
| 
 | ||||
| void iounmap(volatile void __iomem *token) | ||||
| @ -264,77 +225,8 @@ void iounmap(volatile void __iomem *token) | ||||
| 		__iounmap(token); | ||||
| } | ||||
| 
 | ||||
| static int iounmap_subset_regions(unsigned long addr, unsigned long size) | ||||
| { | ||||
| 	struct vm_struct *area; | ||||
| 
 | ||||
| 	/* Check whether subsets of this region exist */ | ||||
| 	area = im_get_area(addr, size, IM_REGION_SUPERSET); | ||||
| 	if (area == NULL) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	while (area) { | ||||
| 		iounmap((void __iomem *) area->addr); | ||||
| 		area = im_get_area(addr, size, | ||||
| 				IM_REGION_SUPERSET); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int __iounmap_explicit(volatile void __iomem *start, unsigned long size) | ||||
| { | ||||
| 	struct vm_struct *area; | ||||
| 	unsigned long addr; | ||||
| 	int rc; | ||||
| 	 | ||||
| 	addr = (unsigned long __force) start & PAGE_MASK; | ||||
| 
 | ||||
| 	/* Verify that the region either exists or is a subset of an existing
 | ||||
| 	 * region.  In the latter case, split the parent region to create  | ||||
| 	 * the exact region  | ||||
| 	 */ | ||||
| 	area = im_get_area(addr, size,  | ||||
| 			    IM_REGION_EXISTS | IM_REGION_SUBSET); | ||||
| 	if (area == NULL) { | ||||
| 		/* Determine whether subset regions exist.  If so, unmap */ | ||||
| 		rc = iounmap_subset_regions(addr, size); | ||||
| 		if (rc) { | ||||
| 			printk(KERN_ERR | ||||
| 			       "%s() cannot unmap nonexistent range 0x%lx\n", | ||||
|  				__FUNCTION__, addr); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} else { | ||||
| 		iounmap((void __iomem *) area->addr); | ||||
| 	} | ||||
| 	/*
 | ||||
| 	 * FIXME! This can't be right: | ||||
| 	iounmap(area->addr); | ||||
| 	 * Maybe it should be "iounmap(area);" | ||||
| 	 */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| EXPORT_SYMBOL(ioremap); | ||||
| EXPORT_SYMBOL(ioremap_flags); | ||||
| EXPORT_SYMBOL(__ioremap); | ||||
| EXPORT_SYMBOL(iounmap); | ||||
| EXPORT_SYMBOL(__iounmap); | ||||
| 
 | ||||
| static DEFINE_SPINLOCK(phb_io_lock); | ||||
| 
 | ||||
| void __iomem * reserve_phb_iospace(unsigned long size) | ||||
| { | ||||
| 	void __iomem *virt_addr; | ||||
| 		 | ||||
| 	if (phbs_io_bot >= IMALLOC_BASE)  | ||||
| 		panic("reserve_phb_iospace(): phb io space overflow\n"); | ||||
| 			 | ||||
| 	spin_lock(&phb_io_lock); | ||||
| 	virt_addr = (void __iomem *) phbs_io_bot; | ||||
| 	phbs_io_bot += size; | ||||
| 	spin_unlock(&phb_io_lock); | ||||
| 
 | ||||
| 	return virt_addr; | ||||
| } | ||||
|  | ||||
| @ -11,7 +11,6 @@ | ||||
|  *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | ||||
|  *  and Cort Dougan (PReP) (cort@cs.nmt.edu) | ||||
|  *    Copyright (C) 1996 Paul Mackerras | ||||
|  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||||
|  * | ||||
|  *  Derived from "arch/i386/mm/init.c" | ||||
|  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds | ||||
| @ -35,12 +34,12 @@ | ||||
| 
 | ||||
| #include "mmu_decl.h" | ||||
| 
 | ||||
| PTE *Hash, *Hash_end; | ||||
| struct hash_pte *Hash, *Hash_end; | ||||
| unsigned long Hash_size, Hash_mask; | ||||
| unsigned long _SDR1; | ||||
| 
 | ||||
| union ubat {			/* BAT register values to be loaded */ | ||||
| 	BAT	bat; | ||||
| 	struct ppc_bat bat; | ||||
| 	u32	word[2]; | ||||
| } BATS[8][2];			/* 8 pairs of IBAT, DBAT */ | ||||
| 
 | ||||
| @ -245,7 +244,7 @@ void __init MMU_init_hw(void) | ||||
| 	cacheable_memzero(Hash, Hash_size); | ||||
| 	_SDR1 = __pa(Hash) | SDR1_LOW_BITS; | ||||
| 
 | ||||
| 	Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); | ||||
| 	Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size); | ||||
| 
 | ||||
| 	printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", | ||||
| 	       total_memory >> 20, Hash_size >> 10, Hash); | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user