aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_psycho.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-30 06:13:20 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-30 06:13:20 -0400
commitb20bfe41badcbf38512fbe1118fe2e0817098e77 (patch)
treedd4e8aa8de3113af6c265c58f6f015870ed84ddd /arch/sparc64/kernel/pci_psycho.c
parent3822b50964d6702b7d8ba18ffd132d4bf786a17e (diff)
sparc64: Convert PSYCHO PCI controller driver into a real driver.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_psycho.c')
-rw-r--r--arch/sparc64/kernel/pci_psycho.c95
1 files changed, 70 insertions, 25 deletions
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index ef5fe29202c2..4e8f87aad205 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -17,11 +17,13 @@
17#include <asm/irq.h> 17#include <asm/irq.h>
18#include <asm/starfire.h> 18#include <asm/starfire.h>
19#include <asm/prom.h> 19#include <asm/prom.h>
20#include <asm/oplib.h>
21 20
22#include "pci_impl.h" 21#include "pci_impl.h"
23#include "iommu_common.h" 22#include "iommu_common.h"
24 23
24#define DRIVER_NAME "psycho"
25#define PFX DRIVER_NAME ": "
26
25/* All PSYCHO registers are 64-bits. The following accessor 27/* All PSYCHO registers are 64-bits. The following accessor
26 * routines are how they are accessed. The REG parameter 28 * routines are how they are accessed. The REG parameter
27 * is a physical address. 29 * is a physical address.
@@ -840,7 +842,7 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm)
840 control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); 842 control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL);
841 control |= PSYCHO_IOMMU_CTRL_DENAB; 843 control |= PSYCHO_IOMMU_CTRL_DENAB;
842 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); 844 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control);
843 for(i = 0; i < 16; i++) { 845 for (i = 0; i < 16; i++) {
844 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); 846 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
845 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); 847 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
846 } 848 }
@@ -850,8 +852,10 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm)
850 */ 852 */
851 err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, 853 err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff,
852 pbm->numa_node); 854 pbm->numa_node);
853 if (err) 855 if (err) {
856 printk(KERN_ERR PFX "iommu_table_init() fails\n");
854 return err; 857 return err;
858 }
855 859
856 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, 860 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE,
857 __pa(iommu->page_table)); 861 __pa(iommu->page_table));
@@ -982,7 +986,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
982 986
983 pbm->numa_node = -1; 987 pbm->numa_node = -1;
984 988
985 pbm->scan_bus = psycho_scan_bus;
986 pbm->pci_ops = &sun4u_pci_ops; 989 pbm->pci_ops = &sun4u_pci_ops;
987 pbm->config_space_reg_bits = 8; 990 pbm->config_space_reg_bits = 8;
988 991
@@ -1002,7 +1005,7 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
1002 pbm->prom_node = dp; 1005 pbm->prom_node = dp;
1003 pbm->name = dp->full_name; 1006 pbm->name = dp->full_name;
1004 1007
1005 printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", 1008 printk(KERN_INFO "%s: PSYCHO PCI Bus Module ver[%x:%x]\n",
1006 pbm->name, 1009 pbm->name,
1007 pbm->chip_version, pbm->chip_revision); 1010 pbm->chip_version, pbm->chip_revision);
1008 1011
@@ -1011,24 +1014,28 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
1011 pci_get_pbm_props(pbm); 1014 pci_get_pbm_props(pbm);
1012 1015
1013 psycho_pbm_strbuf_init(pbm, is_pbm_a); 1016 psycho_pbm_strbuf_init(pbm, is_pbm_a);
1017
1018 psycho_scan_bus(pbm);
1014} 1019}
1015 1020
1016#define PSYCHO_CONFIGSPACE 0x001000000UL 1021#define PSYCHO_CONFIGSPACE 0x001000000UL
1017 1022
1018void __init psycho_init(struct device_node *dp, char *model_name) 1023static int __devinit psycho_probe(struct of_device *op,
1024 const struct of_device_id *match)
1019{ 1025{
1020 struct linux_prom64_registers *pr_regs; 1026 const struct linux_prom64_registers *pr_regs;
1027 struct device_node *dp = op->node;
1021 struct pci_controller_info *p; 1028 struct pci_controller_info *p;
1022 struct pci_pbm_info *pbm; 1029 struct pci_pbm_info *pbm;
1023 struct iommu *iommu; 1030 struct iommu *iommu;
1024 struct property *prop; 1031 int is_pbm_a, err;
1032 const u32 *p32;
1025 u32 upa_portid; 1033 u32 upa_portid;
1026 int is_pbm_a;
1027 1034
1028 upa_portid = 0xff; 1035 upa_portid = 0xff;
1029 prop = of_find_property(dp, "upa-portid", NULL); 1036 p32 = of_get_property(dp, "upa-portid", NULL);
1030 if (prop) 1037 if (p32)
1031 upa_portid = *(u32 *) prop->value; 1038 upa_portid = *p32;
1032 1039
1033 for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { 1040 for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
1034 struct pci_controller_info *p = pbm->parent; 1041 struct pci_controller_info *p = pbm->parent;
@@ -1036,24 +1043,34 @@ void __init psycho_init(struct device_node *dp, char *model_name)
1036 if (p->pbm_A.portid == upa_portid) { 1043 if (p->pbm_A.portid == upa_portid) {
1037 is_pbm_a = (p->pbm_A.prom_node == NULL); 1044 is_pbm_a = (p->pbm_A.prom_node == NULL);
1038 psycho_pbm_init(p, dp, is_pbm_a); 1045 psycho_pbm_init(p, dp, is_pbm_a);
1039 return; 1046 return 0;
1040 } 1047 }
1041 } 1048 }
1042 1049
1050 err = -ENOMEM;
1043 p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); 1051 p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
1044 if (!p) 1052 if (!p) {
1045 goto fatal_memory_error; 1053 printk(KERN_ERR PFX "Cannot allocate controller info.\n");
1054 goto out_free;
1055 }
1056
1046 iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); 1057 iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
1047 if (!iommu) 1058 if (!iommu) {
1048 goto fatal_memory_error; 1059 printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n");
1060 goto out_free;
1061 }
1049 1062
1050 p->pbm_A.iommu = p->pbm_B.iommu = iommu; 1063 p->pbm_A.iommu = p->pbm_B.iommu = iommu;
1051 1064
1052 p->pbm_A.portid = upa_portid; 1065 p->pbm_A.portid = upa_portid;
1053 p->pbm_B.portid = upa_portid; 1066 p->pbm_B.portid = upa_portid;
1054 1067
1055 prop = of_find_property(dp, "reg", NULL); 1068 pr_regs = of_get_property(dp, "reg", NULL);
1056 pr_regs = prop->value; 1069 err = -ENODEV;
1070 if (!pr_regs) {
1071 printk(KERN_ERR PFX "No reg property.\n");
1072 goto out_free;
1073 }
1057 1074
1058 p->pbm_A.controller_regs = pr_regs[2].phys_addr; 1075 p->pbm_A.controller_regs = pr_regs[2].phys_addr;
1059 p->pbm_B.controller_regs = pr_regs[2].phys_addr; 1076 p->pbm_B.controller_regs = pr_regs[2].phys_addr;
@@ -1063,14 +1080,42 @@ void __init psycho_init(struct device_node *dp, char *model_name)
1063 1080
1064 psycho_controller_hwinit(&p->pbm_A); 1081 psycho_controller_hwinit(&p->pbm_A);
1065 1082
1066 if (psycho_iommu_init(&p->pbm_A)) 1083 err = psycho_iommu_init(&p->pbm_A);
1067 goto fatal_memory_error; 1084 if (err)
1085 goto out_free;
1068 1086
1069 is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); 1087 is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
1088
1070 psycho_pbm_init(p, dp, is_pbm_a); 1089 psycho_pbm_init(p, dp, is_pbm_a);
1071 return;
1072 1090
1073fatal_memory_error: 1091 return 0;
1074 prom_printf("PSYCHO: Fatal memory allocation error.\n"); 1092
1075 prom_halt(); 1093out_free:
1094 if (p) {
1095 if (p->pbm_A.iommu)
1096 kfree(p->pbm_A.iommu);
1097 kfree(p);
1098 }
1099 return err;
1100}
1101
1102static struct of_device_id psycho_match[] = {
1103 {
1104 .name = "pci",
1105 .compatible = "pci108e,8000",
1106 },
1107 {},
1108};
1109
1110static struct of_platform_driver psycho_driver = {
1111 .name = DRIVER_NAME,
1112 .match_table = psycho_match,
1113 .probe = psycho_probe,
1114};
1115
1116static int __init psycho_init(void)
1117{
1118 return of_register_driver(&psycho_driver, &of_bus_type);
1076} 1119}
1120
1121subsys_initcall(psycho_init);