diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2007-05-09 05:35:27 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2007-05-09 05:35:27 -0400 |
| commit | ca3dd88e411648c76e1911a729440e3763ba5049 (patch) | |
| tree | e874ed0c1e91269aa514a443358d4f3738bcb244 | |
| parent | de372ecd80a42c4fb485c7232475301a18d05184 (diff) | |
[SPARC64] PCI: Consolidate PCI access code into pci_common.c
All the sun4u controllers do the same thing to compute the physical
I/O address to poke, and we can move the sun4v code into this common
location too.
This one needs a bit of testing, in particular the Sabre code had some
funny stuff that would break up u16 and/or u32 accesses into pieces
and I didn't think that was needed any more. If it is we need to find
out why and add back code to do it again.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | arch/sparc64/kernel/pci_common.c | 194 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 135 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_impl.h | 6 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 119 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 288 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 122 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 86 |
7 files changed, 210 insertions, 740 deletions
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 76faaa8135dd..f974fefc3ebc 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c | |||
| @@ -14,6 +14,200 @@ | |||
| 14 | #include <asm/oplib.h> | 14 | #include <asm/oplib.h> |
| 15 | 15 | ||
| 16 | #include "pci_impl.h" | 16 | #include "pci_impl.h" |
| 17 | #include "pci_sun4v.h" | ||
| 18 | |||
| 19 | static int config_out_of_range(struct pci_pbm_info *pbm, | ||
| 20 | unsigned long bus, | ||
| 21 | unsigned long devfn, | ||
| 22 | unsigned long reg) | ||
| 23 | { | ||
| 24 | if (bus < pbm->pci_first_busno || | ||
| 25 | bus > pbm->pci_last_busno) | ||
| 26 | return 1; | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm, | ||
| 31 | unsigned long bus, | ||
| 32 | unsigned long devfn, | ||
| 33 | unsigned long reg) | ||
| 34 | { | ||
| 35 | unsigned long rbits = pbm->config_space_reg_bits; | ||
| 36 | |||
| 37 | if (config_out_of_range(pbm, bus, devfn, reg)) | ||
| 38 | return NULL; | ||
| 39 | |||
| 40 | reg = (reg & ((1 << rbits) - 1)); | ||
| 41 | devfn <<= rbits; | ||
| 42 | bus <<= rbits + 8; | ||
| 43 | |||
| 44 | return (void *) (pbm->config_space | bus | devfn | reg); | ||
| 45 | } | ||
| 46 | |||
| 47 | static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 48 | int where, int size, u32 *value) | ||
| 49 | { | ||
| 50 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 51 | unsigned char bus = bus_dev->number; | ||
| 52 | u32 *addr; | ||
| 53 | u16 tmp16; | ||
| 54 | u8 tmp8; | ||
| 55 | |||
| 56 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 57 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
| 58 | size, value); | ||
| 59 | |||
| 60 | switch (size) { | ||
| 61 | case 1: | ||
| 62 | *value = 0xff; | ||
| 63 | break; | ||
| 64 | case 2: | ||
| 65 | *value = 0xffff; | ||
| 66 | break; | ||
| 67 | case 4: | ||
| 68 | *value = 0xffffffff; | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | |||
| 72 | addr = sun4u_config_mkaddr(pbm, bus, devfn, where); | ||
| 73 | if (!addr) | ||
| 74 | return PCIBIOS_SUCCESSFUL; | ||
| 75 | |||
| 76 | switch (size) { | ||
| 77 | case 1: | ||
| 78 | pci_config_read8((u8 *)addr, &tmp8); | ||
| 79 | *value = (u32) tmp8; | ||
| 80 | break; | ||
| 81 | |||
| 82 | case 2: | ||
| 83 | if (where & 0x01) { | ||
| 84 | printk("pci_read_config_word: misaligned reg [%x]\n", | ||
| 85 | where); | ||
| 86 | return PCIBIOS_SUCCESSFUL; | ||
| 87 | } | ||
| 88 | pci_config_read16((u16 *)addr, &tmp16); | ||
| 89 | *value = (u32) tmp16; | ||
| 90 | break; | ||
| 91 | |||
| 92 | case 4: | ||
| 93 | if (where & 0x03) { | ||
| 94 | printk("pci_read_config_dword: misaligned reg [%x]\n", | ||
| 95 | where); | ||
| 96 | return PCIBIOS_SUCCESSFUL; | ||
| 97 | } | ||
| 98 | pci_config_read32(addr, value); | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | return PCIBIOS_SUCCESSFUL; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 105 | int where, int size, u32 value) | ||
| 106 | { | ||
| 107 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 108 | unsigned char bus = bus_dev->number; | ||
| 109 | u32 *addr; | ||
| 110 | |||
| 111 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 112 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
| 113 | size, value); | ||
| 114 | addr = sun4u_config_mkaddr(pbm, bus, devfn, where); | ||
| 115 | if (!addr) | ||
| 116 | return PCIBIOS_SUCCESSFUL; | ||
| 117 | |||
| 118 | switch (size) { | ||
| 119 | case 1: | ||
| 120 | pci_config_write8((u8 *)addr, value); | ||
| 121 | break; | ||
| 122 | |||
| 123 | case 2: | ||
| 124 | if (where & 0x01) { | ||
| 125 | printk("pci_write_config_word: misaligned reg [%x]\n", | ||
| 126 | where); | ||
| 127 | return PCIBIOS_SUCCESSFUL; | ||
| 128 | } | ||
| 129 | pci_config_write16((u16 *)addr, value); | ||
| 130 | break; | ||
| 131 | |||
| 132 | case 4: | ||
| 133 | if (where & 0x03) { | ||
| 134 | printk("pci_write_config_dword: misaligned reg [%x]\n", | ||
| 135 | where); | ||
| 136 | return PCIBIOS_SUCCESSFUL; | ||
| 137 | } | ||
| 138 | pci_config_write32(addr, value); | ||
| 139 | } | ||
| 140 | return PCIBIOS_SUCCESSFUL; | ||
| 141 | } | ||
| 142 | |||
| 143 | struct pci_ops sun4u_pci_ops = { | ||
| 144 | .read = sun4u_read_pci_cfg, | ||
| 145 | .write = sun4u_write_pci_cfg, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 149 | int where, int size, u32 *value) | ||
| 150 | { | ||
| 151 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 152 | u32 devhandle = pbm->devhandle; | ||
| 153 | unsigned int bus = bus_dev->number; | ||
| 154 | unsigned int device = PCI_SLOT(devfn); | ||
| 155 | unsigned int func = PCI_FUNC(devfn); | ||
| 156 | unsigned long ret; | ||
| 157 | |||
| 158 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 159 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
| 160 | size, value); | ||
| 161 | if (config_out_of_range(pbm, bus, devfn, where)) { | ||
| 162 | ret = ~0UL; | ||
| 163 | } else { | ||
| 164 | ret = pci_sun4v_config_get(devhandle, | ||
| 165 | HV_PCI_DEVICE_BUILD(bus, device, func), | ||
| 166 | where, size); | ||
| 167 | } | ||
| 168 | switch (size) { | ||
| 169 | case 1: | ||
| 170 | *value = ret & 0xff; | ||
| 171 | break; | ||
| 172 | case 2: | ||
| 173 | *value = ret & 0xffff; | ||
| 174 | break; | ||
| 175 | case 4: | ||
| 176 | *value = ret & 0xffffffff; | ||
| 177 | break; | ||
| 178 | }; | ||
| 179 | |||
| 180 | |||
| 181 | return PCIBIOS_SUCCESSFUL; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 185 | int where, int size, u32 value) | ||
| 186 | { | ||
| 187 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 188 | u32 devhandle = pbm->devhandle; | ||
| 189 | unsigned int bus = bus_dev->number; | ||
| 190 | unsigned int device = PCI_SLOT(devfn); | ||
| 191 | unsigned int func = PCI_FUNC(devfn); | ||
| 192 | unsigned long ret; | ||
| 193 | |||
| 194 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 195 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
| 196 | size, value); | ||
| 197 | if (config_out_of_range(pbm, bus, devfn, where)) { | ||
| 198 | /* Do nothing. */ | ||
| 199 | } else { | ||
| 200 | ret = pci_sun4v_config_put(devhandle, | ||
| 201 | HV_PCI_DEVICE_BUILD(bus, device, func), | ||
| 202 | where, size, value); | ||
| 203 | } | ||
| 204 | return PCIBIOS_SUCCESSFUL; | ||
| 205 | } | ||
| 206 | |||
| 207 | struct pci_ops sun4v_pci_ops = { | ||
| 208 | .read = sun4v_read_pci_cfg, | ||
| 209 | .write = sun4v_write_pci_cfg, | ||
| 210 | }; | ||
| 17 | 211 | ||
| 18 | void pci_get_pbm_props(struct pci_pbm_info *pbm) | 212 | void pci_get_pbm_props(struct pci_pbm_info *pbm) |
| 19 | { | 213 | { |
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 2e0eb4ee8f71..9198c1a0f7a5 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c | |||
| @@ -27,138 +27,6 @@ | |||
| 27 | "i" (ASI_PHYS_BYPASS_EC_E) \ | 27 | "i" (ASI_PHYS_BYPASS_EC_E) \ |
| 28 | : "memory") | 28 | : "memory") |
| 29 | 29 | ||
| 30 | /* Fire config space address format is nearly identical to | ||
| 31 | * that of SCHIZO and PSYCHO, except that in order to accomodate | ||
| 32 | * PCI-E extended config space the encoding can handle 12 bits | ||
| 33 | * of register address: | ||
| 34 | * | ||
| 35 | * 32 28 27 20 19 15 14 12 11 2 1 0 | ||
| 36 | * ------------------------------------------------- | ||
| 37 | * |0 0 0 0 0| bus | device | function | reg | 0 0 | | ||
| 38 | * ------------------------------------------------- | ||
| 39 | */ | ||
| 40 | #define FIRE_CONFIG_BASE(PBM) ((PBM)->config_space) | ||
| 41 | #define FIRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ | ||
| 42 | (((unsigned long)(BUS) << 20) | \ | ||
| 43 | ((unsigned long)(DEVFN) << 12) | \ | ||
| 44 | ((unsigned long)(REG))) | ||
| 45 | |||
| 46 | static void *fire_pci_config_mkaddr(struct pci_pbm_info *pbm, | ||
| 47 | unsigned char bus, | ||
| 48 | unsigned int devfn, | ||
| 49 | int where) | ||
| 50 | { | ||
| 51 | if (!pbm) | ||
| 52 | return NULL; | ||
| 53 | return (void *) | ||
| 54 | (FIRE_CONFIG_BASE(pbm) | | ||
| 55 | FIRE_CONFIG_ENCODE(bus, devfn, where)); | ||
| 56 | } | ||
| 57 | |||
| 58 | /* FIRE PCI configuration space accessors. */ | ||
| 59 | |||
| 60 | static int fire_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 61 | int where, int size, u32 *value) | ||
| 62 | { | ||
| 63 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 64 | unsigned char bus = bus_dev->number; | ||
| 65 | u32 *addr; | ||
| 66 | u16 tmp16; | ||
| 67 | u8 tmp8; | ||
| 68 | |||
| 69 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 70 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
| 71 | size, value); | ||
| 72 | switch (size) { | ||
| 73 | case 1: | ||
| 74 | *value = 0xff; | ||
| 75 | break; | ||
| 76 | case 2: | ||
| 77 | *value = 0xffff; | ||
| 78 | break; | ||
| 79 | case 4: | ||
| 80 | *value = 0xffffffff; | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | |||
| 84 | addr = fire_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 85 | if (!addr) | ||
| 86 | return PCIBIOS_SUCCESSFUL; | ||
| 87 | |||
| 88 | switch (size) { | ||
| 89 | case 1: | ||
| 90 | pci_config_read8((u8 *)addr, &tmp8); | ||
| 91 | *value = tmp8; | ||
| 92 | break; | ||
| 93 | |||
| 94 | case 2: | ||
| 95 | if (where & 0x01) { | ||
| 96 | printk("pci_read_config_word: misaligned reg [%x]\n", | ||
| 97 | where); | ||
| 98 | return PCIBIOS_SUCCESSFUL; | ||
| 99 | } | ||
| 100 | pci_config_read16((u16 *)addr, &tmp16); | ||
| 101 | *value = tmp16; | ||
| 102 | break; | ||
| 103 | |||
| 104 | case 4: | ||
| 105 | if (where & 0x03) { | ||
| 106 | printk("pci_read_config_dword: misaligned reg [%x]\n", | ||
| 107 | where); | ||
| 108 | return PCIBIOS_SUCCESSFUL; | ||
| 109 | } | ||
| 110 | |||
| 111 | pci_config_read32(addr, value); | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | return PCIBIOS_SUCCESSFUL; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int fire_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 118 | int where, int size, u32 value) | ||
| 119 | { | ||
| 120 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 121 | unsigned char bus = bus_dev->number; | ||
| 122 | u32 *addr; | ||
| 123 | |||
| 124 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 125 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
| 126 | size, value); | ||
| 127 | addr = fire_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 128 | if (!addr) | ||
| 129 | return PCIBIOS_SUCCESSFUL; | ||
| 130 | |||
| 131 | switch (size) { | ||
| 132 | case 1: | ||
| 133 | pci_config_write8((u8 *)addr, value); | ||
| 134 | break; | ||
| 135 | |||
| 136 | case 2: | ||
| 137 | if (where & 0x01) { | ||
| 138 | printk("pci_write_config_word: misaligned reg [%x]\n", | ||
| 139 | where); | ||
| 140 | return PCIBIOS_SUCCESSFUL; | ||
| 141 | } | ||
| 142 | pci_config_write16((u16 *)addr, value); | ||
| 143 | break; | ||
| 144 | |||
| 145 | case 4: | ||
| 146 | if (where & 0x03) { | ||
| 147 | printk("pci_write_config_dword: misaligned reg [%x]\n", | ||
| 148 | where); | ||
| 149 | return PCIBIOS_SUCCESSFUL; | ||
| 150 | } | ||
| 151 | |||
| 152 | pci_config_write32(addr, value); | ||
| 153 | } | ||
| 154 | return PCIBIOS_SUCCESSFUL; | ||
| 155 | } | ||
| 156 | |||
| 157 | static struct pci_ops pci_fire_ops = { | ||
| 158 | .read = fire_read_pci_cfg, | ||
| 159 | .write = fire_write_pci_cfg, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static void pci_fire_scan_bus(struct pci_pbm_info *pbm) | 30 | static void pci_fire_scan_bus(struct pci_pbm_info *pbm) |
| 163 | { | 31 | { |
| 164 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 32 | pbm->pci_bus = pci_scan_one_pbm(pbm); |
| @@ -314,7 +182,8 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, | |||
| 314 | pci_pbm_root = pbm; | 182 | pci_pbm_root = pbm; |
| 315 | 183 | ||
| 316 | pbm->scan_bus = pci_fire_scan_bus; | 184 | pbm->scan_bus = pci_fire_scan_bus; |
| 317 | pbm->pci_ops = &pci_fire_ops; | 185 | pbm->pci_ops = &sun4u_pci_ops; |
| 186 | pbm->config_space_reg_bits = 12; | ||
| 318 | 187 | ||
| 319 | pbm->index = pci_num_pbms++; | 188 | pbm->index = pci_num_pbms++; |
| 320 | 189 | ||
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 8e38023868aa..f660c2b685eb 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h | |||
| @@ -77,6 +77,9 @@ struct pci_pbm_info { | |||
| 77 | /* Base of PCI Config space, can be per-PBM or shared. */ | 77 | /* Base of PCI Config space, can be per-PBM or shared. */ |
| 78 | unsigned long config_space; | 78 | unsigned long config_space; |
| 79 | 79 | ||
| 80 | /* This will be 12 on PCI-E controllers, 8 elsewhere. */ | ||
| 81 | unsigned long config_space_reg_bits; | ||
| 82 | |||
| 80 | /* State of 66MHz capabilities on this PBM. */ | 83 | /* State of 66MHz capabilities on this PBM. */ |
| 81 | int is_66mhz_capable; | 84 | int is_66mhz_capable; |
| 82 | int all_devs_66mhz; | 85 | int all_devs_66mhz; |
| @@ -156,4 +159,7 @@ extern void pci_config_write8(u8 *addr, u8 val); | |||
| 156 | extern void pci_config_write16(u16 *addr, u16 val); | 159 | extern void pci_config_write16(u16 *addr, u16 val); |
| 157 | extern void pci_config_write32(u32 *addr, u32 val); | 160 | extern void pci_config_write32(u32 *addr, u32 val); |
| 158 | 161 | ||
| 162 | extern struct pci_ops sun4u_pci_ops; | ||
| 163 | extern struct pci_ops sun4v_pci_ops; | ||
| 164 | |||
| 159 | #endif /* !(PCI_IMPL_H) */ | 165 | #endif /* !(PCI_IMPL_H) */ |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 2edcb1dd13c3..598393a2df16 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
| @@ -94,122 +94,6 @@ static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, | |||
| 94 | PSYCHO_CONFIG_ENCODE(bus, devfn, where)); | 94 | PSYCHO_CONFIG_ENCODE(bus, devfn, where)); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static int psycho_out_of_range(struct pci_pbm_info *pbm, | ||
| 98 | unsigned char bus, | ||
| 99 | unsigned char devfn) | ||
| 100 | { | ||
| 101 | return ((bus == pbm->pci_first_busno) && | ||
| 102 | PCI_SLOT(devfn) > 8); | ||
| 103 | } | ||
| 104 | |||
| 105 | /* PSYCHO PCI configuration space accessors. */ | ||
| 106 | |||
| 107 | static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 108 | int where, int size, u32 *value) | ||
| 109 | { | ||
| 110 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 111 | unsigned char bus = bus_dev->number; | ||
| 112 | u32 *addr; | ||
| 113 | u16 tmp16; | ||
| 114 | u8 tmp8; | ||
| 115 | |||
| 116 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 117 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
| 118 | size, value); | ||
| 119 | |||
| 120 | switch (size) { | ||
| 121 | case 1: | ||
| 122 | *value = 0xff; | ||
| 123 | break; | ||
| 124 | case 2: | ||
| 125 | *value = 0xffff; | ||
| 126 | break; | ||
| 127 | case 4: | ||
| 128 | *value = 0xffffffff; | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | |||
| 132 | addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 133 | if (!addr) | ||
| 134 | return PCIBIOS_SUCCESSFUL; | ||
| 135 | |||
| 136 | if (psycho_out_of_range(pbm, bus, devfn)) | ||
| 137 | return PCIBIOS_SUCCESSFUL; | ||
| 138 | switch (size) { | ||
| 139 | case 1: | ||
| 140 | pci_config_read8((u8 *)addr, &tmp8); | ||
| 141 | *value = (u32) tmp8; | ||
| 142 | break; | ||
| 143 | |||
| 144 | case 2: | ||
| 145 | if (where & 0x01) { | ||
| 146 | printk("pci_read_config_word: misaligned reg [%x]\n", | ||
| 147 | where); | ||
| 148 | return PCIBIOS_SUCCESSFUL; | ||
| 149 | } | ||
| 150 | pci_config_read16((u16 *)addr, &tmp16); | ||
| 151 | *value = (u32) tmp16; | ||
| 152 | break; | ||
| 153 | |||
| 154 | case 4: | ||
| 155 | if (where & 0x03) { | ||
| 156 | printk("pci_read_config_dword: misaligned reg [%x]\n", | ||
| 157 | where); | ||
| 158 | return PCIBIOS_SUCCESSFUL; | ||
| 159 | } | ||
| 160 | pci_config_read32(addr, value); | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | return PCIBIOS_SUCCESSFUL; | ||
| 164 | } | ||
| 165 | |||
| 166 | static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 167 | int where, int size, u32 value) | ||
| 168 | { | ||
| 169 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 170 | unsigned char bus = bus_dev->number; | ||
| 171 | u32 *addr; | ||
| 172 | |||
| 173 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 174 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
| 175 | size, value); | ||
| 176 | addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 177 | if (!addr) | ||
| 178 | return PCIBIOS_SUCCESSFUL; | ||
| 179 | |||
| 180 | if (psycho_out_of_range(pbm, bus, devfn)) | ||
| 181 | return PCIBIOS_SUCCESSFUL; | ||
| 182 | |||
| 183 | switch (size) { | ||
| 184 | case 1: | ||
| 185 | pci_config_write8((u8 *)addr, value); | ||
| 186 | break; | ||
| 187 | |||
| 188 | case 2: | ||
| 189 | if (where & 0x01) { | ||
| 190 | printk("pci_write_config_word: misaligned reg [%x]\n", | ||
| 191 | where); | ||
| 192 | return PCIBIOS_SUCCESSFUL; | ||
| 193 | } | ||
| 194 | pci_config_write16((u16 *)addr, value); | ||
| 195 | break; | ||
| 196 | |||
| 197 | case 4: | ||
| 198 | if (where & 0x03) { | ||
| 199 | printk("pci_write_config_dword: misaligned reg [%x]\n", | ||
| 200 | where); | ||
| 201 | return PCIBIOS_SUCCESSFUL; | ||
| 202 | } | ||
| 203 | pci_config_write32(addr, value); | ||
| 204 | } | ||
| 205 | return PCIBIOS_SUCCESSFUL; | ||
| 206 | } | ||
| 207 | |||
| 208 | static struct pci_ops psycho_ops = { | ||
| 209 | .read = psycho_read_pci_cfg, | ||
| 210 | .write = psycho_write_pci_cfg, | ||
| 211 | }; | ||
| 212 | |||
| 213 | /* PSYCHO error handling support. */ | 97 | /* PSYCHO error handling support. */ |
| 214 | enum psycho_error_type { | 98 | enum psycho_error_type { |
| 215 | UE_ERR, CE_ERR, PCI_ERR | 99 | UE_ERR, CE_ERR, PCI_ERR |
| @@ -1089,7 +973,8 @@ static void psycho_pbm_init(struct pci_controller_info *p, | |||
| 1089 | pci_pbm_root = pbm; | 973 | pci_pbm_root = pbm; |
| 1090 | 974 | ||
| 1091 | pbm->scan_bus = psycho_scan_bus; | 975 | pbm->scan_bus = psycho_scan_bus; |
| 1092 | pbm->pci_ops = &psycho_ops; | 976 | pbm->pci_ops = &sun4u_pci_ops; |
| 977 | pbm->config_space_reg_bits = 8; | ||
| 1093 | 978 | ||
| 1094 | pbm->index = pci_num_pbms++; | 979 | pbm->index = pci_num_pbms++; |
| 1095 | 980 | ||
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 4cefe6e83b24..e2377796de89 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
| @@ -205,294 +205,9 @@ | |||
| 205 | #define SABRE_MEMSPACE 0x100000000UL | 205 | #define SABRE_MEMSPACE 0x100000000UL |
| 206 | #define SABRE_MEMSPACE_SIZE 0x07fffffffUL | 206 | #define SABRE_MEMSPACE_SIZE 0x07fffffffUL |
| 207 | 207 | ||
| 208 | /* UltraSparc-IIi Programmer's Manual, page 325, PCI | ||
| 209 | * configuration space address format: | ||
| 210 | * | ||
| 211 | * 32 24 23 16 15 11 10 8 7 2 1 0 | ||
| 212 | * --------------------------------------------------------- | ||
| 213 | * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | | ||
| 214 | * --------------------------------------------------------- | ||
| 215 | */ | ||
| 216 | #define SABRE_CONFIG_BASE(PBM) \ | ||
| 217 | ((PBM)->config_space | (1UL << 24)) | ||
| 218 | #define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ | ||
| 219 | (((unsigned long)(BUS) << 16) | \ | ||
| 220 | ((unsigned long)(DEVFN) << 8) | \ | ||
| 221 | ((unsigned long)(REG))) | ||
| 222 | |||
| 223 | static int hummingbird_p; | 208 | static int hummingbird_p; |
| 224 | static struct pci_bus *sabre_root_bus; | 209 | static struct pci_bus *sabre_root_bus; |
| 225 | 210 | ||
| 226 | static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm, | ||
| 227 | unsigned char bus, | ||
| 228 | unsigned int devfn, | ||
| 229 | int where) | ||
| 230 | { | ||
| 231 | if (!pbm) | ||
| 232 | return NULL; | ||
| 233 | return (void *) | ||
| 234 | (SABRE_CONFIG_BASE(pbm) | | ||
| 235 | SABRE_CONFIG_ENCODE(bus, devfn, where)); | ||
| 236 | } | ||
| 237 | |||
| 238 | static int sabre_out_of_range(unsigned char devfn) | ||
| 239 | { | ||
| 240 | if (hummingbird_p) | ||
| 241 | return 0; | ||
| 242 | |||
| 243 | return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) || | ||
| 244 | ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) || | ||
| 245 | (PCI_SLOT(devfn) > 1)); | ||
| 246 | } | ||
| 247 | |||
| 248 | static int __sabre_out_of_range(struct pci_pbm_info *pbm, | ||
| 249 | unsigned char bus, | ||
| 250 | unsigned char devfn) | ||
| 251 | { | ||
| 252 | if (hummingbird_p) | ||
| 253 | return 0; | ||
| 254 | |||
| 255 | return ((pbm->parent == 0) || | ||
| 256 | ((pbm == &pbm->parent->pbm_A) && | ||
| 257 | (bus == pbm->pci_first_busno) && | ||
| 258 | PCI_SLOT(devfn) > 8)); | ||
| 259 | } | ||
| 260 | |||
| 261 | static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 262 | int where, int size, u32 *value) | ||
| 263 | { | ||
| 264 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 265 | unsigned char bus = bus_dev->number; | ||
| 266 | u32 *addr; | ||
| 267 | u16 tmp16; | ||
| 268 | u8 tmp8; | ||
| 269 | |||
| 270 | switch (size) { | ||
| 271 | case 1: | ||
| 272 | *value = 0xff; | ||
| 273 | break; | ||
| 274 | case 2: | ||
| 275 | *value = 0xffff; | ||
| 276 | break; | ||
| 277 | case 4: | ||
| 278 | *value = 0xffffffff; | ||
| 279 | break; | ||
| 280 | } | ||
| 281 | |||
| 282 | addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 283 | if (!addr) | ||
| 284 | return PCIBIOS_SUCCESSFUL; | ||
| 285 | |||
| 286 | if (__sabre_out_of_range(pbm, bus, devfn)) | ||
| 287 | return PCIBIOS_SUCCESSFUL; | ||
| 288 | |||
| 289 | switch (size) { | ||
| 290 | case 1: | ||
| 291 | pci_config_read8((u8 *) addr, &tmp8); | ||
| 292 | *value = tmp8; | ||
| 293 | break; | ||
| 294 | |||
| 295 | case 2: | ||
| 296 | if (where & 0x01) { | ||
| 297 | printk("pci_read_config_word: misaligned reg [%x]\n", | ||
| 298 | where); | ||
| 299 | return PCIBIOS_SUCCESSFUL; | ||
| 300 | } | ||
| 301 | pci_config_read16((u16 *) addr, &tmp16); | ||
| 302 | *value = tmp16; | ||
| 303 | break; | ||
| 304 | |||
| 305 | case 4: | ||
| 306 | if (where & 0x03) { | ||
| 307 | printk("pci_read_config_dword: misaligned reg [%x]\n", | ||
| 308 | where); | ||
| 309 | return PCIBIOS_SUCCESSFUL; | ||
| 310 | } | ||
| 311 | pci_config_read32(addr, value); | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | |||
| 315 | return PCIBIOS_SUCCESSFUL; | ||
| 316 | } | ||
| 317 | |||
| 318 | static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, | ||
| 319 | int where, int size, u32 *value) | ||
| 320 | { | ||
| 321 | struct pci_pbm_info *pbm = bus->sysdata; | ||
| 322 | |||
| 323 | if (bus == pbm->pci_bus && devfn == 0x00) | ||
| 324 | return pci_host_bridge_read_pci_cfg(bus, devfn, where, | ||
| 325 | size, value); | ||
| 326 | |||
| 327 | if (!bus->number && sabre_out_of_range(devfn)) { | ||
| 328 | switch (size) { | ||
| 329 | case 1: | ||
| 330 | *value = 0xff; | ||
| 331 | break; | ||
| 332 | case 2: | ||
| 333 | *value = 0xffff; | ||
| 334 | break; | ||
| 335 | case 4: | ||
| 336 | *value = 0xffffffff; | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | return PCIBIOS_SUCCESSFUL; | ||
| 340 | } | ||
| 341 | |||
| 342 | if (bus->number || PCI_SLOT(devfn)) | ||
| 343 | return __sabre_read_pci_cfg(bus, devfn, where, size, value); | ||
| 344 | |||
| 345 | /* When accessing PCI config space of the PCI controller itself (bus | ||
| 346 | * 0, device slot 0, function 0) there are restrictions. Each | ||
| 347 | * register must be accessed as it's natural size. Thus, for example | ||
| 348 | * the Vendor ID must be accessed as a 16-bit quantity. | ||
| 349 | */ | ||
| 350 | |||
| 351 | switch (size) { | ||
| 352 | case 1: | ||
| 353 | if (where < 8) { | ||
| 354 | u32 tmp32; | ||
| 355 | u16 tmp16; | ||
| 356 | |||
| 357 | __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); | ||
| 358 | tmp16 = (u16) tmp32; | ||
| 359 | if (where & 1) | ||
| 360 | *value = tmp16 >> 8; | ||
| 361 | else | ||
| 362 | *value = tmp16 & 0xff; | ||
| 363 | } else | ||
| 364 | return __sabre_read_pci_cfg(bus, devfn, where, 1, value); | ||
| 365 | break; | ||
| 366 | |||
| 367 | case 2: | ||
| 368 | if (where < 8) | ||
| 369 | return __sabre_read_pci_cfg(bus, devfn, where, 2, value); | ||
| 370 | else { | ||
| 371 | u32 tmp32; | ||
| 372 | u8 tmp8; | ||
| 373 | |||
| 374 | __sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32); | ||
| 375 | tmp8 = (u8) tmp32; | ||
| 376 | *value = tmp8; | ||
| 377 | __sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32); | ||
| 378 | tmp8 = (u8) tmp32; | ||
| 379 | *value |= tmp8 << 8; | ||
| 380 | } | ||
| 381 | break; | ||
| 382 | |||
| 383 | case 4: { | ||
| 384 | u32 tmp32; | ||
| 385 | u16 tmp16; | ||
| 386 | |||
| 387 | sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32); | ||
| 388 | tmp16 = (u16) tmp32; | ||
| 389 | *value = tmp16; | ||
| 390 | sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32); | ||
| 391 | tmp16 = (u16) tmp32; | ||
| 392 | *value |= tmp16 << 16; | ||
| 393 | break; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | return PCIBIOS_SUCCESSFUL; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 400 | int where, int size, u32 value) | ||
| 401 | { | ||
| 402 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 403 | unsigned char bus = bus_dev->number; | ||
| 404 | u32 *addr; | ||
| 405 | |||
| 406 | addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 407 | if (!addr) | ||
| 408 | return PCIBIOS_SUCCESSFUL; | ||
| 409 | |||
| 410 | if (__sabre_out_of_range(pbm, bus, devfn)) | ||
| 411 | return PCIBIOS_SUCCESSFUL; | ||
| 412 | |||
| 413 | switch (size) { | ||
| 414 | case 1: | ||
| 415 | pci_config_write8((u8 *) addr, value); | ||
| 416 | break; | ||
| 417 | |||
| 418 | case 2: | ||
| 419 | if (where & 0x01) { | ||
| 420 | printk("pci_write_config_word: misaligned reg [%x]\n", | ||
| 421 | where); | ||
| 422 | return PCIBIOS_SUCCESSFUL; | ||
| 423 | } | ||
| 424 | pci_config_write16((u16 *) addr, value); | ||
| 425 | break; | ||
| 426 | |||
| 427 | case 4: | ||
| 428 | if (where & 0x03) { | ||
| 429 | printk("pci_write_config_dword: misaligned reg [%x]\n", | ||
| 430 | where); | ||
| 431 | return PCIBIOS_SUCCESSFUL; | ||
| 432 | } | ||
| 433 | pci_config_write32(addr, value); | ||
| 434 | break; | ||
| 435 | } | ||
| 436 | |||
| 437 | return PCIBIOS_SUCCESSFUL; | ||
| 438 | } | ||
| 439 | |||
| 440 | static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, | ||
| 441 | int where, int size, u32 value) | ||
| 442 | { | ||
| 443 | struct pci_pbm_info *pbm = bus->sysdata; | ||
| 444 | |||
| 445 | if (bus == pbm->pci_bus && devfn == 0x00) | ||
| 446 | return pci_host_bridge_write_pci_cfg(bus, devfn, where, | ||
| 447 | size, value); | ||
| 448 | |||
| 449 | if (bus->number) | ||
| 450 | return __sabre_write_pci_cfg(bus, devfn, where, size, value); | ||
| 451 | |||
| 452 | if (sabre_out_of_range(devfn)) | ||
| 453 | return PCIBIOS_SUCCESSFUL; | ||
| 454 | |||
| 455 | switch (size) { | ||
| 456 | case 1: | ||
| 457 | if (where < 8) { | ||
| 458 | u32 tmp32; | ||
| 459 | u16 tmp16; | ||
| 460 | |||
| 461 | __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); | ||
| 462 | tmp16 = (u16) tmp32; | ||
| 463 | if (where & 1) { | ||
| 464 | value &= 0x00ff; | ||
| 465 | value |= tmp16 << 8; | ||
| 466 | } else { | ||
| 467 | value &= 0xff00; | ||
| 468 | value |= tmp16; | ||
| 469 | } | ||
| 470 | tmp32 = (u32) tmp16; | ||
| 471 | return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32); | ||
| 472 | } else | ||
| 473 | return __sabre_write_pci_cfg(bus, devfn, where, 1, value); | ||
| 474 | break; | ||
| 475 | case 2: | ||
| 476 | if (where < 8) | ||
| 477 | return __sabre_write_pci_cfg(bus, devfn, where, 2, value); | ||
| 478 | else { | ||
| 479 | __sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff); | ||
| 480 | __sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8); | ||
| 481 | } | ||
| 482 | break; | ||
| 483 | case 4: | ||
| 484 | sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff); | ||
| 485 | sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16); | ||
| 486 | break; | ||
| 487 | } | ||
| 488 | return PCIBIOS_SUCCESSFUL; | ||
| 489 | } | ||
| 490 | |||
| 491 | static struct pci_ops sabre_ops = { | ||
| 492 | .read = sabre_read_pci_cfg, | ||
| 493 | .write = sabre_write_pci_cfg, | ||
| 494 | }; | ||
| 495 | |||
| 496 | /* SABRE error handling support. */ | 211 | /* SABRE error handling support. */ |
| 497 | static void sabre_check_iommu_error(struct pci_pbm_info *pbm, | 212 | static void sabre_check_iommu_error(struct pci_pbm_info *pbm, |
| 498 | unsigned long afsr, | 213 | unsigned long afsr, |
| @@ -1010,7 +725,8 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *p | |||
| 1010 | printk("%s: SABRE PCI Bus Module\n", pbm->name); | 725 | printk("%s: SABRE PCI Bus Module\n", pbm->name); |
| 1011 | 726 | ||
| 1012 | pbm->scan_bus = sabre_scan_bus; | 727 | pbm->scan_bus = sabre_scan_bus; |
| 1013 | pbm->pci_ops = &sabre_ops; | 728 | pbm->pci_ops = &sun4u_pci_ops; |
| 729 | pbm->config_space_reg_bits = 8; | ||
| 1014 | 730 | ||
| 1015 | pbm->index = pci_num_pbms++; | 731 | pbm->index = pci_num_pbms++; |
| 1016 | 732 | ||
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e375d72b8eed..ae76898bbe2b 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
| @@ -104,125 +104,6 @@ static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm, | |||
| 104 | SCHIZO_CONFIG_ENCODE(bus, devfn, where)); | 104 | SCHIZO_CONFIG_ENCODE(bus, devfn, where)); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | /* Just make sure the bus number is in range. */ | ||
| 108 | static int schizo_out_of_range(struct pci_pbm_info *pbm, | ||
| 109 | unsigned char bus, | ||
| 110 | unsigned char devfn) | ||
| 111 | { | ||
| 112 | if (bus < pbm->pci_first_busno || | ||
| 113 | bus > pbm->pci_last_busno) | ||
| 114 | return 1; | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* SCHIZO PCI configuration space accessors. */ | ||
| 119 | |||
| 120 | static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 121 | int where, int size, u32 *value) | ||
| 122 | { | ||
| 123 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 124 | unsigned char bus = bus_dev->number; | ||
| 125 | u32 *addr; | ||
| 126 | u16 tmp16; | ||
| 127 | u8 tmp8; | ||
| 128 | |||
| 129 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 130 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
| 131 | size, value); | ||
| 132 | switch (size) { | ||
| 133 | case 1: | ||
| 134 | *value = 0xff; | ||
| 135 | break; | ||
| 136 | case 2: | ||
| 137 | *value = 0xffff; | ||
| 138 | break; | ||
| 139 | case 4: | ||
| 140 | *value = 0xffffffff; | ||
| 141 | break; | ||
| 142 | } | ||
| 143 | |||
| 144 | addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 145 | if (!addr) | ||
| 146 | return PCIBIOS_SUCCESSFUL; | ||
| 147 | |||
| 148 | if (schizo_out_of_range(pbm, bus, devfn)) | ||
| 149 | return PCIBIOS_SUCCESSFUL; | ||
| 150 | switch (size) { | ||
| 151 | case 1: | ||
| 152 | pci_config_read8((u8 *)addr, &tmp8); | ||
| 153 | *value = tmp8; | ||
| 154 | break; | ||
| 155 | |||
| 156 | case 2: | ||
| 157 | if (where & 0x01) { | ||
| 158 | printk("pci_read_config_word: misaligned reg [%x]\n", | ||
| 159 | where); | ||
| 160 | return PCIBIOS_SUCCESSFUL; | ||
| 161 | } | ||
| 162 | pci_config_read16((u16 *)addr, &tmp16); | ||
| 163 | *value = tmp16; | ||
| 164 | break; | ||
| 165 | |||
| 166 | case 4: | ||
| 167 | if (where & 0x03) { | ||
| 168 | printk("pci_read_config_dword: misaligned reg [%x]\n", | ||
| 169 | where); | ||
| 170 | return PCIBIOS_SUCCESSFUL; | ||
| 171 | } | ||
| 172 | pci_config_read32(addr, value); | ||
| 173 | break; | ||
| 174 | } | ||
| 175 | return PCIBIOS_SUCCESSFUL; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 179 | int where, int size, u32 value) | ||
| 180 | { | ||
| 181 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 182 | unsigned char bus = bus_dev->number; | ||
| 183 | u32 *addr; | ||
| 184 | |||
| 185 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 186 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
| 187 | size, value); | ||
| 188 | addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); | ||
| 189 | if (!addr) | ||
| 190 | return PCIBIOS_SUCCESSFUL; | ||
| 191 | |||
| 192 | if (schizo_out_of_range(pbm, bus, devfn)) | ||
| 193 | return PCIBIOS_SUCCESSFUL; | ||
| 194 | |||
| 195 | switch (size) { | ||
| 196 | case 1: | ||
| 197 | pci_config_write8((u8 *)addr, value); | ||
| 198 | break; | ||
| 199 | |||
| 200 | case 2: | ||
| 201 | if (where & 0x01) { | ||
| 202 | printk("pci_write_config_word: misaligned reg [%x]\n", | ||
| 203 | where); | ||
| 204 | return PCIBIOS_SUCCESSFUL; | ||
| 205 | } | ||
| 206 | pci_config_write16((u16 *)addr, value); | ||
| 207 | break; | ||
| 208 | |||
| 209 | case 4: | ||
| 210 | if (where & 0x03) { | ||
| 211 | printk("pci_write_config_dword: misaligned reg [%x]\n", | ||
| 212 | where); | ||
| 213 | return PCIBIOS_SUCCESSFUL; | ||
| 214 | } | ||
| 215 | |||
| 216 | pci_config_write32(addr, value); | ||
| 217 | } | ||
| 218 | return PCIBIOS_SUCCESSFUL; | ||
| 219 | } | ||
| 220 | |||
| 221 | static struct pci_ops schizo_ops = { | ||
| 222 | .read = schizo_read_pci_cfg, | ||
| 223 | .write = schizo_write_pci_cfg, | ||
| 224 | }; | ||
| 225 | |||
| 226 | /* SCHIZO error handling support. */ | 107 | /* SCHIZO error handling support. */ |
| 227 | enum schizo_error_type { | 108 | enum schizo_error_type { |
| 228 | UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR | 109 | UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR |
| @@ -1494,7 +1375,8 @@ static void schizo_pbm_init(struct pci_controller_info *p, | |||
| 1494 | pci_pbm_root = pbm; | 1375 | pci_pbm_root = pbm; |
| 1495 | 1376 | ||
| 1496 | pbm->scan_bus = schizo_scan_bus; | 1377 | pbm->scan_bus = schizo_scan_bus; |
| 1497 | pbm->pci_ops = &schizo_ops; | 1378 | pbm->pci_ops = &sun4u_pci_ops; |
| 1379 | pbm->config_space_reg_bits = 8; | ||
| 1498 | 1380 | ||
| 1499 | pbm->index = pci_num_pbms++; | 1381 | pbm->index = pci_num_pbms++; |
| 1500 | 1382 | ||
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 0c76a8891a96..34df4047587a 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
| @@ -593,89 +593,6 @@ const struct pci_iommu_ops pci_sun4v_iommu_ops = { | |||
| 593 | .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, | 593 | .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, |
| 594 | }; | 594 | }; |
| 595 | 595 | ||
| 596 | static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) | ||
| 597 | { | ||
| 598 | if (bus < pbm->pci_first_busno || | ||
| 599 | bus > pbm->pci_last_busno) | ||
| 600 | return 1; | ||
| 601 | return 0; | ||
| 602 | } | ||
| 603 | |||
| 604 | static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 605 | int where, int size, u32 *value) | ||
| 606 | { | ||
| 607 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 608 | u32 devhandle = pbm->devhandle; | ||
| 609 | unsigned int bus = bus_dev->number; | ||
| 610 | unsigned int device = PCI_SLOT(devfn); | ||
| 611 | unsigned int func = PCI_FUNC(devfn); | ||
| 612 | unsigned long ret; | ||
| 613 | |||
| 614 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 615 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
| 616 | size, value); | ||
| 617 | if (pci_sun4v_out_of_range(pbm, bus, device, func)) { | ||
| 618 | ret = ~0UL; | ||
| 619 | } else { | ||
| 620 | ret = pci_sun4v_config_get(devhandle, | ||
| 621 | HV_PCI_DEVICE_BUILD(bus, device, func), | ||
| 622 | where, size); | ||
| 623 | #if 0 | ||
| 624 | printk("rcfg: [%x:%x:%x:%d]=[%lx]\n", | ||
| 625 | devhandle, HV_PCI_DEVICE_BUILD(bus, device, func), | ||
| 626 | where, size, ret); | ||
| 627 | #endif | ||
| 628 | } | ||
| 629 | switch (size) { | ||
| 630 | case 1: | ||
| 631 | *value = ret & 0xff; | ||
| 632 | break; | ||
| 633 | case 2: | ||
| 634 | *value = ret & 0xffff; | ||
| 635 | break; | ||
| 636 | case 4: | ||
| 637 | *value = ret & 0xffffffff; | ||
| 638 | break; | ||
| 639 | }; | ||
| 640 | |||
| 641 | |||
| 642 | return PCIBIOS_SUCCESSFUL; | ||
| 643 | } | ||
| 644 | |||
| 645 | static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | ||
| 646 | int where, int size, u32 value) | ||
| 647 | { | ||
| 648 | struct pci_pbm_info *pbm = bus_dev->sysdata; | ||
| 649 | u32 devhandle = pbm->devhandle; | ||
| 650 | unsigned int bus = bus_dev->number; | ||
| 651 | unsigned int device = PCI_SLOT(devfn); | ||
| 652 | unsigned int func = PCI_FUNC(devfn); | ||
| 653 | unsigned long ret; | ||
| 654 | |||
| 655 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
| 656 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
| 657 | size, value); | ||
| 658 | if (pci_sun4v_out_of_range(pbm, bus, device, func)) { | ||
| 659 | /* Do nothing. */ | ||
| 660 | } else { | ||
| 661 | ret = pci_sun4v_config_put(devhandle, | ||
| 662 | HV_PCI_DEVICE_BUILD(bus, device, func), | ||
| 663 | where, size, value); | ||
| 664 | #if 0 | ||
| 665 | printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n", | ||
| 666 | devhandle, HV_PCI_DEVICE_BUILD(bus, device, func), | ||
| 667 | where, size, value, ret); | ||
| 668 | #endif | ||
| 669 | } | ||
| 670 | return PCIBIOS_SUCCESSFUL; | ||
| 671 | } | ||
| 672 | |||
| 673 | static struct pci_ops pci_sun4v_ops = { | ||
| 674 | .read = pci_sun4v_read_pci_cfg, | ||
| 675 | .write = pci_sun4v_write_pci_cfg, | ||
| 676 | }; | ||
| 677 | |||
| 678 | |||
| 679 | static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) | 596 | static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) |
| 680 | { | 597 | { |
| 681 | struct property *prop; | 598 | struct property *prop; |
| @@ -1238,7 +1155,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
| 1238 | pci_pbm_root = pbm; | 1155 | pci_pbm_root = pbm; |
| 1239 | 1156 | ||
| 1240 | pbm->scan_bus = pci_sun4v_scan_bus; | 1157 | pbm->scan_bus = pci_sun4v_scan_bus; |
| 1241 | pbm->pci_ops = &pci_sun4v_ops; | 1158 | pbm->pci_ops = &sun4v_pci_ops; |
| 1159 | pbm->config_space_reg_bits = 12; | ||
| 1242 | 1160 | ||
| 1243 | pbm->index = pci_num_pbms++; | 1161 | pbm->index = pci_num_pbms++; |
| 1244 | 1162 | ||
