diff options
| -rw-r--r-- | arch/sparc64/kernel/pci.c | 2 | ||||
| -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 | ||||
| -rw-r--r-- | arch/sparc64/kernel/prom.c | 19 | ||||
| -rw-r--r-- | drivers/serial/sunzilog.c | 138 | ||||
| -rw-r--r-- | drivers/serial/sunzilog.h | 19 | ||||
| -rw-r--r-- | include/asm-sparc64/openprom.h | 2 |
12 files changed, 349 insertions, 781 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index d85e1ed7c3e4..cf9a75112d0f 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
| @@ -377,7 +377,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
| 377 | const char *type; | 377 | const char *type; |
| 378 | u32 class; | 378 | u32 class; |
| 379 | 379 | ||
| 380 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); | 380 | dev = alloc_pci_dev(); |
| 381 | if (!dev) | 381 | if (!dev) |
| 382 | return NULL; | 382 | return NULL; |
| 383 | 383 | ||
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 | ||
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index c54d4d8af014..b7976b14d0ba 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
| @@ -1636,10 +1636,21 @@ static struct device_node * __init create_node(phandle node, struct device_node | |||
| 1636 | 1636 | ||
| 1637 | static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) | 1637 | static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) |
| 1638 | { | 1638 | { |
| 1639 | struct device_node *ret = NULL, *prev_sibling = NULL; | ||
| 1639 | struct device_node *dp; | 1640 | struct device_node *dp; |
| 1640 | 1641 | ||
| 1641 | dp = create_node(node, parent); | 1642 | while (1) { |
| 1642 | if (dp) { | 1643 | dp = create_node(node, parent); |
| 1644 | if (!dp) | ||
| 1645 | break; | ||
| 1646 | |||
| 1647 | if (prev_sibling) | ||
| 1648 | prev_sibling->sibling = dp; | ||
| 1649 | |||
| 1650 | if (!ret) | ||
| 1651 | ret = dp; | ||
| 1652 | prev_sibling = dp; | ||
| 1653 | |||
| 1643 | *(*nextp) = dp; | 1654 | *(*nextp) = dp; |
| 1644 | *nextp = &dp->allnext; | 1655 | *nextp = &dp->allnext; |
| 1645 | 1656 | ||
| @@ -1648,10 +1659,10 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl | |||
| 1648 | 1659 | ||
| 1649 | dp->child = build_tree(dp, prom_getchild(node), nextp); | 1660 | dp->child = build_tree(dp, prom_getchild(node), nextp); |
| 1650 | 1661 | ||
| 1651 | dp->sibling = build_tree(parent, prom_getsibling(node), nextp); | 1662 | node = prom_getsibling(node); |
| 1652 | } | 1663 | } |
| 1653 | 1664 | ||
| 1654 | return dp; | 1665 | return ret; |
| 1655 | } | 1666 | } |
| 1656 | 1667 | ||
| 1657 | void __init prom_build_devicetree(void) | 1668 | void __init prom_build_devicetree(void) |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index da73205e54cd..0985193dc57d 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
| @@ -92,6 +92,8 @@ struct uart_sunzilog_port { | |||
| 92 | #define SUNZILOG_FLAG_REGS_HELD 0x00000040 | 92 | #define SUNZILOG_FLAG_REGS_HELD 0x00000040 |
| 93 | #define SUNZILOG_FLAG_TX_STOPPED 0x00000080 | 93 | #define SUNZILOG_FLAG_TX_STOPPED 0x00000080 |
| 94 | #define SUNZILOG_FLAG_TX_ACTIVE 0x00000100 | 94 | #define SUNZILOG_FLAG_TX_ACTIVE 0x00000100 |
| 95 | #define SUNZILOG_FLAG_ESCC 0x00000200 | ||
| 96 | #define SUNZILOG_FLAG_ISR_HANDLER 0x00000400 | ||
| 95 | 97 | ||
| 96 | unsigned int cflag; | 98 | unsigned int cflag; |
| 97 | 99 | ||
| @@ -174,9 +176,11 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel) | |||
| 174 | /* This function must only be called when the TX is not busy. The UART | 176 | /* This function must only be called when the TX is not busy. The UART |
| 175 | * port lock must be held and local interrupts disabled. | 177 | * port lock must be held and local interrupts disabled. |
| 176 | */ | 178 | */ |
| 177 | static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) | 179 | static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) |
| 178 | { | 180 | { |
| 179 | int i; | 181 | int i; |
| 182 | int escc; | ||
| 183 | unsigned char r15; | ||
| 180 | 184 | ||
| 181 | /* Let pending transmits finish. */ | 185 | /* Let pending transmits finish. */ |
| 182 | for (i = 0; i < 1000; i++) { | 186 | for (i = 0; i < 1000; i++) { |
| @@ -229,11 +233,25 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char * | |||
| 229 | write_zsreg(channel, R14, regs[R14]); | 233 | write_zsreg(channel, R14, regs[R14]); |
| 230 | 234 | ||
| 231 | /* External status interrupt control. */ | 235 | /* External status interrupt control. */ |
| 232 | write_zsreg(channel, R15, regs[R15]); | 236 | write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN); |
| 237 | |||
| 238 | /* ESCC Extension Register */ | ||
| 239 | r15 = read_zsreg(channel, R15); | ||
| 240 | if (r15 & 0x01) { | ||
| 241 | write_zsreg(channel, R7, regs[R7p]); | ||
| 242 | |||
| 243 | /* External status interrupt and FIFO control. */ | ||
| 244 | write_zsreg(channel, R15, regs[R15] & ~WR7pEN); | ||
| 245 | escc = 1; | ||
| 246 | } else { | ||
| 247 | /* Clear FIFO bit case it is an issue */ | ||
| 248 | regs[R15] &= ~FIFOEN; | ||
| 249 | escc = 0; | ||
| 250 | } | ||
| 233 | 251 | ||
| 234 | /* Reset external status interrupts. */ | 252 | /* Reset external status interrupts. */ |
| 235 | write_zsreg(channel, R0, RES_EXT_INT); | 253 | write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */ |
| 236 | write_zsreg(channel, R0, RES_EXT_INT); | 254 | write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */ |
| 237 | 255 | ||
| 238 | /* Rewrite R3/R5, this time without enables masked. */ | 256 | /* Rewrite R3/R5, this time without enables masked. */ |
| 239 | write_zsreg(channel, R3, regs[R3]); | 257 | write_zsreg(channel, R3, regs[R3]); |
| @@ -241,6 +259,8 @@ static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char * | |||
| 241 | 259 | ||
| 242 | /* Rewrite R1, this time without IRQ enabled masked. */ | 260 | /* Rewrite R1, this time without IRQ enabled masked. */ |
| 243 | write_zsreg(channel, R1, regs[R1]); | 261 | write_zsreg(channel, R1, regs[R1]); |
| 262 | |||
| 263 | return escc; | ||
| 244 | } | 264 | } |
| 245 | 265 | ||
| 246 | /* Reprogram the Zilog channel HW registers with the copies found in the | 266 | /* Reprogram the Zilog channel HW registers with the copies found in the |
| @@ -731,7 +751,7 @@ static void sunzilog_enable_ms(struct uart_port *port) | |||
| 731 | up->curregs[R15] = new_reg; | 751 | up->curregs[R15] = new_reg; |
| 732 | 752 | ||
| 733 | /* NOTE: Not subject to 'transmitter active' rule. */ | 753 | /* NOTE: Not subject to 'transmitter active' rule. */ |
| 734 | write_zsreg(channel, R15, up->curregs[R15]); | 754 | write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN); |
| 735 | } | 755 | } |
| 736 | } | 756 | } |
| 737 | 757 | ||
| @@ -861,44 +881,44 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, | |||
| 861 | up->curregs[R14] = BRSRC | BRENAB; | 881 | up->curregs[R14] = BRSRC | BRENAB; |
| 862 | 882 | ||
| 863 | /* Character size, stop bits, and parity. */ | 883 | /* Character size, stop bits, and parity. */ |
| 864 | up->curregs[3] &= ~RxN_MASK; | 884 | up->curregs[R3] &= ~RxN_MASK; |
| 865 | up->curregs[5] &= ~TxN_MASK; | 885 | up->curregs[R5] &= ~TxN_MASK; |
| 866 | switch (cflag & CSIZE) { | 886 | switch (cflag & CSIZE) { |
| 867 | case CS5: | 887 | case CS5: |
| 868 | up->curregs[3] |= Rx5; | 888 | up->curregs[R3] |= Rx5; |
| 869 | up->curregs[5] |= Tx5; | 889 | up->curregs[R5] |= Tx5; |
| 870 | up->parity_mask = 0x1f; | 890 | up->parity_mask = 0x1f; |
| 871 | break; | 891 | break; |
| 872 | case CS6: | 892 | case CS6: |
| 873 | up->curregs[3] |= Rx6; | 893 | up->curregs[R3] |= Rx6; |
| 874 | up->curregs[5] |= Tx6; | 894 | up->curregs[R5] |= Tx6; |
| 875 | up->parity_mask = 0x3f; | 895 | up->parity_mask = 0x3f; |
| 876 | break; | 896 | break; |
| 877 | case CS7: | 897 | case CS7: |
| 878 | up->curregs[3] |= Rx7; | 898 | up->curregs[R3] |= Rx7; |
| 879 | up->curregs[5] |= Tx7; | 899 | up->curregs[R5] |= Tx7; |
| 880 | up->parity_mask = 0x7f; | 900 | up->parity_mask = 0x7f; |
| 881 | break; | 901 | break; |
| 882 | case CS8: | 902 | case CS8: |
| 883 | default: | 903 | default: |
| 884 | up->curregs[3] |= Rx8; | 904 | up->curregs[R3] |= Rx8; |
| 885 | up->curregs[5] |= Tx8; | 905 | up->curregs[R5] |= Tx8; |
| 886 | up->parity_mask = 0xff; | 906 | up->parity_mask = 0xff; |
| 887 | break; | 907 | break; |
| 888 | }; | 908 | }; |
| 889 | up->curregs[4] &= ~0x0c; | 909 | up->curregs[R4] &= ~0x0c; |
| 890 | if (cflag & CSTOPB) | 910 | if (cflag & CSTOPB) |
| 891 | up->curregs[4] |= SB2; | 911 | up->curregs[R4] |= SB2; |
| 892 | else | 912 | else |
| 893 | up->curregs[4] |= SB1; | 913 | up->curregs[R4] |= SB1; |
| 894 | if (cflag & PARENB) | 914 | if (cflag & PARENB) |
| 895 | up->curregs[4] |= PAR_ENAB; | 915 | up->curregs[R4] |= PAR_ENAB; |
| 896 | else | 916 | else |
| 897 | up->curregs[4] &= ~PAR_ENAB; | 917 | up->curregs[R4] &= ~PAR_ENAB; |
| 898 | if (!(cflag & PARODD)) | 918 | if (!(cflag & PARODD)) |
| 899 | up->curregs[4] |= PAR_EVEN; | 919 | up->curregs[R4] |= PAR_EVEN; |
| 900 | else | 920 | else |
| 901 | up->curregs[4] &= ~PAR_EVEN; | 921 | up->curregs[R4] &= ~PAR_EVEN; |
| 902 | 922 | ||
| 903 | up->port.read_status_mask = Rx_OVR; | 923 | up->port.read_status_mask = Rx_OVR; |
| 904 | if (iflag & INPCK) | 924 | if (iflag & INPCK) |
| @@ -952,7 +972,9 @@ sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 952 | 972 | ||
| 953 | static const char *sunzilog_type(struct uart_port *port) | 973 | static const char *sunzilog_type(struct uart_port *port) |
| 954 | { | 974 | { |
| 955 | return "zs"; | 975 | struct uart_sunzilog_port *up = UART_ZILOG(port); |
| 976 | |||
| 977 | return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs"; | ||
| 956 | } | 978 | } |
| 957 | 979 | ||
| 958 | /* We do not request/release mappings of the registers here, this | 980 | /* We do not request/release mappings of the registers here, this |
| @@ -1170,7 +1192,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) | |||
| 1170 | 1192 | ||
| 1171 | spin_lock_irqsave(&up->port.lock, flags); | 1193 | spin_lock_irqsave(&up->port.lock, flags); |
| 1172 | 1194 | ||
| 1173 | up->curregs[R15] = BRKIE; | 1195 | up->curregs[R15] |= BRKIE; |
| 1174 | sunzilog_convert_to_zs(up, con->cflag, 0, brg); | 1196 | sunzilog_convert_to_zs(up, con->cflag, 0, brg); |
| 1175 | 1197 | ||
| 1176 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); | 1198 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); |
| @@ -1229,7 +1251,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe | |||
| 1229 | baud = 4800; | 1251 | baud = 4800; |
| 1230 | } | 1252 | } |
| 1231 | 1253 | ||
| 1232 | up->curregs[R15] = BRKIE; | 1254 | up->curregs[R15] |= BRKIE; |
| 1233 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); | 1255 | brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); |
| 1234 | sunzilog_convert_to_zs(up, up->cflag, 0, brg); | 1256 | sunzilog_convert_to_zs(up, up->cflag, 0, brg); |
| 1235 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); | 1257 | sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); |
| @@ -1283,8 +1305,18 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | |||
| 1283 | 1305 | ||
| 1284 | if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | | 1306 | if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | |
| 1285 | SUNZILOG_FLAG_CONS_MOUSE)) { | 1307 | SUNZILOG_FLAG_CONS_MOUSE)) { |
| 1308 | up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; | ||
| 1309 | up->curregs[R4] = PAR_EVEN | X16CLK | SB1; | ||
| 1310 | up->curregs[R3] = RxENAB | Rx8; | ||
| 1311 | up->curregs[R5] = TxENAB | Tx8; | ||
| 1312 | up->curregs[R6] = 0x00; /* SDLC Address */ | ||
| 1313 | up->curregs[R7] = 0x7E; /* SDLC Flag */ | ||
| 1314 | up->curregs[R9] = NV; | ||
| 1315 | up->curregs[R7p] = 0x00; | ||
| 1286 | sunzilog_init_kbdms(up, up->port.line); | 1316 | sunzilog_init_kbdms(up, up->port.line); |
| 1287 | up->curregs[R9] |= (NV | MIE); | 1317 | /* Only enable interrupts if an ISR handler available */ |
| 1318 | if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) | ||
| 1319 | up->curregs[R9] |= MIE; | ||
| 1288 | write_zsreg(channel, R9, up->curregs[R9]); | 1320 | write_zsreg(channel, R9, up->curregs[R9]); |
| 1289 | } else { | 1321 | } else { |
| 1290 | /* Normal serial TTY. */ | 1322 | /* Normal serial TTY. */ |
| @@ -1293,7 +1325,9 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | |||
| 1293 | up->curregs[R4] = PAR_EVEN | X16CLK | SB1; | 1325 | up->curregs[R4] = PAR_EVEN | X16CLK | SB1; |
| 1294 | up->curregs[R3] = RxENAB | Rx8; | 1326 | up->curregs[R3] = RxENAB | Rx8; |
| 1295 | up->curregs[R5] = TxENAB | Tx8; | 1327 | up->curregs[R5] = TxENAB | Tx8; |
| 1296 | up->curregs[R9] = NV | MIE; | 1328 | up->curregs[R6] = 0x00; /* SDLC Address */ |
| 1329 | up->curregs[R7] = 0x7E; /* SDLC Flag */ | ||
| 1330 | up->curregs[R9] = NV; | ||
| 1297 | up->curregs[R10] = NRZ; | 1331 | up->curregs[R10] = NRZ; |
| 1298 | up->curregs[R11] = TCBR | RCBR; | 1332 | up->curregs[R11] = TCBR | RCBR; |
| 1299 | baud = 9600; | 1333 | baud = 9600; |
| @@ -1301,7 +1335,14 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | |||
| 1301 | up->curregs[R12] = (brg & 0xff); | 1335 | up->curregs[R12] = (brg & 0xff); |
| 1302 | up->curregs[R13] = (brg >> 8) & 0xff; | 1336 | up->curregs[R13] = (brg >> 8) & 0xff; |
| 1303 | up->curregs[R14] = BRSRC | BRENAB; | 1337 | up->curregs[R14] = BRSRC | BRENAB; |
| 1304 | __load_zsregs(channel, up->curregs); | 1338 | up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */ |
| 1339 | up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL; | ||
| 1340 | if (__load_zsregs(channel, up->curregs)) { | ||
| 1341 | up->flags |= SUNZILOG_FLAG_ESCC; | ||
| 1342 | } | ||
| 1343 | /* Only enable interrupts if an ISR handler available */ | ||
| 1344 | if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) | ||
| 1345 | up->curregs[R9] |= MIE; | ||
| 1305 | write_zsreg(channel, R9, up->curregs[R9]); | 1346 | write_zsreg(channel, R9, up->curregs[R9]); |
| 1306 | } | 1347 | } |
| 1307 | 1348 | ||
| @@ -1390,12 +1431,14 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m | |||
| 1390 | return err; | 1431 | return err; |
| 1391 | } | 1432 | } |
| 1392 | } else { | 1433 | } else { |
| 1393 | printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) " | 1434 | printk(KERN_INFO "%s: Keyboard at MMIO 0x%lx (irq = %d) " |
| 1394 | "is a zs\n", | 1435 | "is a %s\n", |
| 1395 | op->dev.bus_id, up[0].port.mapbase, op->irqs[0]); | 1436 | op->dev.bus_id, up[0].port.mapbase, op->irqs[0], |
| 1396 | printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) " | 1437 | sunzilog_type (&up[0].port)); |
| 1397 | "is a zs\n", | 1438 | printk(KERN_INFO "%s: Mouse at MMIO 0x%lx (irq = %d) " |
| 1398 | op->dev.bus_id, up[1].port.mapbase, op->irqs[0]); | 1439 | "is a %s\n", |
| 1440 | op->dev.bus_id, up[1].port.mapbase, op->irqs[0], | ||
| 1441 | sunzilog_type (&up[1].port)); | ||
| 1399 | } | 1442 | } |
| 1400 | 1443 | ||
| 1401 | dev_set_drvdata(&op->dev, &up[0]); | 1444 | dev_set_drvdata(&op->dev, &up[0]); |
| @@ -1487,10 +1530,23 @@ static int __init sunzilog_init(void) | |||
| 1487 | goto out_unregister_uart; | 1530 | goto out_unregister_uart; |
| 1488 | 1531 | ||
| 1489 | if (zilog_irq != -1) { | 1532 | if (zilog_irq != -1) { |
| 1533 | struct uart_sunzilog_port *up = sunzilog_irq_chain; | ||
| 1490 | err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, | 1534 | err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, |
| 1491 | "zs", sunzilog_irq_chain); | 1535 | "zs", sunzilog_irq_chain); |
| 1492 | if (err) | 1536 | if (err) |
| 1493 | goto out_unregister_driver; | 1537 | goto out_unregister_driver; |
| 1538 | |||
| 1539 | /* Enable Interrupts */ | ||
| 1540 | while (up) { | ||
| 1541 | struct zilog_channel __iomem *channel; | ||
| 1542 | |||
| 1543 | /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */ | ||
| 1544 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); | ||
| 1545 | up->flags |= SUNZILOG_FLAG_ISR_HANDLER; | ||
| 1546 | up->curregs[R9] |= MIE; | ||
| 1547 | write_zsreg(channel, R9, up->curregs[R9]); | ||
| 1548 | up = up->next; | ||
| 1549 | } | ||
| 1494 | } | 1550 | } |
| 1495 | 1551 | ||
| 1496 | out: | 1552 | out: |
| @@ -1515,6 +1571,20 @@ static void __exit sunzilog_exit(void) | |||
| 1515 | of_unregister_driver(&zs_driver); | 1571 | of_unregister_driver(&zs_driver); |
| 1516 | 1572 | ||
| 1517 | if (zilog_irq != -1) { | 1573 | if (zilog_irq != -1) { |
| 1574 | struct uart_sunzilog_port *up = sunzilog_irq_chain; | ||
| 1575 | |||
| 1576 | /* Disable Interrupts */ | ||
| 1577 | while (up) { | ||
| 1578 | struct zilog_channel __iomem *channel; | ||
| 1579 | |||
| 1580 | /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */ | ||
| 1581 | channel = ZILOG_CHANNEL_FROM_PORT(&up->port); | ||
| 1582 | up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER; | ||
| 1583 | up->curregs[R9] &= ~MIE; | ||
| 1584 | write_zsreg(channel, R9, up->curregs[R9]); | ||
| 1585 | up = up->next; | ||
| 1586 | } | ||
| 1587 | |||
| 1518 | free_irq(zilog_irq, sunzilog_irq_chain); | 1588 | free_irq(zilog_irq, sunzilog_irq_chain); |
| 1519 | zilog_irq = -1; | 1589 | zilog_irq = -1; |
| 1520 | } | 1590 | } |
diff --git a/drivers/serial/sunzilog.h b/drivers/serial/sunzilog.h index 7939b6d71270..5dec7b47cc38 100644 --- a/drivers/serial/sunzilog.h +++ b/drivers/serial/sunzilog.h | |||
| @@ -13,7 +13,8 @@ struct zilog_layout { | |||
| 13 | struct zilog_channel channelA; | 13 | struct zilog_channel channelA; |
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | #define NUM_ZSREGS 16 | 16 | #define NUM_ZSREGS 17 |
| 17 | #define R7p 16 /* Written as R7 with P15 bit 0 set */ | ||
| 17 | 18 | ||
| 18 | /* Conversion routines to/from brg time constants from/to bits | 19 | /* Conversion routines to/from brg time constants from/to bits |
| 19 | * per second. | 20 | * per second. |
| @@ -127,6 +128,15 @@ struct zilog_layout { | |||
| 127 | 128 | ||
| 128 | /* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ | 129 | /* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ |
| 129 | 130 | ||
| 131 | /* Write Register 7' (ESCC Only) */ | ||
| 132 | #define AUTO_TxFLAG 1 /* Automatic Tx SDLC Flag */ | ||
| 133 | #define AUTO_EOM_RST 2 /* Automatic EOM Reset */ | ||
| 134 | #define AUTOnRTS 4 /* Automatic /RTS pin deactivation */ | ||
| 135 | #define RxFIFO_LVL 8 /* Receive FIFO interrupt level */ | ||
| 136 | #define nDTRnREQ 0x10 /* /DTR/REQ timing */ | ||
| 137 | #define TxFIFO_LVL 0x20 /* Transmit FIFO interrupt level */ | ||
| 138 | #define EXT_RD_EN 0x40 /* Extended read register enable */ | ||
| 139 | |||
| 130 | /* Write Register 8 (transmit buffer) */ | 140 | /* Write Register 8 (transmit buffer) */ |
| 131 | 141 | ||
| 132 | /* Write Register 9 (Master interrupt control) */ | 142 | /* Write Register 9 (Master interrupt control) */ |
| @@ -135,6 +145,7 @@ struct zilog_layout { | |||
| 135 | #define DLC 4 /* Disable Lower Chain */ | 145 | #define DLC 4 /* Disable Lower Chain */ |
| 136 | #define MIE 8 /* Master Interrupt Enable */ | 146 | #define MIE 8 /* Master Interrupt Enable */ |
| 137 | #define STATHI 0x10 /* Status high */ | 147 | #define STATHI 0x10 /* Status high */ |
| 148 | #define SWIACK 0x20 /* Software Interrupt Ack (not on NMOS) */ | ||
| 138 | #define NORESET 0 /* No reset on write to R9 */ | 149 | #define NORESET 0 /* No reset on write to R9 */ |
| 139 | #define CHRB 0x40 /* Reset channel B */ | 150 | #define CHRB 0x40 /* Reset channel B */ |
| 140 | #define CHRA 0x80 /* Reset channel A */ | 151 | #define CHRA 0x80 /* Reset channel A */ |
| @@ -187,7 +198,9 @@ struct zilog_layout { | |||
| 187 | #define SNRZI 0xe0 /* Set NRZI mode */ | 198 | #define SNRZI 0xe0 /* Set NRZI mode */ |
| 188 | 199 | ||
| 189 | /* Write Register 15 (external/status interrupt control) */ | 200 | /* Write Register 15 (external/status interrupt control) */ |
| 201 | #define WR7pEN 1 /* WR7' Enable (ESCC only) */ | ||
| 190 | #define ZCIE 2 /* Zero count IE */ | 202 | #define ZCIE 2 /* Zero count IE */ |
| 203 | #define FIFOEN 4 /* FIFO Enable (ESCC only) */ | ||
| 191 | #define DCDIE 8 /* DCD IE */ | 204 | #define DCDIE 8 /* DCD IE */ |
| 192 | #define SYNCIE 0x10 /* Sync/hunt IE */ | 205 | #define SYNCIE 0x10 /* Sync/hunt IE */ |
| 193 | #define CTSIE 0x20 /* CTS IE */ | 206 | #define CTSIE 0x20 /* CTS IE */ |
| @@ -241,6 +254,10 @@ struct zilog_layout { | |||
| 241 | #define CHATxIP 0x10 /* Channel A Tx IP */ | 254 | #define CHATxIP 0x10 /* Channel A Tx IP */ |
| 242 | #define CHARxIP 0x20 /* Channel A Rx IP */ | 255 | #define CHARxIP 0x20 /* Channel A Rx IP */ |
| 243 | 256 | ||
| 257 | /* Read Register 6 (LSB frame byte count [Not on NMOS]) */ | ||
| 258 | |||
| 259 | /* Read Register 7 (MSB frame byte count and FIFO status [Not on NMOS]) */ | ||
| 260 | |||
| 244 | /* Read Register 8 (receive data register) */ | 261 | /* Read Register 8 (receive data register) */ |
| 245 | 262 | ||
| 246 | /* Read Register 10 (misc status bits) */ | 263 | /* Read Register 10 (misc status bits) */ |
diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h index e01b80559c93..26ec046715c8 100644 --- a/include/asm-sparc64/openprom.h +++ b/include/asm-sparc64/openprom.h | |||
| @@ -177,7 +177,7 @@ struct linux_nodeops { | |||
| 177 | /* More fun PROM structures for device probing. */ | 177 | /* More fun PROM structures for device probing. */ |
| 178 | #define PROMREG_MAX 24 | 178 | #define PROMREG_MAX 24 |
| 179 | #define PROMVADDR_MAX 16 | 179 | #define PROMVADDR_MAX 16 |
| 180 | #define PROMINTR_MAX 15 | 180 | #define PROMINTR_MAX 32 |
| 181 | 181 | ||
| 182 | struct linux_prom_registers { | 182 | struct linux_prom_registers { |
| 183 | unsigned which_io; /* hi part of physical address */ | 183 | unsigned which_io; /* hi part of physical address */ |
