aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/pci-calgary.c161
1 files changed, 125 insertions, 36 deletions
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index f53b581dfd0b..afc0a53505f1 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -41,6 +41,7 @@
41#include <asm/pci-direct.h> 41#include <asm/pci-direct.h>
42#include <asm/system.h> 42#include <asm/system.h>
43#include <asm/dma.h> 43#include <asm/dma.h>
44#include <asm/rio.h>
44 45
45#define PCI_DEVICE_ID_IBM_CALGARY 0x02a1 46#define PCI_DEVICE_ID_IBM_CALGARY 0x02a1
46#define PCI_VENDOR_DEVICE_ID_CALGARY \ 47#define PCI_VENDOR_DEVICE_ID_CALGARY \
@@ -115,14 +116,35 @@ static const unsigned long phb_offsets[] = {
115 0xB000 /* PHB3 */ 116 0xB000 /* PHB3 */
116}; 117};
117 118
119/* PHB debug registers */
120
121static const unsigned long phb_debug_offsets[] = {
122 0x4000 /* PHB 0 DEBUG */,
123 0x5000 /* PHB 1 DEBUG */,
124 0x6000 /* PHB 2 DEBUG */,
125 0x7000 /* PHB 3 DEBUG */
126};
127
128/*
129 * STUFF register for each debug PHB,
130 * byte 1 = start bus number, byte 2 = end bus number
131 */
132
133#define PHB_DEBUG_STUFF_OFFSET 0x0020
134
118unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; 135unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
119static int translate_empty_slots __read_mostly = 0; 136static int translate_empty_slots __read_mostly = 0;
120static int calgary_detected __read_mostly = 0; 137static int calgary_detected __read_mostly = 0;
121 138
139static struct rio_table_hdr *rio_table_hdr __initdata;
140static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata;
141static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata;
142
122struct calgary_bus_info { 143struct calgary_bus_info {
123 void *tce_space; 144 void *tce_space;
124 unsigned char translation_disabled; 145 unsigned char translation_disabled;
125 signed char phbid; 146 signed char phbid;
147 void __iomem *bbar;
126}; 148};
127 149
128static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, }; 150static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
@@ -475,6 +497,11 @@ static struct dma_mapping_ops calgary_dma_ops = {
475 .unmap_sg = calgary_unmap_sg, 497 .unmap_sg = calgary_unmap_sg,
476}; 498};
477 499
500static inline void __iomem * busno_to_bbar(unsigned char num)
501{
502 return bus_info[num].bbar;
503}
504
478static inline int busno_to_phbid(unsigned char num) 505static inline int busno_to_phbid(unsigned char num)
479{ 506{
480 return bus_info[num].phbid; 507 return bus_info[num].phbid;
@@ -828,31 +855,9 @@ static void __init calgary_disable_translation(struct pci_dev *dev)
828 del_timer_sync(&tbl->watchdog_timer); 855 del_timer_sync(&tbl->watchdog_timer);
829} 856}
830 857
831static inline unsigned int __init locate_register_space(struct pci_dev *dev) 858static inline void __iomem * __init locate_register_space(struct pci_dev *dev)
832{ 859{
833 int rionodeid; 860 return busno_to_bbar(dev->bus->number);
834 u32 address;
835
836 /*
837 * Each Calgary has four busses. The first four busses (first Calgary)
838 * have RIO node ID 2, then the next four (second Calgary) have RIO
839 * node ID 3, the next four (third Calgary) have node ID 2 again, etc.
840 * We use a gross hack - relying on the dev->bus->number ordering,
841 * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1,
842 * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the
843 * second (id 3), and then it repeats modulo 14.
844 */
845 rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2;
846 /*
847 * register space address calculation as follows:
848 * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase)
849 * ChassisBase is always zero for x366/x260/x460
850 * RioNodeId is 2 for first Calgary, 3 for second Calgary
851 */
852 address = START_ADDRESS -
853 (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) +
854 (0x100000) * (rionodeid - CHASSIS_BASE);
855 return address;
856} 861}
857 862
858static void __init calgary_init_one_nontraslated(struct pci_dev *dev) 863static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
@@ -864,15 +869,12 @@ static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
864 869
865static int __init calgary_init_one(struct pci_dev *dev) 870static int __init calgary_init_one(struct pci_dev *dev)
866{ 871{
867 u32 address;
868 void __iomem *bbar; 872 void __iomem *bbar;
869 int ret; 873 int ret;
870 874
871 BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM); 875 BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
872 876
873 address = locate_register_space(dev); 877 bbar = locate_register_space(dev);
874 /* map entire 1MB of Calgary config space */
875 bbar = ioremap_nocache(address, 1024 * 1024);
876 if (!bbar) { 878 if (!bbar) {
877 ret = -ENODATA; 879 ret = -ENODATA;
878 goto done; 880 goto done;
@@ -898,6 +900,35 @@ static int __init calgary_init(void)
898{ 900{
899 int ret = -ENODEV; 901 int ret = -ENODEV;
900 struct pci_dev *dev = NULL; 902 struct pci_dev *dev = NULL;
903 int rio, phb, bus;
904 void __iomem *bbar;
905 void __iomem *target;
906 u8 start_bus, end_bus;
907 u32 val;
908
909 for (rio = 0; rio < rio_table_hdr->num_rio_dev; rio++) {
910
911 if ( (rio_devs[rio]->type != COMPAT_CALGARY) &&
912 (rio_devs[rio]->type != ALT_CALGARY) )
913 continue;
914
915 /* map entire 1MB of Calgary config space */
916 bbar = ioremap_nocache(rio_devs[rio]->BBAR, 1024 * 1024);
917
918 for (phb = 0; phb < PHBS_PER_CALGARY; phb++) {
919
920 target = calgary_reg(bbar, phb_debug_offsets[phb] |
921 PHB_DEBUG_STUFF_OFFSET);
922 val = be32_to_cpu(readl(target));
923 start_bus = (u8)((val & 0x00FF0000) >> 16);
924 end_bus = (u8)((val & 0x0000FF00) >> 8);
925 for (bus = start_bus; bus <= end_bus; bus++) {
926 bus_info[bus].bbar = bbar;
927 bus_info[bus].phbid = phb;
928 }
929 }
930 }
931
901 932
902 do { 933 do {
903 dev = pci_get_device(PCI_VENDOR_ID_IBM, 934 dev = pci_get_device(PCI_VENDOR_ID_IBM,
@@ -962,13 +993,55 @@ static inline int __init determine_tce_table_size(u64 ram)
962 return ret; 993 return ret;
963} 994}
964 995
996static int __init build_detail_arrays(void)
997{
998 unsigned long ptr;
999 int i, scal_detail_size, rio_detail_size;
1000
1001 if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
1002 printk(KERN_WARNING
1003 "Calgary: MAX_NUMNODES too low! Defined as %d, "
1004 "but system has %d nodes.\n",
1005 MAX_NUMNODES, rio_table_hdr->num_scal_dev);
1006 return -ENODEV;
1007 }
1008
1009 switch (rio_table_hdr->version){
1010 default:
1011 printk(KERN_WARNING
1012 "Calgary: Invalid Rio Grande Table Version: %d\n",
1013 rio_table_hdr->version);
1014 return -ENODEV;
1015 case 2:
1016 scal_detail_size = 11;
1017 rio_detail_size = 13;
1018 break;
1019 case 3:
1020 scal_detail_size = 12;
1021 rio_detail_size = 15;
1022 break;
1023 }
1024
1025 ptr = ((unsigned long)rio_table_hdr) + 3;
1026 for (i = 0; i < rio_table_hdr->num_scal_dev;
1027 i++, ptr += scal_detail_size)
1028 scal_devs[i] = (struct scal_detail *)ptr;
1029
1030 for (i = 0; i < rio_table_hdr->num_rio_dev;
1031 i++, ptr += rio_detail_size)
1032 rio_devs[i] = (struct rio_detail *)ptr;
1033
1034 return 0;
1035}
1036
965void __init detect_calgary(void) 1037void __init detect_calgary(void)
966{ 1038{
967 u32 val; 1039 u32 val;
968 int bus; 1040 int bus;
969 void *tbl; 1041 void *tbl;
970 int calgary_found = 0; 1042 int calgary_found = 0;
971 int phb = -1; 1043 unsigned long ptr;
1044 int offset;
972 1045
973 /* 1046 /*
974 * if the user specified iommu=off or iommu=soft or we found 1047 * if the user specified iommu=off or iommu=soft or we found
@@ -980,6 +1053,29 @@ void __init detect_calgary(void)
980 if (!early_pci_allowed()) 1053 if (!early_pci_allowed())
981 return; 1054 return;
982 1055
1056 ptr = (unsigned long)phys_to_virt(get_bios_ebda());
1057
1058 rio_table_hdr = NULL;
1059 offset = 0x180;
1060 while (offset) {
1061 /* The block id is stored in the 2nd word */
1062 if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
1063 /* set the pointer past the offset & block id */
1064 rio_table_hdr = (struct rio_table_hdr *)(ptr+offset+4);
1065 break;
1066 }
1067 /* The next offset is stored in the 1st word. 0 means no more */
1068 offset = *((unsigned short *)(ptr + offset));
1069 }
1070 if (!rio_table_hdr){
1071 printk(KERN_ERR "Calgary: Unable to locate "
1072 "Rio Grande Table in EBDA - bailing!\n");
1073 return;
1074 }
1075
1076 if (build_detail_arrays())
1077 return;
1078
983 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); 1079 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
984 1080
985 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { 1081 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
@@ -990,12 +1086,6 @@ void __init detect_calgary(void)
990 if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY) 1086 if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
991 continue; 1087 continue;
992 1088
993 /*
994 * There are 4 PHBs per Calgary chip. Set phb to which phb (0-3)
995 * it is connected to releative to the clagary chip.
996 */
997 phb = (phb + 1) % PHBS_PER_CALGARY;
998
999 if (info->translation_disabled) 1089 if (info->translation_disabled)
1000 continue; 1090 continue;
1001 1091
@@ -1010,7 +1100,6 @@ void __init detect_calgary(void)
1010 if (!tbl) 1100 if (!tbl)
1011 goto cleanup; 1101 goto cleanup;
1012 info->tce_space = tbl; 1102 info->tce_space = tbl;
1013 info->phbid = phb;
1014 calgary_found = 1; 1103 calgary_found = 1;
1015 break; 1104 break;
1016 } 1105 }