aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/Kconfig4
-rw-r--r--arch/powerpc/boot/dts/bluestone.dts25
-rw-r--r--arch/powerpc/kernel/misc_32.S203
-rw-r--r--arch/powerpc/platforms/44x/Kconfig2
-rw-r--r--arch/powerpc/sysdev/ppc4xx_msi.c42
5 files changed, 252 insertions, 24 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index feab3bad6d0f..38786c821e98 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -353,7 +353,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
353 353
354config KEXEC 354config KEXEC
355 bool "kexec system call (EXPERIMENTAL)" 355 bool "kexec system call (EXPERIMENTAL)"
356 depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL 356 depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) && EXPERIMENTAL
357 help 357 help
358 kexec is a system call that implements the ability to shutdown your 358 kexec is a system call that implements the ability to shutdown your
359 current kernel, and to start another kernel. It is like a reboot 359 current kernel, and to start another kernel. It is like a reboot
@@ -370,7 +370,7 @@ config KEXEC
370 370
371config CRASH_DUMP 371config CRASH_DUMP
372 bool "Build a kdump crash kernel" 372 bool "Build a kdump crash kernel"
373 depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP && !PPC_47x) 373 depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
374 select RELOCATABLE if PPC64 || 44x 374 select RELOCATABLE if PPC64 || 44x
375 select DYNAMIC_MEMSTART if FSL_BOOKE 375 select DYNAMIC_MEMSTART if FSL_BOOKE
376 help 376 help
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
index 7bda373f10ef..9d4917aebe6b 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -373,5 +373,30 @@
373 0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */ 373 0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */
374 0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>; 374 0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>;
375 }; 375 };
376
377 MSI: ppc4xx-msi@C10000000 {
378 compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
379 reg = < 0xC 0x10000000 0x100
380 0xC 0x10000000 0x100>;
381 sdr-base = <0x36C>;
382 msi-data = <0x00004440>;
383 msi-mask = <0x0000ffe0>;
384 interrupts =<0 1 2 3 4 5 6 7>;
385 interrupt-parent = <&MSI>;
386 #interrupt-cells = <1>;
387 #address-cells = <0>;
388 #size-cells = <0>;
389 msi-available-ranges = <0x0 0x100>;
390 interrupt-map = <
391 0 &UIC3 0x18 1
392 1 &UIC3 0x19 1
393 2 &UIC3 0x1A 1
394 3 &UIC3 0x1B 1
395 4 &UIC3 0x1C 1
396 5 &UIC3 0x1D 1
397 6 &UIC3 0x1E 1
398 7 &UIC3 0x1F 1
399 >;
400 };
376 }; 401 };
377}; 402};
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 7cd07b42ca1a..386d57f66f28 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -738,8 +738,23 @@ relocate_new_kernel:
738 mr r5, r31 738 mr r5, r31
739 739
740 li r0, 0 740 li r0, 0
741#elif defined(CONFIG_44x) && !defined(CONFIG_PPC_47x) 741#elif defined(CONFIG_44x)
742 742
743 /* Save our parameters */
744 mr r29, r3
745 mr r30, r4
746 mr r31, r5
747
748#ifdef CONFIG_PPC_47x
749 /* Check for 47x cores */
750 mfspr r3,SPRN_PVR
751 srwi r3,r3,16
752 cmplwi cr0,r3,PVR_476@h
753 beq setup_map_47x
754 cmplwi cr0,r3,PVR_476_ISS@h
755 beq setup_map_47x
756#endif /* CONFIG_PPC_47x */
757
743/* 758/*
744 * Code for setting up 1:1 mapping for PPC440x for KEXEC 759 * Code for setting up 1:1 mapping for PPC440x for KEXEC
745 * 760 *
@@ -753,16 +768,15 @@ relocate_new_kernel:
753 * 5) Invalidate the tmp mapping. 768 * 5) Invalidate the tmp mapping.
754 * 769 *
755 * - Based on the kexec support code for FSL BookE 770 * - Based on the kexec support code for FSL BookE
756 * - Doesn't support 47x yet.
757 * 771 *
758 */ 772 */
759 /* Save our parameters */
760 mr r29, r3
761 mr r30, r4
762 mr r31, r5
763 773
764 /* Load our MSR_IS and TID to MMUCR for TLB search */ 774 /*
765 mfspr r3,SPRN_PID 775 * Load the PID with kernel PID (0).
776 * Also load our MSR_IS and TID to MMUCR for TLB search.
777 */
778 li r3, 0
779 mtspr SPRN_PID, r3
766 mfmsr r4 780 mfmsr r4
767 andi. r4,r4,MSR_IS@l 781 andi. r4,r4,MSR_IS@l
768 beq wmmucr 782 beq wmmucr
@@ -900,6 +914,179 @@ next_tlb:
900 li r3, 0 914 li r3, 0
901 tlbwe r3, r24, PPC44x_TLB_PAGEID 915 tlbwe r3, r24, PPC44x_TLB_PAGEID
902 sync 916 sync
917 b ppc44x_map_done
918
919#ifdef CONFIG_PPC_47x
920
921 /* 1:1 mapping for 47x */
922
923setup_map_47x:
924
925 /*
926 * Load the kernel pid (0) to PID and also to MMUCR[TID].
927 * Also set the MSR IS->MMUCR STS
928 */
929 li r3, 0
930 mtspr SPRN_PID, r3 /* Set PID */
931 mfmsr r4 /* Get MSR */
932 andi. r4, r4, MSR_IS@l /* TS=1? */
933 beq 1f /* If not, leave STS=0 */
934 oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */
9351: mtspr SPRN_MMUCR, r3 /* Put MMUCR */
936 sync
937
938 /* Find the entry we are running from */
939 bl 2f
9402: mflr r23
941 tlbsx r23, 0, r23
942 tlbre r24, r23, 0 /* TLB Word 0 */
943 tlbre r25, r23, 1 /* TLB Word 1 */
944 tlbre r26, r23, 2 /* TLB Word 2 */
945
946
947 /*
948 * Invalidates all the tlb entries by writing to 256 RPNs(r4)
949 * of 4k page size in all 4 ways (0-3 in r3).
950 * This would invalidate the entire UTLB including the one we are
951 * running from. However the shadow TLB entries would help us
952 * to continue the execution, until we flush them (rfi/isync).
953 */
954 addis r3, 0, 0x8000 /* specify the way */
955 addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */
956 addi r5, 0, 0
957 b clear_utlb_entry
958
959 /* Align the loop to speed things up. from head_44x.S */
960 .align 6
961
962clear_utlb_entry:
963
964 tlbwe r4, r3, 0
965 tlbwe r5, r3, 1
966 tlbwe r5, r3, 2
967 addis r3, r3, 0x2000 /* Increment the way */
968 cmpwi r3, 0
969 bne clear_utlb_entry
970 addis r3, 0, 0x8000
971 addis r4, r4, 0x100 /* Increment the EPN */
972 cmpwi r4, 0
973 bne clear_utlb_entry
974
975 /* Create the entries in the other address space */
976 mfmsr r5
977 rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */
978 xori r7, r7, 1 /* r7 = !TS */
979
980 insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */
981
982 /*
983 * write out the TLB entries for the tmp mapping
984 * Use way '0' so that we could easily invalidate it later.
985 */
986 lis r3, 0x8000 /* Way '0' */
987
988 tlbwe r24, r3, 0
989 tlbwe r25, r3, 1
990 tlbwe r26, r3, 2
991
992 /* Update the msr to the new TS */
993 insrwi r5, r7, 1, 26
994
995 bl 1f
9961: mflr r6
997 addi r6, r6, (2f-1b)
998
999 mtspr SPRN_SRR0, r6
1000 mtspr SPRN_SRR1, r5
1001 rfi
1002
1003 /*
1004 * Now we are in the tmp address space.
1005 * Create a 1:1 mapping for 0-2GiB in the original TS.
1006 */
10072:
1008 li r3, 0
1009 li r4, 0 /* TLB Word 0 */
1010 li r5, 0 /* TLB Word 1 */
1011 li r6, 0
1012 ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */
1013
1014 li r8, 0 /* PageIndex */
1015
1016 xori r7, r7, 1 /* revert back to original TS */
1017
1018write_utlb:
1019 rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */
1020 /* ERPN = 0 as we don't use memory above 2G */
1021
1022 mr r4, r5 /* EPN = RPN */
1023 ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
1024 insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */
1025
1026 tlbwe r4, r3, 0 /* Write out the entries */
1027 tlbwe r5, r3, 1
1028 tlbwe r6, r3, 2
1029 addi r8, r8, 1
1030 cmpwi r8, 8 /* Have we completed ? */
1031 bne write_utlb
1032
1033 /* make sure we complete the TLB write up */
1034 isync
1035
1036 /*
1037 * Prepare to jump to the 1:1 mapping.
1038 * 1) Extract page size of the tmp mapping
1039 * DSIZ = TLB_Word0[22:27]
1040 * 2) Calculate the physical address of the address
1041 * to jump to.
1042 */
1043 rlwinm r10, r24, 0, 22, 27
1044
1045 cmpwi r10, PPC47x_TLB0_4K
1046 bne 0f
1047 li r10, 0x1000 /* r10 = 4k */
1048 bl 1f
1049
10500:
1051 /* Defaults to 256M */
1052 lis r10, 0x1000
1053
1054 bl 1f
10551: mflr r4
1056 addi r4, r4, (2f-1b) /* virtual address of 2f */
1057
1058 subi r11, r10, 1 /* offsetmask = Pagesize - 1 */
1059 not r10, r11 /* Pagemask = ~(offsetmask) */
1060
1061 and r5, r25, r10 /* Physical page */
1062 and r6, r4, r11 /* offset within the current page */
1063
1064 or r5, r5, r6 /* Physical address for 2f */
1065
1066 /* Switch the TS in MSR to the original one */
1067 mfmsr r8
1068 insrwi r8, r7, 1, 26
1069
1070 mtspr SPRN_SRR1, r8
1071 mtspr SPRN_SRR0, r5
1072 rfi
1073
10742:
1075 /* Invalidate the tmp mapping */
1076 lis r3, 0x8000 /* Way '0' */
1077
1078 clrrwi r24, r24, 12 /* Clear the valid bit */
1079 tlbwe r24, r3, 0
1080 tlbwe r25, r3, 1
1081 tlbwe r26, r3, 2
1082
1083 /* Make sure we complete the TLB write and flush the shadow TLB */
1084 isync
1085
1086#endif
1087
1088ppc44x_map_done:
1089
903 1090
904 /* Restore the parameters */ 1091 /* Restore the parameters */
905 mr r3, r29 1092 mr r3, r29
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 2e4e64abfab4..8abf6fb8f410 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -23,6 +23,8 @@ config BLUESTONE
23 default n 23 default n
24 select PPC44x_SIMPLE 24 select PPC44x_SIMPLE
25 select APM821xx 25 select APM821xx
26 select PCI_MSI
27 select PPC4xx_MSI
26 select PPC4xx_PCI_EXPRESS 28 select PPC4xx_PCI_EXPRESS
27 select IBM_EMAC_RGMII 29 select IBM_EMAC_RGMII
28 help 30 help
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
index 1c2d7af17bbe..82c6702dcbab 100644
--- a/arch/powerpc/sysdev/ppc4xx_msi.c
+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
@@ -28,10 +28,11 @@
28#include <linux/of_platform.h> 28#include <linux/of_platform.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/export.h> 30#include <linux/export.h>
31#include <linux/kernel.h>
31#include <asm/prom.h> 32#include <asm/prom.h>
32#include <asm/hw_irq.h> 33#include <asm/hw_irq.h>
33#include <asm/ppc-pci.h> 34#include <asm/ppc-pci.h>
34#include <boot/dcr.h> 35#include <asm/dcr.h>
35#include <asm/dcr-regs.h> 36#include <asm/dcr-regs.h>
36#include <asm/msi_bitmap.h> 37#include <asm/msi_bitmap.h>
37 38
@@ -43,13 +44,14 @@
43#define PEIH_FLUSH0 0x30 44#define PEIH_FLUSH0 0x30
44#define PEIH_FLUSH1 0x38 45#define PEIH_FLUSH1 0x38
45#define PEIH_CNTRST 0x48 46#define PEIH_CNTRST 0x48
46#define NR_MSI_IRQS 4 47
48static int msi_irqs;
47 49
48struct ppc4xx_msi { 50struct ppc4xx_msi {
49 u32 msi_addr_lo; 51 u32 msi_addr_lo;
50 u32 msi_addr_hi; 52 u32 msi_addr_hi;
51 void __iomem *msi_regs; 53 void __iomem *msi_regs;
52 int msi_virqs[NR_MSI_IRQS]; 54 int *msi_virqs;
53 struct msi_bitmap bitmap; 55 struct msi_bitmap bitmap;
54 struct device_node *msi_dev; 56 struct device_node *msi_dev;
55}; 57};
@@ -61,7 +63,7 @@ static int ppc4xx_msi_init_allocator(struct platform_device *dev,
61{ 63{
62 int err; 64 int err;
63 65
64 err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, 66 err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs,
65 dev->dev.of_node); 67 dev->dev.of_node);
66 if (err) 68 if (err)
67 return err; 69 return err;
@@ -83,6 +85,11 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
83 struct msi_desc *entry; 85 struct msi_desc *entry;
84 struct ppc4xx_msi *msi_data = &ppc4xx_msi; 86 struct ppc4xx_msi *msi_data = &ppc4xx_msi;
85 87
88 msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int),
89 GFP_KERNEL);
90 if (!msi_data->msi_virqs)
91 return -ENOMEM;
92
86 list_for_each_entry(entry, &dev->msi_list, list) { 93 list_for_each_entry(entry, &dev->msi_list, list) {
87 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 94 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
88 if (int_no >= 0) 95 if (int_no >= 0)
@@ -150,12 +157,11 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
150 if (!sdr_addr) 157 if (!sdr_addr)
151 return -1; 158 return -1;
152 159
153 SDR0_WRITE(sdr_addr, (u64)res.start >> 32); /*HIGH addr */ 160 mtdcri(SDR0, *sdr_addr, upper_32_bits(res.start)); /*HIGH addr */
154 SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */ 161 mtdcri(SDR0, *sdr_addr + 1, lower_32_bits(res.start)); /* Low addr */
155
156 162
157 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi"); 163 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
158 if (msi->msi_dev) 164 if (!msi->msi_dev)
159 return -ENODEV; 165 return -ENODEV;
160 166
161 msi->msi_regs = of_iomap(msi->msi_dev, 0); 167 msi->msi_regs = of_iomap(msi->msi_dev, 0);
@@ -167,9 +173,12 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
167 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs)); 173 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
168 174
169 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL); 175 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);
170 msi->msi_addr_hi = 0x0; 176 if (!msi_virt)
171 msi->msi_addr_lo = (u32) msi_phys; 177 return -ENOMEM;
172 dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x\n", msi->msi_addr_lo); 178 msi->msi_addr_hi = upper_32_bits(msi_phys);
179 msi->msi_addr_lo = lower_32_bits(msi_phys & 0xffffffff);
180 dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n",
181 msi->msi_addr_hi, msi->msi_addr_lo);
173 182
174 /* Progam the Interrupt handler Termination addr registers */ 183 /* Progam the Interrupt handler Termination addr registers */
175 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi); 184 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
@@ -185,6 +194,8 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
185 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data); 194 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
186 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask); 195 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
187 196
197 dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys);
198
188 return 0; 199 return 0;
189} 200}
190 201
@@ -194,7 +205,7 @@ static int ppc4xx_of_msi_remove(struct platform_device *dev)
194 int i; 205 int i;
195 int virq; 206 int virq;
196 207
197 for (i = 0; i < NR_MSI_IRQS; i++) { 208 for (i = 0; i < msi_irqs; i++) {
198 virq = msi->msi_virqs[i]; 209 virq = msi->msi_virqs[i];
199 if (virq != NO_IRQ) 210 if (virq != NO_IRQ)
200 irq_dispose_mapping(virq); 211 irq_dispose_mapping(virq);
@@ -215,8 +226,6 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
215 struct resource res; 226 struct resource res;
216 int err = 0; 227 int err = 0;
217 228
218 msi = &ppc4xx_msi;/*keep the msi data for further use*/
219
220 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n"); 229 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
221 230
222 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL); 231 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL);
@@ -234,6 +243,10 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
234 goto error_out; 243 goto error_out;
235 } 244 }
236 245
246 msi_irqs = of_irq_count(dev->dev.of_node);
247 if (!msi_irqs)
248 return -ENODEV;
249
237 if (ppc4xx_setup_pcieh_hw(dev, res, msi)) 250 if (ppc4xx_setup_pcieh_hw(dev, res, msi))
238 goto error_out; 251 goto error_out;
239 252
@@ -242,6 +255,7 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
242 dev_err(&dev->dev, "Error allocating MSI bitmap\n"); 255 dev_err(&dev->dev, "Error allocating MSI bitmap\n");
243 goto error_out; 256 goto error_out;
244 } 257 }
258 ppc4xx_msi = *msi;
245 259
246 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs; 260 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
247 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs; 261 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;