diff options
Diffstat (limited to 'arch/sparc64')
48 files changed, 3077 insertions, 4412 deletions
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 36b4b7ab9cfb..5446e2a499b1 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
| @@ -18,6 +18,13 @@ config SPARC64 | |||
| 18 | select HAVE_ARCH_KGDB | 18 | select HAVE_ARCH_KGDB |
| 19 | select USE_GENERIC_SMP_HELPERS if SMP | 19 | select USE_GENERIC_SMP_HELPERS if SMP |
| 20 | select HAVE_ARCH_TRACEHOOK | 20 | select HAVE_ARCH_TRACEHOOK |
| 21 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
| 22 | select RTC_CLASS | ||
| 23 | select RTC_DRV_M48T59 | ||
| 24 | select RTC_DRV_CMOS | ||
| 25 | select RTC_DRV_BQ4802 | ||
| 26 | select RTC_DRV_SUN4V | ||
| 27 | select RTC_DRV_STARFIRE | ||
| 21 | 28 | ||
| 22 | config GENERIC_TIME | 29 | config GENERIC_TIME |
| 23 | bool | 30 | bool |
| @@ -31,6 +38,11 @@ config GENERIC_CLOCKEVENTS | |||
| 31 | bool | 38 | bool |
| 32 | default y | 39 | default y |
| 33 | 40 | ||
| 41 | config GENERIC_GPIO | ||
| 42 | bool | ||
| 43 | help | ||
| 44 | Generic GPIO API support | ||
| 45 | |||
| 34 | config 64BIT | 46 | config 64BIT |
| 35 | def_bool y | 47 | def_bool y |
| 36 | 48 | ||
| @@ -185,6 +197,17 @@ config US2E_FREQ | |||
| 185 | 197 | ||
| 186 | If in doubt, say N. | 198 | If in doubt, say N. |
| 187 | 199 | ||
| 200 | config US3_MC | ||
| 201 | tristate "UltraSPARC-III Memory Controller driver" | ||
| 202 | default y | ||
| 203 | help | ||
| 204 | This adds a driver for the UltraSPARC-III memory controller. | ||
| 205 | Loading this driver allows exact mnemonic strings to be | ||
| 206 | printed in the event of a memory error, so that the faulty DIMM | ||
| 207 | on the motherboard can be matched to the error. | ||
| 208 | |||
| 209 | If in doubt, say Y, as this information can be very useful. | ||
| 210 | |||
| 188 | # Global things across all Sun machines. | 211 | # Global things across all Sun machines. |
| 189 | config GENERIC_LOCKBREAK | 212 | config GENERIC_LOCKBREAK |
| 190 | bool | 213 | bool |
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index b785a395b12f..c7214abc0d84 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) | 7 | # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) |
| 8 | # | 8 | # |
| 9 | 9 | ||
| 10 | CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -m64 | 10 | CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64 |
| 11 | 11 | ||
| 12 | # Undefine sparc when processing vmlinux.lds - it is used | 12 | # Undefine sparc when processing vmlinux.lds - it is used |
| 13 | # And teach CPP we are doing 64 bit builds (for this case) | 13 | # And teach CPP we are doing 64 bit builds (for this case) |
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 418b5782096e..c0b8009ab196 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile | |||
| @@ -7,16 +7,16 @@ EXTRA_CFLAGS := -Werror | |||
| 7 | 7 | ||
| 8 | extra-y := head.o init_task.o vmlinux.lds | 8 | extra-y := head.o init_task.o vmlinux.lds |
| 9 | 9 | ||
| 10 | obj-y := process.o setup.o cpu.o idprom.o \ | 10 | obj-y := process.o setup.o cpu.o idprom.o reboot.o \ |
| 11 | traps.o auxio.o una_asm.o sysfs.o iommu.o \ | 11 | traps.o auxio.o una_asm.o sysfs.o iommu.o \ |
| 12 | irq.o ptrace.o time.o sys_sparc.o signal.o \ | 12 | irq.o ptrace.o time.o sys_sparc.o signal.o \ |
| 13 | unaligned.o central.o pci.o starfire.o \ | 13 | unaligned.o central.o starfire.o \ |
| 14 | power.o sbus.o sparc64_ksyms.o chmc.o \ | 14 | power.o sbus.o sparc64_ksyms.o ebus.o \ |
| 15 | visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o | 15 | visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o |
| 16 | 16 | ||
| 17 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 17 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
| 18 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 18 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
| 19 | obj-$(CONFIG_PCI) += ebus.o pci_common.o \ | 19 | obj-$(CONFIG_PCI) += pci.o pci_common.o psycho_common.o \ |
| 20 | pci_psycho.o pci_sabre.o pci_schizo.o \ | 20 | pci_psycho.o pci_sabre.o pci_schizo.o \ |
| 21 | pci_sun4v.o pci_sun4v_asm.o pci_fire.o | 21 | pci_sun4v.o pci_sun4v_asm.o pci_fire.o |
| 22 | obj-$(CONFIG_PCI_MSI) += pci_msi.o | 22 | obj-$(CONFIG_PCI_MSI) += pci_msi.o |
| @@ -25,6 +25,7 @@ obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o | |||
| 25 | obj-$(CONFIG_MODULES) += module.o | 25 | obj-$(CONFIG_MODULES) += module.o |
| 26 | obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o | 26 | obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o |
| 27 | obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o | 27 | obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o |
| 28 | obj-$(CONFIG_US3_MC) += chmc.o | ||
| 28 | obj-$(CONFIG_KPROBES) += kprobes.o | 29 | obj-$(CONFIG_KPROBES) += kprobes.o |
| 29 | obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o | 30 | obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o |
| 30 | obj-$(CONFIG_AUDIT) += audit.o | 31 | obj-$(CONFIG_AUDIT) += audit.o |
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index dd5c7bf87619..858beda86524 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c | |||
| @@ -109,7 +109,7 @@ void auxio_set_lte(int on) | |||
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | static struct of_device_id auxio_match[] = { | 112 | static struct of_device_id __initdata auxio_match[] = { |
| 113 | { | 113 | { |
| 114 | .name = "auxio", | 114 | .name = "auxio", |
| 115 | }, | 115 | }, |
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index f2e87d0d7e1d..05f1c916db06 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c | |||
| @@ -1,461 +1,268 @@ | |||
| 1 | /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire. | 1 | /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 1997, 1999 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
| 8 | #include <linux/string.h> | 8 | #include <linux/string.h> |
| 9 | #include <linux/timer.h> | ||
| 10 | #include <linux/sched.h> | ||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 13 | #include <linux/bootmem.h> | 10 | #include <linux/of_device.h> |
| 11 | #include <linux/platform_device.h> | ||
| 14 | 12 | ||
| 15 | #include <asm/page.h> | ||
| 16 | #include <asm/fhc.h> | 13 | #include <asm/fhc.h> |
| 17 | #include <asm/starfire.h> | 14 | #include <asm/upa.h> |
| 18 | 15 | ||
| 19 | static struct linux_central *central_bus = NULL; | 16 | struct clock_board { |
| 20 | static struct linux_fhc *fhc_list = NULL; | 17 | void __iomem *clock_freq_regs; |
| 18 | void __iomem *clock_regs; | ||
| 19 | void __iomem *clock_ver_reg; | ||
| 20 | int num_slots; | ||
| 21 | struct resource leds_resource; | ||
| 22 | struct platform_device leds_pdev; | ||
| 23 | }; | ||
| 24 | |||
| 25 | struct fhc { | ||
| 26 | void __iomem *pregs; | ||
| 27 | bool central; | ||
| 28 | bool jtag_master; | ||
| 29 | int board_num; | ||
| 30 | struct resource leds_resource; | ||
| 31 | struct platform_device leds_pdev; | ||
| 32 | }; | ||
| 33 | |||
| 34 | static int __devinit clock_board_calc_nslots(struct clock_board *p) | ||
| 35 | { | ||
| 36 | u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0; | ||
| 21 | 37 | ||
| 22 | #define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child) | 38 | switch (reg) { |
| 39 | case 0x40: | ||
| 40 | return 16; | ||
| 23 | 41 | ||
| 24 | static void central_probe_failure(int line) | 42 | case 0xc0: |
| 25 | { | 43 | return 8; |
| 26 | prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n", | ||
| 27 | line); | ||
| 28 | prom_halt(); | ||
| 29 | } | ||
| 30 | 44 | ||
| 31 | static void central_ranges_init(struct linux_central *central) | 45 | case 0x80: |
| 32 | { | 46 | reg = 0; |
| 33 | struct device_node *dp = central->prom_node; | 47 | if (p->clock_ver_reg) |
| 34 | const void *pval; | 48 | reg = upa_readb(p->clock_ver_reg); |
| 35 | int len; | 49 | if (reg) { |
| 36 | 50 | if (reg & 0x80) | |
| 37 | central->num_central_ranges = 0; | 51 | return 4; |
| 38 | pval = of_get_property(dp, "ranges", &len); | 52 | else |
| 39 | if (pval) { | 53 | return 5; |
| 40 | memcpy(central->central_ranges, pval, len); | 54 | } |
| 41 | central->num_central_ranges = | 55 | /* Fallthrough */ |
| 42 | (len / sizeof(struct linux_prom_ranges)); | 56 | default: |
| 57 | return 4; | ||
| 43 | } | 58 | } |
| 44 | } | 59 | } |
| 45 | 60 | ||
| 46 | static void fhc_ranges_init(struct linux_fhc *fhc) | 61 | static int __devinit clock_board_probe(struct of_device *op, |
| 62 | const struct of_device_id *match) | ||
| 47 | { | 63 | { |
| 48 | struct device_node *dp = fhc->prom_node; | 64 | struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 49 | const void *pval; | 65 | int err = -ENOMEM; |
| 50 | int len; | ||
| 51 | |||
| 52 | fhc->num_fhc_ranges = 0; | ||
| 53 | pval = of_get_property(dp, "ranges", &len); | ||
| 54 | if (pval) { | ||
| 55 | memcpy(fhc->fhc_ranges, pval, len); | ||
| 56 | fhc->num_fhc_ranges = | ||
| 57 | (len / sizeof(struct linux_prom_ranges)); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | 66 | ||
| 61 | /* Range application routines are exported to various drivers, | 67 | if (!p) { |
| 62 | * so do not __init this. | 68 | printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n"); |
| 63 | */ | 69 | goto out; |
| 64 | static void adjust_regs(struct linux_prom_registers *regp, int nregs, | ||
| 65 | struct linux_prom_ranges *rangep, int nranges) | ||
| 66 | { | ||
| 67 | int regc, rngc; | ||
| 68 | |||
| 69 | for (regc = 0; regc < nregs; regc++) { | ||
| 70 | for (rngc = 0; rngc < nranges; rngc++) | ||
| 71 | if (regp[regc].which_io == rangep[rngc].ot_child_space) | ||
| 72 | break; /* Fount it */ | ||
| 73 | if (rngc == nranges) /* oops */ | ||
| 74 | central_probe_failure(__LINE__); | ||
| 75 | regp[regc].which_io = rangep[rngc].ot_parent_space; | ||
| 76 | regp[regc].phys_addr -= rangep[rngc].ot_child_base; | ||
| 77 | regp[regc].phys_addr += rangep[rngc].ot_parent_base; | ||
| 78 | } | 70 | } |
| 79 | } | ||
| 80 | 71 | ||
| 81 | /* Apply probed fhc ranges to registers passed, if no ranges return. */ | 72 | p->clock_freq_regs = of_ioremap(&op->resource[0], 0, |
| 82 | static void apply_fhc_ranges(struct linux_fhc *fhc, | 73 | resource_size(&op->resource[0]), |
| 83 | struct linux_prom_registers *regs, | 74 | "clock_board_freq"); |
| 84 | int nregs) | 75 | if (!p->clock_freq_regs) { |
| 85 | { | 76 | printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n"); |
| 86 | if (fhc->num_fhc_ranges) | 77 | goto out_free; |
| 87 | adjust_regs(regs, nregs, fhc->fhc_ranges, | 78 | } |
| 88 | fhc->num_fhc_ranges); | ||
| 89 | } | ||
| 90 | 79 | ||
| 91 | /* Apply probed central ranges to registers passed, if no ranges return. */ | 80 | p->clock_regs = of_ioremap(&op->resource[1], 0, |
| 92 | static void apply_central_ranges(struct linux_central *central, | 81 | resource_size(&op->resource[1]), |
| 93 | struct linux_prom_registers *regs, int nregs) | 82 | "clock_board_regs"); |
| 94 | { | 83 | if (!p->clock_regs) { |
| 95 | if (central->num_central_ranges) | 84 | printk(KERN_ERR "clock_board: Cannot map clock_regs\n"); |
| 96 | adjust_regs(regs, nregs, central->central_ranges, | 85 | goto out_unmap_clock_freq_regs; |
| 97 | central->num_central_ranges); | 86 | } |
| 98 | } | ||
| 99 | 87 | ||
| 100 | static void * __init central_alloc_bootmem(unsigned long size) | 88 | if (op->resource[2].flags) { |
| 101 | { | 89 | p->clock_ver_reg = of_ioremap(&op->resource[2], 0, |
| 102 | void *ret; | 90 | resource_size(&op->resource[2]), |
| 91 | "clock_ver_reg"); | ||
| 92 | if (!p->clock_ver_reg) { | ||
| 93 | printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n"); | ||
| 94 | goto out_unmap_clock_regs; | ||
| 95 | } | ||
| 96 | } | ||
| 103 | 97 | ||
| 104 | ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); | 98 | p->num_slots = clock_board_calc_nslots(p); |
| 105 | if (ret != NULL) | ||
| 106 | memset(ret, 0, size); | ||
| 107 | 99 | ||
| 108 | return ret; | 100 | p->leds_resource.start = (unsigned long) |
| 109 | } | 101 | (p->clock_regs + CLOCK_CTRL); |
| 102 | p->leds_resource.end = p->leds_resource.end; | ||
| 103 | p->leds_resource.name = "leds"; | ||
| 110 | 104 | ||
| 111 | static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) | 105 | p->leds_pdev.name = "sunfire-clockboard-leds"; |
| 112 | { | 106 | p->leds_pdev.resource = &p->leds_resource; |
| 113 | unsigned long ret = ((unsigned long) r->which_io) << 32; | 107 | p->leds_pdev.num_resources = 1; |
| 108 | p->leds_pdev.dev.parent = &op->dev; | ||
| 114 | 109 | ||
| 115 | return ret | (unsigned long) r->phys_addr; | 110 | err = platform_device_register(&p->leds_pdev); |
| 116 | } | 111 | if (err) { |
| 117 | 112 | printk(KERN_ERR "clock_board: Could not register LEDS " | |
| 118 | static void __init probe_other_fhcs(void) | 113 | "platform device\n"); |
| 119 | { | 114 | goto out_unmap_clock_ver_reg; |
| 120 | struct device_node *dp; | ||
| 121 | const struct linux_prom64_registers *fpregs; | ||
| 122 | |||
| 123 | for_each_node_by_name(dp, "fhc") { | ||
| 124 | struct linux_fhc *fhc; | ||
| 125 | int board; | ||
| 126 | u32 tmp; | ||
| 127 | |||
| 128 | if (dp->parent && | ||
| 129 | dp->parent->parent != NULL) | ||
| 130 | continue; | ||
| 131 | |||
| 132 | fhc = (struct linux_fhc *) | ||
| 133 | central_alloc_bootmem(sizeof(struct linux_fhc)); | ||
| 134 | if (fhc == NULL) | ||
| 135 | central_probe_failure(__LINE__); | ||
| 136 | |||
| 137 | /* Link it into the FHC chain. */ | ||
| 138 | fhc->next = fhc_list; | ||
| 139 | fhc_list = fhc; | ||
| 140 | |||
| 141 | /* Toplevel FHCs have no parent. */ | ||
| 142 | fhc->parent = NULL; | ||
| 143 | |||
| 144 | fhc->prom_node = dp; | ||
| 145 | fhc_ranges_init(fhc); | ||
| 146 | |||
| 147 | /* Non-central FHC's have 64-bit OBP format registers. */ | ||
| 148 | fpregs = of_get_property(dp, "reg", NULL); | ||
| 149 | if (!fpregs) | ||
| 150 | central_probe_failure(__LINE__); | ||
| 151 | |||
| 152 | /* Only central FHC needs special ranges applied. */ | ||
| 153 | fhc->fhc_regs.pregs = fpregs[0].phys_addr; | ||
| 154 | fhc->fhc_regs.ireg = fpregs[1].phys_addr; | ||
| 155 | fhc->fhc_regs.ffregs = fpregs[2].phys_addr; | ||
| 156 | fhc->fhc_regs.sregs = fpregs[3].phys_addr; | ||
| 157 | fhc->fhc_regs.uregs = fpregs[4].phys_addr; | ||
| 158 | fhc->fhc_regs.tregs = fpregs[5].phys_addr; | ||
| 159 | |||
| 160 | board = of_getintprop_default(dp, "board#", -1); | ||
| 161 | fhc->board = board; | ||
| 162 | |||
| 163 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); | ||
| 164 | if ((tmp & FHC_JTAG_CTRL_MENAB) != 0) | ||
| 165 | fhc->jtag_master = 1; | ||
| 166 | else | ||
| 167 | fhc->jtag_master = 0; | ||
| 168 | |||
| 169 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); | ||
| 170 | printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n", | ||
| 171 | board, | ||
| 172 | (tmp & FHC_ID_VERS) >> 28, | ||
| 173 | (tmp & FHC_ID_PARTID) >> 12, | ||
| 174 | (tmp & FHC_ID_MANUF) >> 1, | ||
| 175 | (fhc->jtag_master ? "(JTAG Master)" : "")); | ||
| 176 | |||
| 177 | /* This bit must be set in all non-central FHC's in | ||
| 178 | * the system. When it is clear, this identifies | ||
| 179 | * the central board. | ||
| 180 | */ | ||
| 181 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
| 182 | tmp |= FHC_CONTROL_IXIST; | ||
| 183 | upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
| 184 | } | 115 | } |
| 185 | } | ||
| 186 | 116 | ||
| 187 | static void probe_clock_board(struct linux_central *central, | 117 | printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n", |
| 188 | struct linux_fhc *fhc, | 118 | p->num_slots); |
| 189 | struct device_node *fp) | ||
| 190 | { | ||
| 191 | struct device_node *dp; | ||
| 192 | struct linux_prom_registers cregs[3]; | ||
| 193 | const struct linux_prom_registers *pr; | ||
| 194 | int nslots, tmp, nregs; | ||
| 195 | |||
| 196 | dp = fp->child; | ||
| 197 | while (dp) { | ||
| 198 | if (!strcmp(dp->name, "clock-board")) | ||
| 199 | break; | ||
| 200 | dp = dp->sibling; | ||
| 201 | } | ||
| 202 | if (!dp) | ||
| 203 | central_probe_failure(__LINE__); | ||
| 204 | 119 | ||
| 205 | pr = of_get_property(dp, "reg", &nregs); | 120 | err = 0; |
| 206 | if (!pr) | 121 | out: |
| 207 | central_probe_failure(__LINE__); | 122 | return err; |
| 208 | 123 | ||
| 209 | memcpy(cregs, pr, nregs); | 124 | out_unmap_clock_ver_reg: |
| 210 | nregs /= sizeof(struct linux_prom_registers); | 125 | if (p->clock_ver_reg) |
| 126 | of_iounmap(&op->resource[2], p->clock_ver_reg, | ||
| 127 | resource_size(&op->resource[2])); | ||
| 211 | 128 | ||
| 212 | apply_fhc_ranges(fhc, &cregs[0], nregs); | 129 | out_unmap_clock_regs: |
| 213 | apply_central_ranges(central, &cregs[0], nregs); | 130 | of_iounmap(&op->resource[1], p->clock_regs, |
| 214 | central->cfreg = prom_reg_to_paddr(&cregs[0]); | 131 | resource_size(&op->resource[1])); |
| 215 | central->clkregs = prom_reg_to_paddr(&cregs[1]); | ||
| 216 | 132 | ||
| 217 | if (nregs == 2) | 133 | out_unmap_clock_freq_regs: |
| 218 | central->clkver = 0UL; | 134 | of_iounmap(&op->resource[0], p->clock_freq_regs, |
| 219 | else | 135 | resource_size(&op->resource[0])); |
| 220 | central->clkver = prom_reg_to_paddr(&cregs[2]); | ||
| 221 | 136 | ||
| 222 | tmp = upa_readb(central->clkregs + CLOCK_STAT1); | 137 | out_free: |
| 223 | tmp &= 0xc0; | 138 | kfree(p); |
| 224 | switch(tmp) { | 139 | goto out; |
| 225 | case 0x40: | ||
| 226 | nslots = 16; | ||
| 227 | break; | ||
| 228 | case 0xc0: | ||
| 229 | nslots = 8; | ||
| 230 | break; | ||
| 231 | case 0x80: | ||
| 232 | if (central->clkver != 0UL && | ||
| 233 | upa_readb(central->clkver) != 0) { | ||
| 234 | if ((upa_readb(central->clkver) & 0x80) != 0) | ||
| 235 | nslots = 4; | ||
| 236 | else | ||
| 237 | nslots = 5; | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | default: | ||
| 241 | nslots = 4; | ||
| 242 | break; | ||
| 243 | }; | ||
| 244 | central->slots = nslots; | ||
| 245 | printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n", | ||
| 246 | central->slots, upa_readb(central->cfreg), | ||
| 247 | (central->clkver ? upa_readb(central->clkver) : 0x00)); | ||
| 248 | } | 140 | } |
| 249 | 141 | ||
| 250 | static void ZAP(unsigned long iclr, unsigned long imap) | 142 | static struct of_device_id __initdata clock_board_match[] = { |
| 143 | { | ||
| 144 | .name = "clock-board", | ||
| 145 | }, | ||
| 146 | {}, | ||
| 147 | }; | ||
| 148 | |||
| 149 | static struct of_platform_driver clock_board_driver = { | ||
| 150 | .match_table = clock_board_match, | ||
| 151 | .probe = clock_board_probe, | ||
| 152 | .driver = { | ||
| 153 | .name = "clock_board", | ||
| 154 | }, | ||
| 155 | }; | ||
| 156 | |||
| 157 | static int __devinit fhc_probe(struct of_device *op, | ||
| 158 | const struct of_device_id *match) | ||
| 251 | { | 159 | { |
| 252 | u32 imap_tmp; | 160 | struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 253 | 161 | int err = -ENOMEM; | |
| 254 | upa_writel(0, iclr); | 162 | u32 reg; |
| 255 | upa_readl(iclr); | ||
| 256 | imap_tmp = upa_readl(imap); | ||
| 257 | imap_tmp &= ~(0x80000000); | ||
| 258 | upa_writel(imap_tmp, imap); | ||
| 259 | upa_readl(imap); | ||
| 260 | } | ||
| 261 | 163 | ||
| 262 | static void init_all_fhc_hw(void) | 164 | if (!p) { |
| 263 | { | 165 | printk(KERN_ERR "fhc: Cannot allocate struct fhc\n"); |
| 264 | struct linux_fhc *fhc; | 166 | goto out; |
| 265 | |||
| 266 | for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) { | ||
| 267 | u32 tmp; | ||
| 268 | |||
| 269 | /* Clear all of the interrupt mapping registers | ||
| 270 | * just in case OBP left them in a foul state. | ||
| 271 | */ | ||
| 272 | ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR, | ||
| 273 | fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP); | ||
| 274 | ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR, | ||
| 275 | fhc->fhc_regs.sregs + FHC_SREGS_IMAP); | ||
| 276 | ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR, | ||
| 277 | fhc->fhc_regs.uregs + FHC_UREGS_IMAP); | ||
| 278 | ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR, | ||
| 279 | fhc->fhc_regs.tregs + FHC_TREGS_IMAP); | ||
| 280 | |||
| 281 | /* Setup FHC control register. */ | ||
| 282 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
| 283 | |||
| 284 | /* All non-central boards have this bit set. */ | ||
| 285 | if (! IS_CENTRAL_FHC(fhc)) | ||
| 286 | tmp |= FHC_CONTROL_IXIST; | ||
| 287 | |||
| 288 | /* For all FHCs, clear the firmware synchronization | ||
| 289 | * line and both low power mode enables. | ||
| 290 | */ | ||
| 291 | tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | | ||
| 292 | FHC_CONTROL_SLINE); | ||
| 293 | |||
| 294 | upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
| 295 | upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
| 296 | } | 167 | } |
| 297 | 168 | ||
| 298 | } | 169 | if (!strcmp(op->node->parent->name, "central")) |
| 170 | p->central = true; | ||
| 299 | 171 | ||
| 300 | void __init central_probe(void) | 172 | p->pregs = of_ioremap(&op->resource[0], 0, |
| 301 | { | 173 | resource_size(&op->resource[0]), |
| 302 | struct linux_prom_registers fpregs[6]; | 174 | "fhc_pregs"); |
| 303 | const struct linux_prom_registers *pr; | 175 | if (!p->pregs) { |
| 304 | struct linux_fhc *fhc; | 176 | printk(KERN_ERR "fhc: Cannot map pregs\n"); |
| 305 | struct device_node *dp, *fp; | 177 | goto out_free; |
| 306 | int err; | ||
| 307 | |||
| 308 | dp = of_find_node_by_name(NULL, "central"); | ||
| 309 | if (!dp) { | ||
| 310 | if (this_is_starfire) | ||
| 311 | starfire_cpu_setup(); | ||
| 312 | return; | ||
| 313 | } | 178 | } |
| 314 | 179 | ||
| 315 | /* Ok we got one, grab some memory for software state. */ | 180 | if (p->central) { |
| 316 | central_bus = (struct linux_central *) | 181 | reg = upa_readl(p->pregs + FHC_PREGS_BSR); |
| 317 | central_alloc_bootmem(sizeof(struct linux_central)); | 182 | p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e); |
| 318 | if (central_bus == NULL) | 183 | } else { |
| 319 | central_probe_failure(__LINE__); | 184 | p->board_num = of_getintprop_default(op->node, "board#", -1); |
| 320 | 185 | if (p->board_num == -1) { | |
| 321 | fhc = (struct linux_fhc *) | 186 | printk(KERN_ERR "fhc: No board# property\n"); |
| 322 | central_alloc_bootmem(sizeof(struct linux_fhc)); | 187 | goto out_unmap_pregs; |
| 323 | if (fhc == NULL) | 188 | } |
| 324 | central_probe_failure(__LINE__); | 189 | if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB) |
| 325 | 190 | p->jtag_master = true; | |
| 326 | /* First init central. */ | ||
| 327 | central_bus->child = fhc; | ||
| 328 | central_bus->prom_node = dp; | ||
| 329 | central_ranges_init(central_bus); | ||
| 330 | |||
| 331 | /* And then central's FHC. */ | ||
| 332 | fhc->next = fhc_list; | ||
| 333 | fhc_list = fhc; | ||
| 334 | |||
| 335 | fhc->parent = central_bus; | ||
| 336 | fp = dp->child; | ||
| 337 | while (fp) { | ||
| 338 | if (!strcmp(fp->name, "fhc")) | ||
| 339 | break; | ||
| 340 | fp = fp->sibling; | ||
| 341 | } | 191 | } |
| 342 | if (!fp) | ||
| 343 | central_probe_failure(__LINE__); | ||
| 344 | |||
| 345 | fhc->prom_node = fp; | ||
| 346 | fhc_ranges_init(fhc); | ||
| 347 | |||
| 348 | /* Now, map in FHC register set. */ | ||
| 349 | pr = of_get_property(fp, "reg", NULL); | ||
| 350 | if (!pr) | ||
| 351 | central_probe_failure(__LINE__); | ||
| 352 | memcpy(fpregs, pr, sizeof(fpregs)); | ||
| 353 | |||
| 354 | apply_central_ranges(central_bus, &fpregs[0], 6); | ||
| 355 | |||
| 356 | fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]); | ||
| 357 | fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]); | ||
| 358 | fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]); | ||
| 359 | fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]); | ||
| 360 | fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]); | ||
| 361 | fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]); | ||
| 362 | |||
| 363 | /* Obtain board number from board status register, Central's | ||
| 364 | * FHC lacks "board#" property. | ||
| 365 | */ | ||
| 366 | err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR); | ||
| 367 | fhc->board = (((err >> 16) & 0x01) | | ||
| 368 | ((err >> 12) & 0x0e)); | ||
| 369 | |||
| 370 | fhc->jtag_master = 0; | ||
| 371 | |||
| 372 | /* Attach the clock board registers for CENTRAL. */ | ||
| 373 | probe_clock_board(central_bus, fhc, fp); | ||
| 374 | |||
| 375 | err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); | ||
| 376 | printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", | ||
| 377 | fhc->board, | ||
| 378 | ((err & FHC_ID_VERS) >> 28), | ||
| 379 | ((err & FHC_ID_PARTID) >> 12), | ||
| 380 | ((err & FHC_ID_MANUF) >> 1)); | ||
| 381 | |||
| 382 | probe_other_fhcs(); | ||
| 383 | |||
| 384 | init_all_fhc_hw(); | ||
| 385 | } | ||
| 386 | 192 | ||
| 387 | static inline void fhc_ledblink(struct linux_fhc *fhc, int on) | 193 | if (!p->central) { |
| 388 | { | 194 | p->leds_resource.start = (unsigned long) |
| 389 | u32 tmp; | 195 | (p->pregs + FHC_PREGS_CTRL); |
| 196 | p->leds_resource.end = p->leds_resource.end; | ||
| 197 | p->leds_resource.name = "leds"; | ||
| 198 | |||
| 199 | p->leds_pdev.name = "sunfire-fhc-leds"; | ||
| 200 | p->leds_pdev.resource = &p->leds_resource; | ||
| 201 | p->leds_pdev.num_resources = 1; | ||
| 202 | p->leds_pdev.dev.parent = &op->dev; | ||
| 203 | |||
| 204 | err = platform_device_register(&p->leds_pdev); | ||
| 205 | if (err) { | ||
| 206 | printk(KERN_ERR "fhc: Could not register LEDS " | ||
| 207 | "platform device\n"); | ||
| 208 | goto out_unmap_pregs; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | reg = upa_readl(p->pregs + FHC_PREGS_CTRL); | ||
| 390 | 212 | ||
| 391 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | 213 | if (!p->central) |
| 214 | reg |= FHC_CONTROL_IXIST; | ||
| 392 | 215 | ||
| 393 | /* NOTE: reverse logic on this bit */ | 216 | reg &= ~(FHC_CONTROL_AOFF | |
| 394 | if (on) | 217 | FHC_CONTROL_BOFF | |
| 395 | tmp &= ~(FHC_CONTROL_RLED); | 218 | FHC_CONTROL_SLINE); |
| 396 | else | ||
| 397 | tmp |= FHC_CONTROL_RLED; | ||
| 398 | tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); | ||
| 399 | 219 | ||
| 400 | upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | 220 | upa_writel(reg, p->pregs + FHC_PREGS_CTRL); |
| 401 | upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | 221 | upa_readl(p->pregs + FHC_PREGS_CTRL); |
| 402 | } | ||
| 403 | 222 | ||
| 404 | static inline void central_ledblink(struct linux_central *central, int on) | 223 | reg = upa_readl(p->pregs + FHC_PREGS_ID); |
| 405 | { | 224 | printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n", |
| 406 | u8 tmp; | 225 | p->board_num, |
| 407 | 226 | (reg & FHC_ID_VERS) >> 28, | |
| 408 | tmp = upa_readb(central->clkregs + CLOCK_CTRL); | 227 | (reg & FHC_ID_PARTID) >> 12, |
| 228 | (reg & FHC_ID_MANUF) >> 1, | ||
| 229 | (p->jtag_master ? | ||
| 230 | "(JTAG Master)" : | ||
| 231 | (p->central ? "(Central)" : ""))); | ||
| 409 | 232 | ||
| 410 | /* NOTE: reverse logic on this bit */ | 233 | err = 0; |
| 411 | if (on) | ||
| 412 | tmp &= ~(CLOCK_CTRL_RLED); | ||
| 413 | else | ||
| 414 | tmp |= CLOCK_CTRL_RLED; | ||
| 415 | 234 | ||
| 416 | upa_writeb(tmp, central->clkregs + CLOCK_CTRL); | 235 | out: |
| 417 | upa_readb(central->clkregs + CLOCK_CTRL); | 236 | return err; |
| 418 | } | ||
| 419 | 237 | ||
| 420 | static struct timer_list sftimer; | 238 | out_unmap_pregs: |
| 421 | static int led_state; | 239 | of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0])); |
| 422 | 240 | ||
| 423 | static void sunfire_timer(unsigned long __ignored) | 241 | out_free: |
| 424 | { | 242 | kfree(p); |
| 425 | struct linux_fhc *fhc; | 243 | goto out; |
| 426 | |||
| 427 | central_ledblink(central_bus, led_state); | ||
| 428 | for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) | ||
| 429 | if (! IS_CENTRAL_FHC(fhc)) | ||
| 430 | fhc_ledblink(fhc, led_state); | ||
| 431 | led_state = ! led_state; | ||
| 432 | sftimer.expires = jiffies + (HZ >> 1); | ||
| 433 | add_timer(&sftimer); | ||
| 434 | } | 244 | } |
| 435 | 245 | ||
| 436 | /* After PCI/SBUS busses have been probed, this is called to perform | 246 | static struct of_device_id __initdata fhc_match[] = { |
| 437 | * final initialization of all FireHose Controllers in the system. | 247 | { |
| 438 | */ | 248 | .name = "fhc", |
| 439 | void firetruck_init(void) | 249 | }, |
| 250 | {}, | ||
| 251 | }; | ||
| 252 | |||
| 253 | static struct of_platform_driver fhc_driver = { | ||
| 254 | .match_table = fhc_match, | ||
| 255 | .probe = fhc_probe, | ||
| 256 | .driver = { | ||
| 257 | .name = "fhc", | ||
| 258 | }, | ||
| 259 | }; | ||
| 260 | |||
| 261 | static int __init sunfire_init(void) | ||
| 440 | { | 262 | { |
| 441 | struct linux_central *central = central_bus; | 263 | (void) of_register_driver(&fhc_driver, &of_platform_bus_type); |
| 442 | u8 ctrl; | 264 | (void) of_register_driver(&clock_board_driver, &of_platform_bus_type); |
| 443 | 265 | return 0; | |
| 444 | /* No central bus, nothing to do. */ | ||
| 445 | if (central == NULL) | ||
| 446 | return; | ||
| 447 | |||
| 448 | /* OBP leaves it on, turn it off so clock board timer LED | ||
| 449 | * is in sync with FHC ones. | ||
| 450 | */ | ||
| 451 | ctrl = upa_readb(central->clkregs + CLOCK_CTRL); | ||
| 452 | ctrl &= ~(CLOCK_CTRL_RLED); | ||
| 453 | upa_writeb(ctrl, central->clkregs + CLOCK_CTRL); | ||
| 454 | |||
| 455 | led_state = 0; | ||
| 456 | init_timer(&sftimer); | ||
| 457 | sftimer.data = 0; | ||
| 458 | sftimer.function = &sunfire_timer; | ||
| 459 | sftimer.expires = jiffies + (HZ >> 1); | ||
| 460 | add_timer(&sftimer); | ||
| 461 | } | 266 | } |
| 267 | |||
| 268 | subsys_initcall(sunfire_init); | ||
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 6d4f02e8a4cf..967b04886822 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* memctrlr.c: Driver for UltraSPARC-III memory controller. | 1 | /* chmc.c: Driver for UltraSPARC-III memory controller. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2001, 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2001, 2007, 2008 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
| @@ -13,45 +13,64 @@ | |||
| 13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
| 14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/of.h> | ||
| 17 | #include <linux/of_device.h> | ||
| 16 | #include <asm/spitfire.h> | 18 | #include <asm/spitfire.h> |
| 17 | #include <asm/chmctrl.h> | 19 | #include <asm/chmctrl.h> |
| 18 | #include <asm/cpudata.h> | 20 | #include <asm/cpudata.h> |
| 19 | #include <asm/oplib.h> | 21 | #include <asm/oplib.h> |
| 20 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
| 23 | #include <asm/head.h> | ||
| 21 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 25 | #include <asm/memctrl.h> | ||
| 26 | |||
| 27 | #define DRV_MODULE_NAME "chmc" | ||
| 28 | #define PFX DRV_MODULE_NAME ": " | ||
| 29 | #define DRV_MODULE_VERSION "0.2" | ||
| 30 | |||
| 31 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
| 32 | MODULE_DESCRIPTION("UltraSPARC-III memory controller driver"); | ||
| 33 | MODULE_LICENSE("GPL"); | ||
| 34 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
| 35 | |||
| 36 | static int mc_type; | ||
| 37 | #define MC_TYPE_SAFARI 1 | ||
| 38 | #define MC_TYPE_JBUS 2 | ||
| 39 | |||
| 40 | static dimm_printer_t us3mc_dimm_printer; | ||
| 22 | 41 | ||
| 23 | #define CHMCTRL_NDGRPS 2 | 42 | #define CHMCTRL_NDGRPS 2 |
| 24 | #define CHMCTRL_NDIMMS 4 | 43 | #define CHMCTRL_NDIMMS 4 |
| 25 | 44 | ||
| 26 | #define DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) | 45 | #define CHMC_DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) |
| 27 | 46 | ||
| 28 | /* OBP memory-layout property format. */ | 47 | /* OBP memory-layout property format. */ |
| 29 | struct obp_map { | 48 | struct chmc_obp_map { |
| 30 | unsigned char dimm_map[144]; | 49 | unsigned char dimm_map[144]; |
| 31 | unsigned char pin_map[576]; | 50 | unsigned char pin_map[576]; |
| 32 | }; | 51 | }; |
| 33 | 52 | ||
| 34 | #define DIMM_LABEL_SZ 8 | 53 | #define DIMM_LABEL_SZ 8 |
| 35 | 54 | ||
| 36 | struct obp_mem_layout { | 55 | struct chmc_obp_mem_layout { |
| 37 | /* One max 8-byte string label per DIMM. Usually | 56 | /* One max 8-byte string label per DIMM. Usually |
| 38 | * this matches the label on the motherboard where | 57 | * this matches the label on the motherboard where |
| 39 | * that DIMM resides. | 58 | * that DIMM resides. |
| 40 | */ | 59 | */ |
| 41 | char dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ]; | 60 | char dimm_labels[CHMC_DIMMS_PER_MC][DIMM_LABEL_SZ]; |
| 42 | 61 | ||
| 43 | /* If symmetric use map[0], else it is | 62 | /* If symmetric use map[0], else it is |
| 44 | * asymmetric and map[1] should be used. | 63 | * asymmetric and map[1] should be used. |
| 45 | */ | 64 | */ |
| 46 | char symmetric; | 65 | char symmetric; |
| 47 | 66 | ||
| 48 | struct obp_map map[2]; | 67 | struct chmc_obp_map map[2]; |
| 49 | }; | 68 | }; |
| 50 | 69 | ||
| 51 | #define CHMCTRL_NBANKS 4 | 70 | #define CHMCTRL_NBANKS 4 |
| 52 | 71 | ||
| 53 | struct bank_info { | 72 | struct chmc_bank_info { |
| 54 | struct mctrl_info *mp; | 73 | struct chmc *p; |
| 55 | int bank_id; | 74 | int bank_id; |
| 56 | 75 | ||
| 57 | u64 raw_reg; | 76 | u64 raw_reg; |
| @@ -65,28 +84,406 @@ struct bank_info { | |||
| 65 | unsigned long size; | 84 | unsigned long size; |
| 66 | }; | 85 | }; |
| 67 | 86 | ||
| 68 | struct mctrl_info { | 87 | struct chmc { |
| 69 | struct list_head list; | 88 | struct list_head list; |
| 70 | int portid; | 89 | int portid; |
| 90 | |||
| 91 | struct chmc_obp_mem_layout layout_prop; | ||
| 92 | int layout_size; | ||
| 93 | |||
| 94 | void __iomem *regs; | ||
| 71 | 95 | ||
| 72 | struct obp_mem_layout layout_prop; | 96 | u64 timing_control1; |
| 73 | int layout_size; | 97 | u64 timing_control2; |
| 98 | u64 timing_control3; | ||
| 99 | u64 timing_control4; | ||
| 100 | u64 memaddr_control; | ||
| 74 | 101 | ||
| 75 | void __iomem *regs; | 102 | struct chmc_bank_info logical_banks[CHMCTRL_NBANKS]; |
| 103 | }; | ||
| 104 | |||
| 105 | #define JBUSMC_REGS_SIZE 8 | ||
| 106 | |||
| 107 | #define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000UL | ||
| 108 | #define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000UL | ||
| 109 | #define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000UL | ||
| 110 | #define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000UL | ||
| 111 | #define JB_MC_REG1_XOR 0x0000010000000000UL | ||
| 112 | #define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000UL | ||
| 113 | #define JB_MC_REG1_ADDR_GEN_2_SHIFT 37 | ||
| 114 | #define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000UL | ||
| 115 | #define JB_MC_REG1_ADDR_GEN_1_SHIFT 34 | ||
| 116 | #define JB_MC_REG1_INTERLEAVE 0x0000000001800000UL | ||
| 117 | #define JB_MC_REG1_INTERLEAVE_SHIFT 23 | ||
| 118 | #define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000UL | ||
| 119 | #define JB_MC_REG1_DIMM2_PTYPE_SHIFT 21 | ||
| 120 | #define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000UL | ||
| 121 | #define JB_MC_REG1_DIMM1_PTYPE_SHIFT 20 | ||
| 122 | |||
| 123 | #define PART_TYPE_X8 0 | ||
| 124 | #define PART_TYPE_X4 1 | ||
| 125 | |||
| 126 | #define INTERLEAVE_NONE 0 | ||
| 127 | #define INTERLEAVE_SAME 1 | ||
| 128 | #define INTERLEAVE_INTERNAL 2 | ||
| 129 | #define INTERLEAVE_BOTH 3 | ||
| 130 | |||
| 131 | #define ADDR_GEN_128MB 0 | ||
| 132 | #define ADDR_GEN_256MB 1 | ||
| 133 | #define ADDR_GEN_512MB 2 | ||
| 134 | #define ADDR_GEN_1GB 3 | ||
| 135 | |||
| 136 | #define JB_NUM_DIMM_GROUPS 2 | ||
| 137 | #define JB_NUM_DIMMS_PER_GROUP 2 | ||
| 138 | #define JB_NUM_DIMMS (JB_NUM_DIMM_GROUPS * JB_NUM_DIMMS_PER_GROUP) | ||
| 139 | |||
| 140 | struct jbusmc_obp_map { | ||
| 141 | unsigned char dimm_map[18]; | ||
| 142 | unsigned char pin_map[144]; | ||
| 143 | }; | ||
| 144 | |||
| 145 | struct jbusmc_obp_mem_layout { | ||
| 146 | /* One max 8-byte string label per DIMM. Usually | ||
| 147 | * this matches the label on the motherboard where | ||
| 148 | * that DIMM resides. | ||
| 149 | */ | ||
| 150 | char dimm_labels[JB_NUM_DIMMS][DIMM_LABEL_SZ]; | ||
| 151 | |||
| 152 | /* If symmetric use map[0], else it is | ||
| 153 | * asymmetric and map[1] should be used. | ||
| 154 | */ | ||
| 155 | char symmetric; | ||
| 156 | |||
| 157 | struct jbusmc_obp_map map; | ||
| 158 | |||
| 159 | char _pad; | ||
| 160 | }; | ||
| 76 | 161 | ||
| 77 | u64 timing_control1; | 162 | struct jbusmc_dimm_group { |
| 78 | u64 timing_control2; | 163 | struct jbusmc *controller; |
| 79 | u64 timing_control3; | 164 | int index; |
| 80 | u64 timing_control4; | 165 | u64 base_addr; |
| 81 | u64 memaddr_control; | 166 | u64 size; |
| 167 | }; | ||
| 82 | 168 | ||
| 83 | struct bank_info logical_banks[CHMCTRL_NBANKS]; | 169 | struct jbusmc { |
| 170 | void __iomem *regs; | ||
| 171 | u64 mc_reg_1; | ||
| 172 | u32 portid; | ||
| 173 | struct jbusmc_obp_mem_layout layout; | ||
| 174 | int layout_len; | ||
| 175 | int num_dimm_groups; | ||
| 176 | struct jbusmc_dimm_group dimm_groups[JB_NUM_DIMM_GROUPS]; | ||
| 177 | struct list_head list; | ||
| 84 | }; | 178 | }; |
| 85 | 179 | ||
| 180 | static DEFINE_SPINLOCK(mctrl_list_lock); | ||
| 86 | static LIST_HEAD(mctrl_list); | 181 | static LIST_HEAD(mctrl_list); |
| 87 | 182 | ||
| 183 | static void mc_list_add(struct list_head *list) | ||
| 184 | { | ||
| 185 | spin_lock(&mctrl_list_lock); | ||
| 186 | list_add(list, &mctrl_list); | ||
| 187 | spin_unlock(&mctrl_list_lock); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void mc_list_del(struct list_head *list) | ||
| 191 | { | ||
| 192 | spin_lock(&mctrl_list_lock); | ||
| 193 | list_del_init(list); | ||
| 194 | spin_unlock(&mctrl_list_lock); | ||
| 195 | } | ||
| 196 | |||
| 197 | #define SYNDROME_MIN -1 | ||
| 198 | #define SYNDROME_MAX 144 | ||
| 199 | |||
| 200 | /* Covert syndrome code into the way the bits are positioned | ||
| 201 | * on the bus. | ||
| 202 | */ | ||
| 203 | static int syndrome_to_qword_code(int syndrome_code) | ||
| 204 | { | ||
| 205 | if (syndrome_code < 128) | ||
| 206 | syndrome_code += 16; | ||
| 207 | else if (syndrome_code < 128 + 9) | ||
| 208 | syndrome_code -= (128 - 7); | ||
| 209 | else if (syndrome_code < (128 + 9 + 3)) | ||
| 210 | syndrome_code -= (128 + 9 - 4); | ||
| 211 | else | ||
| 212 | syndrome_code -= (128 + 9 + 3); | ||
| 213 | return syndrome_code; | ||
| 214 | } | ||
| 215 | |||
| 216 | /* All this magic has to do with how a cache line comes over the wire | ||
| 217 | * on Safari and JBUS. A 64-bit line comes over in 1 or more quadword | ||
| 218 | * cycles, each of which transmit ECC/MTAG info as well as the actual | ||
| 219 | * data. | ||
| 220 | */ | ||
| 221 | #define L2_LINE_SIZE 64 | ||
| 222 | #define L2_LINE_ADDR_MSK (L2_LINE_SIZE - 1) | ||
| 223 | #define QW_PER_LINE 4 | ||
| 224 | #define QW_BYTES (L2_LINE_SIZE / QW_PER_LINE) | ||
| 225 | #define QW_BITS 144 | ||
| 226 | #define SAFARI_LAST_BIT (576 - 1) | ||
| 227 | #define JBUS_LAST_BIT (144 - 1) | ||
| 228 | |||
| 229 | static void get_pin_and_dimm_str(int syndrome_code, unsigned long paddr, | ||
| 230 | int *pin_p, char **dimm_str_p, void *_prop, | ||
| 231 | int base_dimm_offset) | ||
| 232 | { | ||
| 233 | int qword_code = syndrome_to_qword_code(syndrome_code); | ||
| 234 | int cache_line_offset; | ||
| 235 | int offset_inverse; | ||
| 236 | int dimm_map_index; | ||
| 237 | int map_val; | ||
| 238 | |||
| 239 | if (mc_type == MC_TYPE_JBUS) { | ||
| 240 | struct jbusmc_obp_mem_layout *p = _prop; | ||
| 241 | |||
| 242 | /* JBUS */ | ||
| 243 | cache_line_offset = qword_code; | ||
| 244 | offset_inverse = (JBUS_LAST_BIT - cache_line_offset); | ||
| 245 | dimm_map_index = offset_inverse / 8; | ||
| 246 | map_val = p->map.dimm_map[dimm_map_index]; | ||
| 247 | map_val = ((map_val >> ((7 - (offset_inverse & 7)))) & 1); | ||
| 248 | *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; | ||
| 249 | *pin_p = p->map.pin_map[cache_line_offset]; | ||
| 250 | } else { | ||
| 251 | struct chmc_obp_mem_layout *p = _prop; | ||
| 252 | struct chmc_obp_map *mp; | ||
| 253 | int qword; | ||
| 254 | |||
| 255 | /* Safari */ | ||
| 256 | if (p->symmetric) | ||
| 257 | mp = &p->map[0]; | ||
| 258 | else | ||
| 259 | mp = &p->map[1]; | ||
| 260 | |||
| 261 | qword = (paddr & L2_LINE_ADDR_MSK) / QW_BYTES; | ||
| 262 | cache_line_offset = ((3 - qword) * QW_BITS) + qword_code; | ||
| 263 | offset_inverse = (SAFARI_LAST_BIT - cache_line_offset); | ||
| 264 | dimm_map_index = offset_inverse >> 2; | ||
| 265 | map_val = mp->dimm_map[dimm_map_index]; | ||
| 266 | map_val = ((map_val >> ((3 - (offset_inverse & 3)) << 1)) & 0x3); | ||
| 267 | *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; | ||
| 268 | *pin_p = mp->pin_map[cache_line_offset]; | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | static struct jbusmc_dimm_group *jbusmc_find_dimm_group(unsigned long phys_addr) | ||
| 273 | { | ||
| 274 | struct jbusmc *p; | ||
| 275 | |||
| 276 | list_for_each_entry(p, &mctrl_list, list) { | ||
| 277 | int i; | ||
| 278 | |||
| 279 | for (i = 0; i < p->num_dimm_groups; i++) { | ||
| 280 | struct jbusmc_dimm_group *dp = &p->dimm_groups[i]; | ||
| 281 | |||
| 282 | if (phys_addr < dp->base_addr || | ||
| 283 | (dp->base_addr + dp->size) <= phys_addr) | ||
| 284 | continue; | ||
| 285 | |||
| 286 | return dp; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | return NULL; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int jbusmc_print_dimm(int syndrome_code, | ||
| 293 | unsigned long phys_addr, | ||
| 294 | char *buf, int buflen) | ||
| 295 | { | ||
| 296 | struct jbusmc_obp_mem_layout *prop; | ||
| 297 | struct jbusmc_dimm_group *dp; | ||
| 298 | struct jbusmc *p; | ||
| 299 | int first_dimm; | ||
| 300 | |||
| 301 | dp = jbusmc_find_dimm_group(phys_addr); | ||
| 302 | if (dp == NULL || | ||
| 303 | syndrome_code < SYNDROME_MIN || | ||
| 304 | syndrome_code > SYNDROME_MAX) { | ||
| 305 | buf[0] = '?'; | ||
| 306 | buf[1] = '?'; | ||
| 307 | buf[2] = '?'; | ||
| 308 | buf[3] = '\0'; | ||
| 309 | } | ||
| 310 | p = dp->controller; | ||
| 311 | prop = &p->layout; | ||
| 312 | |||
| 313 | first_dimm = dp->index * JB_NUM_DIMMS_PER_GROUP; | ||
| 314 | |||
| 315 | if (syndrome_code != SYNDROME_MIN) { | ||
| 316 | char *dimm_str; | ||
| 317 | int pin; | ||
| 318 | |||
| 319 | get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, | ||
| 320 | &dimm_str, prop, first_dimm); | ||
| 321 | sprintf(buf, "%s, pin %3d", dimm_str, pin); | ||
| 322 | } else { | ||
| 323 | int dimm; | ||
| 324 | |||
| 325 | /* Multi-bit error, we just dump out all the | ||
| 326 | * dimm labels associated with this dimm group. | ||
| 327 | */ | ||
| 328 | for (dimm = 0; dimm < JB_NUM_DIMMS_PER_GROUP; dimm++) { | ||
| 329 | sprintf(buf, "%s ", | ||
| 330 | prop->dimm_labels[first_dimm + dimm]); | ||
| 331 | buf += strlen(buf); | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static u64 __devinit jbusmc_dimm_group_size(u64 base, | ||
| 339 | const struct linux_prom64_registers *mem_regs, | ||
| 340 | int num_mem_regs) | ||
| 341 | { | ||
| 342 | u64 max = base + (8UL * 1024 * 1024 * 1024); | ||
| 343 | u64 max_seen = base; | ||
| 344 | int i; | ||
| 345 | |||
| 346 | for (i = 0; i < num_mem_regs; i++) { | ||
| 347 | const struct linux_prom64_registers *ent; | ||
| 348 | u64 this_base; | ||
| 349 | u64 this_end; | ||
| 350 | |||
| 351 | ent = &mem_regs[i]; | ||
| 352 | this_base = ent->phys_addr; | ||
| 353 | this_end = this_base + ent->reg_size; | ||
| 354 | if (base < this_base || base >= this_end) | ||
| 355 | continue; | ||
| 356 | if (this_end > max) | ||
| 357 | this_end = max; | ||
| 358 | if (this_end > max_seen) | ||
| 359 | max_seen = this_end; | ||
| 360 | } | ||
| 361 | |||
| 362 | return max_seen - base; | ||
| 363 | } | ||
| 364 | |||
| 365 | static void __devinit jbusmc_construct_one_dimm_group(struct jbusmc *p, | ||
| 366 | unsigned long index, | ||
| 367 | const struct linux_prom64_registers *mem_regs, | ||
| 368 | int num_mem_regs) | ||
| 369 | { | ||
| 370 | struct jbusmc_dimm_group *dp = &p->dimm_groups[index]; | ||
| 371 | |||
| 372 | dp->controller = p; | ||
| 373 | dp->index = index; | ||
| 374 | |||
| 375 | dp->base_addr = (p->portid * (64UL * 1024 * 1024 * 1024)); | ||
| 376 | dp->base_addr += (index * (8UL * 1024 * 1024 * 1024)); | ||
| 377 | dp->size = jbusmc_dimm_group_size(dp->base_addr, mem_regs, num_mem_regs); | ||
| 378 | } | ||
| 379 | |||
| 380 | static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p, | ||
| 381 | const struct linux_prom64_registers *mem_regs, | ||
| 382 | int num_mem_regs) | ||
| 383 | { | ||
| 384 | if (p->mc_reg_1 & JB_MC_REG1_DIMM1_BANK0) { | ||
| 385 | jbusmc_construct_one_dimm_group(p, 0, mem_regs, num_mem_regs); | ||
| 386 | p->num_dimm_groups++; | ||
| 387 | } | ||
| 388 | if (p->mc_reg_1 & JB_MC_REG1_DIMM2_BANK2) { | ||
| 389 | jbusmc_construct_one_dimm_group(p, 1, mem_regs, num_mem_regs); | ||
| 390 | p->num_dimm_groups++; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | static int __devinit jbusmc_probe(struct of_device *op, | ||
| 395 | const struct of_device_id *match) | ||
| 396 | { | ||
| 397 | const struct linux_prom64_registers *mem_regs; | ||
| 398 | struct device_node *mem_node; | ||
| 399 | int err, len, num_mem_regs; | ||
| 400 | struct jbusmc *p; | ||
| 401 | const u32 *prop; | ||
| 402 | const void *ml; | ||
| 403 | |||
| 404 | err = -ENODEV; | ||
| 405 | mem_node = of_find_node_by_path("/memory"); | ||
| 406 | if (!mem_node) { | ||
| 407 | printk(KERN_ERR PFX "Cannot find /memory node.\n"); | ||
| 408 | goto out; | ||
| 409 | } | ||
| 410 | mem_regs = of_get_property(mem_node, "reg", &len); | ||
| 411 | if (!mem_regs) { | ||
| 412 | printk(KERN_ERR PFX "Cannot get reg property of /memory node.\n"); | ||
| 413 | goto out; | ||
| 414 | } | ||
| 415 | num_mem_regs = len / sizeof(*mem_regs); | ||
| 416 | |||
| 417 | err = -ENOMEM; | ||
| 418 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 419 | if (!p) { | ||
| 420 | printk(KERN_ERR PFX "Cannot allocate struct jbusmc.\n"); | ||
| 421 | goto out; | ||
| 422 | } | ||
| 423 | |||
| 424 | INIT_LIST_HEAD(&p->list); | ||
| 425 | |||
| 426 | err = -ENODEV; | ||
| 427 | prop = of_get_property(op->node, "portid", &len); | ||
| 428 | if (!prop || len != 4) { | ||
| 429 | printk(KERN_ERR PFX "Cannot find portid.\n"); | ||
| 430 | goto out_free; | ||
| 431 | } | ||
| 432 | |||
| 433 | p->portid = *prop; | ||
| 434 | |||
| 435 | prop = of_get_property(op->node, "memory-control-register-1", &len); | ||
| 436 | if (!prop || len != 8) { | ||
| 437 | printk(KERN_ERR PFX "Cannot get memory control register 1.\n"); | ||
| 438 | goto out_free; | ||
| 439 | } | ||
| 440 | |||
| 441 | p->mc_reg_1 = ((u64)prop[0] << 32) | (u64) prop[1]; | ||
| 442 | |||
| 443 | err = -ENOMEM; | ||
| 444 | p->regs = of_ioremap(&op->resource[0], 0, JBUSMC_REGS_SIZE, "jbusmc"); | ||
| 445 | if (!p->regs) { | ||
| 446 | printk(KERN_ERR PFX "Cannot map jbusmc regs.\n"); | ||
| 447 | goto out_free; | ||
| 448 | } | ||
| 449 | |||
| 450 | err = -ENODEV; | ||
| 451 | ml = of_get_property(op->node, "memory-layout", &p->layout_len); | ||
| 452 | if (!ml) { | ||
| 453 | printk(KERN_ERR PFX "Cannot get memory layout property.\n"); | ||
| 454 | goto out_iounmap; | ||
| 455 | } | ||
| 456 | if (p->layout_len > sizeof(p->layout)) { | ||
| 457 | printk(KERN_ERR PFX "Unexpected memory-layout size %d\n", | ||
| 458 | p->layout_len); | ||
| 459 | goto out_iounmap; | ||
| 460 | } | ||
| 461 | memcpy(&p->layout, ml, p->layout_len); | ||
| 462 | |||
| 463 | jbusmc_construct_dimm_groups(p, mem_regs, num_mem_regs); | ||
| 464 | |||
| 465 | mc_list_add(&p->list); | ||
| 466 | |||
| 467 | printk(KERN_INFO PFX "UltraSPARC-IIIi memory controller at %s\n", | ||
| 468 | op->node->full_name); | ||
| 469 | |||
| 470 | dev_set_drvdata(&op->dev, p); | ||
| 471 | |||
| 472 | err = 0; | ||
| 473 | |||
| 474 | out: | ||
| 475 | return err; | ||
| 476 | |||
| 477 | out_iounmap: | ||
| 478 | of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); | ||
| 479 | |||
| 480 | out_free: | ||
| 481 | kfree(p); | ||
| 482 | goto out; | ||
| 483 | } | ||
| 484 | |||
| 88 | /* Does BANK decode PHYS_ADDR? */ | 485 | /* Does BANK decode PHYS_ADDR? */ |
| 89 | static int bank_match(struct bank_info *bp, unsigned long phys_addr) | 486 | static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) |
| 90 | { | 487 | { |
| 91 | unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; | 488 | unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; |
| 92 | unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; | 489 | unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; |
| @@ -118,25 +515,18 @@ static int bank_match(struct bank_info *bp, unsigned long phys_addr) | |||
| 118 | } | 515 | } |
| 119 | 516 | ||
| 120 | /* Given PHYS_ADDR, search memory controller banks for a match. */ | 517 | /* Given PHYS_ADDR, search memory controller banks for a match. */ |
| 121 | static struct bank_info *find_bank(unsigned long phys_addr) | 518 | static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) |
| 122 | { | 519 | { |
| 123 | struct list_head *mctrl_head = &mctrl_list; | 520 | struct chmc *p; |
| 124 | struct list_head *mctrl_entry = mctrl_head->next; | ||
| 125 | 521 | ||
| 126 | for (;;) { | 522 | list_for_each_entry(p, &mctrl_list, list) { |
| 127 | struct mctrl_info *mp = | ||
| 128 | list_entry(mctrl_entry, struct mctrl_info, list); | ||
| 129 | int bank_no; | 523 | int bank_no; |
| 130 | 524 | ||
| 131 | if (mctrl_entry == mctrl_head) | ||
| 132 | break; | ||
| 133 | mctrl_entry = mctrl_entry->next; | ||
| 134 | |||
| 135 | for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { | 525 | for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { |
| 136 | struct bank_info *bp; | 526 | struct chmc_bank_info *bp; |
| 137 | 527 | ||
| 138 | bp = &mp->logical_banks[bank_no]; | 528 | bp = &p->logical_banks[bank_no]; |
| 139 | if (bank_match(bp, phys_addr)) | 529 | if (chmc_bank_match(bp, phys_addr)) |
| 140 | return bp; | 530 | return bp; |
| 141 | } | 531 | } |
| 142 | } | 532 | } |
| @@ -145,17 +535,15 @@ static struct bank_info *find_bank(unsigned long phys_addr) | |||
| 145 | } | 535 | } |
| 146 | 536 | ||
| 147 | /* This is the main purpose of this driver. */ | 537 | /* This is the main purpose of this driver. */ |
| 148 | #define SYNDROME_MIN -1 | 538 | static int chmc_print_dimm(int syndrome_code, |
| 149 | #define SYNDROME_MAX 144 | 539 | unsigned long phys_addr, |
| 150 | int chmc_getunumber(int syndrome_code, | 540 | char *buf, int buflen) |
| 151 | unsigned long phys_addr, | ||
| 152 | char *buf, int buflen) | ||
| 153 | { | 541 | { |
| 154 | struct bank_info *bp; | 542 | struct chmc_bank_info *bp; |
| 155 | struct obp_mem_layout *prop; | 543 | struct chmc_obp_mem_layout *prop; |
| 156 | int bank_in_controller, first_dimm; | 544 | int bank_in_controller, first_dimm; |
| 157 | 545 | ||
| 158 | bp = find_bank(phys_addr); | 546 | bp = chmc_find_bank(phys_addr); |
| 159 | if (bp == NULL || | 547 | if (bp == NULL || |
| 160 | syndrome_code < SYNDROME_MIN || | 548 | syndrome_code < SYNDROME_MIN || |
| 161 | syndrome_code > SYNDROME_MAX) { | 549 | syndrome_code > SYNDROME_MAX) { |
| @@ -166,60 +554,18 @@ int chmc_getunumber(int syndrome_code, | |||
| 166 | return 0; | 554 | return 0; |
| 167 | } | 555 | } |
| 168 | 556 | ||
| 169 | prop = &bp->mp->layout_prop; | 557 | prop = &bp->p->layout_prop; |
| 170 | bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); | 558 | bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); |
| 171 | first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); | 559 | first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); |
| 172 | first_dimm *= CHMCTRL_NDIMMS; | 560 | first_dimm *= CHMCTRL_NDIMMS; |
| 173 | 561 | ||
| 174 | if (syndrome_code != SYNDROME_MIN) { | 562 | if (syndrome_code != SYNDROME_MIN) { |
| 175 | struct obp_map *map; | 563 | char *dimm_str; |
| 176 | int qword, where_in_line, where, map_index, map_offset; | 564 | int pin; |
| 177 | unsigned int map_val; | ||
| 178 | 565 | ||
| 179 | /* Yaay, single bit error so we can figure out | 566 | get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, |
| 180 | * the exact dimm. | 567 | &dimm_str, prop, first_dimm); |
| 181 | */ | 568 | sprintf(buf, "%s, pin %3d", dimm_str, pin); |
| 182 | if (prop->symmetric) | ||
| 183 | map = &prop->map[0]; | ||
| 184 | else | ||
| 185 | map = &prop->map[1]; | ||
| 186 | |||
| 187 | /* Covert syndrome code into the way the bits are | ||
| 188 | * positioned on the bus. | ||
| 189 | */ | ||
| 190 | if (syndrome_code < 144 - 16) | ||
| 191 | syndrome_code += 16; | ||
| 192 | else if (syndrome_code < 144) | ||
| 193 | syndrome_code -= (144 - 7); | ||
| 194 | else if (syndrome_code < (144 + 3)) | ||
| 195 | syndrome_code -= (144 + 3 - 4); | ||
| 196 | else | ||
| 197 | syndrome_code -= 144 + 3; | ||
| 198 | |||
| 199 | /* All this magic has to do with how a cache line | ||
| 200 | * comes over the wire on Safari. A 64-bit line | ||
| 201 | * comes over in 4 quadword cycles, each of which | ||
| 202 | * transmit ECC/MTAG info as well as the actual | ||
| 203 | * data. 144 bits per quadword, 576 total. | ||
| 204 | */ | ||
| 205 | #define LINE_SIZE 64 | ||
| 206 | #define LINE_ADDR_MSK (LINE_SIZE - 1) | ||
| 207 | #define QW_PER_LINE 4 | ||
| 208 | #define QW_BYTES (LINE_SIZE / QW_PER_LINE) | ||
| 209 | #define QW_BITS 144 | ||
| 210 | #define LAST_BIT (576 - 1) | ||
| 211 | |||
| 212 | qword = (phys_addr & LINE_ADDR_MSK) / QW_BYTES; | ||
| 213 | where_in_line = ((3 - qword) * QW_BITS) + syndrome_code; | ||
| 214 | where = (LAST_BIT - where_in_line); | ||
| 215 | map_index = where >> 2; | ||
| 216 | map_offset = where & 0x3; | ||
| 217 | map_val = map->dimm_map[map_index]; | ||
| 218 | map_val = ((map_val >> ((3 - map_offset) << 1)) & (2 - 1)); | ||
| 219 | |||
| 220 | sprintf(buf, "%s, pin %3d", | ||
| 221 | prop->dimm_labels[first_dimm + map_val], | ||
| 222 | map->pin_map[where_in_line]); | ||
| 223 | } else { | 569 | } else { |
| 224 | int dimm; | 570 | int dimm; |
| 225 | 571 | ||
| @@ -240,7 +586,7 @@ int chmc_getunumber(int syndrome_code, | |||
| 240 | * the code is executing, you must use special ASI load/store else | 586 | * the code is executing, you must use special ASI load/store else |
| 241 | * you go through the global mapping. | 587 | * you go through the global mapping. |
| 242 | */ | 588 | */ |
| 243 | static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | 589 | static u64 chmc_read_mcreg(struct chmc *p, unsigned long offset) |
| 244 | { | 590 | { |
| 245 | unsigned long ret, this_cpu; | 591 | unsigned long ret, this_cpu; |
| 246 | 592 | ||
| @@ -248,14 +594,14 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | |||
| 248 | 594 | ||
| 249 | this_cpu = real_hard_smp_processor_id(); | 595 | this_cpu = real_hard_smp_processor_id(); |
| 250 | 596 | ||
| 251 | if (mp->portid == this_cpu) { | 597 | if (p->portid == this_cpu) { |
| 252 | __asm__ __volatile__("ldxa [%1] %2, %0" | 598 | __asm__ __volatile__("ldxa [%1] %2, %0" |
| 253 | : "=r" (ret) | 599 | : "=r" (ret) |
| 254 | : "r" (offset), "i" (ASI_MCU_CTRL_REG)); | 600 | : "r" (offset), "i" (ASI_MCU_CTRL_REG)); |
| 255 | } else { | 601 | } else { |
| 256 | __asm__ __volatile__("ldxa [%1] %2, %0" | 602 | __asm__ __volatile__("ldxa [%1] %2, %0" |
| 257 | : "=r" (ret) | 603 | : "=r" (ret) |
| 258 | : "r" (mp->regs + offset), | 604 | : "r" (p->regs + offset), |
| 259 | "i" (ASI_PHYS_BYPASS_EC_E)); | 605 | "i" (ASI_PHYS_BYPASS_EC_E)); |
| 260 | } | 606 | } |
| 261 | 607 | ||
| @@ -265,178 +611,253 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | |||
| 265 | } | 611 | } |
| 266 | 612 | ||
| 267 | #if 0 /* currently unused */ | 613 | #if 0 /* currently unused */ |
| 268 | static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val) | 614 | static void chmc_write_mcreg(struct chmc *p, unsigned long offset, u64 val) |
| 269 | { | 615 | { |
| 270 | if (mp->portid == smp_processor_id()) { | 616 | if (p->portid == smp_processor_id()) { |
| 271 | __asm__ __volatile__("stxa %0, [%1] %2" | 617 | __asm__ __volatile__("stxa %0, [%1] %2" |
| 272 | : : "r" (val), | 618 | : : "r" (val), |
| 273 | "r" (offset), "i" (ASI_MCU_CTRL_REG)); | 619 | "r" (offset), "i" (ASI_MCU_CTRL_REG)); |
| 274 | } else { | 620 | } else { |
| 275 | __asm__ __volatile__("ldxa %0, [%1] %2" | 621 | __asm__ __volatile__("ldxa %0, [%1] %2" |
| 276 | : : "r" (val), | 622 | : : "r" (val), |
| 277 | "r" (mp->regs + offset), | 623 | "r" (p->regs + offset), |
| 278 | "i" (ASI_PHYS_BYPASS_EC_E)); | 624 | "i" (ASI_PHYS_BYPASS_EC_E)); |
| 279 | } | 625 | } |
| 280 | } | 626 | } |
| 281 | #endif | 627 | #endif |
| 282 | 628 | ||
| 283 | static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val) | 629 | static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 val) |
| 284 | { | 630 | { |
| 285 | struct bank_info *p = &mp->logical_banks[which_bank]; | 631 | struct chmc_bank_info *bp = &p->logical_banks[which_bank]; |
| 286 | 632 | ||
| 287 | p->mp = mp; | 633 | bp->p = p; |
| 288 | p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank; | 634 | bp->bank_id = (CHMCTRL_NBANKS * p->portid) + which_bank; |
| 289 | p->raw_reg = val; | 635 | bp->raw_reg = val; |
| 290 | p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; | 636 | bp->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; |
| 291 | p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; | 637 | bp->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; |
| 292 | p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; | 638 | bp->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; |
| 293 | p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; | 639 | bp->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; |
| 294 | p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; | 640 | bp->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; |
| 295 | 641 | ||
| 296 | p->base = (p->um); | 642 | bp->base = (bp->um); |
| 297 | p->base &= ~(p->uk); | 643 | bp->base &= ~(bp->uk); |
| 298 | p->base <<= PA_UPPER_BITS_SHIFT; | 644 | bp->base <<= PA_UPPER_BITS_SHIFT; |
| 299 | 645 | ||
| 300 | switch(p->lk) { | 646 | switch(bp->lk) { |
| 301 | case 0xf: | 647 | case 0xf: |
| 302 | default: | 648 | default: |
| 303 | p->interleave = 1; | 649 | bp->interleave = 1; |
| 304 | break; | 650 | break; |
| 305 | 651 | ||
| 306 | case 0xe: | 652 | case 0xe: |
| 307 | p->interleave = 2; | 653 | bp->interleave = 2; |
| 308 | break; | 654 | break; |
| 309 | 655 | ||
| 310 | case 0xc: | 656 | case 0xc: |
| 311 | p->interleave = 4; | 657 | bp->interleave = 4; |
| 312 | break; | 658 | break; |
| 313 | 659 | ||
| 314 | case 0x8: | 660 | case 0x8: |
| 315 | p->interleave = 8; | 661 | bp->interleave = 8; |
| 316 | break; | 662 | break; |
| 317 | 663 | ||
| 318 | case 0x0: | 664 | case 0x0: |
| 319 | p->interleave = 16; | 665 | bp->interleave = 16; |
| 320 | break; | 666 | break; |
| 321 | }; | 667 | }; |
| 322 | 668 | ||
| 323 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM | 669 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM |
| 324 | * bank size definition. | 670 | * bank size definition. |
| 325 | */ | 671 | */ |
| 326 | p->size = (((unsigned long)p->uk & | 672 | bp->size = (((unsigned long)bp->uk & |
| 327 | ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; | 673 | ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; |
| 328 | p->size /= p->interleave; | 674 | bp->size /= bp->interleave; |
| 329 | } | 675 | } |
| 330 | 676 | ||
| 331 | static void fetch_decode_regs(struct mctrl_info *mp) | 677 | static void chmc_fetch_decode_regs(struct chmc *p) |
| 332 | { | 678 | { |
| 333 | if (mp->layout_size == 0) | 679 | if (p->layout_size == 0) |
| 334 | return; | 680 | return; |
| 335 | 681 | ||
| 336 | interpret_one_decode_reg(mp, 0, | 682 | chmc_interpret_one_decode_reg(p, 0, |
| 337 | read_mcreg(mp, CHMCTRL_DECODE1)); | 683 | chmc_read_mcreg(p, CHMCTRL_DECODE1)); |
| 338 | interpret_one_decode_reg(mp, 1, | 684 | chmc_interpret_one_decode_reg(p, 1, |
| 339 | read_mcreg(mp, CHMCTRL_DECODE2)); | 685 | chmc_read_mcreg(p, CHMCTRL_DECODE2)); |
| 340 | interpret_one_decode_reg(mp, 2, | 686 | chmc_interpret_one_decode_reg(p, 2, |
| 341 | read_mcreg(mp, CHMCTRL_DECODE3)); | 687 | chmc_read_mcreg(p, CHMCTRL_DECODE3)); |
| 342 | interpret_one_decode_reg(mp, 3, | 688 | chmc_interpret_one_decode_reg(p, 3, |
| 343 | read_mcreg(mp, CHMCTRL_DECODE4)); | 689 | chmc_read_mcreg(p, CHMCTRL_DECODE4)); |
| 344 | } | 690 | } |
| 345 | 691 | ||
| 346 | static int init_one_mctrl(struct device_node *dp) | 692 | static int __devinit chmc_probe(struct of_device *op, |
| 693 | const struct of_device_id *match) | ||
| 347 | { | 694 | { |
| 348 | struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL); | 695 | struct device_node *dp = op->node; |
| 349 | int portid = of_getintprop_default(dp, "portid", -1); | 696 | unsigned long ver; |
| 350 | const struct linux_prom64_registers *regs; | ||
| 351 | const void *pval; | 697 | const void *pval; |
| 352 | int len; | 698 | int len, portid; |
| 699 | struct chmc *p; | ||
| 700 | int err; | ||
| 701 | |||
| 702 | err = -ENODEV; | ||
| 703 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); | ||
| 704 | if ((ver >> 32UL) == __JALAPENO_ID || | ||
| 705 | (ver >> 32UL) == __SERRANO_ID) | ||
| 706 | goto out; | ||
| 353 | 707 | ||
| 354 | if (!mp) | 708 | portid = of_getintprop_default(dp, "portid", -1); |
| 355 | return -1; | ||
| 356 | if (portid == -1) | 709 | if (portid == -1) |
| 357 | goto fail; | 710 | goto out; |
| 358 | 711 | ||
| 359 | mp->portid = portid; | ||
| 360 | pval = of_get_property(dp, "memory-layout", &len); | 712 | pval = of_get_property(dp, "memory-layout", &len); |
| 361 | mp->layout_size = len; | 713 | if (pval && len > sizeof(p->layout_prop)) { |
| 362 | if (!pval) | 714 | printk(KERN_ERR PFX "Unexpected memory-layout property " |
| 363 | mp->layout_size = 0; | 715 | "size %d.\n", len); |
| 364 | else { | 716 | goto out; |
| 365 | if (mp->layout_size > sizeof(mp->layout_prop)) | ||
| 366 | goto fail; | ||
| 367 | memcpy(&mp->layout_prop, pval, len); | ||
| 368 | } | 717 | } |
| 369 | 718 | ||
| 370 | regs = of_get_property(dp, "reg", NULL); | 719 | err = -ENOMEM; |
| 371 | if (!regs || regs->reg_size != 0x48) | 720 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 372 | goto fail; | 721 | if (!p) { |
| 722 | printk(KERN_ERR PFX "Could not allocate struct chmc.\n"); | ||
| 723 | goto out; | ||
| 724 | } | ||
| 373 | 725 | ||
| 374 | mp->regs = ioremap(regs->phys_addr, regs->reg_size); | 726 | p->portid = portid; |
| 375 | if (mp->regs == NULL) | 727 | p->layout_size = len; |
| 376 | goto fail; | 728 | if (!pval) |
| 729 | p->layout_size = 0; | ||
| 730 | else | ||
| 731 | memcpy(&p->layout_prop, pval, len); | ||
| 732 | |||
| 733 | p->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); | ||
| 734 | if (!p->regs) { | ||
| 735 | printk(KERN_ERR PFX "Could not map registers.\n"); | ||
| 736 | goto out_free; | ||
| 737 | } | ||
| 377 | 738 | ||
| 378 | if (mp->layout_size != 0UL) { | 739 | if (p->layout_size != 0UL) { |
| 379 | mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); | 740 | p->timing_control1 = chmc_read_mcreg(p, CHMCTRL_TCTRL1); |
| 380 | mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2); | 741 | p->timing_control2 = chmc_read_mcreg(p, CHMCTRL_TCTRL2); |
| 381 | mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3); | 742 | p->timing_control3 = chmc_read_mcreg(p, CHMCTRL_TCTRL3); |
| 382 | mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4); | 743 | p->timing_control4 = chmc_read_mcreg(p, CHMCTRL_TCTRL4); |
| 383 | mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL); | 744 | p->memaddr_control = chmc_read_mcreg(p, CHMCTRL_MACTRL); |
| 384 | } | 745 | } |
| 385 | 746 | ||
| 386 | fetch_decode_regs(mp); | 747 | chmc_fetch_decode_regs(p); |
| 387 | 748 | ||
| 388 | list_add(&mp->list, &mctrl_list); | 749 | mc_list_add(&p->list); |
| 389 | 750 | ||
| 390 | /* Report the device. */ | 751 | printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", |
| 391 | printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n", | ||
| 392 | dp->full_name, | 752 | dp->full_name, |
| 393 | mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); | 753 | (p->layout_size ? "ACTIVE" : "INACTIVE")); |
| 394 | 754 | ||
| 395 | return 0; | 755 | dev_set_drvdata(&op->dev, p); |
| 756 | |||
| 757 | err = 0; | ||
| 758 | |||
| 759 | out: | ||
| 760 | return err; | ||
| 761 | |||
| 762 | out_free: | ||
| 763 | kfree(p); | ||
| 764 | goto out; | ||
| 765 | } | ||
| 396 | 766 | ||
| 397 | fail: | 767 | static int __devinit us3mc_probe(struct of_device *op, |
| 398 | if (mp) { | 768 | const struct of_device_id *match) |
| 399 | if (mp->regs != NULL) | 769 | { |
| 400 | iounmap(mp->regs); | 770 | if (mc_type == MC_TYPE_SAFARI) |
| 401 | kfree(mp); | 771 | return chmc_probe(op, match); |
| 772 | else if (mc_type == MC_TYPE_JBUS) | ||
| 773 | return jbusmc_probe(op, match); | ||
| 774 | return -ENODEV; | ||
| 775 | } | ||
| 776 | |||
| 777 | static void __devexit chmc_destroy(struct of_device *op, struct chmc *p) | ||
| 778 | { | ||
| 779 | list_del(&p->list); | ||
| 780 | of_iounmap(&op->resource[0], p->regs, 0x48); | ||
| 781 | kfree(p); | ||
| 782 | } | ||
| 783 | |||
| 784 | static void __devexit jbusmc_destroy(struct of_device *op, struct jbusmc *p) | ||
| 785 | { | ||
| 786 | mc_list_del(&p->list); | ||
| 787 | of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); | ||
| 788 | kfree(p); | ||
| 789 | } | ||
| 790 | |||
| 791 | static int __devexit us3mc_remove(struct of_device *op) | ||
| 792 | { | ||
| 793 | void *p = dev_get_drvdata(&op->dev); | ||
| 794 | |||
| 795 | if (p) { | ||
| 796 | if (mc_type == MC_TYPE_SAFARI) | ||
| 797 | chmc_destroy(op, p); | ||
| 798 | else if (mc_type == MC_TYPE_JBUS) | ||
| 799 | jbusmc_destroy(op, p); | ||
| 402 | } | 800 | } |
| 403 | return -1; | 801 | return 0; |
| 802 | } | ||
| 803 | |||
| 804 | static const struct of_device_id us3mc_match[] = { | ||
| 805 | { | ||
| 806 | .name = "memory-controller", | ||
| 807 | }, | ||
| 808 | {}, | ||
| 809 | }; | ||
| 810 | MODULE_DEVICE_TABLE(of, us3mc_match); | ||
| 811 | |||
| 812 | static struct of_platform_driver us3mc_driver = { | ||
| 813 | .name = "us3mc", | ||
| 814 | .match_table = us3mc_match, | ||
| 815 | .probe = us3mc_probe, | ||
| 816 | .remove = __devexit_p(us3mc_remove), | ||
| 817 | }; | ||
| 818 | |||
| 819 | static inline bool us3mc_platform(void) | ||
| 820 | { | ||
| 821 | if (tlb_type == cheetah || tlb_type == cheetah_plus) | ||
| 822 | return true; | ||
| 823 | return false; | ||
| 404 | } | 824 | } |
| 405 | 825 | ||
| 406 | static int __init chmc_init(void) | 826 | static int __init us3mc_init(void) |
| 407 | { | 827 | { |
| 408 | struct device_node *dp; | 828 | unsigned long ver; |
| 829 | int ret; | ||
| 409 | 830 | ||
| 410 | /* This driver is only for cheetah platforms. */ | 831 | if (!us3mc_platform()) |
| 411 | if (tlb_type != cheetah && tlb_type != cheetah_plus) | ||
| 412 | return -ENODEV; | 832 | return -ENODEV; |
| 413 | 833 | ||
| 414 | for_each_node_by_name(dp, "memory-controller") | 834 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); |
| 415 | init_one_mctrl(dp); | 835 | if ((ver >> 32UL) == __JALAPENO_ID || |
| 836 | (ver >> 32UL) == __SERRANO_ID) { | ||
| 837 | mc_type = MC_TYPE_JBUS; | ||
| 838 | us3mc_dimm_printer = jbusmc_print_dimm; | ||
| 839 | } else { | ||
| 840 | mc_type = MC_TYPE_SAFARI; | ||
| 841 | us3mc_dimm_printer = chmc_print_dimm; | ||
| 842 | } | ||
| 416 | 843 | ||
| 417 | for_each_node_by_name(dp, "mc-us3") | 844 | ret = register_dimm_printer(us3mc_dimm_printer); |
| 418 | init_one_mctrl(dp); | ||
| 419 | 845 | ||
| 420 | return 0; | 846 | if (!ret) { |
| 847 | ret = of_register_driver(&us3mc_driver, &of_bus_type); | ||
| 848 | if (ret) | ||
| 849 | unregister_dimm_printer(us3mc_dimm_printer); | ||
| 850 | } | ||
| 851 | return ret; | ||
| 421 | } | 852 | } |
| 422 | 853 | ||
| 423 | static void __exit chmc_cleanup(void) | 854 | static void __exit us3mc_cleanup(void) |
| 424 | { | 855 | { |
| 425 | struct list_head *head = &mctrl_list; | 856 | if (us3mc_platform()) { |
| 426 | struct list_head *tmp = head->next; | 857 | unregister_dimm_printer(us3mc_dimm_printer); |
| 427 | 858 | of_unregister_driver(&us3mc_driver); | |
| 428 | for (;;) { | ||
| 429 | struct mctrl_info *p = | ||
| 430 | list_entry(tmp, struct mctrl_info, list); | ||
| 431 | if (tmp == head) | ||
| 432 | break; | ||
| 433 | tmp = tmp->next; | ||
| 434 | |||
| 435 | list_del(&p->list); | ||
| 436 | iounmap(p->regs); | ||
| 437 | kfree(p); | ||
| 438 | } | 859 | } |
| 439 | } | 860 | } |
| 440 | 861 | ||
| 441 | module_init(chmc_init); | 862 | module_init(us3mc_init); |
| 442 | module_exit(chmc_cleanup); | 863 | module_exit(us3mc_cleanup); |
diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index 0097c08dc600..0c9ac83ed0a8 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* cpu.c: Dinky routines to look for the kind of Sparc cpu | 1 | /* cpu.c: Dinky routines to look for the kind of Sparc cpu |
| 2 | * we are on. | 2 | * we are on. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) | 4 | * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net) |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| @@ -19,53 +19,86 @@ | |||
| 19 | 19 | ||
| 20 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; | 20 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; |
| 21 | 21 | ||
| 22 | struct cpu_iu_info { | 22 | struct cpu_chip_info { |
| 23 | short manuf; | 23 | unsigned short manuf; |
| 24 | short impl; | 24 | unsigned short impl; |
| 25 | char* cpu_name; /* should be enough I hope... */ | 25 | const char *cpu_name; |
| 26 | const char *fp_name; | ||
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | struct cpu_fp_info { | 29 | static const struct cpu_chip_info cpu_chips[] = { |
| 29 | short manuf; | 30 | { |
| 30 | short impl; | 31 | .manuf = 0x17, |
| 31 | char fpu_vers; | 32 | .impl = 0x10, |
| 32 | char* fp_name; | 33 | .cpu_name = "TI UltraSparc I (SpitFire)", |
| 34 | .fp_name = "UltraSparc I integrated FPU", | ||
| 35 | }, | ||
| 36 | { | ||
| 37 | .manuf = 0x22, | ||
| 38 | .impl = 0x10, | ||
| 39 | .cpu_name = "TI UltraSparc I (SpitFire)", | ||
| 40 | .fp_name = "UltraSparc I integrated FPU", | ||
| 41 | }, | ||
| 42 | { | ||
| 43 | .manuf = 0x17, | ||
| 44 | .impl = 0x11, | ||
| 45 | .cpu_name = "TI UltraSparc II (BlackBird)", | ||
| 46 | .fp_name = "UltraSparc II integrated FPU", | ||
| 47 | }, | ||
| 48 | { | ||
| 49 | .manuf = 0x17, | ||
| 50 | .impl = 0x12, | ||
| 51 | .cpu_name = "TI UltraSparc IIi (Sabre)", | ||
| 52 | .fp_name = "UltraSparc IIi integrated FPU", | ||
| 53 | }, | ||
| 54 | { | ||
| 55 | .manuf = 0x17, | ||
| 56 | .impl = 0x13, | ||
| 57 | .cpu_name = "TI UltraSparc IIe (Hummingbird)", | ||
| 58 | .fp_name = "UltraSparc IIe integrated FPU", | ||
| 59 | }, | ||
| 60 | { | ||
| 61 | .manuf = 0x3e, | ||
| 62 | .impl = 0x14, | ||
| 63 | .cpu_name = "TI UltraSparc III (Cheetah)", | ||
| 64 | .fp_name = "UltraSparc III integrated FPU", | ||
| 65 | }, | ||
| 66 | { | ||
| 67 | .manuf = 0x3e, | ||
| 68 | .impl = 0x15, | ||
| 69 | .cpu_name = "TI UltraSparc III+ (Cheetah+)", | ||
| 70 | .fp_name = "UltraSparc III+ integrated FPU", | ||
| 71 | }, | ||
| 72 | { | ||
| 73 | .manuf = 0x3e, | ||
| 74 | .impl = 0x16, | ||
| 75 | .cpu_name = "TI UltraSparc IIIi (Jalapeno)", | ||
| 76 | .fp_name = "UltraSparc IIIi integrated FPU", | ||
| 77 | }, | ||
| 78 | { | ||
| 79 | .manuf = 0x3e, | ||
| 80 | .impl = 0x18, | ||
| 81 | .cpu_name = "TI UltraSparc IV (Jaguar)", | ||
| 82 | .fp_name = "UltraSparc IV integrated FPU", | ||
| 83 | }, | ||
| 84 | { | ||
| 85 | .manuf = 0x3e, | ||
| 86 | .impl = 0x19, | ||
| 87 | .cpu_name = "TI UltraSparc IV+ (Panther)", | ||
| 88 | .fp_name = "UltraSparc IV+ integrated FPU", | ||
| 89 | }, | ||
| 90 | { | ||
| 91 | .manuf = 0x3e, | ||
| 92 | .impl = 0x22, | ||
| 93 | .cpu_name = "TI UltraSparc IIIi+ (Serrano)", | ||
| 94 | .fp_name = "UltraSparc IIIi+ integrated FPU", | ||
| 95 | }, | ||
| 33 | }; | 96 | }; |
| 34 | 97 | ||
| 35 | static struct cpu_fp_info linux_sparc_fpu[] = { | 98 | #define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) |
| 36 | { 0x17, 0x10, 0, "UltraSparc I integrated FPU"}, | ||
| 37 | { 0x22, 0x10, 0, "UltraSparc I integrated FPU"}, | ||
| 38 | { 0x17, 0x11, 0, "UltraSparc II integrated FPU"}, | ||
| 39 | { 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"}, | ||
| 40 | { 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"}, | ||
| 41 | { 0x3e, 0x14, 0, "UltraSparc III integrated FPU"}, | ||
| 42 | { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"}, | ||
| 43 | { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"}, | ||
| 44 | { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"}, | ||
| 45 | { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"}, | ||
| 46 | { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"}, | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) | ||
| 50 | |||
| 51 | static struct cpu_iu_info linux_sparc_chips[] = { | ||
| 52 | { 0x17, 0x10, "TI UltraSparc I (SpitFire)"}, | ||
| 53 | { 0x22, 0x10, "TI UltraSparc I (SpitFire)"}, | ||
| 54 | { 0x17, 0x11, "TI UltraSparc II (BlackBird)"}, | ||
| 55 | { 0x17, 0x12, "TI UltraSparc IIi (Sabre)"}, | ||
| 56 | { 0x17, 0x13, "TI UltraSparc IIe (Hummingbird)"}, | ||
| 57 | { 0x3e, 0x14, "TI UltraSparc III (Cheetah)"}, | ||
| 58 | { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"}, | ||
| 59 | { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"}, | ||
| 60 | { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"}, | ||
| 61 | { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"}, | ||
| 62 | { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"}, | ||
| 63 | }; | ||
| 64 | 99 | ||
| 65 | #define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) | 100 | const char *sparc_cpu_type; |
| 66 | 101 | const char *sparc_fpu_type; | |
| 67 | char *sparc_cpu_type; | ||
| 68 | char *sparc_fpu_type; | ||
| 69 | 102 | ||
| 70 | static void __init sun4v_cpu_probe(void) | 103 | static void __init sun4v_cpu_probe(void) |
| 71 | { | 104 | { |
| @@ -89,68 +122,45 @@ static void __init sun4v_cpu_probe(void) | |||
| 89 | } | 122 | } |
| 90 | } | 123 | } |
| 91 | 124 | ||
| 92 | void __init cpu_probe(void) | 125 | static const struct cpu_chip_info * __init find_cpu_chip(unsigned short manuf, |
| 126 | unsigned short impl) | ||
| 93 | { | 127 | { |
| 94 | unsigned long ver, fpu_vers, manuf, impl, fprs; | ||
| 95 | int i; | 128 | int i; |
| 96 | |||
| 97 | if (tlb_type == hypervisor) { | ||
| 98 | sun4v_cpu_probe(); | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | 129 | ||
| 102 | fprs = fprs_read(); | 130 | for (i = 0; i < ARRAY_SIZE(cpu_chips); i++) { |
| 103 | fprs_write(FPRS_FEF); | 131 | const struct cpu_chip_info *p = &cpu_chips[i]; |
| 104 | __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" | ||
| 105 | : "=&r" (ver) | ||
| 106 | : "r" (&fpu_vers)); | ||
| 107 | fprs_write(fprs); | ||
| 108 | |||
| 109 | manuf = ((ver >> 48) & 0xffff); | ||
| 110 | impl = ((ver >> 32) & 0xffff); | ||
| 111 | |||
| 112 | fpu_vers = ((fpu_vers >> 17) & 0x7); | ||
| 113 | |||
| 114 | retry: | ||
| 115 | for (i = 0; i < NSPARCCHIPS; i++) { | ||
| 116 | if (linux_sparc_chips[i].manuf == manuf) { | ||
| 117 | if (linux_sparc_chips[i].impl == impl) { | ||
| 118 | sparc_cpu_type = | ||
| 119 | linux_sparc_chips[i].cpu_name; | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | 132 | ||
| 125 | if (i == NSPARCCHIPS) { | 133 | if (p->manuf == manuf && p->impl == impl) |
| 126 | /* Maybe it is a cheetah+ derivative, report it as cheetah+ | 134 | return p; |
| 127 | * in that case until we learn the real names. | ||
| 128 | */ | ||
| 129 | if (manuf == 0x3e && | ||
| 130 | impl > 0x15) { | ||
| 131 | impl = 0x15; | ||
| 132 | goto retry; | ||
| 133 | } else { | ||
| 134 | printk("DEBUG: manuf[%lx] impl[%lx]\n", | ||
| 135 | manuf, impl); | ||
| 136 | } | ||
| 137 | sparc_cpu_type = "Unknown CPU"; | ||
| 138 | } | 135 | } |
| 136 | return NULL; | ||
| 137 | } | ||
| 139 | 138 | ||
| 140 | for (i = 0; i < NSPARCFPU; i++) { | 139 | static int __init cpu_type_probe(void) |
| 141 | if (linux_sparc_fpu[i].manuf == manuf && | 140 | { |
| 142 | linux_sparc_fpu[i].impl == impl) { | 141 | if (tlb_type == hypervisor) { |
| 143 | if (linux_sparc_fpu[i].fpu_vers == fpu_vers) { | 142 | sun4v_cpu_probe(); |
| 144 | sparc_fpu_type = | 143 | } else { |
| 145 | linux_sparc_fpu[i].fp_name; | 144 | unsigned long ver, manuf, impl; |
| 146 | break; | 145 | const struct cpu_chip_info *p; |
| 147 | } | 146 | |
| 147 | __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); | ||
| 148 | |||
| 149 | manuf = ((ver >> 48) & 0xffff); | ||
| 150 | impl = ((ver >> 32) & 0xffff); | ||
| 151 | |||
| 152 | p = find_cpu_chip(manuf, impl); | ||
| 153 | if (p) { | ||
| 154 | sparc_cpu_type = p->cpu_name; | ||
| 155 | sparc_fpu_type = p->fp_name; | ||
| 156 | } else { | ||
| 157 | printk(KERN_ERR "CPU: Unknown chip, manuf[%lx] impl[%lx]\n", | ||
| 158 | manuf, impl); | ||
| 159 | sparc_cpu_type = "Unknown CPU"; | ||
| 160 | sparc_fpu_type = "Unknown FPU"; | ||
| 148 | } | 161 | } |
| 149 | } | 162 | } |
| 150 | 163 | return 0; | |
| 151 | if (i == NSPARCFPU) { | ||
| 152 | printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n", | ||
| 153 | manuf, impl, fpu_vers); | ||
| 154 | sparc_fpu_type = "Unknown FPU"; | ||
| 155 | } | ||
| 156 | } | 164 | } |
| 165 | |||
| 166 | arch_initcall(cpu_type_probe); | ||
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index d0fa5aa38934..f52e0534d91d 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* ds.c: Domain Services driver for Logical Domains | 1 | /* ds.c: Domain Services driver for Logical Domains |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| @@ -1217,7 +1217,7 @@ static int ds_remove(struct vio_dev *vdev) | |||
| 1217 | return 0; | 1217 | return 0; |
| 1218 | } | 1218 | } |
| 1219 | 1219 | ||
| 1220 | static struct vio_device_id ds_match[] = { | 1220 | static struct vio_device_id __initdata ds_match[] = { |
| 1221 | { | 1221 | { |
| 1222 | .type = "domain-services-port", | 1222 | .type = "domain-services-port", |
| 1223 | }, | 1223 | }, |
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 60d36d142559..77dbf6d45faf 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* ebus.c: EBUS DMA library code. |
| 2 | * ebus.c: PCI to EBus bridge device. | ||
| 3 | * | 2 | * |
| 4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
| 5 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) | 4 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) |
| @@ -9,23 +8,11 @@ | |||
| 9 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
| 10 | #include <linux/types.h> | 9 | #include <linux/types.h> |
| 11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/string.h> | ||
| 14 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 15 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 16 | #include <linux/pci.h> | ||
| 17 | #include <linux/of_device.h> | ||
| 18 | |||
| 19 | #include <asm/system.h> | ||
| 20 | #include <asm/page.h> | ||
| 21 | #include <asm/ebus.h> | ||
| 22 | #include <asm/oplib.h> | ||
| 23 | #include <asm/prom.h> | ||
| 24 | #include <asm/bpp.h> | ||
| 25 | #include <asm/irq.h> | ||
| 26 | #include <asm/io.h> | ||
| 27 | 13 | ||
| 28 | /* EBUS dma library. */ | 14 | #include <asm/ebus_dma.h> |
| 15 | #include <asm/io.h> | ||
| 29 | 16 | ||
| 30 | #define EBDMA_CSR 0x00UL /* Control/Status */ | 17 | #define EBDMA_CSR 0x00UL /* Control/Status */ |
| 31 | #define EBDMA_ADDR 0x04UL /* DMA Address */ | 18 | #define EBDMA_ADDR 0x04UL /* DMA Address */ |
| @@ -268,283 +255,3 @@ void ebus_dma_enable(struct ebus_dma_info *p, int on) | |||
| 268 | spin_unlock_irqrestore(&p->lock, flags); | 255 | spin_unlock_irqrestore(&p->lock, flags); |
| 269 | } | 256 | } |
| 270 | EXPORT_SYMBOL(ebus_dma_enable); | 257 | EXPORT_SYMBOL(ebus_dma_enable); |
| 271 | |||
| 272 | struct linux_ebus *ebus_chain = NULL; | ||
| 273 | |||
| 274 | static inline void *ebus_alloc(size_t size) | ||
| 275 | { | ||
| 276 | void *mem; | ||
| 277 | |||
| 278 | mem = kzalloc(size, GFP_ATOMIC); | ||
| 279 | if (!mem) | ||
| 280 | panic("ebus_alloc: out of memory"); | ||
| 281 | return mem; | ||
| 282 | } | ||
| 283 | |||
| 284 | static void __init fill_ebus_child(struct device_node *dp, | ||
| 285 | struct linux_ebus_child *dev, | ||
| 286 | int non_standard_regs) | ||
| 287 | { | ||
| 288 | struct of_device *op; | ||
| 289 | const int *regs; | ||
| 290 | int i, len; | ||
| 291 | |||
| 292 | dev->prom_node = dp; | ||
| 293 | printk(" (%s)", dp->name); | ||
| 294 | |||
| 295 | regs = of_get_property(dp, "reg", &len); | ||
| 296 | if (!regs) | ||
| 297 | dev->num_addrs = 0; | ||
| 298 | else | ||
| 299 | dev->num_addrs = len / sizeof(regs[0]); | ||
| 300 | |||
| 301 | if (non_standard_regs) { | ||
| 302 | /* This is to handle reg properties which are not | ||
| 303 | * in the parent relative format. One example are | ||
| 304 | * children of the i2c device on CompactPCI systems. | ||
| 305 | * | ||
| 306 | * So, for such devices we just record the property | ||
| 307 | * raw in the child resources. | ||
| 308 | */ | ||
| 309 | for (i = 0; i < dev->num_addrs; i++) | ||
| 310 | dev->resource[i].start = regs[i]; | ||
| 311 | } else { | ||
| 312 | for (i = 0; i < dev->num_addrs; i++) { | ||
| 313 | int rnum = regs[i]; | ||
| 314 | if (rnum >= dev->parent->num_addrs) { | ||
| 315 | prom_printf("UGH: property for %s was %d, need < %d\n", | ||
| 316 | dp->name, len, dev->parent->num_addrs); | ||
| 317 | prom_halt(); | ||
| 318 | } | ||
| 319 | dev->resource[i].start = dev->parent->resource[i].start; | ||
| 320 | dev->resource[i].end = dev->parent->resource[i].end; | ||
| 321 | dev->resource[i].flags = IORESOURCE_MEM; | ||
| 322 | dev->resource[i].name = dp->name; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | |||
| 326 | op = of_find_device_by_node(dp); | ||
| 327 | if (!op) { | ||
| 328 | dev->num_irqs = 0; | ||
| 329 | } else { | ||
| 330 | dev->num_irqs = op->num_irqs; | ||
| 331 | for (i = 0; i < dev->num_irqs; i++) | ||
| 332 | dev->irqs[i] = op->irqs[i]; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (!dev->num_irqs) { | ||
| 336 | /* | ||
| 337 | * Oh, well, some PROMs don't export interrupts | ||
| 338 | * property to children of EBus devices... | ||
| 339 | * | ||
| 340 | * Be smart about PS/2 keyboard and mouse. | ||
| 341 | */ | ||
| 342 | if (!strcmp(dev->parent->prom_node->name, "8042")) { | ||
| 343 | if (!strcmp(dev->prom_node->name, "kb_ps2")) { | ||
| 344 | dev->num_irqs = 1; | ||
| 345 | dev->irqs[0] = dev->parent->irqs[0]; | ||
| 346 | } else { | ||
| 347 | dev->num_irqs = 1; | ||
| 348 | dev->irqs[0] = dev->parent->irqs[1]; | ||
| 349 | } | ||
| 350 | } | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | static int __init child_regs_nonstandard(struct linux_ebus_device *dev) | ||
| 355 | { | ||
| 356 | if (!strcmp(dev->prom_node->name, "i2c") || | ||
| 357 | !strcmp(dev->prom_node->name, "SUNW,lombus")) | ||
| 358 | return 1; | ||
| 359 | return 0; | ||
| 360 | } | ||
| 361 | |||
| 362 | static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) | ||
| 363 | { | ||
| 364 | struct linux_ebus_child *child; | ||
| 365 | struct dev_archdata *sd; | ||
| 366 | struct of_device *op; | ||
| 367 | int i, len; | ||
| 368 | |||
| 369 | dev->prom_node = dp; | ||
| 370 | |||
| 371 | printk(" [%s", dp->name); | ||
| 372 | |||
| 373 | op = of_find_device_by_node(dp); | ||
| 374 | if (!op) { | ||
| 375 | dev->num_addrs = 0; | ||
| 376 | dev->num_irqs = 0; | ||
| 377 | } else { | ||
| 378 | const int *regs = of_get_property(dp, "reg", &len); | ||
| 379 | |||
| 380 | if (!regs) | ||
| 381 | len = 0; | ||
| 382 | dev->num_addrs = len / sizeof(struct linux_prom_registers); | ||
| 383 | |||
| 384 | for (i = 0; i < dev->num_addrs; i++) | ||
| 385 | memcpy(&dev->resource[i], | ||
| 386 | &op->resource[i], | ||
| 387 | sizeof(struct resource)); | ||
| 388 | |||
| 389 | dev->num_irqs = op->num_irqs; | ||
| 390 | for (i = 0; i < dev->num_irqs; i++) | ||
| 391 | dev->irqs[i] = op->irqs[i]; | ||
| 392 | } | ||
| 393 | |||
| 394 | sd = &dev->ofdev.dev.archdata; | ||
| 395 | sd->prom_node = dp; | ||
| 396 | sd->op = &dev->ofdev; | ||
| 397 | sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; | ||
| 398 | sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; | ||
| 399 | sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node; | ||
| 400 | |||
| 401 | dev->ofdev.node = dp; | ||
| 402 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | ||
| 403 | dev->ofdev.dev.bus = &ebus_bus_type; | ||
| 404 | dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node); | ||
| 405 | |||
| 406 | /* Register with core */ | ||
| 407 | if (of_device_register(&dev->ofdev) != 0) | ||
| 408 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
| 409 | dp->path_component_name); | ||
| 410 | |||
| 411 | dp = dp->child; | ||
| 412 | if (dp) { | ||
| 413 | printk(" ->"); | ||
| 414 | dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); | ||
| 415 | |||
| 416 | child = dev->children; | ||
| 417 | child->next = NULL; | ||
| 418 | child->parent = dev; | ||
| 419 | child->bus = dev->bus; | ||
| 420 | fill_ebus_child(dp, child, | ||
| 421 | child_regs_nonstandard(dev)); | ||
| 422 | |||
| 423 | while ((dp = dp->sibling) != NULL) { | ||
| 424 | child->next = ebus_alloc(sizeof(struct linux_ebus_child)); | ||
| 425 | |||
| 426 | child = child->next; | ||
| 427 | child->next = NULL; | ||
| 428 | child->parent = dev; | ||
| 429 | child->bus = dev->bus; | ||
| 430 | fill_ebus_child(dp, child, | ||
| 431 | child_regs_nonstandard(dev)); | ||
| 432 | } | ||
| 433 | } | ||
| 434 | printk("]"); | ||
| 435 | } | ||
| 436 | |||
| 437 | static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) | ||
| 438 | { | ||
| 439 | struct pci_dev *pdev = start; | ||
| 440 | |||
| 441 | while ((pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev))) | ||
| 442 | if (pdev->device == PCI_DEVICE_ID_SUN_EBUS || | ||
| 443 | pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS) | ||
| 444 | break; | ||
| 445 | |||
| 446 | *is_rio_p = !!(pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS)); | ||
| 447 | |||
| 448 | return pdev; | ||
| 449 | } | ||
| 450 | |||
| 451 | void __init ebus_init(void) | ||
| 452 | { | ||
| 453 | struct linux_ebus_device *dev; | ||
| 454 | struct linux_ebus *ebus; | ||
| 455 | struct pci_dev *pdev; | ||
| 456 | struct device_node *dp; | ||
| 457 | int is_rio; | ||
| 458 | int num_ebus = 0; | ||
| 459 | |||
| 460 | pdev = find_next_ebus(NULL, &is_rio); | ||
| 461 | if (!pdev) { | ||
| 462 | printk("ebus: No EBus's found.\n"); | ||
| 463 | return; | ||
| 464 | } | ||
| 465 | |||
| 466 | dp = pci_device_to_OF_node(pdev); | ||
| 467 | |||
| 468 | ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); | ||
| 469 | ebus->next = NULL; | ||
| 470 | ebus->is_rio = is_rio; | ||
| 471 | |||
| 472 | while (dp) { | ||
| 473 | struct device_node *child; | ||
| 474 | |||
| 475 | /* SUNW,pci-qfe uses four empty ebuses on it. | ||
| 476 | I think we should not consider them here, | ||
| 477 | as they have half of the properties this | ||
| 478 | code expects and once we do PCI hot-plug, | ||
| 479 | we'd have to tweak with the ebus_chain | ||
| 480 | in the runtime after initialization. -jj */ | ||
| 481 | if (!dp->child) { | ||
| 482 | pdev = find_next_ebus(pdev, &is_rio); | ||
| 483 | if (!pdev) { | ||
| 484 | if (ebus == ebus_chain) { | ||
| 485 | ebus_chain = NULL; | ||
| 486 | printk("ebus: No EBus's found.\n"); | ||
| 487 | return; | ||
| 488 | } | ||
| 489 | break; | ||
| 490 | } | ||
| 491 | ebus->is_rio = is_rio; | ||
| 492 | dp = pci_device_to_OF_node(pdev); | ||
| 493 | continue; | ||
| 494 | } | ||
| 495 | printk("ebus%d:", num_ebus); | ||
| 496 | |||
| 497 | ebus->index = num_ebus; | ||
| 498 | ebus->prom_node = dp; | ||
| 499 | ebus->self = pdev; | ||
| 500 | |||
| 501 | ebus->ofdev.node = dp; | ||
| 502 | ebus->ofdev.dev.parent = &pdev->dev; | ||
| 503 | ebus->ofdev.dev.bus = &ebus_bus_type; | ||
| 504 | dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus); | ||
| 505 | |||
| 506 | /* Register with core */ | ||
| 507 | if (of_device_register(&ebus->ofdev) != 0) | ||
| 508 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
| 509 | dp->path_component_name); | ||
| 510 | |||
| 511 | |||
| 512 | child = dp->child; | ||
| 513 | if (!child) | ||
| 514 | goto next_ebus; | ||
| 515 | |||
| 516 | ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); | ||
| 517 | |||
| 518 | dev = ebus->devices; | ||
| 519 | dev->next = NULL; | ||
| 520 | dev->children = NULL; | ||
| 521 | dev->bus = ebus; | ||
| 522 | fill_ebus_device(child, dev); | ||
| 523 | |||
| 524 | while ((child = child->sibling) != NULL) { | ||
| 525 | dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); | ||
| 526 | |||
| 527 | dev = dev->next; | ||
| 528 | dev->next = NULL; | ||
| 529 | dev->children = NULL; | ||
| 530 | dev->bus = ebus; | ||
| 531 | fill_ebus_device(child, dev); | ||
| 532 | } | ||
| 533 | |||
| 534 | next_ebus: | ||
| 535 | printk("\n"); | ||
| 536 | |||
| 537 | pdev = find_next_ebus(pdev, &is_rio); | ||
| 538 | if (!pdev) | ||
| 539 | break; | ||
| 540 | |||
| 541 | dp = pci_device_to_OF_node(pdev); | ||
| 542 | |||
| 543 | ebus->next = ebus_alloc(sizeof(struct linux_ebus)); | ||
| 544 | ebus = ebus->next; | ||
| 545 | ebus->next = NULL; | ||
| 546 | ebus->is_rio = is_rio; | ||
| 547 | ++num_ebus; | ||
| 548 | } | ||
| 549 | pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ | ||
| 550 | } | ||
diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index fc294a292899..34d7ab5e10d2 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
| 7 | 7 | ||
| 8 | extern char *sparc_cpu_type; | 8 | extern const char *sparc_cpu_type; |
| 9 | extern char *sparc_fpu_type; | 9 | extern const char *sparc_fpu_type; |
| 10 | 10 | ||
| 11 | extern void __init per_cpu_patch(void); | 11 | extern void __init per_cpu_patch(void); |
| 12 | extern void __init sun4v_patch(void); | 12 | extern void __init sun4v_patch(void); |
| @@ -22,7 +22,8 @@ extern void do_notify_resume(struct pt_regs *regs, | |||
| 22 | unsigned long orig_i0, | 22 | unsigned long orig_i0, |
| 23 | unsigned long thread_info_flags); | 23 | unsigned long thread_info_flags); |
| 24 | 24 | ||
| 25 | extern asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p); | 25 | extern asmlinkage int syscall_trace_enter(struct pt_regs *regs); |
| 26 | extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); | ||
| 26 | 27 | ||
| 27 | extern void bad_trap_tl1(struct pt_regs *regs, long lvl); | 28 | extern void bad_trap_tl1(struct pt_regs *regs, long lvl); |
| 28 | 29 | ||
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index c9afef093d51..353226fa0239 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
| 11 | #include <linux/threads.h> | 11 | #include <linux/threads.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/linkage.h> | ||
| 13 | #include <asm/thread_info.h> | 14 | #include <asm/thread_info.h> |
| 14 | #include <asm/asi.h> | 15 | #include <asm/asi.h> |
| 15 | #include <asm/pstate.h> | 16 | #include <asm/pstate.h> |
diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c index 691760b5b012..1d272c3b5740 100644 --- a/arch/sparc64/kernel/hvapi.c +++ b/arch/sparc64/kernel/hvapi.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | #include <asm/hypervisor.h> | 10 | #include <asm/hypervisor.h> |
| 11 | #include <asm/oplib.h> | 11 | #include <asm/oplib.h> |
| 12 | #include <asm/sstate.h> | ||
| 13 | 12 | ||
| 14 | /* If the hypervisor indicates that the API setting | 13 | /* If the hypervisor indicates that the API setting |
| 15 | * calls are unsupported, by returning HV_EBADTRAP or | 14 | * calls are unsupported, by returning HV_EBADTRAP or |
| @@ -184,8 +183,6 @@ void __init sun4v_hvapi_init(void) | |||
| 184 | if (sun4v_hvapi_register(group, major, &minor)) | 183 | if (sun4v_hvapi_register(group, major, &minor)) |
| 185 | goto bad; | 184 | goto bad; |
| 186 | 185 | ||
| 187 | sun4v_sstate_init(); | ||
| 188 | |||
| 189 | return; | 186 | return; |
| 190 | 187 | ||
| 191 | bad: | 188 | bad: |
diff --git a/arch/sparc64/kernel/hvcalls.S b/arch/sparc64/kernel/hvcalls.S index a2810f3ac70f..e066269d1594 100644 --- a/arch/sparc64/kernel/hvcalls.S +++ b/arch/sparc64/kernel/hvcalls.S | |||
| @@ -3,89 +3,75 @@ | |||
| 3 | * | 3 | * |
| 4 | * returns %o0: sysino | 4 | * returns %o0: sysino |
| 5 | */ | 5 | */ |
| 6 | .globl sun4v_devino_to_sysino | 6 | ENTRY(sun4v_devino_to_sysino) |
| 7 | .type sun4v_devino_to_sysino,#function | ||
| 8 | sun4v_devino_to_sysino: | ||
| 9 | mov HV_FAST_INTR_DEVINO2SYSINO, %o5 | 7 | mov HV_FAST_INTR_DEVINO2SYSINO, %o5 |
| 10 | ta HV_FAST_TRAP | 8 | ta HV_FAST_TRAP |
| 11 | retl | 9 | retl |
| 12 | mov %o1, %o0 | 10 | mov %o1, %o0 |
| 13 | .size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino | 11 | ENDPROC(sun4v_devino_to_sysino) |
| 14 | 12 | ||
| 15 | /* %o0: sysino | 13 | /* %o0: sysino |
| 16 | * | 14 | * |
| 17 | * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED}) | 15 | * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED}) |
| 18 | */ | 16 | */ |
| 19 | .globl sun4v_intr_getenabled | 17 | ENTRY(sun4v_intr_getenabled) |
| 20 | .type sun4v_intr_getenabled,#function | ||
| 21 | sun4v_intr_getenabled: | ||
| 22 | mov HV_FAST_INTR_GETENABLED, %o5 | 18 | mov HV_FAST_INTR_GETENABLED, %o5 |
| 23 | ta HV_FAST_TRAP | 19 | ta HV_FAST_TRAP |
| 24 | retl | 20 | retl |
| 25 | mov %o1, %o0 | 21 | mov %o1, %o0 |
| 26 | .size sun4v_intr_getenabled, .-sun4v_intr_getenabled | 22 | ENDPROC(sun4v_intr_getenabled) |
| 27 | 23 | ||
| 28 | /* %o0: sysino | 24 | /* %o0: sysino |
| 29 | * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED}) | 25 | * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED}) |
| 30 | */ | 26 | */ |
| 31 | .globl sun4v_intr_setenabled | 27 | ENTRY(sun4v_intr_setenabled) |
| 32 | .type sun4v_intr_setenabled,#function | ||
| 33 | sun4v_intr_setenabled: | ||
| 34 | mov HV_FAST_INTR_SETENABLED, %o5 | 28 | mov HV_FAST_INTR_SETENABLED, %o5 |
| 35 | ta HV_FAST_TRAP | 29 | ta HV_FAST_TRAP |
| 36 | retl | 30 | retl |
| 37 | nop | 31 | nop |
| 38 | .size sun4v_intr_setenabled, .-sun4v_intr_setenabled | 32 | ENDPROC(sun4v_intr_setenabled) |
| 39 | 33 | ||
| 40 | /* %o0: sysino | 34 | /* %o0: sysino |
| 41 | * | 35 | * |
| 42 | * returns %o0: intr_state (HV_INTR_STATE_*) | 36 | * returns %o0: intr_state (HV_INTR_STATE_*) |
| 43 | */ | 37 | */ |
| 44 | .globl sun4v_intr_getstate | 38 | ENTRY(sun4v_intr_getstate) |
| 45 | .type sun4v_intr_getstate,#function | ||
| 46 | sun4v_intr_getstate: | ||
| 47 | mov HV_FAST_INTR_GETSTATE, %o5 | 39 | mov HV_FAST_INTR_GETSTATE, %o5 |
| 48 | ta HV_FAST_TRAP | 40 | ta HV_FAST_TRAP |
| 49 | retl | 41 | retl |
| 50 | mov %o1, %o0 | 42 | mov %o1, %o0 |
| 51 | .size sun4v_intr_getstate, .-sun4v_intr_getstate | 43 | ENDPROC(sun4v_intr_getstate) |
| 52 | 44 | ||
| 53 | /* %o0: sysino | 45 | /* %o0: sysino |
| 54 | * %o1: intr_state (HV_INTR_STATE_*) | 46 | * %o1: intr_state (HV_INTR_STATE_*) |
| 55 | */ | 47 | */ |
| 56 | .globl sun4v_intr_setstate | 48 | ENTRY(sun4v_intr_setstate) |
| 57 | .type sun4v_intr_setstate,#function | ||
| 58 | sun4v_intr_setstate: | ||
| 59 | mov HV_FAST_INTR_SETSTATE, %o5 | 49 | mov HV_FAST_INTR_SETSTATE, %o5 |
| 60 | ta HV_FAST_TRAP | 50 | ta HV_FAST_TRAP |
| 61 | retl | 51 | retl |
| 62 | nop | 52 | nop |
| 63 | .size sun4v_intr_setstate, .-sun4v_intr_setstate | 53 | ENDPROC(sun4v_intr_setstate) |
| 64 | 54 | ||
| 65 | /* %o0: sysino | 55 | /* %o0: sysino |
| 66 | * | 56 | * |
| 67 | * returns %o0: cpuid | 57 | * returns %o0: cpuid |
| 68 | */ | 58 | */ |
| 69 | .globl sun4v_intr_gettarget | 59 | ENTRY(sun4v_intr_gettarget) |
| 70 | .type sun4v_intr_gettarget,#function | ||
| 71 | sun4v_intr_gettarget: | ||
| 72 | mov HV_FAST_INTR_GETTARGET, %o5 | 60 | mov HV_FAST_INTR_GETTARGET, %o5 |
| 73 | ta HV_FAST_TRAP | 61 | ta HV_FAST_TRAP |
| 74 | retl | 62 | retl |
| 75 | mov %o1, %o0 | 63 | mov %o1, %o0 |
| 76 | .size sun4v_intr_gettarget, .-sun4v_intr_gettarget | 64 | ENDPROC(sun4v_intr_gettarget) |
| 77 | 65 | ||
| 78 | /* %o0: sysino | 66 | /* %o0: sysino |
| 79 | * %o1: cpuid | 67 | * %o1: cpuid |
| 80 | */ | 68 | */ |
| 81 | .globl sun4v_intr_settarget | 69 | ENTRY(sun4v_intr_settarget) |
| 82 | .type sun4v_intr_settarget,#function | ||
| 83 | sun4v_intr_settarget: | ||
| 84 | mov HV_FAST_INTR_SETTARGET, %o5 | 70 | mov HV_FAST_INTR_SETTARGET, %o5 |
| 85 | ta HV_FAST_TRAP | 71 | ta HV_FAST_TRAP |
| 86 | retl | 72 | retl |
| 87 | nop | 73 | nop |
| 88 | .size sun4v_intr_settarget, .-sun4v_intr_settarget | 74 | ENDPROC(sun4v_intr_settarget) |
| 89 | 75 | ||
| 90 | /* %o0: cpuid | 76 | /* %o0: cpuid |
| 91 | * %o1: pc | 77 | * %o1: pc |
| @@ -94,37 +80,31 @@ sun4v_intr_settarget: | |||
| 94 | * | 80 | * |
| 95 | * returns %o0: status | 81 | * returns %o0: status |
| 96 | */ | 82 | */ |
| 97 | .globl sun4v_cpu_start | 83 | ENTRY(sun4v_cpu_start) |
| 98 | .type sun4v_cpu_start,#function | ||
| 99 | sun4v_cpu_start: | ||
| 100 | mov HV_FAST_CPU_START, %o5 | 84 | mov HV_FAST_CPU_START, %o5 |
| 101 | ta HV_FAST_TRAP | 85 | ta HV_FAST_TRAP |
| 102 | retl | 86 | retl |
| 103 | nop | 87 | nop |
| 104 | .size sun4v_cpu_start, .-sun4v_cpu_start | 88 | ENDPROC(sun4v_cpu_start) |
| 105 | 89 | ||
| 106 | /* %o0: cpuid | 90 | /* %o0: cpuid |
| 107 | * | 91 | * |
| 108 | * returns %o0: status | 92 | * returns %o0: status |
| 109 | */ | 93 | */ |
| 110 | .globl sun4v_cpu_stop | 94 | ENTRY(sun4v_cpu_stop) |
| 111 | .type sun4v_cpu_stop,#function | ||
| 112 | sun4v_cpu_stop: | ||
| 113 | mov HV_FAST_CPU_STOP, %o5 | 95 | mov HV_FAST_CPU_STOP, %o5 |
| 114 | ta HV_FAST_TRAP | 96 | ta HV_FAST_TRAP |
| 115 | retl | 97 | retl |
| 116 | nop | 98 | nop |
| 117 | .size sun4v_cpu_stop, .-sun4v_cpu_stop | 99 | ENDPROC(sun4v_cpu_stop) |
| 118 | 100 | ||
| 119 | /* returns %o0: status */ | 101 | /* returns %o0: status */ |
| 120 | .globl sun4v_cpu_yield | 102 | ENTRY(sun4v_cpu_yield) |
| 121 | .type sun4v_cpu_yield, #function | ||
| 122 | sun4v_cpu_yield: | ||
| 123 | mov HV_FAST_CPU_YIELD, %o5 | 103 | mov HV_FAST_CPU_YIELD, %o5 |
| 124 | ta HV_FAST_TRAP | 104 | ta HV_FAST_TRAP |
| 125 | retl | 105 | retl |
| 126 | nop | 106 | nop |
| 127 | .size sun4v_cpu_yield, .-sun4v_cpu_yield | 107 | ENDPROC(sun4v_cpu_yield) |
| 128 | 108 | ||
| 129 | /* %o0: type | 109 | /* %o0: type |
| 130 | * %o1: queue paddr | 110 | * %o1: queue paddr |
| @@ -132,14 +112,12 @@ sun4v_cpu_yield: | |||
| 132 | * | 112 | * |
| 133 | * returns %o0: status | 113 | * returns %o0: status |
| 134 | */ | 114 | */ |
| 135 | .globl sun4v_cpu_qconf | 115 | ENTRY(sun4v_cpu_qconf) |
| 136 | .type sun4v_cpu_qconf,#function | ||
| 137 | sun4v_cpu_qconf: | ||
| 138 | mov HV_FAST_CPU_QCONF, %o5 | 116 | mov HV_FAST_CPU_QCONF, %o5 |
| 139 | ta HV_FAST_TRAP | 117 | ta HV_FAST_TRAP |
| 140 | retl | 118 | retl |
| 141 | nop | 119 | nop |
| 142 | .size sun4v_cpu_qconf, .-sun4v_cpu_qconf | 120 | ENDPROC(sun4v_cpu_qconf) |
| 143 | 121 | ||
| 144 | /* %o0: num cpus in cpu list | 122 | /* %o0: num cpus in cpu list |
| 145 | * %o1: cpu list paddr | 123 | * %o1: cpu list paddr |
| @@ -147,23 +125,19 @@ sun4v_cpu_qconf: | |||
| 147 | * | 125 | * |
| 148 | * returns %o0: status | 126 | * returns %o0: status |
| 149 | */ | 127 | */ |
| 150 | .globl sun4v_cpu_mondo_send | 128 | ENTRY(sun4v_cpu_mondo_send) |
| 151 | .type sun4v_cpu_mondo_send,#function | ||
| 152 | sun4v_cpu_mondo_send: | ||
| 153 | mov HV_FAST_CPU_MONDO_SEND, %o5 | 129 | mov HV_FAST_CPU_MONDO_SEND, %o5 |
| 154 | ta HV_FAST_TRAP | 130 | ta HV_FAST_TRAP |
| 155 | retl | 131 | retl |
| 156 | nop | 132 | nop |
| 157 | .size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send | 133 | ENDPROC(sun4v_cpu_mondo_send) |
| 158 | 134 | ||
| 159 | /* %o0: CPU ID | 135 | /* %o0: CPU ID |
| 160 | * | 136 | * |
| 161 | * returns %o0: -status if status non-zero, else | 137 | * returns %o0: -status if status non-zero, else |
| 162 | * %o0: cpu state as HV_CPU_STATE_* | 138 | * %o0: cpu state as HV_CPU_STATE_* |
| 163 | */ | 139 | */ |
| 164 | .globl sun4v_cpu_state | 140 | ENTRY(sun4v_cpu_state) |
| 165 | .type sun4v_cpu_state,#function | ||
| 166 | sun4v_cpu_state: | ||
| 167 | mov HV_FAST_CPU_STATE, %o5 | 141 | mov HV_FAST_CPU_STATE, %o5 |
| 168 | ta HV_FAST_TRAP | 142 | ta HV_FAST_TRAP |
| 169 | brnz,pn %o0, 1f | 143 | brnz,pn %o0, 1f |
| @@ -171,7 +145,7 @@ sun4v_cpu_state: | |||
| 171 | mov %o1, %o0 | 145 | mov %o1, %o0 |
| 172 | 1: retl | 146 | 1: retl |
| 173 | nop | 147 | nop |
| 174 | .size sun4v_cpu_state, .-sun4v_cpu_state | 148 | ENDPROC(sun4v_cpu_state) |
| 175 | 149 | ||
| 176 | /* %o0: virtual address | 150 | /* %o0: virtual address |
| 177 | * %o1: must be zero | 151 | * %o1: must be zero |
| @@ -180,28 +154,24 @@ sun4v_cpu_state: | |||
| 180 | * | 154 | * |
| 181 | * returns %o0: status | 155 | * returns %o0: status |
| 182 | */ | 156 | */ |
| 183 | .globl sun4v_mmu_map_perm_addr | 157 | ENTRY(sun4v_mmu_map_perm_addr) |
| 184 | .type sun4v_mmu_map_perm_addr,#function | ||
| 185 | sun4v_mmu_map_perm_addr: | ||
| 186 | mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 | 158 | mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 |
| 187 | ta HV_FAST_TRAP | 159 | ta HV_FAST_TRAP |
| 188 | retl | 160 | retl |
| 189 | nop | 161 | nop |
| 190 | .size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr | 162 | ENDPROC(sun4v_mmu_map_perm_addr) |
| 191 | 163 | ||
| 192 | /* %o0: number of TSB descriptions | 164 | /* %o0: number of TSB descriptions |
| 193 | * %o1: TSB descriptions real address | 165 | * %o1: TSB descriptions real address |
| 194 | * | 166 | * |
| 195 | * returns %o0: status | 167 | * returns %o0: status |
| 196 | */ | 168 | */ |
| 197 | .globl sun4v_mmu_tsb_ctx0 | 169 | ENTRY(sun4v_mmu_tsb_ctx0) |
| 198 | .type sun4v_mmu_tsb_ctx0,#function | ||
| 199 | sun4v_mmu_tsb_ctx0: | ||
| 200 | mov HV_FAST_MMU_TSB_CTX0, %o5 | 170 | mov HV_FAST_MMU_TSB_CTX0, %o5 |
| 201 | ta HV_FAST_TRAP | 171 | ta HV_FAST_TRAP |
| 202 | retl | 172 | retl |
| 203 | nop | 173 | nop |
| 204 | .size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0 | 174 | ENDPROC(sun4v_mmu_tsb_ctx0) |
| 205 | 175 | ||
| 206 | /* %o0: API group number | 176 | /* %o0: API group number |
| 207 | * %o1: pointer to unsigned long major number storage | 177 | * %o1: pointer to unsigned long major number storage |
| @@ -209,9 +179,7 @@ sun4v_mmu_tsb_ctx0: | |||
| 209 | * | 179 | * |
| 210 | * returns %o0: status | 180 | * returns %o0: status |
| 211 | */ | 181 | */ |
| 212 | .globl sun4v_get_version | 182 | ENTRY(sun4v_get_version) |
| 213 | .type sun4v_get_version,#function | ||
| 214 | sun4v_get_version: | ||
| 215 | mov HV_CORE_GET_VER, %o5 | 183 | mov HV_CORE_GET_VER, %o5 |
| 216 | mov %o1, %o3 | 184 | mov %o1, %o3 |
| 217 | mov %o2, %o4 | 185 | mov %o2, %o4 |
| @@ -219,7 +187,7 @@ sun4v_get_version: | |||
| 219 | stx %o1, [%o3] | 187 | stx %o1, [%o3] |
| 220 | retl | 188 | retl |
| 221 | stx %o2, [%o4] | 189 | stx %o2, [%o4] |
| 222 | .size sun4v_get_version, .-sun4v_get_version | 190 | ENDPROC(sun4v_get_version) |
| 223 | 191 | ||
| 224 | /* %o0: API group number | 192 | /* %o0: API group number |
| 225 | * %o1: desired major number | 193 | * %o1: desired major number |
| @@ -228,51 +196,43 @@ sun4v_get_version: | |||
| 228 | * | 196 | * |
| 229 | * returns %o0: status | 197 | * returns %o0: status |
| 230 | */ | 198 | */ |
| 231 | .globl sun4v_set_version | 199 | ENTRY(sun4v_set_version) |
| 232 | .type sun4v_set_version,#function | ||
| 233 | sun4v_set_version: | ||
| 234 | mov HV_CORE_SET_VER, %o5 | 200 | mov HV_CORE_SET_VER, %o5 |
| 235 | mov %o3, %o4 | 201 | mov %o3, %o4 |
| 236 | ta HV_CORE_TRAP | 202 | ta HV_CORE_TRAP |
| 237 | retl | 203 | retl |
| 238 | stx %o1, [%o4] | 204 | stx %o1, [%o4] |
| 239 | .size sun4v_set_version, .-sun4v_set_version | 205 | ENDPROC(sun4v_set_version) |
| 240 | 206 | ||
| 241 | /* %o0: pointer to unsigned long time | 207 | /* %o0: pointer to unsigned long time |
| 242 | * | 208 | * |
| 243 | * returns %o0: status | 209 | * returns %o0: status |
| 244 | */ | 210 | */ |
| 245 | .globl sun4v_tod_get | 211 | ENTRY(sun4v_tod_get) |
| 246 | .type sun4v_tod_get,#function | ||
| 247 | sun4v_tod_get: | ||
| 248 | mov %o0, %o4 | 212 | mov %o0, %o4 |
| 249 | mov HV_FAST_TOD_GET, %o5 | 213 | mov HV_FAST_TOD_GET, %o5 |
| 250 | ta HV_FAST_TRAP | 214 | ta HV_FAST_TRAP |
| 251 | stx %o1, [%o4] | 215 | stx %o1, [%o4] |
| 252 | retl | 216 | retl |
| 253 | nop | 217 | nop |
| 254 | .size sun4v_tod_get, .-sun4v_tod_get | 218 | ENDPROC(sun4v_tod_get) |
| 255 | 219 | ||
| 256 | /* %o0: time | 220 | /* %o0: time |
| 257 | * | 221 | * |
| 258 | * returns %o0: status | 222 | * returns %o0: status |
| 259 | */ | 223 | */ |
| 260 | .globl sun4v_tod_set | 224 | ENTRY(sun4v_tod_set) |
| 261 | .type sun4v_tod_set,#function | ||
| 262 | sun4v_tod_set: | ||
| 263 | mov HV_FAST_TOD_SET, %o5 | 225 | mov HV_FAST_TOD_SET, %o5 |
| 264 | ta HV_FAST_TRAP | 226 | ta HV_FAST_TRAP |
| 265 | retl | 227 | retl |
| 266 | nop | 228 | nop |
| 267 | .size sun4v_tod_set, .-sun4v_tod_set | 229 | ENDPROC(sun4v_tod_set) |
| 268 | 230 | ||
| 269 | /* %o0: pointer to unsigned long status | 231 | /* %o0: pointer to unsigned long status |
| 270 | * | 232 | * |
| 271 | * returns %o0: signed character | 233 | * returns %o0: signed character |
| 272 | */ | 234 | */ |
| 273 | .globl sun4v_con_getchar | 235 | ENTRY(sun4v_con_getchar) |
| 274 | .type sun4v_con_getchar,#function | ||
| 275 | sun4v_con_getchar: | ||
| 276 | mov %o0, %o4 | 236 | mov %o0, %o4 |
| 277 | mov HV_FAST_CONS_GETCHAR, %o5 | 237 | mov HV_FAST_CONS_GETCHAR, %o5 |
| 278 | clr %o0 | 238 | clr %o0 |
| @@ -281,20 +241,18 @@ sun4v_con_getchar: | |||
| 281 | stx %o0, [%o4] | 241 | stx %o0, [%o4] |
| 282 | retl | 242 | retl |
| 283 | sra %o1, 0, %o0 | 243 | sra %o1, 0, %o0 |
| 284 | .size sun4v_con_getchar, .-sun4v_con_getchar | 244 | ENDPROC(sun4v_con_getchar) |
| 285 | 245 | ||
| 286 | /* %o0: signed long character | 246 | /* %o0: signed long character |
| 287 | * | 247 | * |
| 288 | * returns %o0: status | 248 | * returns %o0: status |
| 289 | */ | 249 | */ |
| 290 | .globl sun4v_con_putchar | 250 | ENTRY(sun4v_con_putchar) |
| 291 | .type sun4v_con_putchar,#function | ||
| 292 | sun4v_con_putchar: | ||
| 293 | mov HV_FAST_CONS_PUTCHAR, %o5 | 251 | mov HV_FAST_CONS_PUTCHAR, %o5 |
| 294 | ta HV_FAST_TRAP | 252 | ta HV_FAST_TRAP |
| 295 | retl | 253 | retl |
| 296 | sra %o0, 0, %o0 | 254 | sra %o0, 0, %o0 |
| 297 | .size sun4v_con_putchar, .-sun4v_con_putchar | 255 | ENDPROC(sun4v_con_putchar) |
| 298 | 256 | ||
| 299 | /* %o0: buffer real address | 257 | /* %o0: buffer real address |
| 300 | * %o1: buffer size | 258 | * %o1: buffer size |
| @@ -302,9 +260,7 @@ sun4v_con_putchar: | |||
| 302 | * | 260 | * |
| 303 | * returns %o0: status | 261 | * returns %o0: status |
| 304 | */ | 262 | */ |
| 305 | .globl sun4v_con_read | 263 | ENTRY(sun4v_con_read) |
| 306 | .type sun4v_con_read,#function | ||
| 307 | sun4v_con_read: | ||
| 308 | mov %o2, %o4 | 264 | mov %o2, %o4 |
| 309 | mov HV_FAST_CONS_READ, %o5 | 265 | mov HV_FAST_CONS_READ, %o5 |
| 310 | ta HV_FAST_TRAP | 266 | ta HV_FAST_TRAP |
| @@ -318,7 +274,7 @@ sun4v_con_read: | |||
| 318 | stx %o1, [%o4] | 274 | stx %o1, [%o4] |
| 319 | 1: retl | 275 | 1: retl |
| 320 | nop | 276 | nop |
| 321 | .size sun4v_con_read, .-sun4v_con_read | 277 | ENDPROC(sun4v_con_read) |
| 322 | 278 | ||
| 323 | /* %o0: buffer real address | 279 | /* %o0: buffer real address |
| 324 | * %o1: buffer size | 280 | * %o1: buffer size |
| @@ -326,43 +282,37 @@ sun4v_con_read: | |||
| 326 | * | 282 | * |
| 327 | * returns %o0: status | 283 | * returns %o0: status |
| 328 | */ | 284 | */ |
| 329 | .globl sun4v_con_write | 285 | ENTRY(sun4v_con_write) |
| 330 | .type sun4v_con_write,#function | ||
| 331 | sun4v_con_write: | ||
| 332 | mov %o2, %o4 | 286 | mov %o2, %o4 |
| 333 | mov HV_FAST_CONS_WRITE, %o5 | 287 | mov HV_FAST_CONS_WRITE, %o5 |
| 334 | ta HV_FAST_TRAP | 288 | ta HV_FAST_TRAP |
| 335 | stx %o1, [%o4] | 289 | stx %o1, [%o4] |
| 336 | retl | 290 | retl |
| 337 | nop | 291 | nop |
| 338 | .size sun4v_con_write, .-sun4v_con_write | 292 | ENDPROC(sun4v_con_write) |
| 339 | 293 | ||
| 340 | /* %o0: soft state | 294 | /* %o0: soft state |
| 341 | * %o1: address of description string | 295 | * %o1: address of description string |
| 342 | * | 296 | * |
| 343 | * returns %o0: status | 297 | * returns %o0: status |
| 344 | */ | 298 | */ |
| 345 | .globl sun4v_mach_set_soft_state | 299 | ENTRY(sun4v_mach_set_soft_state) |
| 346 | .type sun4v_mach_set_soft_state,#function | ||
| 347 | sun4v_mach_set_soft_state: | ||
| 348 | mov HV_FAST_MACH_SET_SOFT_STATE, %o5 | 300 | mov HV_FAST_MACH_SET_SOFT_STATE, %o5 |
| 349 | ta HV_FAST_TRAP | 301 | ta HV_FAST_TRAP |
| 350 | retl | 302 | retl |
| 351 | nop | 303 | nop |
| 352 | .size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state | 304 | ENDPROC(sun4v_mach_set_soft_state) |
| 353 | 305 | ||
| 354 | /* %o0: exit code | 306 | /* %o0: exit code |
| 355 | * | 307 | * |
| 356 | * Does not return. | 308 | * Does not return. |
| 357 | */ | 309 | */ |
| 358 | .globl sun4v_mach_exit | 310 | ENTRY(sun4v_mach_exit) |
| 359 | .type sun4v_mach_exit,#function | ||
| 360 | sun4v_mach_exit: | ||
| 361 | mov HV_FAST_MACH_EXIT, %o5 | 311 | mov HV_FAST_MACH_EXIT, %o5 |
| 362 | ta HV_FAST_TRAP | 312 | ta HV_FAST_TRAP |
| 363 | retl | 313 | retl |
| 364 | nop | 314 | nop |
| 365 | .size sun4v_mach_exit, .-sun4v_mach_exit | 315 | ENDPROC(sun4v_mach_exit) |
| 366 | 316 | ||
| 367 | /* %o0: buffer real address | 317 | /* %o0: buffer real address |
| 368 | * %o1: buffer length | 318 | * %o1: buffer length |
| @@ -370,44 +320,38 @@ sun4v_mach_exit: | |||
| 370 | * | 320 | * |
| 371 | * returns %o0: status | 321 | * returns %o0: status |
| 372 | */ | 322 | */ |
| 373 | .globl sun4v_mach_desc | 323 | ENTRY(sun4v_mach_desc) |
| 374 | .type sun4v_mach_desc,#function | ||
| 375 | sun4v_mach_desc: | ||
| 376 | mov %o2, %o4 | 324 | mov %o2, %o4 |
| 377 | mov HV_FAST_MACH_DESC, %o5 | 325 | mov HV_FAST_MACH_DESC, %o5 |
| 378 | ta HV_FAST_TRAP | 326 | ta HV_FAST_TRAP |
| 379 | stx %o1, [%o4] | 327 | stx %o1, [%o4] |
| 380 | retl | 328 | retl |
| 381 | nop | 329 | nop |
| 382 | .size sun4v_mach_desc, .-sun4v_mach_desc | 330 | ENDPROC(sun4v_mach_desc) |
| 383 | 331 | ||
| 384 | /* %o0: new timeout in milliseconds | 332 | /* %o0: new timeout in milliseconds |
| 385 | * %o1: pointer to unsigned long orig_timeout | 333 | * %o1: pointer to unsigned long orig_timeout |
| 386 | * | 334 | * |
| 387 | * returns %o0: status | 335 | * returns %o0: status |
| 388 | */ | 336 | */ |
| 389 | .globl sun4v_mach_set_watchdog | 337 | ENTRY(sun4v_mach_set_watchdog) |
| 390 | .type sun4v_mach_set_watchdog,#function | ||
| 391 | sun4v_mach_set_watchdog: | ||
| 392 | mov %o1, %o4 | 338 | mov %o1, %o4 |
| 393 | mov HV_FAST_MACH_SET_WATCHDOG, %o5 | 339 | mov HV_FAST_MACH_SET_WATCHDOG, %o5 |
| 394 | ta HV_FAST_TRAP | 340 | ta HV_FAST_TRAP |
| 395 | stx %o1, [%o4] | 341 | stx %o1, [%o4] |
| 396 | retl | 342 | retl |
| 397 | nop | 343 | nop |
| 398 | .size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog | 344 | ENDPROC(sun4v_mach_set_watchdog) |
| 399 | 345 | ||
| 400 | /* No inputs and does not return. */ | 346 | /* No inputs and does not return. */ |
| 401 | .globl sun4v_mach_sir | 347 | ENTRY(sun4v_mach_sir) |
| 402 | .type sun4v_mach_sir,#function | ||
| 403 | sun4v_mach_sir: | ||
| 404 | mov %o1, %o4 | 348 | mov %o1, %o4 |
| 405 | mov HV_FAST_MACH_SIR, %o5 | 349 | mov HV_FAST_MACH_SIR, %o5 |
| 406 | ta HV_FAST_TRAP | 350 | ta HV_FAST_TRAP |
| 407 | stx %o1, [%o4] | 351 | stx %o1, [%o4] |
| 408 | retl | 352 | retl |
| 409 | nop | 353 | nop |
| 410 | .size sun4v_mach_sir, .-sun4v_mach_sir | 354 | ENDPROC(sun4v_mach_sir) |
| 411 | 355 | ||
| 412 | /* %o0: channel | 356 | /* %o0: channel |
| 413 | * %o1: ra | 357 | * %o1: ra |
| @@ -415,14 +359,12 @@ sun4v_mach_sir: | |||
| 415 | * | 359 | * |
| 416 | * returns %o0: status | 360 | * returns %o0: status |
| 417 | */ | 361 | */ |
| 418 | .globl sun4v_ldc_tx_qconf | 362 | ENTRY(sun4v_ldc_tx_qconf) |
| 419 | .type sun4v_ldc_tx_qconf,#function | ||
| 420 | sun4v_ldc_tx_qconf: | ||
| 421 | mov HV_FAST_LDC_TX_QCONF, %o5 | 363 | mov HV_FAST_LDC_TX_QCONF, %o5 |
| 422 | ta HV_FAST_TRAP | 364 | ta HV_FAST_TRAP |
| 423 | retl | 365 | retl |
| 424 | nop | 366 | nop |
| 425 | .size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf | 367 | ENDPROC(sun4v_ldc_tx_qconf) |
| 426 | 368 | ||
| 427 | /* %o0: channel | 369 | /* %o0: channel |
| 428 | * %o1: pointer to unsigned long ra | 370 | * %o1: pointer to unsigned long ra |
| @@ -430,9 +372,7 @@ sun4v_ldc_tx_qconf: | |||
| 430 | * | 372 | * |
| 431 | * returns %o0: status | 373 | * returns %o0: status |
| 432 | */ | 374 | */ |
| 433 | .globl sun4v_ldc_tx_qinfo | 375 | ENTRY(sun4v_ldc_tx_qinfo) |
| 434 | .type sun4v_ldc_tx_qinfo,#function | ||
| 435 | sun4v_ldc_tx_qinfo: | ||
| 436 | mov %o1, %g1 | 376 | mov %o1, %g1 |
| 437 | mov %o2, %g2 | 377 | mov %o2, %g2 |
| 438 | mov HV_FAST_LDC_TX_QINFO, %o5 | 378 | mov HV_FAST_LDC_TX_QINFO, %o5 |
| @@ -441,7 +381,7 @@ sun4v_ldc_tx_qinfo: | |||
| 441 | stx %o2, [%g2] | 381 | stx %o2, [%g2] |
| 442 | retl | 382 | retl |
| 443 | nop | 383 | nop |
| 444 | .size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo | 384 | ENDPROC(sun4v_ldc_tx_qinfo) |
| 445 | 385 | ||
| 446 | /* %o0: channel | 386 | /* %o0: channel |
| 447 | * %o1: pointer to unsigned long head_off | 387 | * %o1: pointer to unsigned long head_off |
| @@ -450,9 +390,7 @@ sun4v_ldc_tx_qinfo: | |||
| 450 | * | 390 | * |
| 451 | * returns %o0: status | 391 | * returns %o0: status |
| 452 | */ | 392 | */ |
| 453 | .globl sun4v_ldc_tx_get_state | 393 | ENTRY(sun4v_ldc_tx_get_state) |
| 454 | .type sun4v_ldc_tx_get_state,#function | ||
| 455 | sun4v_ldc_tx_get_state: | ||
| 456 | mov %o1, %g1 | 394 | mov %o1, %g1 |
| 457 | mov %o2, %g2 | 395 | mov %o2, %g2 |
| 458 | mov %o3, %g3 | 396 | mov %o3, %g3 |
| @@ -463,21 +401,19 @@ sun4v_ldc_tx_get_state: | |||
| 463 | stx %o3, [%g3] | 401 | stx %o3, [%g3] |
| 464 | retl | 402 | retl |
| 465 | nop | 403 | nop |
| 466 | .size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state | 404 | ENDPROC(sun4v_ldc_tx_get_state) |
| 467 | 405 | ||
| 468 | /* %o0: channel | 406 | /* %o0: channel |
| 469 | * %o1: tail_off | 407 | * %o1: tail_off |
| 470 | * | 408 | * |
| 471 | * returns %o0: status | 409 | * returns %o0: status |
| 472 | */ | 410 | */ |
| 473 | .globl sun4v_ldc_tx_set_qtail | 411 | ENTRY(sun4v_ldc_tx_set_qtail) |
| 474 | .type sun4v_ldc_tx_set_qtail,#function | ||
| 475 | sun4v_ldc_tx_set_qtail: | ||
| 476 | mov HV_FAST_LDC_TX_SET_QTAIL, %o5 | 412 | mov HV_FAST_LDC_TX_SET_QTAIL, %o5 |
| 477 | ta HV_FAST_TRAP | 413 | ta HV_FAST_TRAP |
| 478 | retl | 414 | retl |
| 479 | nop | 415 | nop |
| 480 | .size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail | 416 | ENDPROC(sun4v_ldc_tx_set_qtail) |
| 481 | 417 | ||
| 482 | /* %o0: channel | 418 | /* %o0: channel |
| 483 | * %o1: ra | 419 | * %o1: ra |
| @@ -485,14 +421,12 @@ sun4v_ldc_tx_set_qtail: | |||
| 485 | * | 421 | * |
| 486 | * returns %o0: status | 422 | * returns %o0: status |
| 487 | */ | 423 | */ |
| 488 | .globl sun4v_ldc_rx_qconf | 424 | ENTRY(sun4v_ldc_rx_qconf) |
| 489 | .type sun4v_ldc_rx_qconf,#function | ||
| 490 | sun4v_ldc_rx_qconf: | ||
| 491 | mov HV_FAST_LDC_RX_QCONF, %o5 | 425 | mov HV_FAST_LDC_RX_QCONF, %o5 |
| 492 | ta HV_FAST_TRAP | 426 | ta HV_FAST_TRAP |
| 493 | retl | 427 | retl |
| 494 | nop | 428 | nop |
| 495 | .size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf | 429 | ENDPROC(sun4v_ldc_rx_qconf) |
| 496 | 430 | ||
| 497 | /* %o0: channel | 431 | /* %o0: channel |
| 498 | * %o1: pointer to unsigned long ra | 432 | * %o1: pointer to unsigned long ra |
| @@ -500,9 +434,7 @@ sun4v_ldc_rx_qconf: | |||
| 500 | * | 434 | * |
| 501 | * returns %o0: status | 435 | * returns %o0: status |
| 502 | */ | 436 | */ |
| 503 | .globl sun4v_ldc_rx_qinfo | 437 | ENTRY(sun4v_ldc_rx_qinfo) |
| 504 | .type sun4v_ldc_rx_qinfo,#function | ||
| 505 | sun4v_ldc_rx_qinfo: | ||
| 506 | mov %o1, %g1 | 438 | mov %o1, %g1 |
| 507 | mov %o2, %g2 | 439 | mov %o2, %g2 |
| 508 | mov HV_FAST_LDC_RX_QINFO, %o5 | 440 | mov HV_FAST_LDC_RX_QINFO, %o5 |
| @@ -511,7 +443,7 @@ sun4v_ldc_rx_qinfo: | |||
| 511 | stx %o2, [%g2] | 443 | stx %o2, [%g2] |
| 512 | retl | 444 | retl |
| 513 | nop | 445 | nop |
| 514 | .size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo | 446 | ENDPROC(sun4v_ldc_rx_qinfo) |
| 515 | 447 | ||
| 516 | /* %o0: channel | 448 | /* %o0: channel |
| 517 | * %o1: pointer to unsigned long head_off | 449 | * %o1: pointer to unsigned long head_off |
| @@ -520,9 +452,7 @@ sun4v_ldc_rx_qinfo: | |||
| 520 | * | 452 | * |
| 521 | * returns %o0: status | 453 | * returns %o0: status |
| 522 | */ | 454 | */ |
| 523 | .globl sun4v_ldc_rx_get_state | 455 | ENTRY(sun4v_ldc_rx_get_state) |
| 524 | .type sun4v_ldc_rx_get_state,#function | ||
| 525 | sun4v_ldc_rx_get_state: | ||
| 526 | mov %o1, %g1 | 456 | mov %o1, %g1 |
| 527 | mov %o2, %g2 | 457 | mov %o2, %g2 |
| 528 | mov %o3, %g3 | 458 | mov %o3, %g3 |
| @@ -533,21 +463,19 @@ sun4v_ldc_rx_get_state: | |||
| 533 | stx %o3, [%g3] | 463 | stx %o3, [%g3] |
| 534 | retl | 464 | retl |
| 535 | nop | 465 | nop |
| 536 | .size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state | 466 | ENDPROC(sun4v_ldc_rx_get_state) |
| 537 | 467 | ||
| 538 | /* %o0: channel | 468 | /* %o0: channel |
| 539 | * %o1: head_off | 469 | * %o1: head_off |
| 540 | * | 470 | * |
| 541 | * returns %o0: status | 471 | * returns %o0: status |
| 542 | */ | 472 | */ |
| 543 | .globl sun4v_ldc_rx_set_qhead | 473 | ENTRY(sun4v_ldc_rx_set_qhead) |
| 544 | .type sun4v_ldc_rx_set_qhead,#function | ||
| 545 | sun4v_ldc_rx_set_qhead: | ||
| 546 | mov HV_FAST_LDC_RX_SET_QHEAD, %o5 | 474 | mov HV_FAST_LDC_RX_SET_QHEAD, %o5 |
| 547 | ta HV_FAST_TRAP | 475 | ta HV_FAST_TRAP |
| 548 | retl | 476 | retl |
| 549 | nop | 477 | nop |
| 550 | .size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead | 478 | ENDPROC(sun4v_ldc_rx_set_qhead) |
| 551 | 479 | ||
| 552 | /* %o0: channel | 480 | /* %o0: channel |
| 553 | * %o1: ra | 481 | * %o1: ra |
| @@ -555,14 +483,12 @@ sun4v_ldc_rx_set_qhead: | |||
| 555 | * | 483 | * |
| 556 | * returns %o0: status | 484 | * returns %o0: status |
| 557 | */ | 485 | */ |
| 558 | .globl sun4v_ldc_set_map_table | 486 | ENTRY(sun4v_ldc_set_map_table) |
| 559 | .type sun4v_ldc_set_map_table,#function | ||
| 560 | sun4v_ldc_set_map_table: | ||
| 561 | mov HV_FAST_LDC_SET_MAP_TABLE, %o5 | 487 | mov HV_FAST_LDC_SET_MAP_TABLE, %o5 |
| 562 | ta HV_FAST_TRAP | 488 | ta HV_FAST_TRAP |
| 563 | retl | 489 | retl |
| 564 | nop | 490 | nop |
| 565 | .size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table | 491 | ENDPROC(sun4v_ldc_set_map_table) |
| 566 | 492 | ||
| 567 | /* %o0: channel | 493 | /* %o0: channel |
| 568 | * %o1: pointer to unsigned long ra | 494 | * %o1: pointer to unsigned long ra |
| @@ -570,9 +496,7 @@ sun4v_ldc_set_map_table: | |||
| 570 | * | 496 | * |
| 571 | * returns %o0: status | 497 | * returns %o0: status |
| 572 | */ | 498 | */ |
| 573 | .globl sun4v_ldc_get_map_table | 499 | ENTRY(sun4v_ldc_get_map_table) |
| 574 | .type sun4v_ldc_get_map_table,#function | ||
| 575 | sun4v_ldc_get_map_table: | ||
| 576 | mov %o1, %g1 | 500 | mov %o1, %g1 |
| 577 | mov %o2, %g2 | 501 | mov %o2, %g2 |
| 578 | mov HV_FAST_LDC_GET_MAP_TABLE, %o5 | 502 | mov HV_FAST_LDC_GET_MAP_TABLE, %o5 |
| @@ -581,7 +505,7 @@ sun4v_ldc_get_map_table: | |||
| 581 | stx %o2, [%g2] | 505 | stx %o2, [%g2] |
| 582 | retl | 506 | retl |
| 583 | nop | 507 | nop |
| 584 | .size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table | 508 | ENDPROC(sun4v_ldc_get_map_table) |
| 585 | 509 | ||
| 586 | /* %o0: channel | 510 | /* %o0: channel |
| 587 | * %o1: dir_code | 511 | * %o1: dir_code |
| @@ -592,16 +516,14 @@ sun4v_ldc_get_map_table: | |||
| 592 | * | 516 | * |
| 593 | * returns %o0: status | 517 | * returns %o0: status |
| 594 | */ | 518 | */ |
| 595 | .globl sun4v_ldc_copy | 519 | ENTRY(sun4v_ldc_copy) |
| 596 | .type sun4v_ldc_copy,#function | ||
| 597 | sun4v_ldc_copy: | ||
| 598 | mov %o5, %g1 | 520 | mov %o5, %g1 |
| 599 | mov HV_FAST_LDC_COPY, %o5 | 521 | mov HV_FAST_LDC_COPY, %o5 |
| 600 | ta HV_FAST_TRAP | 522 | ta HV_FAST_TRAP |
| 601 | stx %o1, [%g1] | 523 | stx %o1, [%g1] |
| 602 | retl | 524 | retl |
| 603 | nop | 525 | nop |
| 604 | .size sun4v_ldc_copy, .-sun4v_ldc_copy | 526 | ENDPROC(sun4v_ldc_copy) |
| 605 | 527 | ||
| 606 | /* %o0: channel | 528 | /* %o0: channel |
| 607 | * %o1: cookie | 529 | * %o1: cookie |
| @@ -610,9 +532,7 @@ sun4v_ldc_copy: | |||
| 610 | * | 532 | * |
| 611 | * returns %o0: status | 533 | * returns %o0: status |
| 612 | */ | 534 | */ |
| 613 | .globl sun4v_ldc_mapin | 535 | ENTRY(sun4v_ldc_mapin) |
| 614 | .type sun4v_ldc_mapin,#function | ||
| 615 | sun4v_ldc_mapin: | ||
| 616 | mov %o2, %g1 | 536 | mov %o2, %g1 |
| 617 | mov %o3, %g2 | 537 | mov %o3, %g2 |
| 618 | mov HV_FAST_LDC_MAPIN, %o5 | 538 | mov HV_FAST_LDC_MAPIN, %o5 |
| @@ -621,20 +541,18 @@ sun4v_ldc_mapin: | |||
| 621 | stx %o2, [%g2] | 541 | stx %o2, [%g2] |
| 622 | retl | 542 | retl |
| 623 | nop | 543 | nop |
| 624 | .size sun4v_ldc_mapin, .-sun4v_ldc_mapin | 544 | ENDPROC(sun4v_ldc_mapin) |
| 625 | 545 | ||
| 626 | /* %o0: ra | 546 | /* %o0: ra |
| 627 | * | 547 | * |
| 628 | * returns %o0: status | 548 | * returns %o0: status |
| 629 | */ | 549 | */ |
| 630 | .globl sun4v_ldc_unmap | 550 | ENTRY(sun4v_ldc_unmap) |
| 631 | .type sun4v_ldc_unmap,#function | ||
| 632 | sun4v_ldc_unmap: | ||
| 633 | mov HV_FAST_LDC_UNMAP, %o5 | 551 | mov HV_FAST_LDC_UNMAP, %o5 |
| 634 | ta HV_FAST_TRAP | 552 | ta HV_FAST_TRAP |
| 635 | retl | 553 | retl |
| 636 | nop | 554 | nop |
| 637 | .size sun4v_ldc_unmap, .-sun4v_ldc_unmap | 555 | ENDPROC(sun4v_ldc_unmap) |
| 638 | 556 | ||
| 639 | /* %o0: channel | 557 | /* %o0: channel |
| 640 | * %o1: cookie | 558 | * %o1: cookie |
| @@ -642,14 +560,12 @@ sun4v_ldc_unmap: | |||
| 642 | * | 560 | * |
| 643 | * returns %o0: status | 561 | * returns %o0: status |
| 644 | */ | 562 | */ |
| 645 | .globl sun4v_ldc_revoke | 563 | ENTRY(sun4v_ldc_revoke) |
| 646 | .type sun4v_ldc_revoke,#function | ||
| 647 | sun4v_ldc_revoke: | ||
| 648 | mov HV_FAST_LDC_REVOKE, %o5 | 564 | mov HV_FAST_LDC_REVOKE, %o5 |
| 649 | ta HV_FAST_TRAP | 565 | ta HV_FAST_TRAP |
| 650 | retl | 566 | retl |
| 651 | nop | 567 | nop |
| 652 | .size sun4v_ldc_revoke, .-sun4v_ldc_revoke | 568 | ENDPROC(sun4v_ldc_revoke) |
| 653 | 569 | ||
| 654 | /* %o0: device handle | 570 | /* %o0: device handle |
| 655 | * %o1: device INO | 571 | * %o1: device INO |
| @@ -657,16 +573,14 @@ sun4v_ldc_revoke: | |||
| 657 | * | 573 | * |
| 658 | * returns %o0: status | 574 | * returns %o0: status |
| 659 | */ | 575 | */ |
| 660 | .globl sun4v_vintr_get_cookie | 576 | ENTRY(sun4v_vintr_get_cookie) |
| 661 | .type sun4v_vintr_get_cookie,#function | ||
| 662 | sun4v_vintr_get_cookie: | ||
| 663 | mov %o2, %g1 | 577 | mov %o2, %g1 |
| 664 | mov HV_FAST_VINTR_GET_COOKIE, %o5 | 578 | mov HV_FAST_VINTR_GET_COOKIE, %o5 |
| 665 | ta HV_FAST_TRAP | 579 | ta HV_FAST_TRAP |
| 666 | stx %o1, [%g1] | 580 | stx %o1, [%g1] |
| 667 | retl | 581 | retl |
| 668 | nop | 582 | nop |
| 669 | .size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie | 583 | ENDPROC(sun4v_vintr_get_cookie) |
| 670 | 584 | ||
| 671 | /* %o0: device handle | 585 | /* %o0: device handle |
| 672 | * %o1: device INO | 586 | * %o1: device INO |
| @@ -674,14 +588,12 @@ sun4v_vintr_get_cookie: | |||
| 674 | * | 588 | * |
| 675 | * returns %o0: status | 589 | * returns %o0: status |
| 676 | */ | 590 | */ |
| 677 | .globl sun4v_vintr_set_cookie | 591 | ENTRY(sun4v_vintr_set_cookie) |
| 678 | .type sun4v_vintr_set_cookie,#function | ||
| 679 | sun4v_vintr_set_cookie: | ||
| 680 | mov HV_FAST_VINTR_SET_COOKIE, %o5 | 592 | mov HV_FAST_VINTR_SET_COOKIE, %o5 |
| 681 | ta HV_FAST_TRAP | 593 | ta HV_FAST_TRAP |
| 682 | retl | 594 | retl |
| 683 | nop | 595 | nop |
| 684 | .size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie | 596 | ENDPROC(sun4v_vintr_set_cookie) |
| 685 | 597 | ||
| 686 | /* %o0: device handle | 598 | /* %o0: device handle |
| 687 | * %o1: device INO | 599 | * %o1: device INO |
| @@ -689,16 +601,14 @@ sun4v_vintr_set_cookie: | |||
| 689 | * | 601 | * |
| 690 | * returns %o0: status | 602 | * returns %o0: status |
| 691 | */ | 603 | */ |
| 692 | .globl sun4v_vintr_get_valid | 604 | ENTRY(sun4v_vintr_get_valid) |
| 693 | .type sun4v_vintr_get_valid,#function | ||
| 694 | sun4v_vintr_get_valid: | ||
| 695 | mov %o2, %g1 | 605 | mov %o2, %g1 |
| 696 | mov HV_FAST_VINTR_GET_VALID, %o5 | 606 | mov HV_FAST_VINTR_GET_VALID, %o5 |
| 697 | ta HV_FAST_TRAP | 607 | ta HV_FAST_TRAP |
| 698 | stx %o1, [%g1] | 608 | stx %o1, [%g1] |
| 699 | retl | 609 | retl |
| 700 | nop | 610 | nop |
| 701 | .size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid | 611 | ENDPROC(sun4v_vintr_get_valid) |
| 702 | 612 | ||
| 703 | /* %o0: device handle | 613 | /* %o0: device handle |
| 704 | * %o1: device INO | 614 | * %o1: device INO |
| @@ -706,14 +616,12 @@ sun4v_vintr_get_valid: | |||
| 706 | * | 616 | * |
| 707 | * returns %o0: status | 617 | * returns %o0: status |
| 708 | */ | 618 | */ |
| 709 | .globl sun4v_vintr_set_valid | 619 | ENTRY(sun4v_vintr_set_valid) |
| 710 | .type sun4v_vintr_set_valid,#function | ||
| 711 | sun4v_vintr_set_valid: | ||
| 712 | mov HV_FAST_VINTR_SET_VALID, %o5 | 620 | mov HV_FAST_VINTR_SET_VALID, %o5 |
| 713 | ta HV_FAST_TRAP | 621 | ta HV_FAST_TRAP |
| 714 | retl | 622 | retl |
| 715 | nop | 623 | nop |
| 716 | .size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid | 624 | ENDPROC(sun4v_vintr_set_valid) |
| 717 | 625 | ||
| 718 | /* %o0: device handle | 626 | /* %o0: device handle |
| 719 | * %o1: device INO | 627 | * %o1: device INO |
| @@ -721,16 +629,14 @@ sun4v_vintr_set_valid: | |||
| 721 | * | 629 | * |
| 722 | * returns %o0: status | 630 | * returns %o0: status |
| 723 | */ | 631 | */ |
| 724 | .globl sun4v_vintr_get_state | 632 | ENTRY(sun4v_vintr_get_state) |
| 725 | .type sun4v_vintr_get_state,#function | ||
| 726 | sun4v_vintr_get_state: | ||
| 727 | mov %o2, %g1 | 633 | mov %o2, %g1 |
| 728 | mov HV_FAST_VINTR_GET_STATE, %o5 | 634 | mov HV_FAST_VINTR_GET_STATE, %o5 |
| 729 | ta HV_FAST_TRAP | 635 | ta HV_FAST_TRAP |
| 730 | stx %o1, [%g1] | 636 | stx %o1, [%g1] |
| 731 | retl | 637 | retl |
| 732 | nop | 638 | nop |
| 733 | .size sun4v_vintr_get_state, .-sun4v_vintr_get_state | 639 | ENDPROC(sun4v_vintr_get_state) |
| 734 | 640 | ||
| 735 | /* %o0: device handle | 641 | /* %o0: device handle |
| 736 | * %o1: device INO | 642 | * %o1: device INO |
| @@ -738,14 +644,12 @@ sun4v_vintr_get_state: | |||
| 738 | * | 644 | * |
| 739 | * returns %o0: status | 645 | * returns %o0: status |
| 740 | */ | 646 | */ |
| 741 | .globl sun4v_vintr_set_state | 647 | ENTRY(sun4v_vintr_set_state) |
| 742 | .type sun4v_vintr_set_state,#function | ||
| 743 | sun4v_vintr_set_state: | ||
| 744 | mov HV_FAST_VINTR_SET_STATE, %o5 | 648 | mov HV_FAST_VINTR_SET_STATE, %o5 |
| 745 | ta HV_FAST_TRAP | 649 | ta HV_FAST_TRAP |
| 746 | retl | 650 | retl |
| 747 | nop | 651 | nop |
| 748 | .size sun4v_vintr_set_state, .-sun4v_vintr_set_state | 652 | ENDPROC(sun4v_vintr_set_state) |
| 749 | 653 | ||
| 750 | /* %o0: device handle | 654 | /* %o0: device handle |
| 751 | * %o1: device INO | 655 | * %o1: device INO |
| @@ -753,16 +657,14 @@ sun4v_vintr_set_state: | |||
| 753 | * | 657 | * |
| 754 | * returns %o0: status | 658 | * returns %o0: status |
| 755 | */ | 659 | */ |
| 756 | .globl sun4v_vintr_get_target | 660 | ENTRY(sun4v_vintr_get_target) |
| 757 | .type sun4v_vintr_get_target,#function | ||
| 758 | sun4v_vintr_get_target: | ||
| 759 | mov %o2, %g1 | 661 | mov %o2, %g1 |
| 760 | mov HV_FAST_VINTR_GET_TARGET, %o5 | 662 | mov HV_FAST_VINTR_GET_TARGET, %o5 |
| 761 | ta HV_FAST_TRAP | 663 | ta HV_FAST_TRAP |
| 762 | stx %o1, [%g1] | 664 | stx %o1, [%g1] |
| 763 | retl | 665 | retl |
| 764 | nop | 666 | nop |
| 765 | .size sun4v_vintr_get_target, .-sun4v_vintr_get_target | 667 | ENDPROC(sun4v_vintr_get_target) |
| 766 | 668 | ||
| 767 | /* %o0: device handle | 669 | /* %o0: device handle |
| 768 | * %o1: device INO | 670 | * %o1: device INO |
| @@ -770,14 +672,12 @@ sun4v_vintr_get_target: | |||
| 770 | * | 672 | * |
| 771 | * returns %o0: status | 673 | * returns %o0: status |
| 772 | */ | 674 | */ |
| 773 | .globl sun4v_vintr_set_target | 675 | ENTRY(sun4v_vintr_set_target) |
| 774 | .type sun4v_vintr_set_target,#function | ||
| 775 | sun4v_vintr_set_target: | ||
| 776 | mov HV_FAST_VINTR_SET_TARGET, %o5 | 676 | mov HV_FAST_VINTR_SET_TARGET, %o5 |
| 777 | ta HV_FAST_TRAP | 677 | ta HV_FAST_TRAP |
| 778 | retl | 678 | retl |
| 779 | nop | 679 | nop |
| 780 | .size sun4v_vintr_set_target, .-sun4v_vintr_set_target | 680 | ENDPROC(sun4v_vintr_set_target) |
| 781 | 681 | ||
| 782 | /* %o0: NCS sub-function | 682 | /* %o0: NCS sub-function |
| 783 | * %o1: sub-function arg real-address | 683 | * %o1: sub-function arg real-address |
| @@ -785,18 +685,14 @@ sun4v_vintr_set_target: | |||
| 785 | * | 685 | * |
| 786 | * returns %o0: status | 686 | * returns %o0: status |
| 787 | */ | 687 | */ |
| 788 | .globl sun4v_ncs_request | 688 | ENTRY(sun4v_ncs_request) |
| 789 | .type sun4v_ncs_request,#function | ||
| 790 | sun4v_ncs_request: | ||
| 791 | mov HV_FAST_NCS_REQUEST, %o5 | 689 | mov HV_FAST_NCS_REQUEST, %o5 |
| 792 | ta HV_FAST_TRAP | 690 | ta HV_FAST_TRAP |
| 793 | retl | 691 | retl |
| 794 | nop | 692 | nop |
| 795 | .size sun4v_ncs_request, .-sun4v_ncs_request | 693 | ENDPROC(sun4v_ncs_request) |
| 796 | 694 | ||
| 797 | .globl sun4v_svc_send | 695 | ENTRY(sun4v_svc_send) |
| 798 | .type sun4v_svc_send,#function | ||
| 799 | sun4v_svc_send: | ||
| 800 | save %sp, -192, %sp | 696 | save %sp, -192, %sp |
| 801 | mov %i0, %o0 | 697 | mov %i0, %o0 |
| 802 | mov %i1, %o1 | 698 | mov %i1, %o1 |
| @@ -806,11 +702,9 @@ sun4v_svc_send: | |||
| 806 | stx %o1, [%i3] | 702 | stx %o1, [%i3] |
| 807 | ret | 703 | ret |
| 808 | restore | 704 | restore |
| 809 | .size sun4v_svc_send, .-sun4v_svc_send | 705 | ENDPROC(sun4v_svc_send) |
| 810 | 706 | ||
| 811 | .globl sun4v_svc_recv | 707 | ENTRY(sun4v_svc_recv) |
| 812 | .type sun4v_svc_recv,#function | ||
| 813 | sun4v_svc_recv: | ||
| 814 | save %sp, -192, %sp | 708 | save %sp, -192, %sp |
| 815 | mov %i0, %o0 | 709 | mov %i0, %o0 |
| 816 | mov %i1, %o1 | 710 | mov %i1, %o1 |
| @@ -820,62 +714,50 @@ sun4v_svc_recv: | |||
| 820 | stx %o1, [%i3] | 714 | stx %o1, [%i3] |
| 821 | ret | 715 | ret |
| 822 | restore | 716 | restore |
| 823 | .size sun4v_svc_recv, .-sun4v_svc_recv | 717 | ENDPROC(sun4v_svc_recv) |
| 824 | 718 | ||
| 825 | .globl sun4v_svc_getstatus | 719 | ENTRY(sun4v_svc_getstatus) |
| 826 | .type sun4v_svc_getstatus,#function | ||
| 827 | sun4v_svc_getstatus: | ||
| 828 | mov HV_FAST_SVC_GETSTATUS, %o5 | 720 | mov HV_FAST_SVC_GETSTATUS, %o5 |
| 829 | mov %o1, %o4 | 721 | mov %o1, %o4 |
| 830 | ta HV_FAST_TRAP | 722 | ta HV_FAST_TRAP |
| 831 | stx %o1, [%o4] | 723 | stx %o1, [%o4] |
| 832 | retl | 724 | retl |
| 833 | nop | 725 | nop |
| 834 | .size sun4v_svc_getstatus, .-sun4v_svc_getstatus | 726 | ENDPROC(sun4v_svc_getstatus) |
| 835 | 727 | ||
| 836 | .globl sun4v_svc_setstatus | 728 | ENTRY(sun4v_svc_setstatus) |
| 837 | .type sun4v_svc_setstatus,#function | ||
| 838 | sun4v_svc_setstatus: | ||
| 839 | mov HV_FAST_SVC_SETSTATUS, %o5 | 729 | mov HV_FAST_SVC_SETSTATUS, %o5 |
| 840 | ta HV_FAST_TRAP | 730 | ta HV_FAST_TRAP |
| 841 | retl | 731 | retl |
| 842 | nop | 732 | nop |
| 843 | .size sun4v_svc_setstatus, .-sun4v_svc_setstatus | 733 | ENDPROC(sun4v_svc_setstatus) |
| 844 | 734 | ||
| 845 | .globl sun4v_svc_clrstatus | 735 | ENTRY(sun4v_svc_clrstatus) |
| 846 | .type sun4v_svc_clrstatus,#function | ||
| 847 | sun4v_svc_clrstatus: | ||
| 848 | mov HV_FAST_SVC_CLRSTATUS, %o5 | 736 | mov HV_FAST_SVC_CLRSTATUS, %o5 |
| 849 | ta HV_FAST_TRAP | 737 | ta HV_FAST_TRAP |
| 850 | retl | 738 | retl |
| 851 | nop | 739 | nop |
| 852 | .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus | 740 | ENDPROC(sun4v_svc_clrstatus) |
| 853 | 741 | ||
| 854 | .globl sun4v_mmustat_conf | 742 | ENTRY(sun4v_mmustat_conf) |
| 855 | .type sun4v_mmustat_conf,#function | ||
| 856 | sun4v_mmustat_conf: | ||
| 857 | mov %o1, %o4 | 743 | mov %o1, %o4 |
| 858 | mov HV_FAST_MMUSTAT_CONF, %o5 | 744 | mov HV_FAST_MMUSTAT_CONF, %o5 |
| 859 | ta HV_FAST_TRAP | 745 | ta HV_FAST_TRAP |
| 860 | stx %o1, [%o4] | 746 | stx %o1, [%o4] |
| 861 | retl | 747 | retl |
| 862 | nop | 748 | nop |
| 863 | .size sun4v_mmustat_conf, .-sun4v_mmustat_conf | 749 | ENDPROC(sun4v_mmustat_conf) |
| 864 | 750 | ||
| 865 | .globl sun4v_mmustat_info | 751 | ENTRY(sun4v_mmustat_info) |
| 866 | .type sun4v_mmustat_info,#function | ||
| 867 | sun4v_mmustat_info: | ||
| 868 | mov %o0, %o4 | 752 | mov %o0, %o4 |
| 869 | mov HV_FAST_MMUSTAT_INFO, %o5 | 753 | mov HV_FAST_MMUSTAT_INFO, %o5 |
| 870 | ta HV_FAST_TRAP | 754 | ta HV_FAST_TRAP |
| 871 | stx %o1, [%o4] | 755 | stx %o1, [%o4] |
| 872 | retl | 756 | retl |
| 873 | nop | 757 | nop |
| 874 | .size sun4v_mmustat_info, .-sun4v_mmustat_info | 758 | ENDPROC(sun4v_mmustat_info) |
| 875 | 759 | ||
| 876 | .globl sun4v_mmu_demap_all | 760 | ENTRY(sun4v_mmu_demap_all) |
| 877 | .type sun4v_mmu_demap_all,#function | ||
| 878 | sun4v_mmu_demap_all: | ||
| 879 | clr %o0 | 761 | clr %o0 |
| 880 | clr %o1 | 762 | clr %o1 |
| 881 | mov HV_MMU_ALL, %o2 | 763 | mov HV_MMU_ALL, %o2 |
| @@ -883,4 +765,4 @@ sun4v_mmu_demap_all: | |||
| 883 | ta HV_FAST_TRAP | 765 | ta HV_FAST_TRAP |
| 884 | retl | 766 | retl |
| 885 | nop | 767 | nop |
| 886 | .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all | 768 | ENDPROC(sun4v_mmu_demap_all) |
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 9b6689d9d570..52fc836f464d 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
| 10 | #include <linux/linkage.h> | ||
| 10 | #include <linux/ptrace.h> | 11 | #include <linux/ptrace.h> |
| 11 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 12 | #include <linux/kernel_stat.h> | 13 | #include <linux/kernel_stat.h> |
| @@ -28,7 +29,6 @@ | |||
| 28 | #include <asm/system.h> | 29 | #include <asm/system.h> |
| 29 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
| 30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
| 31 | #include <asm/sbus.h> | ||
| 32 | #include <asm/iommu.h> | 32 | #include <asm/iommu.h> |
| 33 | #include <asm/upa.h> | 33 | #include <asm/upa.h> |
| 34 | #include <asm/oplib.h> | 34 | #include <asm/oplib.h> |
| @@ -792,6 +792,8 @@ void fixup_irqs(void) | |||
| 792 | } | 792 | } |
| 793 | spin_unlock_irqrestore(&irq_desc[irq].lock, flags); | 793 | spin_unlock_irqrestore(&irq_desc[irq].lock, flags); |
| 794 | } | 794 | } |
| 795 | |||
| 796 | tick_ops->disable_irq(); | ||
| 795 | } | 797 | } |
| 796 | #endif | 798 | #endif |
| 797 | 799 | ||
| @@ -864,7 +866,7 @@ static void kill_prom_timer(void) | |||
| 864 | : "g1", "g2"); | 866 | : "g1", "g2"); |
| 865 | } | 867 | } |
| 866 | 868 | ||
| 867 | void init_irqwork_curcpu(void) | 869 | void notrace init_irqwork_curcpu(void) |
| 868 | { | 870 | { |
| 869 | int cpu = hard_smp_processor_id(); | 871 | int cpu = hard_smp_processor_id(); |
| 870 | 872 | ||
| @@ -895,7 +897,7 @@ static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type | |||
| 895 | } | 897 | } |
| 896 | } | 898 | } |
| 897 | 899 | ||
| 898 | void __cpuinit sun4v_register_mondo_queues(int this_cpu) | 900 | void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu) |
| 899 | { | 901 | { |
| 900 | struct trap_per_cpu *tb = &trap_block[this_cpu]; | 902 | struct trap_per_cpu *tb = &trap_block[this_cpu]; |
| 901 | 903 | ||
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index f845f150f565..0f616ae3246c 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c | |||
| @@ -55,15 +55,38 @@ struct of_device *of_find_device_by_node(struct device_node *dp) | |||
| 55 | } | 55 | } |
| 56 | EXPORT_SYMBOL(of_find_device_by_node); | 56 | EXPORT_SYMBOL(of_find_device_by_node); |
| 57 | 57 | ||
| 58 | #ifdef CONFIG_PCI | 58 | unsigned int irq_of_parse_and_map(struct device_node *node, int index) |
| 59 | struct bus_type ebus_bus_type; | 59 | { |
| 60 | EXPORT_SYMBOL(ebus_bus_type); | 60 | struct of_device *op = of_find_device_by_node(node); |
| 61 | #endif | 61 | |
| 62 | if (!op || index >= op->num_irqs) | ||
| 63 | return 0; | ||
| 64 | |||
| 65 | return op->irqs[index]; | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL(irq_of_parse_and_map); | ||
| 68 | |||
| 69 | /* Take the archdata values for IOMMU, STC, and HOSTDATA found in | ||
| 70 | * BUS and propagate to all child of_device objects. | ||
| 71 | */ | ||
| 72 | void of_propagate_archdata(struct of_device *bus) | ||
| 73 | { | ||
| 74 | struct dev_archdata *bus_sd = &bus->dev.archdata; | ||
| 75 | struct device_node *bus_dp = bus->node; | ||
| 76 | struct device_node *dp; | ||
| 62 | 77 | ||
| 63 | #ifdef CONFIG_SBUS | 78 | for (dp = bus_dp->child; dp; dp = dp->sibling) { |
| 64 | struct bus_type sbus_bus_type; | 79 | struct of_device *op = of_find_device_by_node(dp); |
| 65 | EXPORT_SYMBOL(sbus_bus_type); | 80 | |
| 66 | #endif | 81 | op->dev.archdata.iommu = bus_sd->iommu; |
| 82 | op->dev.archdata.stc = bus_sd->stc; | ||
| 83 | op->dev.archdata.host_controller = bus_sd->host_controller; | ||
| 84 | op->dev.archdata.numa_node = bus_sd->numa_node; | ||
| 85 | |||
| 86 | if (dp->child) | ||
| 87 | of_propagate_archdata(op); | ||
| 88 | } | ||
| 89 | } | ||
| 67 | 90 | ||
| 68 | struct bus_type of_platform_bus_type; | 91 | struct bus_type of_platform_bus_type; |
| 69 | EXPORT_SYMBOL(of_platform_bus_type); | 92 | EXPORT_SYMBOL(of_platform_bus_type); |
| @@ -169,7 +192,7 @@ static unsigned long of_bus_default_get_flags(const u32 *addr, unsigned long fla | |||
| 169 | 192 | ||
| 170 | static int of_bus_pci_match(struct device_node *np) | 193 | static int of_bus_pci_match(struct device_node *np) |
| 171 | { | 194 | { |
| 172 | if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { | 195 | if (!strcmp(np->name, "pci")) { |
| 173 | const char *model = of_get_property(np, "model", NULL); | 196 | const char *model = of_get_property(np, "model", NULL); |
| 174 | 197 | ||
| 175 | if (model && !strcmp(model, "SUNW,simba")) | 198 | if (model && !strcmp(model, "SUNW,simba")) |
| @@ -200,7 +223,7 @@ static int of_bus_simba_match(struct device_node *np) | |||
| 200 | /* Treat PCI busses lacking ranges property just like | 223 | /* Treat PCI busses lacking ranges property just like |
| 201 | * simba. | 224 | * simba. |
| 202 | */ | 225 | */ |
| 203 | if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { | 226 | if (!strcmp(np->name, "pci")) { |
| 204 | if (!of_find_property(np, "ranges", NULL)) | 227 | if (!of_find_property(np, "ranges", NULL)) |
| 205 | return 1; | 228 | return 1; |
| 206 | } | 229 | } |
| @@ -378,8 +401,7 @@ static int __init build_one_resource(struct device_node *parent, | |||
| 378 | int na, int ns, int pna) | 401 | int na, int ns, int pna) |
| 379 | { | 402 | { |
| 380 | const u32 *ranges; | 403 | const u32 *ranges; |
| 381 | unsigned int rlen; | 404 | int rone, rlen; |
| 382 | int rone; | ||
| 383 | 405 | ||
| 384 | ranges = of_get_property(parent, "ranges", &rlen); | 406 | ranges = of_get_property(parent, "ranges", &rlen); |
| 385 | if (ranges == NULL || rlen == 0) { | 407 | if (ranges == NULL || rlen == 0) { |
| @@ -421,15 +443,24 @@ static int __init use_1to1_mapping(struct device_node *pp) | |||
| 421 | 443 | ||
| 422 | /* If the parent is the dma node of an ISA bus, pass | 444 | /* If the parent is the dma node of an ISA bus, pass |
| 423 | * the translation up to the root. | 445 | * the translation up to the root. |
| 446 | * | ||
| 447 | * Some SBUS devices use intermediate nodes to express | ||
| 448 | * hierarchy within the device itself. These aren't | ||
| 449 | * real bus nodes, and don't have a 'ranges' property. | ||
| 450 | * But, we should still pass the translation work up | ||
| 451 | * to the SBUS itself. | ||
| 424 | */ | 452 | */ |
| 425 | if (!strcmp(pp->name, "dma")) | 453 | if (!strcmp(pp->name, "dma") || |
| 454 | !strcmp(pp->name, "espdma") || | ||
| 455 | !strcmp(pp->name, "ledma") || | ||
| 456 | !strcmp(pp->name, "lebuffer")) | ||
| 426 | return 0; | 457 | return 0; |
| 427 | 458 | ||
| 428 | /* Similarly for all PCI bridges, if we get this far | 459 | /* Similarly for all PCI bridges, if we get this far |
| 429 | * it lacks a ranges property, and this will include | 460 | * it lacks a ranges property, and this will include |
| 430 | * cases like Simba. | 461 | * cases like Simba. |
| 431 | */ | 462 | */ |
| 432 | if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex")) | 463 | if (!strcmp(pp->name, "pci")) |
| 433 | return 0; | 464 | return 0; |
| 434 | 465 | ||
| 435 | return 1; | 466 | return 1; |
| @@ -714,8 +745,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, | |||
| 714 | break; | 745 | break; |
| 715 | } | 746 | } |
| 716 | } else { | 747 | } else { |
| 717 | if (!strcmp(pp->type, "pci") || | 748 | if (!strcmp(pp->name, "pci")) { |
| 718 | !strcmp(pp->type, "pciex")) { | ||
| 719 | unsigned int this_orig_irq = irq; | 749 | unsigned int this_orig_irq = irq; |
| 720 | 750 | ||
| 721 | irq = pci_irq_swizzle(dp, pp, irq); | 751 | irq = pci_irq_swizzle(dp, pp, irq); |
| @@ -845,15 +875,6 @@ static int __init of_bus_driver_init(void) | |||
| 845 | int err; | 875 | int err; |
| 846 | 876 | ||
| 847 | err = of_bus_type_init(&of_platform_bus_type, "of"); | 877 | err = of_bus_type_init(&of_platform_bus_type, "of"); |
| 848 | #ifdef CONFIG_PCI | ||
| 849 | if (!err) | ||
| 850 | err = of_bus_type_init(&ebus_bus_type, "ebus"); | ||
| 851 | #endif | ||
| 852 | #ifdef CONFIG_SBUS | ||
| 853 | if (!err) | ||
| 854 | err = of_bus_type_init(&sbus_bus_type, "sbus"); | ||
| 855 | #endif | ||
| 856 | |||
| 857 | if (!err) | 878 | if (!err) |
| 858 | scan_of_devices(); | 879 | scan_of_devices(); |
| 859 | 880 | ||
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 55096195458f..242ac1ccae7d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
| @@ -18,32 +18,17 @@ | |||
| 18 | #include <linux/msi.h> | 18 | #include <linux/msi.h> |
| 19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <linux/of.h> | ||
| 22 | #include <linux/of_device.h> | ||
| 21 | 23 | ||
| 22 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
| 23 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
| 24 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
| 25 | #include <asm/ebus.h> | ||
| 26 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
| 27 | #include <asm/apb.h> | 28 | #include <asm/apb.h> |
| 28 | 29 | ||
| 29 | #include "pci_impl.h" | 30 | #include "pci_impl.h" |
| 30 | 31 | ||
| 31 | #ifndef CONFIG_PCI | ||
| 32 | /* A "nop" PCI implementation. */ | ||
| 33 | asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, | ||
| 34 | unsigned long off, unsigned long len, | ||
| 35 | unsigned char *buf) | ||
| 36 | { | ||
| 37 | return 0; | ||
| 38 | } | ||
| 39 | asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, | ||
| 40 | unsigned long off, unsigned long len, | ||
| 41 | unsigned char *buf) | ||
| 42 | { | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | #else | ||
| 46 | |||
| 47 | /* List of all PCI controllers found in the system. */ | 32 | /* List of all PCI controllers found in the system. */ |
| 48 | struct pci_pbm_info *pci_pbm_root = NULL; | 33 | struct pci_pbm_info *pci_pbm_root = NULL; |
| 49 | 34 | ||
| @@ -179,97 +164,6 @@ void pci_config_write32(u32 *addr, u32 val) | |||
| 179 | spin_unlock_irqrestore(&pci_poke_lock, flags); | 164 | spin_unlock_irqrestore(&pci_poke_lock, flags); |
| 180 | } | 165 | } |
| 181 | 166 | ||
| 182 | /* Probe for all PCI controllers in the system. */ | ||
| 183 | extern void sabre_init(struct device_node *, const char *); | ||
| 184 | extern void psycho_init(struct device_node *, const char *); | ||
| 185 | extern void schizo_init(struct device_node *, const char *); | ||
| 186 | extern void schizo_plus_init(struct device_node *, const char *); | ||
| 187 | extern void tomatillo_init(struct device_node *, const char *); | ||
| 188 | extern void sun4v_pci_init(struct device_node *, const char *); | ||
| 189 | extern void fire_pci_init(struct device_node *, const char *); | ||
| 190 | |||
| 191 | static struct { | ||
| 192 | char *model_name; | ||
| 193 | void (*init)(struct device_node *, const char *); | ||
| 194 | } pci_controller_table[] __initdata = { | ||
| 195 | { "SUNW,sabre", sabre_init }, | ||
| 196 | { "pci108e,a000", sabre_init }, | ||
| 197 | { "pci108e,a001", sabre_init }, | ||
| 198 | { "SUNW,psycho", psycho_init }, | ||
| 199 | { "pci108e,8000", psycho_init }, | ||
| 200 | { "SUNW,schizo", schizo_init }, | ||
| 201 | { "pci108e,8001", schizo_init }, | ||
| 202 | { "SUNW,schizo+", schizo_plus_init }, | ||
| 203 | { "pci108e,8002", schizo_plus_init }, | ||
| 204 | { "SUNW,tomatillo", tomatillo_init }, | ||
| 205 | { "pci108e,a801", tomatillo_init }, | ||
| 206 | { "SUNW,sun4v-pci", sun4v_pci_init }, | ||
| 207 | { "pciex108e,80f0", fire_pci_init }, | ||
| 208 | }; | ||
| 209 | #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) | ||
| 210 | |||
| 211 | static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) | ||
| 212 | { | ||
| 213 | int i; | ||
| 214 | |||
| 215 | for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { | ||
| 216 | if (!strncmp(model_name, | ||
| 217 | pci_controller_table[i].model_name, | ||
| 218 | namelen)) { | ||
| 219 | pci_controller_table[i].init(dp, model_name); | ||
| 220 | return 1; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) | ||
| 228 | { | ||
| 229 | struct device_node *dp; | ||
| 230 | int count = 0; | ||
| 231 | |||
| 232 | for_each_node_by_name(dp, "pci") { | ||
| 233 | struct property *prop; | ||
| 234 | int len; | ||
| 235 | |||
| 236 | prop = of_find_property(dp, "model", &len); | ||
| 237 | if (!prop) | ||
| 238 | prop = of_find_property(dp, "compatible", &len); | ||
| 239 | |||
| 240 | if (prop) { | ||
| 241 | const char *model = prop->value; | ||
| 242 | int item_len = 0; | ||
| 243 | |||
| 244 | /* Our value may be a multi-valued string in the | ||
| 245 | * case of some compatible properties. For sanity, | ||
| 246 | * only try the first one. | ||
| 247 | */ | ||
| 248 | while (model[item_len] && len) { | ||
| 249 | len--; | ||
| 250 | item_len++; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (handler(model, item_len, dp)) | ||
| 254 | count++; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | return count; | ||
| 259 | } | ||
| 260 | |||
| 261 | /* Find each controller in the system, attach and initialize | ||
| 262 | * software state structure for each and link into the | ||
| 263 | * pci_pbm_root. Setup the controller enough such | ||
| 264 | * that bus scanning can be done. | ||
| 265 | */ | ||
| 266 | static void __init pci_controller_probe(void) | ||
| 267 | { | ||
| 268 | printk("PCI: Probing for controllers.\n"); | ||
| 269 | |||
| 270 | pci_controller_scan(pci_controller_init); | ||
| 271 | } | ||
| 272 | |||
| 273 | static int ofpci_verbose; | 167 | static int ofpci_verbose; |
| 274 | 168 | ||
| 275 | static int __init ofpci_debug(char *str) | 169 | static int __init ofpci_debug(char *str) |
| @@ -348,11 +242,12 @@ static void pci_parse_of_addrs(struct of_device *op, | |||
| 348 | } | 242 | } |
| 349 | } | 243 | } |
| 350 | 244 | ||
| 351 | struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | 245 | static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, |
| 352 | struct device_node *node, | 246 | struct device_node *node, |
| 353 | struct pci_bus *bus, int devfn) | 247 | struct pci_bus *bus, int devfn) |
| 354 | { | 248 | { |
| 355 | struct dev_archdata *sd; | 249 | struct dev_archdata *sd; |
| 250 | struct of_device *op; | ||
| 356 | struct pci_dev *dev; | 251 | struct pci_dev *dev; |
| 357 | const char *type; | 252 | const char *type; |
| 358 | u32 class; | 253 | u32 class; |
| @@ -366,14 +261,17 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
| 366 | sd->stc = &pbm->stc; | 261 | sd->stc = &pbm->stc; |
| 367 | sd->host_controller = pbm; | 262 | sd->host_controller = pbm; |
| 368 | sd->prom_node = node; | 263 | sd->prom_node = node; |
| 369 | sd->op = of_find_device_by_node(node); | 264 | sd->op = op = of_find_device_by_node(node); |
| 370 | sd->numa_node = pbm->numa_node; | 265 | sd->numa_node = pbm->numa_node; |
| 371 | 266 | ||
| 372 | sd = &sd->op->dev.archdata; | 267 | sd = &op->dev.archdata; |
| 373 | sd->iommu = pbm->iommu; | 268 | sd->iommu = pbm->iommu; |
| 374 | sd->stc = &pbm->stc; | 269 | sd->stc = &pbm->stc; |
| 375 | sd->numa_node = pbm->numa_node; | 270 | sd->numa_node = pbm->numa_node; |
| 376 | 271 | ||
| 272 | if (!strcmp(node->name, "ebus")) | ||
| 273 | of_propagate_archdata(op); | ||
| 274 | |||
| 377 | type = of_get_property(node, "device_type", NULL); | 275 | type = of_get_property(node, "device_type", NULL); |
| 378 | if (type == NULL) | 276 | if (type == NULL) |
| 379 | type = ""; | 277 | type = ""; |
| @@ -425,7 +323,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
| 425 | dev->current_state = 4; /* unknown power state */ | 323 | dev->current_state = 4; /* unknown power state */ |
| 426 | dev->error_state = pci_channel_io_normal; | 324 | dev->error_state = pci_channel_io_normal; |
| 427 | 325 | ||
| 428 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { | 326 | if (!strcmp(node->name, "pci")) { |
| 429 | /* a PCI-PCI bridge */ | 327 | /* a PCI-PCI bridge */ |
| 430 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | 328 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; |
| 431 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | 329 | dev->rom_base_reg = PCI_ROM_ADDRESS1; |
| @@ -775,15 +673,15 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) | |||
| 775 | pci_bus_register_of_sysfs(child_bus); | 673 | pci_bus_register_of_sysfs(child_bus); |
| 776 | } | 674 | } |
| 777 | 675 | ||
| 778 | struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) | 676 | struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, |
| 677 | struct device *parent) | ||
| 779 | { | 678 | { |
| 780 | struct device_node *node = pbm->prom_node; | 679 | struct device_node *node = pbm->op->node; |
| 781 | struct pci_bus *bus; | 680 | struct pci_bus *bus; |
| 782 | 681 | ||
| 783 | printk("PCI: Scanning PBM %s\n", node->full_name); | 682 | printk("PCI: Scanning PBM %s\n", node->full_name); |
| 784 | 683 | ||
| 785 | /* XXX parent device? XXX */ | 684 | bus = pci_create_bus(parent, pbm->pci_first_busno, pbm->pci_ops, pbm); |
| 786 | bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm); | ||
| 787 | if (!bus) { | 685 | if (!bus) { |
| 788 | printk(KERN_ERR "Failed to create bus for %s\n", | 686 | printk(KERN_ERR "Failed to create bus for %s\n", |
| 789 | node->full_name); | 687 | node->full_name); |
| @@ -802,32 +700,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) | |||
| 802 | return bus; | 700 | return bus; |
| 803 | } | 701 | } |
| 804 | 702 | ||
| 805 | static void __init pci_scan_each_controller_bus(void) | ||
| 806 | { | ||
| 807 | struct pci_pbm_info *pbm; | ||
| 808 | |||
| 809 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) | ||
| 810 | pbm->scan_bus(pbm); | ||
| 811 | } | ||
| 812 | |||
| 813 | extern void power_init(void); | ||
| 814 | |||
| 815 | static int __init pcibios_init(void) | ||
| 816 | { | ||
| 817 | pci_controller_probe(); | ||
| 818 | if (pci_pbm_root == NULL) | ||
| 819 | return 0; | ||
| 820 | |||
| 821 | pci_scan_each_controller_bus(); | ||
| 822 | |||
| 823 | ebus_init(); | ||
| 824 | power_init(); | ||
| 825 | |||
| 826 | return 0; | ||
| 827 | } | ||
| 828 | |||
| 829 | subsys_initcall(pcibios_init); | ||
| 830 | |||
| 831 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) | 703 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) |
| 832 | { | 704 | { |
| 833 | struct pci_pbm_info *pbm = pbus->sysdata; | 705 | struct pci_pbm_info *pbm = pbus->sysdata; |
| @@ -1105,14 +977,14 @@ int pcibus_to_node(struct pci_bus *pbus) | |||
| 1105 | EXPORT_SYMBOL(pcibus_to_node); | 977 | EXPORT_SYMBOL(pcibus_to_node); |
| 1106 | #endif | 978 | #endif |
| 1107 | 979 | ||
| 1108 | /* Return the domain nuber for this pci bus */ | 980 | /* Return the domain number for this pci bus */ |
| 1109 | 981 | ||
| 1110 | int pci_domain_nr(struct pci_bus *pbus) | 982 | int pci_domain_nr(struct pci_bus *pbus) |
| 1111 | { | 983 | { |
| 1112 | struct pci_pbm_info *pbm = pbus->sysdata; | 984 | struct pci_pbm_info *pbm = pbus->sysdata; |
| 1113 | int ret; | 985 | int ret; |
| 1114 | 986 | ||
| 1115 | if (pbm == NULL || pbm->parent == NULL) { | 987 | if (!pbm) { |
| 1116 | ret = -ENXIO; | 988 | ret = -ENXIO; |
| 1117 | } else { | 989 | } else { |
| 1118 | ret = pbm->index; | 990 | ret = pbm->index; |
| @@ -1126,7 +998,7 @@ EXPORT_SYMBOL(pci_domain_nr); | |||
| 1126 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | 998 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) |
| 1127 | { | 999 | { |
| 1128 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1000 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
| 1129 | int virt_irq; | 1001 | unsigned int virt_irq; |
| 1130 | 1002 | ||
| 1131 | if (!pbm->setup_msi_irq) | 1003 | if (!pbm->setup_msi_irq) |
| 1132 | return -EINVAL; | 1004 | return -EINVAL; |
| @@ -1140,10 +1012,8 @@ void arch_teardown_msi_irq(unsigned int virt_irq) | |||
| 1140 | struct pci_dev *pdev = entry->dev; | 1012 | struct pci_dev *pdev = entry->dev; |
| 1141 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1013 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
| 1142 | 1014 | ||
| 1143 | if (!pbm->teardown_msi_irq) | 1015 | if (pbm->teardown_msi_irq) |
| 1144 | return; | 1016 | pbm->teardown_msi_irq(virt_irq, pdev); |
| 1145 | |||
| 1146 | return pbm->teardown_msi_irq(virt_irq, pdev); | ||
| 1147 | } | 1017 | } |
| 1148 | #endif /* !(CONFIG_PCI_MSI) */ | 1018 | #endif /* !(CONFIG_PCI_MSI) */ |
| 1149 | 1019 | ||
| @@ -1215,5 +1085,3 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar, | |||
| 1215 | *start = rp->start - offset; | 1085 | *start = rp->start - offset; |
| 1216 | *end = rp->end - offset; | 1086 | *end = rp->end - offset; |
| 1217 | } | 1087 | } |
| 1218 | |||
| 1219 | #endif /* !(CONFIG_PCI) */ | ||
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 09a5ec200c61..23b88082d0b2 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c | |||
| @@ -314,12 +314,12 @@ struct pci_ops sun4v_pci_ops = { | |||
| 314 | 314 | ||
| 315 | void pci_get_pbm_props(struct pci_pbm_info *pbm) | 315 | void pci_get_pbm_props(struct pci_pbm_info *pbm) |
| 316 | { | 316 | { |
| 317 | const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL); | 317 | const u32 *val = of_get_property(pbm->op->node, "bus-range", NULL); |
| 318 | 318 | ||
| 319 | pbm->pci_first_busno = val[0]; | 319 | pbm->pci_first_busno = val[0]; |
| 320 | pbm->pci_last_busno = val[1]; | 320 | pbm->pci_last_busno = val[1]; |
| 321 | 321 | ||
| 322 | val = of_get_property(pbm->prom_node, "ino-bitmap", NULL); | 322 | val = of_get_property(pbm->op->node, "ino-bitmap", NULL); |
| 323 | if (val) { | 323 | if (val) { |
| 324 | pbm->ino_bitmap = (((u64)val[1] << 32UL) | | 324 | pbm->ino_bitmap = (((u64)val[1] << 32UL) | |
| 325 | ((u64)val[0] << 0UL)); | 325 | ((u64)val[0] << 0UL)); |
| @@ -365,7 +365,7 @@ static void pci_register_legacy_regions(struct resource *io_res, | |||
| 365 | 365 | ||
| 366 | static void pci_register_iommu_region(struct pci_pbm_info *pbm) | 366 | static void pci_register_iommu_region(struct pci_pbm_info *pbm) |
| 367 | { | 367 | { |
| 368 | const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); | 368 | const u32 *vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); |
| 369 | 369 | ||
| 370 | if (vdma) { | 370 | if (vdma) { |
| 371 | struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); | 371 | struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); |
| @@ -389,7 +389,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) | |||
| 389 | int num_pbm_ranges; | 389 | int num_pbm_ranges; |
| 390 | 390 | ||
| 391 | saw_mem = saw_io = 0; | 391 | saw_mem = saw_io = 0; |
| 392 | pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i); | 392 | pbm_ranges = of_get_property(pbm->op->node, "ranges", &i); |
| 393 | if (!pbm_ranges) { | 393 | if (!pbm_ranges) { |
| 394 | prom_printf("PCI: Fatal error, missing PBM ranges property " | 394 | prom_printf("PCI: Fatal error, missing PBM ranges property " |
| 395 | " for %s\n", | 395 | " for %s\n", |
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index d23bb6f53cda..9462b68f4894 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c | |||
| @@ -8,34 +8,16 @@ | |||
| 8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
| 9 | #include <linux/msi.h> | 9 | #include <linux/msi.h> |
| 10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
| 11 | #include <linux/of_device.h> | ||
| 11 | 12 | ||
| 12 | #include <asm/oplib.h> | ||
| 13 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
| 14 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
| 15 | #include <asm/upa.h> | ||
| 15 | 16 | ||
| 16 | #include "pci_impl.h" | 17 | #include "pci_impl.h" |
| 17 | 18 | ||
| 18 | #define fire_read(__reg) \ | 19 | #define DRIVER_NAME "fire" |
| 19 | ({ u64 __ret; \ | 20 | #define PFX DRIVER_NAME ": " |
| 20 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
| 21 | : "=r" (__ret) \ | ||
| 22 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 23 | : "memory"); \ | ||
| 24 | __ret; \ | ||
| 25 | }) | ||
| 26 | #define fire_write(__reg, __val) \ | ||
| 27 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
| 28 | : /* no outputs */ \ | ||
| 29 | : "r" (__val), "r" (__reg), \ | ||
| 30 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 31 | : "memory") | ||
| 32 | |||
| 33 | static void __init pci_fire_scan_bus(struct pci_pbm_info *pbm) | ||
| 34 | { | ||
| 35 | pbm->pci_bus = pci_scan_one_pbm(pbm); | ||
| 36 | |||
| 37 | /* XXX register error interrupt handlers XXX */ | ||
| 38 | } | ||
| 39 | 21 | ||
| 40 | #define FIRE_IOMMU_CONTROL 0x40000UL | 22 | #define FIRE_IOMMU_CONTROL 0x40000UL |
| 41 | #define FIRE_IOMMU_TSBBASE 0x40008UL | 23 | #define FIRE_IOMMU_TSBBASE 0x40008UL |
| @@ -69,21 +51,21 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 69 | /* | 51 | /* |
| 70 | * Invalidate TLB Entries. | 52 | * Invalidate TLB Entries. |
| 71 | */ | 53 | */ |
| 72 | fire_write(iommu->iommu_flushinv, ~(u64)0); | 54 | upa_writeq(~(u64)0, iommu->iommu_flushinv); |
| 73 | 55 | ||
| 74 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, | 56 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, |
| 75 | pbm->numa_node); | 57 | pbm->numa_node); |
| 76 | if (err) | 58 | if (err) |
| 77 | return err; | 59 | return err; |
| 78 | 60 | ||
| 79 | fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL); | 61 | upa_writeq(__pa(iommu->page_table) | 0x7UL, iommu->iommu_tsbbase); |
| 80 | 62 | ||
| 81 | control = fire_read(iommu->iommu_control); | 63 | control = upa_readq(iommu->iommu_control); |
| 82 | control |= (0x00000400 /* TSB cache snoop enable */ | | 64 | control |= (0x00000400 /* TSB cache snoop enable */ | |
| 83 | 0x00000300 /* Cache mode */ | | 65 | 0x00000300 /* Cache mode */ | |
| 84 | 0x00000002 /* Bypass enable */ | | 66 | 0x00000002 /* Bypass enable */ | |
| 85 | 0x00000001 /* Translation enable */); | 67 | 0x00000001 /* Translation enable */); |
| 86 | fire_write(iommu->iommu_control, control); | 68 | upa_writeq(control, iommu->iommu_control); |
| 87 | 69 | ||
| 88 | return 0; | 70 | return 0; |
| 89 | } | 71 | } |
| @@ -165,7 +147,7 @@ struct pci_msiq_entry { | |||
| 165 | static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, | 147 | static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, |
| 166 | unsigned long *head) | 148 | unsigned long *head) |
| 167 | { | 149 | { |
| 168 | *head = fire_read(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); | 150 | *head = upa_readq(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); |
| 169 | return 0; | 151 | return 0; |
| 170 | } | 152 | } |
| 171 | 153 | ||
| @@ -191,8 +173,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, | |||
| 191 | *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> | 173 | *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> |
| 192 | MSIQ_WORD0_DATA0_SHIFT); | 174 | MSIQ_WORD0_DATA0_SHIFT); |
| 193 | 175 | ||
| 194 | fire_write(pbm->pbm_regs + MSI_CLEAR(msi_num), | 176 | upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi_num)); |
| 195 | MSI_CLEAR_EQWR_N); | ||
| 196 | 177 | ||
| 197 | /* Clear the entry. */ | 178 | /* Clear the entry. */ |
| 198 | ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; | 179 | ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; |
| @@ -208,7 +189,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, | |||
| 208 | static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, | 189 | static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, |
| 209 | unsigned long head) | 190 | unsigned long head) |
| 210 | { | 191 | { |
| 211 | fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid), head); | 192 | upa_writeq(head, pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); |
| 212 | return 0; | 193 | return 0; |
| 213 | } | 194 | } |
| 214 | 195 | ||
| @@ -217,17 +198,16 @@ static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, | |||
| 217 | { | 198 | { |
| 218 | u64 val; | 199 | u64 val; |
| 219 | 200 | ||
| 220 | val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); | 201 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); |
| 221 | val &= ~(MSI_MAP_EQNUM); | 202 | val &= ~(MSI_MAP_EQNUM); |
| 222 | val |= msiqid; | 203 | val |= msiqid; |
| 223 | fire_write(pbm->pbm_regs + MSI_MAP(msi), val); | 204 | upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); |
| 224 | 205 | ||
| 225 | fire_write(pbm->pbm_regs + MSI_CLEAR(msi), | 206 | upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi)); |
| 226 | MSI_CLEAR_EQWR_N); | ||
| 227 | 207 | ||
| 228 | val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); | 208 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); |
| 229 | val |= MSI_MAP_VALID; | 209 | val |= MSI_MAP_VALID; |
| 230 | fire_write(pbm->pbm_regs + MSI_MAP(msi), val); | 210 | upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); |
| 231 | 211 | ||
| 232 | return 0; | 212 | return 0; |
| 233 | } | 213 | } |
| @@ -237,12 +217,12 @@ static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) | |||
| 237 | unsigned long msiqid; | 217 | unsigned long msiqid; |
| 238 | u64 val; | 218 | u64 val; |
| 239 | 219 | ||
| 240 | val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); | 220 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); |
| 241 | msiqid = (val & MSI_MAP_EQNUM); | 221 | msiqid = (val & MSI_MAP_EQNUM); |
| 242 | 222 | ||
| 243 | val &= ~MSI_MAP_VALID; | 223 | val &= ~MSI_MAP_VALID; |
| 244 | 224 | ||
| 245 | fire_write(pbm->pbm_regs + MSI_MAP(msi), val); | 225 | upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); |
| 246 | 226 | ||
| 247 | return 0; | 227 | return 0; |
| 248 | } | 228 | } |
| @@ -261,22 +241,19 @@ static int pci_fire_msiq_alloc(struct pci_pbm_info *pbm) | |||
| 261 | memset((char *)pages, 0, PAGE_SIZE << order); | 241 | memset((char *)pages, 0, PAGE_SIZE << order); |
| 262 | pbm->msi_queues = (void *) pages; | 242 | pbm->msi_queues = (void *) pages; |
| 263 | 243 | ||
| 264 | fire_write(pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG, | 244 | upa_writeq((EVENT_QUEUE_BASE_ADDR_ALL_ONES | |
| 265 | (EVENT_QUEUE_BASE_ADDR_ALL_ONES | | 245 | __pa(pbm->msi_queues)), |
| 266 | __pa(pbm->msi_queues))); | 246 | pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG); |
| 267 | 247 | ||
| 268 | fire_write(pbm->pbm_regs + IMONDO_DATA0, | 248 | upa_writeq(pbm->portid << 6, pbm->pbm_regs + IMONDO_DATA0); |
| 269 | pbm->portid << 6); | 249 | upa_writeq(0, pbm->pbm_regs + IMONDO_DATA1); |
| 270 | fire_write(pbm->pbm_regs + IMONDO_DATA1, 0); | ||
| 271 | 250 | ||
| 272 | fire_write(pbm->pbm_regs + MSI_32BIT_ADDR, | 251 | upa_writeq(pbm->msi32_start, pbm->pbm_regs + MSI_32BIT_ADDR); |
| 273 | pbm->msi32_start); | 252 | upa_writeq(pbm->msi64_start, pbm->pbm_regs + MSI_64BIT_ADDR); |
| 274 | fire_write(pbm->pbm_regs + MSI_64BIT_ADDR, | ||
| 275 | pbm->msi64_start); | ||
| 276 | 253 | ||
| 277 | for (i = 0; i < pbm->msiq_num; i++) { | 254 | for (i = 0; i < pbm->msiq_num; i++) { |
| 278 | fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(i), 0); | 255 | upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_HEAD(i)); |
| 279 | fire_write(pbm->pbm_regs + EVENT_QUEUE_TAIL(i), 0); | 256 | upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_TAIL(i)); |
| 280 | } | 257 | } |
| 281 | 258 | ||
| 282 | return 0; | 259 | return 0; |
| @@ -310,9 +287,9 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, | |||
| 310 | /* XXX iterate amongst the 4 IRQ controllers XXX */ | 287 | /* XXX iterate amongst the 4 IRQ controllers XXX */ |
| 311 | int_ctrlr = (1UL << 6); | 288 | int_ctrlr = (1UL << 6); |
| 312 | 289 | ||
| 313 | val = fire_read(imap_reg); | 290 | val = upa_readq(imap_reg); |
| 314 | val |= (1UL << 63) | int_ctrlr; | 291 | val |= (1UL << 63) | int_ctrlr; |
| 315 | fire_write(imap_reg, val); | 292 | upa_writeq(val, imap_reg); |
| 316 | 293 | ||
| 317 | fixup = ((pbm->portid << 6) | devino) - int_ctrlr; | 294 | fixup = ((pbm->portid << 6) | devino) - int_ctrlr; |
| 318 | 295 | ||
| @@ -320,9 +297,8 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, | |||
| 320 | if (!virt_irq) | 297 | if (!virt_irq) |
| 321 | return -ENOMEM; | 298 | return -ENOMEM; |
| 322 | 299 | ||
| 323 | fire_write(pbm->pbm_regs + | 300 | upa_writeq(EVENT_QUEUE_CONTROL_SET_EN, |
| 324 | EVENT_QUEUE_CONTROL_SET(msiqid), | 301 | pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid)); |
| 325 | EVENT_QUEUE_CONTROL_SET_EN); | ||
| 326 | 302 | ||
| 327 | return virt_irq; | 303 | return virt_irq; |
| 328 | } | 304 | } |
| @@ -390,77 +366,65 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) | |||
| 390 | { | 366 | { |
| 391 | u64 val; | 367 | u64 val; |
| 392 | 368 | ||
| 393 | fire_write(pbm->controller_regs + FIRE_PARITY_CONTROL, | 369 | upa_writeq(FIRE_PARITY_ENAB, |
| 394 | FIRE_PARITY_ENAB); | 370 | pbm->controller_regs + FIRE_PARITY_CONTROL); |
| 395 | 371 | ||
| 396 | fire_write(pbm->controller_regs + FIRE_FATAL_RESET_CTL, | 372 | upa_writeq((FIRE_FATAL_RESET_SPARE | |
| 397 | (FIRE_FATAL_RESET_SPARE | | ||
| 398 | FIRE_FATAL_RESET_MB | | 373 | FIRE_FATAL_RESET_MB | |
| 399 | FIRE_FATAL_RESET_CPE | | 374 | FIRE_FATAL_RESET_CPE | |
| 400 | FIRE_FATAL_RESET_APE | | 375 | FIRE_FATAL_RESET_APE | |
| 401 | FIRE_FATAL_RESET_PIO | | 376 | FIRE_FATAL_RESET_PIO | |
| 402 | FIRE_FATAL_RESET_JW | | 377 | FIRE_FATAL_RESET_JW | |
| 403 | FIRE_FATAL_RESET_JI | | 378 | FIRE_FATAL_RESET_JI | |
| 404 | FIRE_FATAL_RESET_JR)); | 379 | FIRE_FATAL_RESET_JR), |
| 380 | pbm->controller_regs + FIRE_FATAL_RESET_CTL); | ||
| 405 | 381 | ||
| 406 | fire_write(pbm->controller_regs + FIRE_CORE_INTR_ENABLE, ~(u64)0); | 382 | upa_writeq(~(u64)0, pbm->controller_regs + FIRE_CORE_INTR_ENABLE); |
| 407 | 383 | ||
| 408 | val = fire_read(pbm->pbm_regs + FIRE_TLU_CTRL); | 384 | val = upa_readq(pbm->pbm_regs + FIRE_TLU_CTRL); |
| 409 | val |= (FIRE_TLU_CTRL_TIM | | 385 | val |= (FIRE_TLU_CTRL_TIM | |
| 410 | FIRE_TLU_CTRL_QDET | | 386 | FIRE_TLU_CTRL_QDET | |
| 411 | FIRE_TLU_CTRL_CFG); | 387 | FIRE_TLU_CTRL_CFG); |
| 412 | fire_write(pbm->pbm_regs + FIRE_TLU_CTRL, val); | 388 | upa_writeq(val, pbm->pbm_regs + FIRE_TLU_CTRL); |
| 413 | fire_write(pbm->pbm_regs + FIRE_TLU_DEV_CTRL, 0); | 389 | upa_writeq(0, pbm->pbm_regs + FIRE_TLU_DEV_CTRL); |
| 414 | fire_write(pbm->pbm_regs + FIRE_TLU_LINK_CTRL, | 390 | upa_writeq(FIRE_TLU_LINK_CTRL_CLK, |
| 415 | FIRE_TLU_LINK_CTRL_CLK); | 391 | pbm->pbm_regs + FIRE_TLU_LINK_CTRL); |
| 416 | 392 | ||
| 417 | fire_write(pbm->pbm_regs + FIRE_LPU_RESET, 0); | 393 | upa_writeq(0, pbm->pbm_regs + FIRE_LPU_RESET); |
| 418 | fire_write(pbm->pbm_regs + FIRE_LPU_LLCFG, | 394 | upa_writeq(FIRE_LPU_LLCFG_VC0, pbm->pbm_regs + FIRE_LPU_LLCFG); |
| 419 | FIRE_LPU_LLCFG_VC0); | 395 | upa_writeq((FIRE_LPU_FCTRL_UCTRL_N | FIRE_LPU_FCTRL_UCTRL_P), |
| 420 | fire_write(pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL, | 396 | pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL); |
| 421 | (FIRE_LPU_FCTRL_UCTRL_N | | 397 | upa_writeq(((0xffff << 16) | (0x0000 << 0)), |
| 422 | FIRE_LPU_FCTRL_UCTRL_P)); | 398 | pbm->pbm_regs + FIRE_LPU_TXL_FIFOP); |
| 423 | fire_write(pbm->pbm_regs + FIRE_LPU_TXL_FIFOP, | 399 | upa_writeq(3000000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2); |
| 424 | ((0xffff << 16) | (0x0000 << 0))); | 400 | upa_writeq(500000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3); |
| 425 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2, 3000000); | 401 | upa_writeq((2 << 16) | (140 << 8), |
| 426 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3, 500000); | 402 | pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4); |
| 427 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4, | 403 | upa_writeq(0, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5); |
| 428 | (2 << 16) | (140 << 8)); | 404 | |
| 429 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5, 0); | 405 | upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_DMC_IENAB); |
| 430 | 406 | upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_A); | |
| 431 | fire_write(pbm->pbm_regs + FIRE_DMC_IENAB, ~(u64)0); | 407 | upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_B); |
| 432 | fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_A, 0); | 408 | |
| 433 | fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_B, 0); | 409 | upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_PEC_IENAB); |
| 434 | |||
| 435 | fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); | ||
| 436 | } | 410 | } |
| 437 | 411 | ||
| 438 | static int __init pci_fire_pbm_init(struct pci_controller_info *p, | 412 | static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, |
| 439 | struct device_node *dp, u32 portid) | 413 | struct of_device *op, u32 portid) |
| 440 | { | 414 | { |
| 441 | const struct linux_prom64_registers *regs; | 415 | const struct linux_prom64_registers *regs; |
| 442 | struct pci_pbm_info *pbm; | 416 | struct device_node *dp = op->node; |
| 443 | int err; | 417 | int err; |
| 444 | 418 | ||
| 445 | if ((portid & 1) == 0) | ||
| 446 | pbm = &p->pbm_A; | ||
| 447 | else | ||
| 448 | pbm = &p->pbm_B; | ||
| 449 | |||
| 450 | pbm->next = pci_pbm_root; | ||
| 451 | pci_pbm_root = pbm; | ||
| 452 | |||
| 453 | pbm->numa_node = -1; | 419 | pbm->numa_node = -1; |
| 454 | 420 | ||
| 455 | pbm->scan_bus = pci_fire_scan_bus; | ||
| 456 | pbm->pci_ops = &sun4u_pci_ops; | 421 | pbm->pci_ops = &sun4u_pci_ops; |
| 457 | pbm->config_space_reg_bits = 12; | 422 | pbm->config_space_reg_bits = 12; |
| 458 | 423 | ||
| 459 | pbm->index = pci_num_pbms++; | 424 | pbm->index = pci_num_pbms++; |
| 460 | 425 | ||
| 461 | pbm->portid = portid; | 426 | pbm->portid = portid; |
| 462 | pbm->parent = p; | 427 | pbm->op = op; |
| 463 | pbm->prom_node = dp; | ||
| 464 | pbm->name = dp->full_name; | 428 | pbm->name = dp->full_name; |
| 465 | 429 | ||
| 466 | regs = of_get_property(dp, "reg", NULL); | 430 | regs = of_get_property(dp, "reg", NULL); |
| @@ -481,53 +445,77 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, | |||
| 481 | 445 | ||
| 482 | pci_fire_msi_init(pbm); | 446 | pci_fire_msi_init(pbm); |
| 483 | 447 | ||
| 484 | return 0; | 448 | pbm->pci_bus = pci_scan_one_pbm(pbm, &op->dev); |
| 485 | } | 449 | |
| 450 | /* XXX register error interrupt handlers XXX */ | ||
| 451 | |||
| 452 | pbm->next = pci_pbm_root; | ||
| 453 | pci_pbm_root = pbm; | ||
| 486 | 454 | ||
| 487 | static inline int portid_compare(u32 x, u32 y) | ||
| 488 | { | ||
| 489 | if (x == (y ^ 1)) | ||
| 490 | return 1; | ||
| 491 | return 0; | 455 | return 0; |
| 492 | } | 456 | } |
| 493 | 457 | ||
| 494 | void __init fire_pci_init(struct device_node *dp, const char *model_name) | 458 | static int __devinit fire_probe(struct of_device *op, |
| 459 | const struct of_device_id *match) | ||
| 495 | { | 460 | { |
| 496 | struct pci_controller_info *p; | 461 | struct device_node *dp = op->node; |
| 497 | u32 portid = of_getintprop_default(dp, "portid", 0xff); | ||
| 498 | struct iommu *iommu; | ||
| 499 | struct pci_pbm_info *pbm; | 462 | struct pci_pbm_info *pbm; |
| 463 | struct iommu *iommu; | ||
| 464 | u32 portid; | ||
| 465 | int err; | ||
| 500 | 466 | ||
| 501 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 467 | portid = of_getintprop_default(dp, "portid", 0xff); |
| 502 | if (portid_compare(pbm->portid, portid)) { | 468 | |
| 503 | if (pci_fire_pbm_init(pbm->parent, dp, portid)) | 469 | err = -ENOMEM; |
| 504 | goto fatal_memory_error; | 470 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
| 505 | return; | 471 | if (!pbm) { |
| 506 | } | 472 | printk(KERN_ERR PFX "Cannot allocate pci_pbminfo.\n"); |
| 473 | goto out_err; | ||
| 507 | } | 474 | } |
| 508 | 475 | ||
| 509 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 476 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); |
| 510 | if (!p) | 477 | if (!iommu) { |
| 511 | goto fatal_memory_error; | 478 | printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); |
| 479 | goto out_free_controller; | ||
| 480 | } | ||
| 512 | 481 | ||
| 513 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 482 | pbm->iommu = iommu; |
| 514 | if (!iommu) | ||
| 515 | goto fatal_memory_error; | ||
| 516 | 483 | ||
| 517 | p->pbm_A.iommu = iommu; | 484 | err = pci_fire_pbm_init(pbm, op, portid); |
| 485 | if (err) | ||
| 486 | goto out_free_iommu; | ||
| 518 | 487 | ||
| 519 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 488 | dev_set_drvdata(&op->dev, pbm); |
| 520 | if (!iommu) | ||
| 521 | goto fatal_memory_error; | ||
| 522 | 489 | ||
| 523 | p->pbm_B.iommu = iommu; | 490 | return 0; |
| 524 | 491 | ||
| 525 | if (pci_fire_pbm_init(p, dp, portid)) | 492 | out_free_iommu: |
| 526 | goto fatal_memory_error; | 493 | kfree(pbm->iommu); |
| 494 | |||
| 495 | out_free_controller: | ||
| 496 | kfree(pbm); | ||
| 527 | 497 | ||
| 528 | return; | 498 | out_err: |
| 499 | return err; | ||
| 500 | } | ||
| 501 | |||
| 502 | static struct of_device_id __initdata fire_match[] = { | ||
| 503 | { | ||
| 504 | .name = "pci", | ||
| 505 | .compatible = "pciex108e,80f0", | ||
| 506 | }, | ||
| 507 | {}, | ||
| 508 | }; | ||
| 529 | 509 | ||
| 530 | fatal_memory_error: | 510 | static struct of_platform_driver fire_driver = { |
| 531 | prom_printf("PCI_FIRE: Fatal memory allocation error.\n"); | 511 | .name = DRIVER_NAME, |
| 532 | prom_halt(); | 512 | .match_table = fire_match, |
| 513 | .probe = fire_probe, | ||
| 514 | }; | ||
| 515 | |||
| 516 | static int __init fire_init(void) | ||
| 517 | { | ||
| 518 | return of_register_driver(&fire_driver, &of_bus_type); | ||
| 533 | } | 519 | } |
| 520 | |||
| 521 | subsys_initcall(fire_init); | ||
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index c385d126be11..03186824327e 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
| 11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
| 12 | #include <linux/msi.h> | 12 | #include <linux/msi.h> |
| 13 | #include <linux/of_device.h> | ||
| 13 | #include <asm/io.h> | 14 | #include <asm/io.h> |
| 14 | #include <asm/prom.h> | 15 | #include <asm/prom.h> |
| 15 | #include <asm/iommu.h> | 16 | #include <asm/iommu.h> |
| @@ -56,15 +57,11 @@ struct sparc64_msiq_cookie { | |||
| 56 | }; | 57 | }; |
| 57 | #endif | 58 | #endif |
| 58 | 59 | ||
| 59 | struct pci_controller_info; | ||
| 60 | |||
| 61 | struct pci_pbm_info { | 60 | struct pci_pbm_info { |
| 62 | struct pci_pbm_info *next; | 61 | struct pci_pbm_info *next; |
| 62 | struct pci_pbm_info *sibling; | ||
| 63 | int index; | 63 | int index; |
| 64 | 64 | ||
| 65 | /* PCI controller we sit under. */ | ||
| 66 | struct pci_controller_info *parent; | ||
| 67 | |||
| 68 | /* Physical address base of controller registers. */ | 65 | /* Physical address base of controller registers. */ |
| 69 | unsigned long controller_regs; | 66 | unsigned long controller_regs; |
| 70 | 67 | ||
| @@ -94,7 +91,7 @@ struct pci_pbm_info { | |||
| 94 | char *name; | 91 | char *name; |
| 95 | 92 | ||
| 96 | /* OBP specific information. */ | 93 | /* OBP specific information. */ |
| 97 | struct device_node *prom_node; | 94 | struct of_device *op; |
| 98 | u64 ino_bitmap; | 95 | u64 ino_bitmap; |
| 99 | 96 | ||
| 100 | /* PBM I/O and Memory space resources. */ | 97 | /* PBM I/O and Memory space resources. */ |
| @@ -107,6 +104,10 @@ struct pci_pbm_info { | |||
| 107 | /* This will be 12 on PCI-E controllers, 8 elsewhere. */ | 104 | /* This will be 12 on PCI-E controllers, 8 elsewhere. */ |
| 108 | unsigned long config_space_reg_bits; | 105 | unsigned long config_space_reg_bits; |
| 109 | 106 | ||
| 107 | unsigned long pci_afsr; | ||
| 108 | unsigned long pci_afar; | ||
| 109 | unsigned long pci_csr; | ||
| 110 | |||
| 110 | /* State of 66MHz capabilities on this PBM. */ | 111 | /* State of 66MHz capabilities on this PBM. */ |
| 111 | int is_66mhz_capable; | 112 | int is_66mhz_capable; |
| 112 | int all_devs_66mhz; | 113 | int all_devs_66mhz; |
| @@ -146,25 +147,19 @@ struct pci_pbm_info { | |||
| 146 | unsigned int pci_first_busno; | 147 | unsigned int pci_first_busno; |
| 147 | unsigned int pci_last_busno; | 148 | unsigned int pci_last_busno; |
| 148 | struct pci_bus *pci_bus; | 149 | struct pci_bus *pci_bus; |
| 149 | void (*scan_bus)(struct pci_pbm_info *); | ||
| 150 | struct pci_ops *pci_ops; | 150 | struct pci_ops *pci_ops; |
| 151 | 151 | ||
| 152 | int numa_node; | 152 | int numa_node; |
| 153 | }; | 153 | }; |
| 154 | 154 | ||
| 155 | struct pci_controller_info { | ||
| 156 | /* The PCI bus modules controlled by us. */ | ||
| 157 | struct pci_pbm_info pbm_A; | ||
| 158 | struct pci_pbm_info pbm_B; | ||
| 159 | }; | ||
| 160 | |||
| 161 | extern struct pci_pbm_info *pci_pbm_root; | 155 | extern struct pci_pbm_info *pci_pbm_root; |
| 162 | 156 | ||
| 163 | extern int pci_num_pbms; | 157 | extern int pci_num_pbms; |
| 164 | 158 | ||
| 165 | /* PCI bus scanning and fixup support. */ | 159 | /* PCI bus scanning and fixup support. */ |
| 166 | extern void pci_get_pbm_props(struct pci_pbm_info *pbm); | 160 | extern void pci_get_pbm_props(struct pci_pbm_info *pbm); |
| 167 | extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); | 161 | extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, |
| 162 | struct device *parent); | ||
| 168 | extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); | 163 | extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); |
| 169 | 164 | ||
| 170 | /* Error reporting support. */ | 165 | /* Error reporting support. */ |
| @@ -183,4 +178,8 @@ extern void pci_config_write32(u32 *addr, u32 val); | |||
| 183 | extern struct pci_ops sun4u_pci_ops; | 178 | extern struct pci_ops sun4u_pci_ops; |
| 184 | extern struct pci_ops sun4v_pci_ops; | 179 | extern struct pci_ops sun4v_pci_ops; |
| 185 | 180 | ||
| 181 | extern volatile int pci_poke_in_progress; | ||
| 182 | extern volatile int pci_poke_cpu; | ||
| 183 | extern volatile int pci_poke_faulted; | ||
| 184 | |||
| 186 | #endif /* !(PCI_IMPL_H) */ | 185 | #endif /* !(PCI_IMPL_H) */ |
diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c index 60c71e350212..2e680f34f727 100644 --- a/arch/sparc64/kernel/pci_msi.c +++ b/arch/sparc64/kernel/pci_msi.c | |||
| @@ -323,7 +323,7 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, | |||
| 323 | const u32 *val; | 323 | const u32 *val; |
| 324 | int len; | 324 | int len; |
| 325 | 325 | ||
| 326 | val = of_get_property(pbm->prom_node, "#msi-eqs", &len); | 326 | val = of_get_property(pbm->op->node, "#msi-eqs", &len); |
| 327 | if (!val || len != 4) | 327 | if (!val || len != 4) |
| 328 | goto no_msi; | 328 | goto no_msi; |
| 329 | pbm->msiq_num = *val; | 329 | pbm->msiq_num = *val; |
| @@ -346,16 +346,16 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, | |||
| 346 | u32 msi64_len; | 346 | u32 msi64_len; |
| 347 | } *arng; | 347 | } *arng; |
| 348 | 348 | ||
| 349 | val = of_get_property(pbm->prom_node, "msi-eq-size", &len); | 349 | val = of_get_property(pbm->op->node, "msi-eq-size", &len); |
| 350 | if (!val || len != 4) | 350 | if (!val || len != 4) |
| 351 | goto no_msi; | 351 | goto no_msi; |
| 352 | 352 | ||
| 353 | pbm->msiq_ent_count = *val; | 353 | pbm->msiq_ent_count = *val; |
| 354 | 354 | ||
| 355 | mqp = of_get_property(pbm->prom_node, | 355 | mqp = of_get_property(pbm->op->node, |
| 356 | "msi-eq-to-devino", &len); | 356 | "msi-eq-to-devino", &len); |
| 357 | if (!mqp) | 357 | if (!mqp) |
| 358 | mqp = of_get_property(pbm->prom_node, | 358 | mqp = of_get_property(pbm->op->node, |
| 359 | "msi-eq-devino", &len); | 359 | "msi-eq-devino", &len); |
| 360 | if (!mqp || len != sizeof(struct msiq_prop)) | 360 | if (!mqp || len != sizeof(struct msiq_prop)) |
| 361 | goto no_msi; | 361 | goto no_msi; |
| @@ -363,27 +363,27 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, | |||
| 363 | pbm->msiq_first = mqp->first_msiq; | 363 | pbm->msiq_first = mqp->first_msiq; |
| 364 | pbm->msiq_first_devino = mqp->first_devino; | 364 | pbm->msiq_first_devino = mqp->first_devino; |
| 365 | 365 | ||
| 366 | val = of_get_property(pbm->prom_node, "#msi", &len); | 366 | val = of_get_property(pbm->op->node, "#msi", &len); |
| 367 | if (!val || len != 4) | 367 | if (!val || len != 4) |
| 368 | goto no_msi; | 368 | goto no_msi; |
| 369 | pbm->msi_num = *val; | 369 | pbm->msi_num = *val; |
| 370 | 370 | ||
| 371 | mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); | 371 | mrng = of_get_property(pbm->op->node, "msi-ranges", &len); |
| 372 | if (!mrng || len != sizeof(struct msi_range_prop)) | 372 | if (!mrng || len != sizeof(struct msi_range_prop)) |
| 373 | goto no_msi; | 373 | goto no_msi; |
| 374 | pbm->msi_first = mrng->first_msi; | 374 | pbm->msi_first = mrng->first_msi; |
| 375 | 375 | ||
| 376 | val = of_get_property(pbm->prom_node, "msi-data-mask", &len); | 376 | val = of_get_property(pbm->op->node, "msi-data-mask", &len); |
| 377 | if (!val || len != 4) | 377 | if (!val || len != 4) |
| 378 | goto no_msi; | 378 | goto no_msi; |
| 379 | pbm->msi_data_mask = *val; | 379 | pbm->msi_data_mask = *val; |
| 380 | 380 | ||
| 381 | val = of_get_property(pbm->prom_node, "msix-data-width", &len); | 381 | val = of_get_property(pbm->op->node, "msix-data-width", &len); |
| 382 | if (!val || len != 4) | 382 | if (!val || len != 4) |
| 383 | goto no_msi; | 383 | goto no_msi; |
| 384 | pbm->msix_data_width = *val; | 384 | pbm->msix_data_width = *val; |
| 385 | 385 | ||
| 386 | arng = of_get_property(pbm->prom_node, "msi-address-ranges", | 386 | arng = of_get_property(pbm->op->node, "msi-address-ranges", |
| 387 | &len); | 387 | &len); |
| 388 | if (!arng || len != sizeof(struct addr_range_prop)) | 388 | if (!arng || len != sizeof(struct addr_range_prop)) |
| 389 | goto no_msi; | 389 | goto no_msi; |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index ef5fe29202c2..dfb3ec892987 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
| @@ -17,29 +17,14 @@ | |||
| 17 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
| 18 | #include <asm/starfire.h> | 18 | #include <asm/starfire.h> |
| 19 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
| 20 | #include <asm/oplib.h> | 20 | #include <asm/upa.h> |
| 21 | 21 | ||
| 22 | #include "pci_impl.h" | 22 | #include "pci_impl.h" |
| 23 | #include "iommu_common.h" | 23 | #include "iommu_common.h" |
| 24 | #include "psycho_common.h" | ||
| 24 | 25 | ||
| 25 | /* All PSYCHO registers are 64-bits. The following accessor | 26 | #define DRIVER_NAME "psycho" |
| 26 | * routines are how they are accessed. The REG parameter | 27 | #define PFX DRIVER_NAME ": " |
| 27 | * is a physical address. | ||
| 28 | */ | ||
| 29 | #define psycho_read(__reg) \ | ||
| 30 | ({ u64 __ret; \ | ||
| 31 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
| 32 | : "=r" (__ret) \ | ||
| 33 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 34 | : "memory"); \ | ||
| 35 | __ret; \ | ||
| 36 | }) | ||
| 37 | #define psycho_write(__reg, __val) \ | ||
| 38 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
| 39 | : /* no outputs */ \ | ||
| 40 | : "r" (__val), "r" (__reg), \ | ||
| 41 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 42 | : "memory") | ||
| 43 | 28 | ||
| 44 | /* Misc. PSYCHO PCI controller register offsets and definitions. */ | 29 | /* Misc. PSYCHO PCI controller register offsets and definitions. */ |
| 45 | #define PSYCHO_CONTROL 0x0010UL | 30 | #define PSYCHO_CONTROL 0x0010UL |
| @@ -67,37 +52,7 @@ | |||
| 67 | #define PSYCHO_PCICTRL_RESV4 0x00000000000000c0UL /* Reserved */ | 52 | #define PSYCHO_PCICTRL_RESV4 0x00000000000000c0UL /* Reserved */ |
| 68 | #define PSYCHO_PCICTRL_AEN 0x000000000000003fUL /* PCI DVMA Arbitration Enable */ | 53 | #define PSYCHO_PCICTRL_AEN 0x000000000000003fUL /* PCI DVMA Arbitration Enable */ |
| 69 | 54 | ||
| 70 | /* U2P Programmer's Manual, page 13-55, configuration space | ||
| 71 | * address format: | ||
| 72 | * | ||
| 73 | * 32 24 23 16 15 11 10 8 7 2 1 0 | ||
| 74 | * --------------------------------------------------------- | ||
| 75 | * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | | ||
| 76 | * --------------------------------------------------------- | ||
| 77 | */ | ||
| 78 | #define PSYCHO_CONFIG_BASE(PBM) \ | ||
| 79 | ((PBM)->config_space | (1UL << 24)) | ||
| 80 | #define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG) \ | ||
| 81 | (((unsigned long)(BUS) << 16) | \ | ||
| 82 | ((unsigned long)(DEVFN) << 8) | \ | ||
| 83 | ((unsigned long)(REG))) | ||
| 84 | |||
| 85 | static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, | ||
| 86 | unsigned char bus, | ||
| 87 | unsigned int devfn, | ||
| 88 | int where) | ||
| 89 | { | ||
| 90 | if (!pbm) | ||
| 91 | return NULL; | ||
| 92 | return (void *) | ||
| 93 | (PSYCHO_CONFIG_BASE(pbm) | | ||
| 94 | PSYCHO_CONFIG_ENCODE(bus, devfn, where)); | ||
| 95 | } | ||
| 96 | |||
| 97 | /* PSYCHO error handling support. */ | 55 | /* PSYCHO error handling support. */ |
| 98 | enum psycho_error_type { | ||
| 99 | UE_ERR, CE_ERR, PCI_ERR | ||
| 100 | }; | ||
| 101 | 56 | ||
| 102 | /* Helper function of IOMMU error checking, which checks out | 57 | /* Helper function of IOMMU error checking, which checks out |
| 103 | * the state of the streaming buffers. The IOMMU lock is | 58 | * the state of the streaming buffers. The IOMMU lock is |
| @@ -122,129 +77,10 @@ enum psycho_error_type { | |||
| 122 | #define PSYCHO_STC_DATA_B 0xc000UL | 77 | #define PSYCHO_STC_DATA_B 0xc000UL |
| 123 | #define PSYCHO_STC_ERR_A 0xb400UL | 78 | #define PSYCHO_STC_ERR_A 0xb400UL |
| 124 | #define PSYCHO_STC_ERR_B 0xc400UL | 79 | #define PSYCHO_STC_ERR_B 0xc400UL |
| 125 | #define PSYCHO_STCERR_WRITE 0x0000000000000002UL /* Write Error */ | ||
| 126 | #define PSYCHO_STCERR_READ 0x0000000000000001UL /* Read Error */ | ||
| 127 | #define PSYCHO_STC_TAG_A 0xb800UL | 80 | #define PSYCHO_STC_TAG_A 0xb800UL |
| 128 | #define PSYCHO_STC_TAG_B 0xc800UL | 81 | #define PSYCHO_STC_TAG_B 0xc800UL |
| 129 | #define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL /* Physical Page Number */ | ||
| 130 | #define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL /* Virtual Page Number */ | ||
| 131 | #define PSYCHO_STCTAG_VALID 0x0000000000000002UL /* Valid */ | ||
| 132 | #define PSYCHO_STCTAG_WRITE 0x0000000000000001UL /* Writable */ | ||
| 133 | #define PSYCHO_STC_LINE_A 0xb900UL | 82 | #define PSYCHO_STC_LINE_A 0xb900UL |
| 134 | #define PSYCHO_STC_LINE_B 0xc900UL | 83 | #define PSYCHO_STC_LINE_B 0xc900UL |
| 135 | #define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL /* LRU Index */ | ||
| 136 | #define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL /* Dirty Data Start Pointer */ | ||
| 137 | #define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL /* Line Address */ | ||
| 138 | #define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL /* Dirty Data End Pointer */ | ||
| 139 | #define PSYCHO_STCLINE_VALID 0x0000000000000002UL /* Valid */ | ||
| 140 | #define PSYCHO_STCLINE_FOFN 0x0000000000000001UL /* Fetch Outstanding / Flush Necessary */ | ||
| 141 | |||
| 142 | static DEFINE_SPINLOCK(stc_buf_lock); | ||
| 143 | static unsigned long stc_error_buf[128]; | ||
| 144 | static unsigned long stc_tag_buf[16]; | ||
| 145 | static unsigned long stc_line_buf[16]; | ||
| 146 | |||
| 147 | static void __psycho_check_one_stc(struct pci_pbm_info *pbm, | ||
| 148 | int is_pbm_a) | ||
| 149 | { | ||
| 150 | struct strbuf *strbuf = &pbm->stc; | ||
| 151 | unsigned long regbase = pbm->controller_regs; | ||
| 152 | unsigned long err_base, tag_base, line_base; | ||
| 153 | u64 control; | ||
| 154 | int i; | ||
| 155 | |||
| 156 | if (is_pbm_a) { | ||
| 157 | err_base = regbase + PSYCHO_STC_ERR_A; | ||
| 158 | tag_base = regbase + PSYCHO_STC_TAG_A; | ||
| 159 | line_base = regbase + PSYCHO_STC_LINE_A; | ||
| 160 | } else { | ||
| 161 | err_base = regbase + PSYCHO_STC_ERR_B; | ||
| 162 | tag_base = regbase + PSYCHO_STC_TAG_B; | ||
| 163 | line_base = regbase + PSYCHO_STC_LINE_B; | ||
| 164 | } | ||
| 165 | |||
| 166 | spin_lock(&stc_buf_lock); | ||
| 167 | |||
| 168 | /* This is __REALLY__ dangerous. When we put the | ||
| 169 | * streaming buffer into diagnostic mode to probe | ||
| 170 | * it's tags and error status, we _must_ clear all | ||
| 171 | * of the line tag valid bits before re-enabling | ||
| 172 | * the streaming buffer. If any dirty data lives | ||
| 173 | * in the STC when we do this, we will end up | ||
| 174 | * invalidating it before it has a chance to reach | ||
| 175 | * main memory. | ||
| 176 | */ | ||
| 177 | control = psycho_read(strbuf->strbuf_control); | ||
| 178 | psycho_write(strbuf->strbuf_control, | ||
| 179 | (control | PSYCHO_STRBUF_CTRL_DENAB)); | ||
| 180 | for (i = 0; i < 128; i++) { | ||
| 181 | unsigned long val; | ||
| 182 | |||
| 183 | val = psycho_read(err_base + (i * 8UL)); | ||
| 184 | psycho_write(err_base + (i * 8UL), 0UL); | ||
| 185 | stc_error_buf[i] = val; | ||
| 186 | } | ||
| 187 | for (i = 0; i < 16; i++) { | ||
| 188 | stc_tag_buf[i] = psycho_read(tag_base + (i * 8UL)); | ||
| 189 | stc_line_buf[i] = psycho_read(line_base + (i * 8UL)); | ||
| 190 | psycho_write(tag_base + (i * 8UL), 0UL); | ||
| 191 | psycho_write(line_base + (i * 8UL), 0UL); | ||
| 192 | } | ||
| 193 | |||
| 194 | /* OK, state is logged, exit diagnostic mode. */ | ||
| 195 | psycho_write(strbuf->strbuf_control, control); | ||
| 196 | |||
| 197 | for (i = 0; i < 16; i++) { | ||
| 198 | int j, saw_error, first, last; | ||
| 199 | |||
| 200 | saw_error = 0; | ||
| 201 | first = i * 8; | ||
| 202 | last = first + 8; | ||
| 203 | for (j = first; j < last; j++) { | ||
| 204 | unsigned long errval = stc_error_buf[j]; | ||
| 205 | if (errval != 0) { | ||
| 206 | saw_error++; | ||
| 207 | printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n", | ||
| 208 | pbm->name, | ||
| 209 | j, | ||
| 210 | (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, | ||
| 211 | (errval & PSYCHO_STCERR_READ) ? 1 : 0); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | if (saw_error != 0) { | ||
| 215 | unsigned long tagval = stc_tag_buf[i]; | ||
| 216 | unsigned long lineval = stc_line_buf[i]; | ||
| 217 | printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", | ||
| 218 | pbm->name, | ||
| 219 | i, | ||
| 220 | ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), | ||
| 221 | (tagval & PSYCHO_STCTAG_VPN), | ||
| 222 | ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), | ||
| 223 | ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); | ||
| 224 | printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" | ||
| 225 | "V(%d)FOFN(%d)]\n", | ||
| 226 | pbm->name, | ||
| 227 | i, | ||
| 228 | ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), | ||
| 229 | ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), | ||
| 230 | ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), | ||
| 231 | ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), | ||
| 232 | ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), | ||
| 233 | ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | spin_unlock(&stc_buf_lock); | ||
| 238 | } | ||
| 239 | |||
| 240 | static void __psycho_check_stc_error(struct pci_pbm_info *pbm, | ||
| 241 | unsigned long afsr, | ||
| 242 | unsigned long afar, | ||
| 243 | enum psycho_error_type type) | ||
| 244 | { | ||
| 245 | __psycho_check_one_stc(pbm, | ||
| 246 | (pbm == &pbm->parent->pbm_A)); | ||
| 247 | } | ||
| 248 | 84 | ||
| 249 | /* When an Uncorrectable Error or a PCI Error happens, we | 85 | /* When an Uncorrectable Error or a PCI Error happens, we |
| 250 | * interrogate the IOMMU state to see if it is the cause. | 86 | * interrogate the IOMMU state to see if it is the cause. |
| @@ -271,122 +107,7 @@ static void __psycho_check_stc_error(struct pci_pbm_info *pbm, | |||
| 271 | #define PSYCHO_IOMMU_TSBBASE 0x0208UL | 107 | #define PSYCHO_IOMMU_TSBBASE 0x0208UL |
| 272 | #define PSYCHO_IOMMU_FLUSH 0x0210UL | 108 | #define PSYCHO_IOMMU_FLUSH 0x0210UL |
| 273 | #define PSYCHO_IOMMU_TAG 0xa580UL | 109 | #define PSYCHO_IOMMU_TAG 0xa580UL |
| 274 | #define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) | ||
| 275 | #define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) | ||
| 276 | #define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) | ||
| 277 | #define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) | ||
| 278 | #define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) | ||
| 279 | #define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL | ||
| 280 | #define PSYCHO_IOMMU_DATA 0xa600UL | 110 | #define PSYCHO_IOMMU_DATA 0xa600UL |
| 281 | #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) | ||
| 282 | #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) | ||
| 283 | #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL | ||
| 284 | static void psycho_check_iommu_error(struct pci_pbm_info *pbm, | ||
| 285 | unsigned long afsr, | ||
| 286 | unsigned long afar, | ||
| 287 | enum psycho_error_type type) | ||
| 288 | { | ||
| 289 | struct iommu *iommu = pbm->iommu; | ||
| 290 | unsigned long iommu_tag[16]; | ||
| 291 | unsigned long iommu_data[16]; | ||
| 292 | unsigned long flags; | ||
| 293 | u64 control; | ||
| 294 | int i; | ||
| 295 | |||
| 296 | spin_lock_irqsave(&iommu->lock, flags); | ||
| 297 | control = psycho_read(iommu->iommu_control); | ||
| 298 | if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { | ||
| 299 | char *type_string; | ||
| 300 | |||
| 301 | /* Clear the error encountered bit. */ | ||
| 302 | control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; | ||
| 303 | psycho_write(iommu->iommu_control, control); | ||
| 304 | |||
| 305 | switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { | ||
| 306 | case 0: | ||
| 307 | type_string = "Protection Error"; | ||
| 308 | break; | ||
| 309 | case 1: | ||
| 310 | type_string = "Invalid Error"; | ||
| 311 | break; | ||
| 312 | case 2: | ||
| 313 | type_string = "TimeOut Error"; | ||
| 314 | break; | ||
| 315 | case 3: | ||
| 316 | default: | ||
| 317 | type_string = "ECC Error"; | ||
| 318 | break; | ||
| 319 | }; | ||
| 320 | printk("%s: IOMMU Error, type[%s]\n", | ||
| 321 | pbm->name, type_string); | ||
| 322 | |||
| 323 | /* Put the IOMMU into diagnostic mode and probe | ||
| 324 | * it's TLB for entries with error status. | ||
| 325 | * | ||
| 326 | * It is very possible for another DVMA to occur | ||
| 327 | * while we do this probe, and corrupt the system | ||
| 328 | * further. But we are so screwed at this point | ||
| 329 | * that we are likely to crash hard anyways, so | ||
| 330 | * get as much diagnostic information to the | ||
| 331 | * console as we can. | ||
| 332 | */ | ||
| 333 | psycho_write(iommu->iommu_control, | ||
| 334 | control | PSYCHO_IOMMU_CTRL_DENAB); | ||
| 335 | for (i = 0; i < 16; i++) { | ||
| 336 | unsigned long base = pbm->controller_regs; | ||
| 337 | |||
| 338 | iommu_tag[i] = | ||
| 339 | psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); | ||
| 340 | iommu_data[i] = | ||
| 341 | psycho_read(base + PSYCHO_IOMMU_DATA + (i * 8UL)); | ||
| 342 | |||
| 343 | /* Now clear out the entry. */ | ||
| 344 | psycho_write(base + PSYCHO_IOMMU_TAG + (i * 8UL), 0); | ||
| 345 | psycho_write(base + PSYCHO_IOMMU_DATA + (i * 8UL), 0); | ||
| 346 | } | ||
| 347 | |||
| 348 | /* Leave diagnostic mode. */ | ||
| 349 | psycho_write(iommu->iommu_control, control); | ||
| 350 | |||
| 351 | for (i = 0; i < 16; i++) { | ||
| 352 | unsigned long tag, data; | ||
| 353 | |||
| 354 | tag = iommu_tag[i]; | ||
| 355 | if (!(tag & PSYCHO_IOMMU_TAG_ERR)) | ||
| 356 | continue; | ||
| 357 | |||
| 358 | data = iommu_data[i]; | ||
| 359 | switch((tag & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { | ||
| 360 | case 0: | ||
| 361 | type_string = "Protection Error"; | ||
| 362 | break; | ||
| 363 | case 1: | ||
| 364 | type_string = "Invalid Error"; | ||
| 365 | break; | ||
| 366 | case 2: | ||
| 367 | type_string = "TimeOut Error"; | ||
| 368 | break; | ||
| 369 | case 3: | ||
| 370 | default: | ||
| 371 | type_string = "ECC Error"; | ||
| 372 | break; | ||
| 373 | }; | ||
| 374 | printk("%s: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", | ||
| 375 | pbm->name, i, type_string, | ||
| 376 | ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), | ||
| 377 | ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), | ||
| 378 | ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), | ||
| 379 | (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); | ||
| 380 | printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", | ||
| 381 | pbm->name, i, | ||
| 382 | ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), | ||
| 383 | ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), | ||
| 384 | (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); | ||
| 385 | } | ||
| 386 | } | ||
| 387 | __psycho_check_stc_error(pbm, afsr, afar, type); | ||
| 388 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
| 389 | } | ||
| 390 | 111 | ||
| 391 | /* Uncorrectable Errors. Cause of the error and the address are | 112 | /* Uncorrectable Errors. Cause of the error and the address are |
| 392 | * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors | 113 | * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors |
| @@ -410,15 +131,14 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, | |||
| 410 | static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | 131 | static irqreturn_t psycho_ue_intr(int irq, void *dev_id) |
| 411 | { | 132 | { |
| 412 | struct pci_pbm_info *pbm = dev_id; | 133 | struct pci_pbm_info *pbm = dev_id; |
| 413 | struct pci_controller_info *p = pbm->parent; | ||
| 414 | unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; | 134 | unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; |
| 415 | unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; | 135 | unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; |
| 416 | unsigned long afsr, afar, error_bits; | 136 | unsigned long afsr, afar, error_bits; |
| 417 | int reported; | 137 | int reported; |
| 418 | 138 | ||
| 419 | /* Latch uncorrectable error status. */ | 139 | /* Latch uncorrectable error status. */ |
| 420 | afar = psycho_read(afar_reg); | 140 | afar = upa_readq(afar_reg); |
| 421 | afsr = psycho_read(afsr_reg); | 141 | afsr = upa_readq(afsr_reg); |
| 422 | 142 | ||
| 423 | /* Clear the primary/secondary error status bits. */ | 143 | /* Clear the primary/secondary error status bits. */ |
| 424 | error_bits = afsr & | 144 | error_bits = afsr & |
| @@ -426,7 +146,7 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | |||
| 426 | PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR); | 146 | PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR); |
| 427 | if (!error_bits) | 147 | if (!error_bits) |
| 428 | return IRQ_NONE; | 148 | return IRQ_NONE; |
| 429 | psycho_write(afsr_reg, error_bits); | 149 | upa_writeq(error_bits, afsr_reg); |
| 430 | 150 | ||
| 431 | /* Log the error. */ | 151 | /* Log the error. */ |
| 432 | printk("%s: Uncorrectable Error, primary error type[%s]\n", | 152 | printk("%s: Uncorrectable Error, primary error type[%s]\n", |
| @@ -463,8 +183,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | |||
| 463 | printk("]\n"); | 183 | printk("]\n"); |
| 464 | 184 | ||
| 465 | /* Interrogate both IOMMUs for error status. */ | 185 | /* Interrogate both IOMMUs for error status. */ |
| 466 | psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); | 186 | psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); |
| 467 | psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); | 187 | if (pbm->sibling) |
| 188 | psycho_check_iommu_error(pbm->sibling, afsr, afar, UE_ERR); | ||
| 468 | 189 | ||
| 469 | return IRQ_HANDLED; | 190 | return IRQ_HANDLED; |
| 470 | } | 191 | } |
| @@ -495,8 +216,8 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) | |||
| 495 | int reported; | 216 | int reported; |
| 496 | 217 | ||
| 497 | /* Latch error status. */ | 218 | /* Latch error status. */ |
| 498 | afar = psycho_read(afar_reg); | 219 | afar = upa_readq(afar_reg); |
| 499 | afsr = psycho_read(afsr_reg); | 220 | afsr = upa_readq(afsr_reg); |
| 500 | 221 | ||
| 501 | /* Clear primary/secondary error status bits. */ | 222 | /* Clear primary/secondary error status bits. */ |
| 502 | error_bits = afsr & | 223 | error_bits = afsr & |
| @@ -504,7 +225,7 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) | |||
| 504 | PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR); | 225 | PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR); |
| 505 | if (!error_bits) | 226 | if (!error_bits) |
| 506 | return IRQ_NONE; | 227 | return IRQ_NONE; |
| 507 | psycho_write(afsr_reg, error_bits); | 228 | upa_writeq(error_bits, afsr_reg); |
| 508 | 229 | ||
| 509 | /* Log the error. */ | 230 | /* Log the error. */ |
| 510 | printk("%s: Correctable Error, primary error type[%s]\n", | 231 | printk("%s: Correctable Error, primary error type[%s]\n", |
| @@ -554,162 +275,9 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) | |||
| 554 | */ | 275 | */ |
| 555 | #define PSYCHO_PCI_AFSR_A 0x2010UL | 276 | #define PSYCHO_PCI_AFSR_A 0x2010UL |
| 556 | #define PSYCHO_PCI_AFSR_B 0x4010UL | 277 | #define PSYCHO_PCI_AFSR_B 0x4010UL |
| 557 | #define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL /* Primary Master Abort Error */ | ||
| 558 | #define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL /* Primary Target Abort Error */ | ||
| 559 | #define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */ | ||
| 560 | #define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */ | ||
| 561 | #define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort Error */ | ||
| 562 | #define PSYCHO_PCIAFSR_STA 0x0400000000000000UL /* Secondary Target Abort Error */ | ||
| 563 | #define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */ | ||
| 564 | #define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */ | ||
| 565 | #define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL /* Reserved */ | ||
| 566 | #define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ | ||
| 567 | #define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL /* Trans was block operation */ | ||
| 568 | #define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL /* Reserved */ | ||
| 569 | #define PSYCHO_PCIAFSR_MID 0x000000003e000000UL /* MID causing the error */ | ||
| 570 | #define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL /* Reserved */ | ||
| 571 | #define PSYCHO_PCI_AFAR_A 0x2018UL | 278 | #define PSYCHO_PCI_AFAR_A 0x2018UL |
| 572 | #define PSYCHO_PCI_AFAR_B 0x4018UL | 279 | #define PSYCHO_PCI_AFAR_B 0x4018UL |
| 573 | 280 | ||
| 574 | static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm_a) | ||
| 575 | { | ||
| 576 | unsigned long csr_reg, csr, csr_error_bits; | ||
| 577 | irqreturn_t ret = IRQ_NONE; | ||
| 578 | u16 stat; | ||
| 579 | |||
| 580 | if (is_pbm_a) { | ||
| 581 | csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL; | ||
| 582 | } else { | ||
| 583 | csr_reg = pbm->controller_regs + PSYCHO_PCIB_CTRL; | ||
| 584 | } | ||
| 585 | csr = psycho_read(csr_reg); | ||
| 586 | csr_error_bits = | ||
| 587 | csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); | ||
| 588 | if (csr_error_bits) { | ||
| 589 | /* Clear the errors. */ | ||
| 590 | psycho_write(csr_reg, csr); | ||
| 591 | |||
| 592 | /* Log 'em. */ | ||
| 593 | if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) | ||
| 594 | printk("%s: PCI streaming byte hole error asserted.\n", | ||
| 595 | pbm->name); | ||
| 596 | if (csr_error_bits & PSYCHO_PCICTRL_SERR) | ||
| 597 | printk("%s: PCI SERR signal asserted.\n", pbm->name); | ||
| 598 | ret = IRQ_HANDLED; | ||
| 599 | } | ||
| 600 | pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); | ||
| 601 | if (stat & (PCI_STATUS_PARITY | | ||
| 602 | PCI_STATUS_SIG_TARGET_ABORT | | ||
| 603 | PCI_STATUS_REC_TARGET_ABORT | | ||
| 604 | PCI_STATUS_REC_MASTER_ABORT | | ||
| 605 | PCI_STATUS_SIG_SYSTEM_ERROR)) { | ||
| 606 | printk("%s: PCI bus error, PCI_STATUS[%04x]\n", | ||
| 607 | pbm->name, stat); | ||
| 608 | pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); | ||
| 609 | ret = IRQ_HANDLED; | ||
| 610 | } | ||
| 611 | return ret; | ||
| 612 | } | ||
| 613 | |||
| 614 | static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | ||
| 615 | { | ||
| 616 | struct pci_pbm_info *pbm = dev_id; | ||
| 617 | struct pci_controller_info *p = pbm->parent; | ||
| 618 | unsigned long afsr_reg, afar_reg; | ||
| 619 | unsigned long afsr, afar, error_bits; | ||
| 620 | int is_pbm_a, reported; | ||
| 621 | |||
| 622 | is_pbm_a = (pbm == &pbm->parent->pbm_A); | ||
| 623 | if (is_pbm_a) { | ||
| 624 | afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A; | ||
| 625 | afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A; | ||
| 626 | } else { | ||
| 627 | afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B; | ||
| 628 | afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B; | ||
| 629 | } | ||
| 630 | |||
| 631 | /* Latch error status. */ | ||
| 632 | afar = psycho_read(afar_reg); | ||
| 633 | afsr = psycho_read(afsr_reg); | ||
| 634 | |||
| 635 | /* Clear primary/secondary error status bits. */ | ||
| 636 | error_bits = afsr & | ||
| 637 | (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | | ||
| 638 | PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | | ||
| 639 | PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | | ||
| 640 | PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); | ||
| 641 | if (!error_bits) | ||
| 642 | return psycho_pcierr_intr_other(pbm, is_pbm_a); | ||
| 643 | psycho_write(afsr_reg, error_bits); | ||
| 644 | |||
| 645 | /* Log the error. */ | ||
| 646 | printk("%s: PCI Error, primary error type[%s]\n", | ||
| 647 | pbm->name, | ||
| 648 | (((error_bits & PSYCHO_PCIAFSR_PMA) ? | ||
| 649 | "Master Abort" : | ||
| 650 | ((error_bits & PSYCHO_PCIAFSR_PTA) ? | ||
| 651 | "Target Abort" : | ||
| 652 | ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? | ||
| 653 | "Excessive Retries" : | ||
| 654 | ((error_bits & PSYCHO_PCIAFSR_PPERR) ? | ||
| 655 | "Parity Error" : "???")))))); | ||
| 656 | printk("%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", | ||
| 657 | pbm->name, | ||
| 658 | (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, | ||
| 659 | (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, | ||
| 660 | (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); | ||
| 661 | printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); | ||
| 662 | printk("%s: PCI Secondary errors [", pbm->name); | ||
| 663 | reported = 0; | ||
| 664 | if (afsr & PSYCHO_PCIAFSR_SMA) { | ||
| 665 | reported++; | ||
| 666 | printk("(Master Abort)"); | ||
| 667 | } | ||
| 668 | if (afsr & PSYCHO_PCIAFSR_STA) { | ||
| 669 | reported++; | ||
| 670 | printk("(Target Abort)"); | ||
| 671 | } | ||
| 672 | if (afsr & PSYCHO_PCIAFSR_SRTRY) { | ||
| 673 | reported++; | ||
| 674 | printk("(Excessive Retries)"); | ||
| 675 | } | ||
| 676 | if (afsr & PSYCHO_PCIAFSR_SPERR) { | ||
| 677 | reported++; | ||
| 678 | printk("(Parity Error)"); | ||
| 679 | } | ||
| 680 | if (!reported) | ||
| 681 | printk("(none)"); | ||
| 682 | printk("]\n"); | ||
| 683 | |||
| 684 | /* For the error types shown, scan PBM's PCI bus for devices | ||
| 685 | * which have logged that error type. | ||
| 686 | */ | ||
| 687 | |||
| 688 | /* If we see a Target Abort, this could be the result of an | ||
| 689 | * IOMMU translation error of some sort. It is extremely | ||
| 690 | * useful to log this information as usually it indicates | ||
| 691 | * a bug in the IOMMU support code or a PCI device driver. | ||
| 692 | */ | ||
| 693 | if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { | ||
| 694 | psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); | ||
| 695 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | ||
| 696 | } | ||
| 697 | if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) | ||
| 698 | pci_scan_for_master_abort(pbm, pbm->pci_bus); | ||
| 699 | |||
| 700 | /* For excessive retries, PSYCHO/PBM will abort the device | ||
| 701 | * and there is no way to specifically check for excessive | ||
| 702 | * retries in the config space status registers. So what | ||
| 703 | * we hope is that we'll catch it via the master/target | ||
| 704 | * abort events. | ||
| 705 | */ | ||
| 706 | |||
| 707 | if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) | ||
| 708 | pci_scan_for_parity_error(pbm, pbm->pci_bus); | ||
| 709 | |||
| 710 | return IRQ_HANDLED; | ||
| 711 | } | ||
| 712 | |||
| 713 | /* XXX What about PowerFail/PowerManagement??? -DaveM */ | 281 | /* XXX What about PowerFail/PowerManagement??? -DaveM */ |
| 714 | #define PSYCHO_ECC_CTRL 0x0020 | 282 | #define PSYCHO_ECC_CTRL 0x0020 |
| 715 | #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ | 283 | #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ |
| @@ -717,7 +285,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | |||
| 717 | #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ | 285 | #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ |
| 718 | static void psycho_register_error_handlers(struct pci_pbm_info *pbm) | 286 | static void psycho_register_error_handlers(struct pci_pbm_info *pbm) |
| 719 | { | 287 | { |
| 720 | struct of_device *op = of_find_device_by_node(pbm->prom_node); | 288 | struct of_device *op = of_find_device_by_node(pbm->op->node); |
| 721 | unsigned long base = pbm->controller_regs; | 289 | unsigned long base = pbm->controller_regs; |
| 722 | u64 tmp; | 290 | u64 tmp; |
| 723 | int err; | 291 | int err; |
| @@ -744,43 +312,42 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 744 | * the second will just error out since we do not pass in | 312 | * the second will just error out since we do not pass in |
| 745 | * IRQF_SHARED. | 313 | * IRQF_SHARED. |
| 746 | */ | 314 | */ |
| 747 | err = request_irq(op->irqs[1], psycho_ue_intr, 0, | 315 | err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, |
| 748 | "PSYCHO_UE", pbm); | 316 | "PSYCHO_UE", pbm); |
| 749 | err = request_irq(op->irqs[2], psycho_ce_intr, 0, | 317 | err = request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, |
| 750 | "PSYCHO_CE", pbm); | 318 | "PSYCHO_CE", pbm); |
| 751 | 319 | ||
| 752 | /* This one, however, ought not to fail. We can just warn | 320 | /* This one, however, ought not to fail. We can just warn |
| 753 | * about it since the system can still operate properly even | 321 | * about it since the system can still operate properly even |
| 754 | * if this fails. | 322 | * if this fails. |
| 755 | */ | 323 | */ |
| 756 | err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, | 324 | err = request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED, |
| 757 | "PSYCHO_PCIERR", pbm); | 325 | "PSYCHO_PCIERR", pbm); |
| 758 | if (err) | 326 | if (err) |
| 759 | printk(KERN_WARNING "%s: Could not register PCIERR, " | 327 | printk(KERN_WARNING "%s: Could not register PCIERR, " |
| 760 | "err=%d\n", pbm->name, err); | 328 | "err=%d\n", pbm->name, err); |
| 761 | 329 | ||
| 762 | /* Enable UE and CE interrupts for controller. */ | 330 | /* Enable UE and CE interrupts for controller. */ |
| 763 | psycho_write(base + PSYCHO_ECC_CTRL, | 331 | upa_writeq((PSYCHO_ECCCTRL_EE | |
| 764 | (PSYCHO_ECCCTRL_EE | | 332 | PSYCHO_ECCCTRL_UE | |
| 765 | PSYCHO_ECCCTRL_UE | | 333 | PSYCHO_ECCCTRL_CE), base + PSYCHO_ECC_CTRL); |
| 766 | PSYCHO_ECCCTRL_CE)); | ||
| 767 | 334 | ||
| 768 | /* Enable PCI Error interrupts and clear error | 335 | /* Enable PCI Error interrupts and clear error |
| 769 | * bits for each PBM. | 336 | * bits for each PBM. |
| 770 | */ | 337 | */ |
| 771 | tmp = psycho_read(base + PSYCHO_PCIA_CTRL); | 338 | tmp = upa_readq(base + PSYCHO_PCIA_CTRL); |
| 772 | tmp |= (PSYCHO_PCICTRL_SERR | | 339 | tmp |= (PSYCHO_PCICTRL_SERR | |
| 773 | PSYCHO_PCICTRL_SBH_ERR | | 340 | PSYCHO_PCICTRL_SBH_ERR | |
| 774 | PSYCHO_PCICTRL_EEN); | 341 | PSYCHO_PCICTRL_EEN); |
| 775 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); | 342 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); |
| 776 | psycho_write(base + PSYCHO_PCIA_CTRL, tmp); | 343 | upa_writeq(tmp, base + PSYCHO_PCIA_CTRL); |
| 777 | 344 | ||
| 778 | tmp = psycho_read(base + PSYCHO_PCIB_CTRL); | 345 | tmp = upa_readq(base + PSYCHO_PCIB_CTRL); |
| 779 | tmp |= (PSYCHO_PCICTRL_SERR | | 346 | tmp |= (PSYCHO_PCICTRL_SERR | |
| 780 | PSYCHO_PCICTRL_SBH_ERR | | 347 | PSYCHO_PCICTRL_SBH_ERR | |
| 781 | PSYCHO_PCICTRL_EEN); | 348 | PSYCHO_PCICTRL_EEN); |
| 782 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); | 349 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); |
| 783 | psycho_write(base + PSYCHO_PCIB_CTRL, tmp); | 350 | upa_writeq(tmp, base + PSYCHO_PCIB_CTRL); |
| 784 | } | 351 | } |
| 785 | 352 | ||
| 786 | /* PSYCHO boot time probing and initialization. */ | 353 | /* PSYCHO boot time probing and initialization. */ |
| @@ -801,11 +368,12 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) | |||
| 801 | pci_config_write8(addr, 64); | 368 | pci_config_write8(addr, 64); |
| 802 | } | 369 | } |
| 803 | 370 | ||
| 804 | static void __init psycho_scan_bus(struct pci_pbm_info *pbm) | 371 | static void __init psycho_scan_bus(struct pci_pbm_info *pbm, |
| 372 | struct device *parent) | ||
| 805 | { | 373 | { |
| 806 | pbm_config_busmastering(pbm); | 374 | pbm_config_busmastering(pbm); |
| 807 | pbm->is_66mhz_capable = 0; | 375 | pbm->is_66mhz_capable = 0; |
| 808 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 376 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
| 809 | 377 | ||
| 810 | /* After the PCI bus scan is complete, we can register | 378 | /* After the PCI bus scan is complete, we can register |
| 811 | * the error interrupt handlers. | 379 | * the error interrupt handlers. |
| @@ -813,61 +381,6 @@ static void __init psycho_scan_bus(struct pci_pbm_info *pbm) | |||
| 813 | psycho_register_error_handlers(pbm); | 381 | psycho_register_error_handlers(pbm); |
| 814 | } | 382 | } |
| 815 | 383 | ||
| 816 | static int psycho_iommu_init(struct pci_pbm_info *pbm) | ||
| 817 | { | ||
| 818 | struct iommu *iommu = pbm->iommu; | ||
| 819 | unsigned long i; | ||
| 820 | u64 control; | ||
| 821 | int err; | ||
| 822 | |||
| 823 | /* Register addresses. */ | ||
| 824 | iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; | ||
| 825 | iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; | ||
| 826 | iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; | ||
| 827 | iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); | ||
| 828 | |||
| 829 | /* PSYCHO's IOMMU lacks ctx flushing. */ | ||
| 830 | iommu->iommu_ctxflush = 0; | ||
| 831 | |||
| 832 | /* We use the main control register of PSYCHO as the write | ||
| 833 | * completion register. | ||
| 834 | */ | ||
| 835 | iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL; | ||
| 836 | |||
| 837 | /* | ||
| 838 | * Invalidate TLB Entries. | ||
| 839 | */ | ||
| 840 | control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); | ||
| 841 | control |= PSYCHO_IOMMU_CTRL_DENAB; | ||
| 842 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); | ||
| 843 | for(i = 0; i < 16; i++) { | ||
| 844 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); | ||
| 845 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); | ||
| 846 | } | ||
| 847 | |||
| 848 | /* Leave diag mode enabled for full-flushing done | ||
| 849 | * in pci_iommu.c | ||
| 850 | */ | ||
| 851 | err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, | ||
| 852 | pbm->numa_node); | ||
| 853 | if (err) | ||
| 854 | return err; | ||
| 855 | |||
| 856 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, | ||
| 857 | __pa(iommu->page_table)); | ||
| 858 | |||
| 859 | control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); | ||
| 860 | control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); | ||
| 861 | control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); | ||
| 862 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); | ||
| 863 | |||
| 864 | /* If necessary, hook us up for starfire IRQ translations. */ | ||
| 865 | if (this_is_starfire) | ||
| 866 | starfire_hookup(pbm->portid); | ||
| 867 | |||
| 868 | return 0; | ||
| 869 | } | ||
| 870 | |||
| 871 | #define PSYCHO_IRQ_RETRY 0x1a00UL | 384 | #define PSYCHO_IRQ_RETRY 0x1a00UL |
| 872 | #define PSYCHO_PCIA_DIAG 0x2020UL | 385 | #define PSYCHO_PCIA_DIAG 0x2020UL |
| 873 | #define PSYCHO_PCIB_DIAG 0x4020UL | 386 | #define PSYCHO_PCIB_DIAG 0x4020UL |
| @@ -884,28 +397,28 @@ static void psycho_controller_hwinit(struct pci_pbm_info *pbm) | |||
| 884 | { | 397 | { |
| 885 | u64 tmp; | 398 | u64 tmp; |
| 886 | 399 | ||
| 887 | psycho_write(pbm->controller_regs + PSYCHO_IRQ_RETRY, 5); | 400 | upa_writeq(5, pbm->controller_regs + PSYCHO_IRQ_RETRY); |
| 888 | 401 | ||
| 889 | /* Enable arbiter for all PCI slots. */ | 402 | /* Enable arbiter for all PCI slots. */ |
| 890 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_CTRL); | 403 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_CTRL); |
| 891 | tmp |= PSYCHO_PCICTRL_AEN; | 404 | tmp |= PSYCHO_PCICTRL_AEN; |
| 892 | psycho_write(pbm->controller_regs + PSYCHO_PCIA_CTRL, tmp); | 405 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_CTRL); |
| 893 | 406 | ||
| 894 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_CTRL); | 407 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_CTRL); |
| 895 | tmp |= PSYCHO_PCICTRL_AEN; | 408 | tmp |= PSYCHO_PCICTRL_AEN; |
| 896 | psycho_write(pbm->controller_regs + PSYCHO_PCIB_CTRL, tmp); | 409 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_CTRL); |
| 897 | 410 | ||
| 898 | /* Disable DMA write / PIO read synchronization on | 411 | /* Disable DMA write / PIO read synchronization on |
| 899 | * both PCI bus segments. | 412 | * both PCI bus segments. |
| 900 | * [ U2P Erratum 1243770, STP2223BGA data sheet ] | 413 | * [ U2P Erratum 1243770, STP2223BGA data sheet ] |
| 901 | */ | 414 | */ |
| 902 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_DIAG); | 415 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_DIAG); |
| 903 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; | 416 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; |
| 904 | psycho_write(pbm->controller_regs + PSYCHO_PCIA_DIAG, tmp); | 417 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_DIAG); |
| 905 | 418 | ||
| 906 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_DIAG); | 419 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_DIAG); |
| 907 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; | 420 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; |
| 908 | psycho_write(pbm->controller_regs + PSYCHO_PCIB_DIAG, tmp); | 421 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_DIAG); |
| 909 | } | 422 | } |
| 910 | 423 | ||
| 911 | static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | 424 | static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, |
| @@ -918,10 +431,16 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
| 918 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; | 431 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; |
| 919 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; | 432 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; |
| 920 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; | 433 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; |
| 434 | pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_A; | ||
| 435 | pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_A; | ||
| 436 | pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_A; | ||
| 921 | } else { | 437 | } else { |
| 922 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; | 438 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; |
| 923 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; | 439 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; |
| 924 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; | 440 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; |
| 441 | pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_B; | ||
| 442 | pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_B; | ||
| 443 | pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_B; | ||
| 925 | } | 444 | } |
| 926 | /* PSYCHO's streaming buffer lacks ctx flushing. */ | 445 | /* PSYCHO's streaming buffer lacks ctx flushing. */ |
| 927 | pbm->stc.strbuf_ctxflush = 0; | 446 | pbm->stc.strbuf_ctxflush = 0; |
| @@ -944,7 +463,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
| 944 | */ | 463 | */ |
| 945 | #undef PSYCHO_STRBUF_RERUN_ENABLE | 464 | #undef PSYCHO_STRBUF_RERUN_ENABLE |
| 946 | #undef PSYCHO_STRBUF_RERUN_DISABLE | 465 | #undef PSYCHO_STRBUF_RERUN_DISABLE |
| 947 | control = psycho_read(pbm->stc.strbuf_control); | 466 | control = upa_readq(pbm->stc.strbuf_control); |
| 948 | control |= PSYCHO_STRBUF_CTRL_ENAB; | 467 | control |= PSYCHO_STRBUF_CTRL_ENAB; |
| 949 | control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); | 468 | control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); |
| 950 | #ifdef PSYCHO_STRBUF_RERUN_ENABLE | 469 | #ifdef PSYCHO_STRBUF_RERUN_ENABLE |
| @@ -954,7 +473,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
| 954 | control |= PSYCHO_STRBUF_CTRL_RRDIS; | 473 | control |= PSYCHO_STRBUF_CTRL_RRDIS; |
| 955 | #endif | 474 | #endif |
| 956 | #endif | 475 | #endif |
| 957 | psycho_write(pbm->stc.strbuf_control, control); | 476 | upa_writeq(control, pbm->stc.strbuf_control); |
| 958 | 477 | ||
| 959 | pbm->stc.strbuf_enabled = 1; | 478 | pbm->stc.strbuf_enabled = 1; |
| 960 | } | 479 | } |
| @@ -966,111 +485,134 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
| 966 | #define PSYCHO_MEMSPACE_B 0x180000000UL | 485 | #define PSYCHO_MEMSPACE_B 0x180000000UL |
| 967 | #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL | 486 | #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL |
| 968 | 487 | ||
| 969 | static void __init psycho_pbm_init(struct pci_controller_info *p, | 488 | static void __init psycho_pbm_init(struct pci_pbm_info *pbm, |
| 970 | struct device_node *dp, int is_pbm_a) | 489 | struct of_device *op, int is_pbm_a) |
| 971 | { | 490 | { |
| 972 | struct property *prop; | 491 | psycho_pbm_init_common(pbm, op, "PSYCHO", PBM_CHIP_TYPE_PSYCHO); |
| 973 | struct pci_pbm_info *pbm; | 492 | psycho_pbm_strbuf_init(pbm, is_pbm_a); |
| 974 | 493 | psycho_scan_bus(pbm, &op->dev); | |
| 975 | if (is_pbm_a) | 494 | } |
| 976 | pbm = &p->pbm_A; | ||
| 977 | else | ||
| 978 | pbm = &p->pbm_B; | ||
| 979 | |||
| 980 | pbm->next = pci_pbm_root; | ||
| 981 | pci_pbm_root = pbm; | ||
| 982 | |||
| 983 | pbm->numa_node = -1; | ||
| 984 | |||
| 985 | pbm->scan_bus = psycho_scan_bus; | ||
| 986 | pbm->pci_ops = &sun4u_pci_ops; | ||
| 987 | pbm->config_space_reg_bits = 8; | ||
| 988 | |||
| 989 | pbm->index = pci_num_pbms++; | ||
| 990 | |||
| 991 | pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; | ||
| 992 | pbm->chip_version = 0; | ||
| 993 | prop = of_find_property(dp, "version#", NULL); | ||
| 994 | if (prop) | ||
| 995 | pbm->chip_version = *(int *) prop->value; | ||
| 996 | pbm->chip_revision = 0; | ||
| 997 | prop = of_find_property(dp, "module-revision#", NULL); | ||
| 998 | if (prop) | ||
| 999 | pbm->chip_revision = *(int *) prop->value; | ||
| 1000 | |||
| 1001 | pbm->parent = p; | ||
| 1002 | pbm->prom_node = dp; | ||
| 1003 | pbm->name = dp->full_name; | ||
| 1004 | |||
| 1005 | printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", | ||
| 1006 | pbm->name, | ||
| 1007 | pbm->chip_version, pbm->chip_revision); | ||
| 1008 | |||
| 1009 | pci_determine_mem_io_space(pbm); | ||
| 1010 | 495 | ||
| 1011 | pci_get_pbm_props(pbm); | 496 | static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid) |
| 497 | { | ||
| 498 | struct pci_pbm_info *pbm; | ||
| 1012 | 499 | ||
| 1013 | psycho_pbm_strbuf_init(pbm, is_pbm_a); | 500 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { |
| 501 | if (pbm->portid == upa_portid) | ||
| 502 | return pbm; | ||
| 503 | } | ||
| 504 | return NULL; | ||
| 1014 | } | 505 | } |
| 1015 | 506 | ||
| 1016 | #define PSYCHO_CONFIGSPACE 0x001000000UL | 507 | #define PSYCHO_CONFIGSPACE 0x001000000UL |
| 1017 | 508 | ||
| 1018 | void __init psycho_init(struct device_node *dp, char *model_name) | 509 | static int __devinit psycho_probe(struct of_device *op, |
| 510 | const struct of_device_id *match) | ||
| 1019 | { | 511 | { |
| 1020 | struct linux_prom64_registers *pr_regs; | 512 | const struct linux_prom64_registers *pr_regs; |
| 1021 | struct pci_controller_info *p; | 513 | struct device_node *dp = op->node; |
| 1022 | struct pci_pbm_info *pbm; | 514 | struct pci_pbm_info *pbm; |
| 1023 | struct iommu *iommu; | 515 | struct iommu *iommu; |
| 1024 | struct property *prop; | 516 | int is_pbm_a, err; |
| 1025 | u32 upa_portid; | 517 | u32 upa_portid; |
| 1026 | int is_pbm_a; | ||
| 1027 | 518 | ||
| 1028 | upa_portid = 0xff; | 519 | upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); |
| 1029 | prop = of_find_property(dp, "upa-portid", NULL); | ||
| 1030 | if (prop) | ||
| 1031 | upa_portid = *(u32 *) prop->value; | ||
| 1032 | 520 | ||
| 1033 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 521 | err = -ENOMEM; |
| 1034 | struct pci_controller_info *p = pbm->parent; | 522 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
| 523 | if (!pbm) { | ||
| 524 | printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); | ||
| 525 | goto out_err; | ||
| 526 | } | ||
| 1035 | 527 | ||
| 1036 | if (p->pbm_A.portid == upa_portid) { | 528 | pbm->sibling = psycho_find_sibling(upa_portid); |
| 1037 | is_pbm_a = (p->pbm_A.prom_node == NULL); | 529 | if (pbm->sibling) { |
| 1038 | psycho_pbm_init(p, dp, is_pbm_a); | 530 | iommu = pbm->sibling->iommu; |
| 1039 | return; | 531 | } else { |
| 532 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); | ||
| 533 | if (!iommu) { | ||
| 534 | printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); | ||
| 535 | goto out_free_controller; | ||
| 1040 | } | 536 | } |
| 1041 | } | 537 | } |
| 1042 | 538 | ||
| 1043 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 539 | pbm->iommu = iommu; |
| 1044 | if (!p) | 540 | pbm->portid = upa_portid; |
| 1045 | goto fatal_memory_error; | ||
| 1046 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | ||
| 1047 | if (!iommu) | ||
| 1048 | goto fatal_memory_error; | ||
| 1049 | 541 | ||
| 1050 | p->pbm_A.iommu = p->pbm_B.iommu = iommu; | 542 | pr_regs = of_get_property(dp, "reg", NULL); |
| 543 | err = -ENODEV; | ||
| 544 | if (!pr_regs) { | ||
| 545 | printk(KERN_ERR PFX "No reg property.\n"); | ||
| 546 | goto out_free_iommu; | ||
| 547 | } | ||
| 1051 | 548 | ||
| 1052 | p->pbm_A.portid = upa_portid; | 549 | is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); |
| 1053 | p->pbm_B.portid = upa_portid; | ||
| 1054 | 550 | ||
| 1055 | prop = of_find_property(dp, "reg", NULL); | 551 | pbm->controller_regs = pr_regs[2].phys_addr; |
| 1056 | pr_regs = prop->value; | 552 | pbm->config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); |
| 1057 | 553 | ||
| 1058 | p->pbm_A.controller_regs = pr_regs[2].phys_addr; | 554 | if (is_pbm_a) { |
| 1059 | p->pbm_B.controller_regs = pr_regs[2].phys_addr; | 555 | pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_A; |
| 556 | pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_A; | ||
| 557 | pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIA_CTRL; | ||
| 558 | } else { | ||
| 559 | pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_B; | ||
| 560 | pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_B; | ||
| 561 | pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIB_CTRL; | ||
| 562 | } | ||
| 1060 | 563 | ||
| 1061 | p->pbm_A.config_space = p->pbm_B.config_space = | 564 | psycho_controller_hwinit(pbm); |
| 1062 | (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); | 565 | if (!pbm->sibling) { |
| 566 | err = psycho_iommu_init(pbm, 128, 0xc0000000, | ||
| 567 | 0xffffffff, PSYCHO_CONTROL); | ||
| 568 | if (err) | ||
| 569 | goto out_free_iommu; | ||
| 1063 | 570 | ||
| 1064 | psycho_controller_hwinit(&p->pbm_A); | 571 | /* If necessary, hook us up for starfire IRQ translations. */ |
| 572 | if (this_is_starfire) | ||
| 573 | starfire_hookup(pbm->portid); | ||
| 574 | } | ||
| 1065 | 575 | ||
| 1066 | if (psycho_iommu_init(&p->pbm_A)) | 576 | psycho_pbm_init(pbm, op, is_pbm_a); |
| 1067 | goto fatal_memory_error; | ||
| 1068 | 577 | ||
| 1069 | is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); | 578 | pbm->next = pci_pbm_root; |
| 1070 | psycho_pbm_init(p, dp, is_pbm_a); | 579 | pci_pbm_root = pbm; |
| 1071 | return; | 580 | |
| 581 | if (pbm->sibling) | ||
| 582 | pbm->sibling->sibling = pbm; | ||
| 583 | |||
| 584 | dev_set_drvdata(&op->dev, pbm); | ||
| 585 | |||
| 586 | return 0; | ||
| 587 | |||
| 588 | out_free_iommu: | ||
| 589 | if (!pbm->sibling) | ||
| 590 | kfree(pbm->iommu); | ||
| 1072 | 591 | ||
| 1073 | fatal_memory_error: | 592 | out_free_controller: |
| 1074 | prom_printf("PSYCHO: Fatal memory allocation error.\n"); | 593 | kfree(pbm); |
| 1075 | prom_halt(); | 594 | |
| 595 | out_err: | ||
| 596 | return err; | ||
| 1076 | } | 597 | } |
| 598 | |||
| 599 | static struct of_device_id __initdata psycho_match[] = { | ||
| 600 | { | ||
| 601 | .name = "pci", | ||
| 602 | .compatible = "pci108e,8000", | ||
| 603 | }, | ||
| 604 | {}, | ||
| 605 | }; | ||
| 606 | |||
| 607 | static struct of_platform_driver psycho_driver = { | ||
| 608 | .name = DRIVER_NAME, | ||
| 609 | .match_table = psycho_match, | ||
| 610 | .probe = psycho_probe, | ||
| 611 | }; | ||
| 612 | |||
| 613 | static int __init psycho_init(void) | ||
| 614 | { | ||
| 615 | return of_register_driver(&psycho_driver, &of_bus_type); | ||
| 616 | } | ||
| 617 | |||
| 618 | subsys_initcall(psycho_init); | ||
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index ade5184e75d1..713257b6963c 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
| @@ -16,31 +16,15 @@ | |||
| 16 | #include <asm/apb.h> | 16 | #include <asm/apb.h> |
| 17 | #include <asm/iommu.h> | 17 | #include <asm/iommu.h> |
| 18 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
| 19 | #include <asm/smp.h> | ||
| 20 | #include <asm/oplib.h> | ||
| 21 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
| 20 | #include <asm/upa.h> | ||
| 22 | 21 | ||
| 23 | #include "pci_impl.h" | 22 | #include "pci_impl.h" |
| 24 | #include "iommu_common.h" | 23 | #include "iommu_common.h" |
| 24 | #include "psycho_common.h" | ||
| 25 | 25 | ||
| 26 | /* All SABRE registers are 64-bits. The following accessor | 26 | #define DRIVER_NAME "sabre" |
| 27 | * routines are how they are accessed. The REG parameter | 27 | #define PFX DRIVER_NAME ": " |
| 28 | * is a physical address. | ||
| 29 | */ | ||
| 30 | #define sabre_read(__reg) \ | ||
| 31 | ({ u64 __ret; \ | ||
| 32 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
| 33 | : "=r" (__ret) \ | ||
| 34 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 35 | : "memory"); \ | ||
| 36 | __ret; \ | ||
| 37 | }) | ||
| 38 | #define sabre_write(__reg, __val) \ | ||
| 39 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
| 40 | : /* no outputs */ \ | ||
| 41 | : "r" (__val), "r" (__reg), \ | ||
| 42 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 43 | : "memory") | ||
| 44 | 28 | ||
| 45 | /* SABRE PCI controller register offsets and definitions. */ | 29 | /* SABRE PCI controller register offsets and definitions. */ |
| 46 | #define SABRE_UE_AFSR 0x0030UL | 30 | #define SABRE_UE_AFSR 0x0030UL |
| @@ -208,95 +192,6 @@ | |||
| 208 | static int hummingbird_p; | 192 | static int hummingbird_p; |
| 209 | static struct pci_bus *sabre_root_bus; | 193 | static struct pci_bus *sabre_root_bus; |
| 210 | 194 | ||
| 211 | /* SABRE error handling support. */ | ||
| 212 | static void sabre_check_iommu_error(struct pci_pbm_info *pbm, | ||
| 213 | unsigned long afsr, | ||
| 214 | unsigned long afar) | ||
| 215 | { | ||
| 216 | struct iommu *iommu = pbm->iommu; | ||
| 217 | unsigned long iommu_tag[16]; | ||
| 218 | unsigned long iommu_data[16]; | ||
| 219 | unsigned long flags; | ||
| 220 | u64 control; | ||
| 221 | int i; | ||
| 222 | |||
| 223 | spin_lock_irqsave(&iommu->lock, flags); | ||
| 224 | control = sabre_read(iommu->iommu_control); | ||
| 225 | if (control & SABRE_IOMMUCTRL_ERR) { | ||
| 226 | char *type_string; | ||
| 227 | |||
| 228 | /* Clear the error encountered bit. | ||
| 229 | * NOTE: On Sabre this is write 1 to clear, | ||
| 230 | * which is different from Psycho. | ||
| 231 | */ | ||
| 232 | sabre_write(iommu->iommu_control, control); | ||
| 233 | switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) { | ||
| 234 | case 1: | ||
| 235 | type_string = "Invalid Error"; | ||
| 236 | break; | ||
| 237 | case 3: | ||
| 238 | type_string = "ECC Error"; | ||
| 239 | break; | ||
| 240 | default: | ||
| 241 | type_string = "Unknown"; | ||
| 242 | break; | ||
| 243 | }; | ||
| 244 | printk("%s: IOMMU Error, type[%s]\n", | ||
| 245 | pbm->name, type_string); | ||
| 246 | |||
| 247 | /* Enter diagnostic mode and probe for error'd | ||
| 248 | * entries in the IOTLB. | ||
| 249 | */ | ||
| 250 | control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR); | ||
| 251 | sabre_write(iommu->iommu_control, | ||
| 252 | (control | SABRE_IOMMUCTRL_DENAB)); | ||
| 253 | for (i = 0; i < 16; i++) { | ||
| 254 | unsigned long base = pbm->controller_regs; | ||
| 255 | |||
| 256 | iommu_tag[i] = | ||
| 257 | sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); | ||
| 258 | iommu_data[i] = | ||
| 259 | sabre_read(base + SABRE_IOMMU_DATA + (i * 8UL)); | ||
| 260 | sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0); | ||
| 261 | sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0); | ||
| 262 | } | ||
| 263 | sabre_write(iommu->iommu_control, control); | ||
| 264 | |||
| 265 | for (i = 0; i < 16; i++) { | ||
| 266 | unsigned long tag, data; | ||
| 267 | |||
| 268 | tag = iommu_tag[i]; | ||
| 269 | if (!(tag & SABRE_IOMMUTAG_ERR)) | ||
| 270 | continue; | ||
| 271 | |||
| 272 | data = iommu_data[i]; | ||
| 273 | switch((tag & SABRE_IOMMUTAG_ERRSTS) >> 23UL) { | ||
| 274 | case 1: | ||
| 275 | type_string = "Invalid Error"; | ||
| 276 | break; | ||
| 277 | case 3: | ||
| 278 | type_string = "ECC Error"; | ||
| 279 | break; | ||
| 280 | default: | ||
| 281 | type_string = "Unknown"; | ||
| 282 | break; | ||
| 283 | }; | ||
| 284 | printk("%s: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", | ||
| 285 | pbm->name, i, tag, type_string, | ||
| 286 | ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), | ||
| 287 | ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), | ||
| 288 | ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); | ||
| 289 | printk("%s: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", | ||
| 290 | pbm->name, i, data, | ||
| 291 | ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), | ||
| 292 | ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), | ||
| 293 | ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), | ||
| 294 | ((data & SABRE_IOMMUDATA_PPN) << IOMMU_PAGE_SHIFT)); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
| 298 | } | ||
| 299 | |||
| 300 | static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | 195 | static irqreturn_t sabre_ue_intr(int irq, void *dev_id) |
| 301 | { | 196 | { |
| 302 | struct pci_pbm_info *pbm = dev_id; | 197 | struct pci_pbm_info *pbm = dev_id; |
| @@ -306,8 +201,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | |||
| 306 | int reported; | 201 | int reported; |
| 307 | 202 | ||
| 308 | /* Latch uncorrectable error status. */ | 203 | /* Latch uncorrectable error status. */ |
| 309 | afar = sabre_read(afar_reg); | 204 | afar = upa_readq(afar_reg); |
| 310 | afsr = sabre_read(afsr_reg); | 205 | afsr = upa_readq(afsr_reg); |
| 311 | 206 | ||
| 312 | /* Clear the primary/secondary error status bits. */ | 207 | /* Clear the primary/secondary error status bits. */ |
| 313 | error_bits = afsr & | 208 | error_bits = afsr & |
| @@ -316,7 +211,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | |||
| 316 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); | 211 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); |
| 317 | if (!error_bits) | 212 | if (!error_bits) |
| 318 | return IRQ_NONE; | 213 | return IRQ_NONE; |
| 319 | sabre_write(afsr_reg, error_bits); | 214 | upa_writeq(error_bits, afsr_reg); |
| 320 | 215 | ||
| 321 | /* Log the error. */ | 216 | /* Log the error. */ |
| 322 | printk("%s: Uncorrectable Error, primary error type[%s%s]\n", | 217 | printk("%s: Uncorrectable Error, primary error type[%s%s]\n", |
| @@ -352,7 +247,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | |||
| 352 | printk("]\n"); | 247 | printk("]\n"); |
| 353 | 248 | ||
| 354 | /* Interrogate IOMMU for error status. */ | 249 | /* Interrogate IOMMU for error status. */ |
| 355 | sabre_check_iommu_error(pbm, afsr, afar); | 250 | psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); |
| 356 | 251 | ||
| 357 | return IRQ_HANDLED; | 252 | return IRQ_HANDLED; |
| 358 | } | 253 | } |
| @@ -366,8 +261,8 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) | |||
| 366 | int reported; | 261 | int reported; |
| 367 | 262 | ||
| 368 | /* Latch error status. */ | 263 | /* Latch error status. */ |
| 369 | afar = sabre_read(afar_reg); | 264 | afar = upa_readq(afar_reg); |
| 370 | afsr = sabre_read(afsr_reg); | 265 | afsr = upa_readq(afsr_reg); |
| 371 | 266 | ||
| 372 | /* Clear primary/secondary error status bits. */ | 267 | /* Clear primary/secondary error status bits. */ |
| 373 | error_bits = afsr & | 268 | error_bits = afsr & |
| @@ -375,7 +270,7 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) | |||
| 375 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); | 270 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); |
| 376 | if (!error_bits) | 271 | if (!error_bits) |
| 377 | return IRQ_NONE; | 272 | return IRQ_NONE; |
| 378 | sabre_write(afsr_reg, error_bits); | 273 | upa_writeq(error_bits, afsr_reg); |
| 379 | 274 | ||
| 380 | /* Log the error. */ | 275 | /* Log the error. */ |
| 381 | printk("%s: Correctable Error, primary error type[%s]\n", | 276 | printk("%s: Correctable Error, primary error type[%s]\n", |
| @@ -413,136 +308,9 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) | |||
| 413 | return IRQ_HANDLED; | 308 | return IRQ_HANDLED; |
| 414 | } | 309 | } |
| 415 | 310 | ||
| 416 | static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) | ||
| 417 | { | ||
| 418 | unsigned long csr_reg, csr, csr_error_bits; | ||
| 419 | irqreturn_t ret = IRQ_NONE; | ||
| 420 | u16 stat; | ||
| 421 | |||
| 422 | csr_reg = pbm->controller_regs + SABRE_PCICTRL; | ||
| 423 | csr = sabre_read(csr_reg); | ||
| 424 | csr_error_bits = | ||
| 425 | csr & SABRE_PCICTRL_SERR; | ||
| 426 | if (csr_error_bits) { | ||
| 427 | /* Clear the errors. */ | ||
| 428 | sabre_write(csr_reg, csr); | ||
| 429 | |||
| 430 | /* Log 'em. */ | ||
| 431 | if (csr_error_bits & SABRE_PCICTRL_SERR) | ||
| 432 | printk("%s: PCI SERR signal asserted.\n", | ||
| 433 | pbm->name); | ||
| 434 | ret = IRQ_HANDLED; | ||
| 435 | } | ||
| 436 | pci_bus_read_config_word(sabre_root_bus, 0, | ||
| 437 | PCI_STATUS, &stat); | ||
| 438 | if (stat & (PCI_STATUS_PARITY | | ||
| 439 | PCI_STATUS_SIG_TARGET_ABORT | | ||
| 440 | PCI_STATUS_REC_TARGET_ABORT | | ||
| 441 | PCI_STATUS_REC_MASTER_ABORT | | ||
| 442 | PCI_STATUS_SIG_SYSTEM_ERROR)) { | ||
| 443 | printk("%s: PCI bus error, PCI_STATUS[%04x]\n", | ||
| 444 | pbm->name, stat); | ||
| 445 | pci_bus_write_config_word(sabre_root_bus, 0, | ||
| 446 | PCI_STATUS, 0xffff); | ||
| 447 | ret = IRQ_HANDLED; | ||
| 448 | } | ||
| 449 | return ret; | ||
| 450 | } | ||
| 451 | |||
| 452 | static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) | ||
| 453 | { | ||
| 454 | struct pci_pbm_info *pbm = dev_id; | ||
| 455 | unsigned long afsr_reg, afar_reg; | ||
| 456 | unsigned long afsr, afar, error_bits; | ||
| 457 | int reported; | ||
| 458 | |||
| 459 | afsr_reg = pbm->controller_regs + SABRE_PIOAFSR; | ||
| 460 | afar_reg = pbm->controller_regs + SABRE_PIOAFAR; | ||
| 461 | |||
| 462 | /* Latch error status. */ | ||
| 463 | afar = sabre_read(afar_reg); | ||
| 464 | afsr = sabre_read(afsr_reg); | ||
| 465 | |||
| 466 | /* Clear primary/secondary error status bits. */ | ||
| 467 | error_bits = afsr & | ||
| 468 | (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA | | ||
| 469 | SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR | | ||
| 470 | SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA | | ||
| 471 | SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR); | ||
| 472 | if (!error_bits) | ||
| 473 | return sabre_pcierr_intr_other(pbm); | ||
| 474 | sabre_write(afsr_reg, error_bits); | ||
| 475 | |||
| 476 | /* Log the error. */ | ||
| 477 | printk("%s: PCI Error, primary error type[%s]\n", | ||
| 478 | pbm->name, | ||
| 479 | (((error_bits & SABRE_PIOAFSR_PMA) ? | ||
| 480 | "Master Abort" : | ||
| 481 | ((error_bits & SABRE_PIOAFSR_PTA) ? | ||
| 482 | "Target Abort" : | ||
| 483 | ((error_bits & SABRE_PIOAFSR_PRTRY) ? | ||
| 484 | "Excessive Retries" : | ||
| 485 | ((error_bits & SABRE_PIOAFSR_PPERR) ? | ||
| 486 | "Parity Error" : "???")))))); | ||
| 487 | printk("%s: bytemask[%04lx] was_block(%d)\n", | ||
| 488 | pbm->name, | ||
| 489 | (afsr & SABRE_PIOAFSR_BMSK) >> 32UL, | ||
| 490 | (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0); | ||
| 491 | printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); | ||
| 492 | printk("%s: PCI Secondary errors [", pbm->name); | ||
| 493 | reported = 0; | ||
| 494 | if (afsr & SABRE_PIOAFSR_SMA) { | ||
| 495 | reported++; | ||
| 496 | printk("(Master Abort)"); | ||
| 497 | } | ||
| 498 | if (afsr & SABRE_PIOAFSR_STA) { | ||
| 499 | reported++; | ||
| 500 | printk("(Target Abort)"); | ||
| 501 | } | ||
| 502 | if (afsr & SABRE_PIOAFSR_SRTRY) { | ||
| 503 | reported++; | ||
| 504 | printk("(Excessive Retries)"); | ||
| 505 | } | ||
| 506 | if (afsr & SABRE_PIOAFSR_SPERR) { | ||
| 507 | reported++; | ||
| 508 | printk("(Parity Error)"); | ||
| 509 | } | ||
| 510 | if (!reported) | ||
| 511 | printk("(none)"); | ||
| 512 | printk("]\n"); | ||
| 513 | |||
| 514 | /* For the error types shown, scan both PCI buses for devices | ||
| 515 | * which have logged that error type. | ||
| 516 | */ | ||
| 517 | |||
| 518 | /* If we see a Target Abort, this could be the result of an | ||
| 519 | * IOMMU translation error of some sort. It is extremely | ||
| 520 | * useful to log this information as usually it indicates | ||
| 521 | * a bug in the IOMMU support code or a PCI device driver. | ||
| 522 | */ | ||
| 523 | if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { | ||
| 524 | sabre_check_iommu_error(pbm, afsr, afar); | ||
| 525 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | ||
| 526 | } | ||
| 527 | if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) | ||
| 528 | pci_scan_for_master_abort(pbm, pbm->pci_bus); | ||
| 529 | |||
| 530 | /* For excessive retries, SABRE/PBM will abort the device | ||
| 531 | * and there is no way to specifically check for excessive | ||
| 532 | * retries in the config space status registers. So what | ||
| 533 | * we hope is that we'll catch it via the master/target | ||
| 534 | * abort events. | ||
| 535 | */ | ||
| 536 | |||
| 537 | if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) | ||
| 538 | pci_scan_for_parity_error(pbm, pbm->pci_bus); | ||
| 539 | |||
| 540 | return IRQ_HANDLED; | ||
| 541 | } | ||
| 542 | |||
| 543 | static void sabre_register_error_handlers(struct pci_pbm_info *pbm) | 311 | static void sabre_register_error_handlers(struct pci_pbm_info *pbm) |
| 544 | { | 312 | { |
| 545 | struct device_node *dp = pbm->prom_node; | 313 | struct device_node *dp = pbm->op->node; |
| 546 | struct of_device *op; | 314 | struct of_device *op; |
| 547 | unsigned long base = pbm->controller_regs; | 315 | unsigned long base = pbm->controller_regs; |
| 548 | u64 tmp; | 316 | u64 tmp; |
| @@ -568,33 +336,34 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 568 | * registering the handler so that we don't get spurious | 336 | * registering the handler so that we don't get spurious |
| 569 | * interrupts. | 337 | * interrupts. |
| 570 | */ | 338 | */ |
| 571 | sabre_write(base + SABRE_UE_AFSR, | 339 | upa_writeq((SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | |
| 572 | (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | | 340 | SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | |
| 573 | SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | | 341 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE), |
| 574 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); | 342 | base + SABRE_UE_AFSR); |
| 575 | 343 | ||
| 576 | err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); | 344 | err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); |
| 577 | if (err) | 345 | if (err) |
| 578 | printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", | 346 | printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", |
| 579 | pbm->name, err); | 347 | pbm->name, err); |
| 580 | 348 | ||
| 581 | sabre_write(base + SABRE_CE_AFSR, | 349 | upa_writeq((SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | |
| 582 | (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | | 350 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR), |
| 583 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); | 351 | base + SABRE_CE_AFSR); |
| 352 | |||
| 584 | 353 | ||
| 585 | err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); | 354 | err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); |
| 586 | if (err) | 355 | if (err) |
| 587 | printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", | 356 | printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", |
| 588 | pbm->name, err); | 357 | pbm->name, err); |
| 589 | err = request_irq(op->irqs[0], sabre_pcierr_intr, 0, | 358 | err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, |
| 590 | "SABRE_PCIERR", pbm); | 359 | "SABRE_PCIERR", pbm); |
| 591 | if (err) | 360 | if (err) |
| 592 | printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", | 361 | printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", |
| 593 | pbm->name, err); | 362 | pbm->name, err); |
| 594 | 363 | ||
| 595 | tmp = sabre_read(base + SABRE_PCICTRL); | 364 | tmp = upa_readq(base + SABRE_PCICTRL); |
| 596 | tmp |= SABRE_PCICTRL_ERREN; | 365 | tmp |= SABRE_PCICTRL_ERREN; |
| 597 | sabre_write(base + SABRE_PCICTRL, tmp); | 366 | upa_writeq(tmp, base + SABRE_PCICTRL); |
| 598 | } | 367 | } |
| 599 | 368 | ||
| 600 | static void apb_init(struct pci_bus *sabre_bus) | 369 | static void apb_init(struct pci_bus *sabre_bus) |
| @@ -633,7 +402,8 @@ static void apb_init(struct pci_bus *sabre_bus) | |||
| 633 | } | 402 | } |
| 634 | } | 403 | } |
| 635 | 404 | ||
| 636 | static void __init sabre_scan_bus(struct pci_pbm_info *pbm) | 405 | static void __init sabre_scan_bus(struct pci_pbm_info *pbm, |
| 406 | struct device *parent) | ||
| 637 | { | 407 | { |
| 638 | static int once; | 408 | static int once; |
| 639 | 409 | ||
| @@ -656,12 +426,12 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) | |||
| 656 | * to live at bus 0. | 426 | * to live at bus 0. |
| 657 | */ | 427 | */ |
| 658 | if (once != 0) { | 428 | if (once != 0) { |
| 659 | prom_printf("SABRE: Multiple controllers unsupported.\n"); | 429 | printk(KERN_ERR PFX "Multiple controllers unsupported.\n"); |
| 660 | prom_halt(); | 430 | return; |
| 661 | } | 431 | } |
| 662 | once++; | 432 | once++; |
| 663 | 433 | ||
| 664 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 434 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
| 665 | if (!pbm->pci_bus) | 435 | if (!pbm->pci_bus) |
| 666 | return; | 436 | return; |
| 667 | 437 | ||
| @@ -672,133 +442,58 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) | |||
| 672 | sabre_register_error_handlers(pbm); | 442 | sabre_register_error_handlers(pbm); |
| 673 | } | 443 | } |
| 674 | 444 | ||
| 675 | static int sabre_iommu_init(struct pci_pbm_info *pbm, | 445 | static void __init sabre_pbm_init(struct pci_pbm_info *pbm, |
| 676 | int tsbsize, unsigned long dvma_offset, | 446 | struct of_device *op) |
| 677 | u32 dma_mask) | ||
| 678 | { | ||
| 679 | struct iommu *iommu = pbm->iommu; | ||
| 680 | unsigned long i; | ||
| 681 | u64 control; | ||
| 682 | int err; | ||
| 683 | |||
| 684 | /* Register addresses. */ | ||
| 685 | iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL; | ||
| 686 | iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE; | ||
| 687 | iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH; | ||
| 688 | iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); | ||
| 689 | iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC; | ||
| 690 | /* Sabre's IOMMU lacks ctx flushing. */ | ||
| 691 | iommu->iommu_ctxflush = 0; | ||
| 692 | |||
| 693 | /* Invalidate TLB Entries. */ | ||
| 694 | control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); | ||
| 695 | control |= SABRE_IOMMUCTRL_DENAB; | ||
| 696 | sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); | ||
| 697 | |||
| 698 | for(i = 0; i < 16; i++) { | ||
| 699 | sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); | ||
| 700 | sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); | ||
| 701 | } | ||
| 702 | |||
| 703 | /* Leave diag mode enabled for full-flushing done | ||
| 704 | * in pci_iommu.c | ||
| 705 | */ | ||
| 706 | err = iommu_table_init(iommu, tsbsize * 1024 * 8, | ||
| 707 | dvma_offset, dma_mask, pbm->numa_node); | ||
| 708 | if (err) | ||
| 709 | return err; | ||
| 710 | |||
| 711 | sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, | ||
| 712 | __pa(iommu->page_table)); | ||
| 713 | |||
| 714 | control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); | ||
| 715 | control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); | ||
| 716 | control |= SABRE_IOMMUCTRL_ENAB; | ||
| 717 | switch(tsbsize) { | ||
| 718 | case 64: | ||
| 719 | control |= SABRE_IOMMU_TSBSZ_64K; | ||
| 720 | break; | ||
| 721 | case 128: | ||
| 722 | control |= SABRE_IOMMU_TSBSZ_128K; | ||
| 723 | break; | ||
| 724 | default: | ||
| 725 | prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); | ||
| 726 | prom_halt(); | ||
| 727 | break; | ||
| 728 | } | ||
| 729 | sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); | ||
| 730 | |||
| 731 | return 0; | ||
| 732 | } | ||
| 733 | |||
| 734 | static void __init sabre_pbm_init(struct pci_controller_info *p, | ||
| 735 | struct pci_pbm_info *pbm, struct device_node *dp) | ||
| 736 | { | 447 | { |
| 737 | pbm->name = dp->full_name; | 448 | psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); |
| 738 | printk("%s: SABRE PCI Bus Module\n", pbm->name); | 449 | pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; |
| 739 | 450 | pbm->pci_afar = pbm->controller_regs + SABRE_PIOAFAR; | |
| 740 | pbm->numa_node = -1; | 451 | pbm->pci_csr = pbm->controller_regs + SABRE_PCICTRL; |
| 741 | 452 | sabre_scan_bus(pbm, &op->dev); | |
| 742 | pbm->scan_bus = sabre_scan_bus; | ||
| 743 | pbm->pci_ops = &sun4u_pci_ops; | ||
| 744 | pbm->config_space_reg_bits = 8; | ||
| 745 | |||
| 746 | pbm->index = pci_num_pbms++; | ||
| 747 | |||
| 748 | pbm->chip_type = PBM_CHIP_TYPE_SABRE; | ||
| 749 | pbm->parent = p; | ||
| 750 | pbm->prom_node = dp; | ||
| 751 | pci_get_pbm_props(pbm); | ||
| 752 | |||
| 753 | pci_determine_mem_io_space(pbm); | ||
| 754 | } | 453 | } |
| 755 | 454 | ||
| 756 | void __init sabre_init(struct device_node *dp, char *model_name) | 455 | static int __devinit sabre_probe(struct of_device *op, |
| 456 | const struct of_device_id *match) | ||
| 757 | { | 457 | { |
| 758 | const struct linux_prom64_registers *pr_regs; | 458 | const struct linux_prom64_registers *pr_regs; |
| 759 | struct pci_controller_info *p; | 459 | struct device_node *dp = op->node; |
| 760 | struct pci_pbm_info *pbm; | 460 | struct pci_pbm_info *pbm; |
| 461 | u32 upa_portid, dma_mask; | ||
| 761 | struct iommu *iommu; | 462 | struct iommu *iommu; |
| 762 | int tsbsize; | 463 | int tsbsize, err; |
| 763 | const u32 *vdma; | 464 | const u32 *vdma; |
| 764 | u32 upa_portid, dma_mask; | ||
| 765 | u64 clear_irq; | 465 | u64 clear_irq; |
| 766 | 466 | ||
| 767 | hummingbird_p = 0; | 467 | hummingbird_p = (match->data != NULL); |
| 768 | if (!strcmp(model_name, "pci108e,a001")) | 468 | if (!hummingbird_p) { |
| 769 | hummingbird_p = 1; | 469 | struct device_node *cpu_dp; |
| 770 | else if (!strcmp(model_name, "SUNW,sabre")) { | 470 | |
| 771 | const char *compat = of_get_property(dp, "compatible", NULL); | 471 | /* Of course, Sun has to encode things a thousand |
| 772 | if (compat && !strcmp(compat, "pci108e,a001")) | 472 | * different ways, inconsistently. |
| 773 | hummingbird_p = 1; | 473 | */ |
| 774 | if (!hummingbird_p) { | 474 | for_each_node_by_type(cpu_dp, "cpu") { |
| 775 | struct device_node *dp; | 475 | if (!strcmp(cpu_dp->name, "SUNW,UltraSPARC-IIe")) |
| 776 | 476 | hummingbird_p = 1; | |
| 777 | /* Of course, Sun has to encode things a thousand | ||
| 778 | * different ways, inconsistently. | ||
| 779 | */ | ||
| 780 | for_each_node_by_type(dp, "cpu") { | ||
| 781 | if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe")) | ||
| 782 | hummingbird_p = 1; | ||
| 783 | } | ||
| 784 | } | 477 | } |
| 785 | } | 478 | } |
| 786 | 479 | ||
| 787 | p = kzalloc(sizeof(*p), GFP_ATOMIC); | 480 | err = -ENOMEM; |
| 788 | if (!p) | 481 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
| 789 | goto fatal_memory_error; | 482 | if (!pbm) { |
| 483 | printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); | ||
| 484 | goto out_err; | ||
| 485 | } | ||
| 486 | |||
| 487 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); | ||
| 488 | if (!iommu) { | ||
| 489 | printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); | ||
| 490 | goto out_free_controller; | ||
| 491 | } | ||
| 790 | 492 | ||
| 791 | iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); | ||
| 792 | if (!iommu) | ||
| 793 | goto fatal_memory_error; | ||
| 794 | pbm = &p->pbm_A; | ||
| 795 | pbm->iommu = iommu; | 493 | pbm->iommu = iommu; |
| 796 | 494 | ||
| 797 | upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); | 495 | upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); |
| 798 | 496 | ||
| 799 | pbm->next = pci_pbm_root; | ||
| 800 | pci_pbm_root = pbm; | ||
| 801 | |||
| 802 | pbm->portid = upa_portid; | 497 | pbm->portid = upa_portid; |
| 803 | 498 | ||
| 804 | /* | 499 | /* |
| @@ -806,6 +501,11 @@ void __init sabre_init(struct device_node *dp, char *model_name) | |||
| 806 | */ | 501 | */ |
| 807 | 502 | ||
| 808 | pr_regs = of_get_property(dp, "reg", NULL); | 503 | pr_regs = of_get_property(dp, "reg", NULL); |
| 504 | err = -ENODEV; | ||
| 505 | if (!pr_regs) { | ||
| 506 | printk(KERN_ERR PFX "No reg property\n"); | ||
| 507 | goto out_free_iommu; | ||
| 508 | } | ||
| 809 | 509 | ||
| 810 | /* | 510 | /* |
| 811 | * First REG in property is base of entire SABRE register space. | 511 | * First REG in property is base of entire SABRE register space. |
| @@ -816,22 +516,25 @@ void __init sabre_init(struct device_node *dp, char *model_name) | |||
| 816 | 516 | ||
| 817 | /* PCI first */ | 517 | /* PCI first */ |
| 818 | for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) | 518 | for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) |
| 819 | sabre_write(pbm->controller_regs + clear_irq, 0x0UL); | 519 | upa_writeq(0x0UL, pbm->controller_regs + clear_irq); |
| 820 | 520 | ||
| 821 | /* Then OBIO */ | 521 | /* Then OBIO */ |
| 822 | for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) | 522 | for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) |
| 823 | sabre_write(pbm->controller_regs + clear_irq, 0x0UL); | 523 | upa_writeq(0x0UL, pbm->controller_regs + clear_irq); |
| 824 | 524 | ||
| 825 | /* Error interrupts are enabled later after the bus scan. */ | 525 | /* Error interrupts are enabled later after the bus scan. */ |
| 826 | sabre_write(pbm->controller_regs + SABRE_PCICTRL, | 526 | upa_writeq((SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | |
| 827 | (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | | 527 | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN), |
| 828 | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); | 528 | pbm->controller_regs + SABRE_PCICTRL); |
| 829 | 529 | ||
| 830 | /* Now map in PCI config space for entire SABRE. */ | 530 | /* Now map in PCI config space for entire SABRE. */ |
| 831 | pbm->config_space = | 531 | pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE; |
| 832 | (pbm->controller_regs + SABRE_CONFIGSPACE); | ||
| 833 | 532 | ||
| 834 | vdma = of_get_property(dp, "virtual-dma", NULL); | 533 | vdma = of_get_property(dp, "virtual-dma", NULL); |
| 534 | if (!vdma) { | ||
| 535 | printk(KERN_ERR PFX "No virtual-dma property\n"); | ||
| 536 | goto out_free_iommu; | ||
| 537 | } | ||
| 835 | 538 | ||
| 836 | dma_mask = vdma[0]; | 539 | dma_mask = vdma[0]; |
| 837 | switch(vdma[1]) { | 540 | switch(vdma[1]) { |
| @@ -849,20 +552,58 @@ void __init sabre_init(struct device_node *dp, char *model_name) | |||
| 849 | tsbsize = 128; | 552 | tsbsize = 128; |
| 850 | break; | 553 | break; |
| 851 | default: | 554 | default: |
| 852 | prom_printf("SABRE: strange virtual-dma size.\n"); | 555 | printk(KERN_ERR PFX "Strange virtual-dma size.\n"); |
| 853 | prom_halt(); | 556 | goto out_free_iommu; |
| 854 | } | 557 | } |
| 855 | 558 | ||
| 856 | if (sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask)) | 559 | err = psycho_iommu_init(pbm, tsbsize, vdma[0], dma_mask, SABRE_WRSYNC); |
| 857 | goto fatal_memory_error; | 560 | if (err) |
| 561 | goto out_free_iommu; | ||
| 858 | 562 | ||
| 859 | /* | 563 | /* |
| 860 | * Look for APB underneath. | 564 | * Look for APB underneath. |
| 861 | */ | 565 | */ |
| 862 | sabre_pbm_init(p, pbm, dp); | 566 | sabre_pbm_init(pbm, op); |
| 863 | return; | ||
| 864 | 567 | ||
| 865 | fatal_memory_error: | 568 | pbm->next = pci_pbm_root; |
| 866 | prom_printf("SABRE: Fatal memory allocation error.\n"); | 569 | pci_pbm_root = pbm; |
| 867 | prom_halt(); | 570 | |
| 571 | dev_set_drvdata(&op->dev, pbm); | ||
| 572 | |||
| 573 | return 0; | ||
| 574 | |||
| 575 | out_free_iommu: | ||
| 576 | kfree(pbm->iommu); | ||
| 577 | |||
| 578 | out_free_controller: | ||
| 579 | kfree(pbm); | ||
| 580 | |||
| 581 | out_err: | ||
| 582 | return err; | ||
| 583 | } | ||
| 584 | |||
| 585 | static struct of_device_id __initdata sabre_match[] = { | ||
| 586 | { | ||
| 587 | .name = "pci", | ||
| 588 | .compatible = "pci108e,a001", | ||
| 589 | .data = (void *) 1, | ||
| 590 | }, | ||
| 591 | { | ||
| 592 | .name = "pci", | ||
| 593 | .compatible = "pci108e,a000", | ||
| 594 | }, | ||
| 595 | {}, | ||
| 596 | }; | ||
| 597 | |||
| 598 | static struct of_platform_driver sabre_driver = { | ||
| 599 | .name = DRIVER_NAME, | ||
| 600 | .match_table = sabre_match, | ||
| 601 | .probe = sabre_probe, | ||
| 602 | }; | ||
| 603 | |||
| 604 | static int __init sabre_init(void) | ||
| 605 | { | ||
| 606 | return of_register_driver(&sabre_driver, &of_bus_type); | ||
| 868 | } | 607 | } |
| 608 | |||
| 609 | subsys_initcall(sabre_init); | ||
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 9248c6737f0e..45d9dba1ba11 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. | 1 | /* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2001, 2002, 2003, 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2001, 2002, 2003, 2007, 2008 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| @@ -13,32 +13,15 @@ | |||
| 13 | 13 | ||
| 14 | #include <asm/iommu.h> | 14 | #include <asm/iommu.h> |
| 15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
| 16 | #include <asm/upa.h> | ||
| 17 | #include <asm/pstate.h> | 16 | #include <asm/pstate.h> |
| 18 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
| 19 | #include <asm/oplib.h> | 18 | #include <asm/upa.h> |
| 20 | 19 | ||
| 21 | #include "pci_impl.h" | 20 | #include "pci_impl.h" |
| 22 | #include "iommu_common.h" | 21 | #include "iommu_common.h" |
| 23 | 22 | ||
| 24 | /* All SCHIZO registers are 64-bits. The following accessor | 23 | #define DRIVER_NAME "schizo" |
| 25 | * routines are how they are accessed. The REG parameter | 24 | #define PFX DRIVER_NAME ": " |
| 26 | * is a physical address. | ||
| 27 | */ | ||
| 28 | #define schizo_read(__reg) \ | ||
| 29 | ({ u64 __ret; \ | ||
| 30 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
| 31 | : "=r" (__ret) \ | ||
| 32 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 33 | : "memory"); \ | ||
| 34 | __ret; \ | ||
| 35 | }) | ||
| 36 | #define schizo_write(__reg, __val) \ | ||
| 37 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
| 38 | : /* no outputs */ \ | ||
| 39 | : "r" (__val), "r" (__reg), \ | ||
| 40 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
| 41 | : "memory") | ||
| 42 | 25 | ||
| 43 | /* This is a convention that at least Excalibur and Merlin | 26 | /* This is a convention that at least Excalibur and Merlin |
| 44 | * follow. I suppose the SCHIZO used in Starcat and friends | 27 | * follow. I suppose the SCHIZO used in Starcat and friends |
| @@ -163,25 +146,25 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, | |||
| 163 | * invalidating it before it has a chance to reach | 146 | * invalidating it before it has a chance to reach |
| 164 | * main memory. | 147 | * main memory. |
| 165 | */ | 148 | */ |
| 166 | control = schizo_read(strbuf->strbuf_control); | 149 | control = upa_readq(strbuf->strbuf_control); |
| 167 | schizo_write(strbuf->strbuf_control, | 150 | upa_writeq((control | SCHIZO_STRBUF_CTRL_DENAB), |
| 168 | (control | SCHIZO_STRBUF_CTRL_DENAB)); | 151 | strbuf->strbuf_control); |
| 169 | for (i = 0; i < 128; i++) { | 152 | for (i = 0; i < 128; i++) { |
| 170 | unsigned long val; | 153 | unsigned long val; |
| 171 | 154 | ||
| 172 | val = schizo_read(err_base + (i * 8UL)); | 155 | val = upa_readq(err_base + (i * 8UL)); |
| 173 | schizo_write(err_base + (i * 8UL), 0UL); | 156 | upa_writeq(0UL, err_base + (i * 8UL)); |
| 174 | stc_error_buf[i] = val; | 157 | stc_error_buf[i] = val; |
| 175 | } | 158 | } |
| 176 | for (i = 0; i < 16; i++) { | 159 | for (i = 0; i < 16; i++) { |
| 177 | stc_tag_buf[i] = schizo_read(tag_base + (i * 8UL)); | 160 | stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); |
| 178 | stc_line_buf[i] = schizo_read(line_base + (i * 8UL)); | 161 | stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); |
| 179 | schizo_write(tag_base + (i * 8UL), 0UL); | 162 | upa_writeq(0UL, tag_base + (i * 8UL)); |
| 180 | schizo_write(line_base + (i * 8UL), 0UL); | 163 | upa_writeq(0UL, line_base + (i * 8UL)); |
| 181 | } | 164 | } |
| 182 | 165 | ||
| 183 | /* OK, state is logged, exit diagnostic mode. */ | 166 | /* OK, state is logged, exit diagnostic mode. */ |
| 184 | schizo_write(strbuf->strbuf_control, control); | 167 | upa_writeq(control, strbuf->strbuf_control); |
| 185 | 168 | ||
| 186 | for (i = 0; i < 16; i++) { | 169 | for (i = 0; i < 16; i++) { |
| 187 | int j, saw_error, first, last; | 170 | int j, saw_error, first, last; |
| @@ -258,14 +241,14 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
| 258 | int i; | 241 | int i; |
| 259 | 242 | ||
| 260 | spin_lock_irqsave(&iommu->lock, flags); | 243 | spin_lock_irqsave(&iommu->lock, flags); |
| 261 | control = schizo_read(iommu->iommu_control); | 244 | control = upa_readq(iommu->iommu_control); |
| 262 | if (control & SCHIZO_IOMMU_CTRL_XLTEERR) { | 245 | if (control & SCHIZO_IOMMU_CTRL_XLTEERR) { |
| 263 | unsigned long base; | 246 | unsigned long base; |
| 264 | char *type_string; | 247 | char *type_string; |
| 265 | 248 | ||
| 266 | /* Clear the error encountered bit. */ | 249 | /* Clear the error encountered bit. */ |
| 267 | control &= ~SCHIZO_IOMMU_CTRL_XLTEERR; | 250 | control &= ~SCHIZO_IOMMU_CTRL_XLTEERR; |
| 268 | schizo_write(iommu->iommu_control, control); | 251 | upa_writeq(control, iommu->iommu_control); |
| 269 | 252 | ||
| 270 | switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) { | 253 | switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) { |
| 271 | case 0: | 254 | case 0: |
| @@ -295,24 +278,24 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
| 295 | * get as much diagnostic information to the | 278 | * get as much diagnostic information to the |
| 296 | * console as we can. | 279 | * console as we can. |
| 297 | */ | 280 | */ |
| 298 | schizo_write(iommu->iommu_control, | 281 | upa_writeq(control | SCHIZO_IOMMU_CTRL_DENAB, |
| 299 | control | SCHIZO_IOMMU_CTRL_DENAB); | 282 | iommu->iommu_control); |
| 300 | 283 | ||
| 301 | base = pbm->pbm_regs; | 284 | base = pbm->pbm_regs; |
| 302 | 285 | ||
| 303 | for (i = 0; i < 16; i++) { | 286 | for (i = 0; i < 16; i++) { |
| 304 | iommu_tag[i] = | 287 | iommu_tag[i] = |
| 305 | schizo_read(base + SCHIZO_IOMMU_TAG + (i * 8UL)); | 288 | upa_readq(base + SCHIZO_IOMMU_TAG + (i * 8UL)); |
| 306 | iommu_data[i] = | 289 | iommu_data[i] = |
| 307 | schizo_read(base + SCHIZO_IOMMU_DATA + (i * 8UL)); | 290 | upa_readq(base + SCHIZO_IOMMU_DATA + (i * 8UL)); |
| 308 | 291 | ||
| 309 | /* Now clear out the entry. */ | 292 | /* Now clear out the entry. */ |
| 310 | schizo_write(base + SCHIZO_IOMMU_TAG + (i * 8UL), 0); | 293 | upa_writeq(0, base + SCHIZO_IOMMU_TAG + (i * 8UL)); |
| 311 | schizo_write(base + SCHIZO_IOMMU_DATA + (i * 8UL), 0); | 294 | upa_writeq(0, base + SCHIZO_IOMMU_DATA + (i * 8UL)); |
| 312 | } | 295 | } |
| 313 | 296 | ||
| 314 | /* Leave diagnostic mode. */ | 297 | /* Leave diagnostic mode. */ |
| 315 | schizo_write(iommu->iommu_control, control); | 298 | upa_writeq(control, iommu->iommu_control); |
| 316 | 299 | ||
| 317 | for (i = 0; i < 16; i++) { | 300 | for (i = 0; i < 16; i++) { |
| 318 | unsigned long tag, data; | 301 | unsigned long tag, data; |
| @@ -357,11 +340,12 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
| 357 | spin_unlock_irqrestore(&iommu->lock, flags); | 340 | spin_unlock_irqrestore(&iommu->lock, flags); |
| 358 | } | 341 | } |
| 359 | 342 | ||
| 360 | static void schizo_check_iommu_error(struct pci_controller_info *p, | 343 | static void schizo_check_iommu_error(struct pci_pbm_info *pbm, |
| 361 | enum schizo_error_type type) | 344 | enum schizo_error_type type) |
| 362 | { | 345 | { |
| 363 | schizo_check_iommu_error_pbm(&p->pbm_A, type); | 346 | schizo_check_iommu_error_pbm(pbm, type); |
| 364 | schizo_check_iommu_error_pbm(&p->pbm_B, type); | 347 | if (pbm->sibling) |
| 348 | schizo_check_iommu_error_pbm(pbm->sibling, type); | ||
| 365 | } | 349 | } |
| 366 | 350 | ||
| 367 | /* Uncorrectable ECC error status gathering. */ | 351 | /* Uncorrectable ECC error status gathering. */ |
| @@ -386,14 +370,13 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, | |||
| 386 | static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | 370 | static irqreturn_t schizo_ue_intr(int irq, void *dev_id) |
| 387 | { | 371 | { |
| 388 | struct pci_pbm_info *pbm = dev_id; | 372 | struct pci_pbm_info *pbm = dev_id; |
| 389 | struct pci_controller_info *p = pbm->parent; | ||
| 390 | unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; | 373 | unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; |
| 391 | unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; | 374 | unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; |
| 392 | unsigned long afsr, afar, error_bits; | 375 | unsigned long afsr, afar, error_bits; |
| 393 | int reported, limit; | 376 | int reported, limit; |
| 394 | 377 | ||
| 395 | /* Latch uncorrectable error status. */ | 378 | /* Latch uncorrectable error status. */ |
| 396 | afar = schizo_read(afar_reg); | 379 | afar = upa_readq(afar_reg); |
| 397 | 380 | ||
| 398 | /* If either of the error pending bits are set in the | 381 | /* If either of the error pending bits are set in the |
| 399 | * AFSR, the error status is being actively updated by | 382 | * AFSR, the error status is being actively updated by |
| @@ -401,7 +384,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | |||
| 401 | */ | 384 | */ |
| 402 | limit = 1000; | 385 | limit = 1000; |
| 403 | do { | 386 | do { |
| 404 | afsr = schizo_read(afsr_reg); | 387 | afsr = upa_readq(afsr_reg); |
| 405 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); | 388 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); |
| 406 | 389 | ||
| 407 | /* Clear the primary/secondary error status bits. */ | 390 | /* Clear the primary/secondary error status bits. */ |
| @@ -410,7 +393,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | |||
| 410 | SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA); | 393 | SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA); |
| 411 | if (!error_bits) | 394 | if (!error_bits) |
| 412 | return IRQ_NONE; | 395 | return IRQ_NONE; |
| 413 | schizo_write(afsr_reg, error_bits); | 396 | upa_writeq(error_bits, afsr_reg); |
| 414 | 397 | ||
| 415 | /* Log the error. */ | 398 | /* Log the error. */ |
| 416 | printk("%s: Uncorrectable Error, primary error type[%s]\n", | 399 | printk("%s: Uncorrectable Error, primary error type[%s]\n", |
| @@ -449,7 +432,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | |||
| 449 | printk("]\n"); | 432 | printk("]\n"); |
| 450 | 433 | ||
| 451 | /* Interrogate IOMMU for error status. */ | 434 | /* Interrogate IOMMU for error status. */ |
| 452 | schizo_check_iommu_error(p, UE_ERR); | 435 | schizo_check_iommu_error(pbm, UE_ERR); |
| 453 | 436 | ||
| 454 | return IRQ_HANDLED; | 437 | return IRQ_HANDLED; |
| 455 | } | 438 | } |
| @@ -481,7 +464,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) | |||
| 481 | int reported, limit; | 464 | int reported, limit; |
| 482 | 465 | ||
| 483 | /* Latch error status. */ | 466 | /* Latch error status. */ |
| 484 | afar = schizo_read(afar_reg); | 467 | afar = upa_readq(afar_reg); |
| 485 | 468 | ||
| 486 | /* If either of the error pending bits are set in the | 469 | /* If either of the error pending bits are set in the |
| 487 | * AFSR, the error status is being actively updated by | 470 | * AFSR, the error status is being actively updated by |
| @@ -489,7 +472,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) | |||
| 489 | */ | 472 | */ |
| 490 | limit = 1000; | 473 | limit = 1000; |
| 491 | do { | 474 | do { |
| 492 | afsr = schizo_read(afsr_reg); | 475 | afsr = upa_readq(afsr_reg); |
| 493 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); | 476 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); |
| 494 | 477 | ||
| 495 | /* Clear primary/secondary error status bits. */ | 478 | /* Clear primary/secondary error status bits. */ |
| @@ -498,7 +481,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) | |||
| 498 | SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); | 481 | SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); |
| 499 | if (!error_bits) | 482 | if (!error_bits) |
| 500 | return IRQ_NONE; | 483 | return IRQ_NONE; |
| 501 | schizo_write(afsr_reg, error_bits); | 484 | upa_writeq(error_bits, afsr_reg); |
| 502 | 485 | ||
| 503 | /* Log the error. */ | 486 | /* Log the error. */ |
| 504 | printk("%s: Correctable Error, primary error type[%s]\n", | 487 | printk("%s: Correctable Error, primary error type[%s]\n", |
| @@ -600,7 +583,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) | |||
| 600 | u16 stat; | 583 | u16 stat; |
| 601 | 584 | ||
| 602 | csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; | 585 | csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; |
| 603 | csr = schizo_read(csr_reg); | 586 | csr = upa_readq(csr_reg); |
| 604 | csr_error_bits = | 587 | csr_error_bits = |
| 605 | csr & (SCHIZO_PCICTRL_BUS_UNUS | | 588 | csr & (SCHIZO_PCICTRL_BUS_UNUS | |
| 606 | SCHIZO_PCICTRL_TTO_ERR | | 589 | SCHIZO_PCICTRL_TTO_ERR | |
| @@ -610,7 +593,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) | |||
| 610 | SCHIZO_PCICTRL_SERR); | 593 | SCHIZO_PCICTRL_SERR); |
| 611 | if (csr_error_bits) { | 594 | if (csr_error_bits) { |
| 612 | /* Clear the errors. */ | 595 | /* Clear the errors. */ |
| 613 | schizo_write(csr_reg, csr); | 596 | upa_writeq(csr, csr_reg); |
| 614 | 597 | ||
| 615 | /* Log 'em. */ | 598 | /* Log 'em. */ |
| 616 | if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) | 599 | if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) |
| @@ -650,7 +633,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) | |||
| 650 | static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | 633 | static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) |
| 651 | { | 634 | { |
| 652 | struct pci_pbm_info *pbm = dev_id; | 635 | struct pci_pbm_info *pbm = dev_id; |
| 653 | struct pci_controller_info *p = pbm->parent; | ||
| 654 | unsigned long afsr_reg, afar_reg, base; | 636 | unsigned long afsr_reg, afar_reg, base; |
| 655 | unsigned long afsr, afar, error_bits; | 637 | unsigned long afsr, afar, error_bits; |
| 656 | int reported; | 638 | int reported; |
| @@ -661,8 +643,8 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
| 661 | afar_reg = base + SCHIZO_PCI_AFAR; | 643 | afar_reg = base + SCHIZO_PCI_AFAR; |
| 662 | 644 | ||
| 663 | /* Latch error status. */ | 645 | /* Latch error status. */ |
| 664 | afar = schizo_read(afar_reg); | 646 | afar = upa_readq(afar_reg); |
| 665 | afsr = schizo_read(afsr_reg); | 647 | afsr = upa_readq(afsr_reg); |
| 666 | 648 | ||
| 667 | /* Clear primary/secondary error status bits. */ | 649 | /* Clear primary/secondary error status bits. */ |
| 668 | error_bits = afsr & | 650 | error_bits = afsr & |
| @@ -674,7 +656,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
| 674 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); | 656 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); |
| 675 | if (!error_bits) | 657 | if (!error_bits) |
| 676 | return schizo_pcierr_intr_other(pbm); | 658 | return schizo_pcierr_intr_other(pbm); |
| 677 | schizo_write(afsr_reg, error_bits); | 659 | upa_writeq(error_bits, afsr_reg); |
| 678 | 660 | ||
| 679 | /* Log the error. */ | 661 | /* Log the error. */ |
| 680 | printk("%s: PCI Error, primary error type[%s]\n", | 662 | printk("%s: PCI Error, primary error type[%s]\n", |
| @@ -744,7 +726,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
| 744 | * a bug in the IOMMU support code or a PCI device driver. | 726 | * a bug in the IOMMU support code or a PCI device driver. |
| 745 | */ | 727 | */ |
| 746 | if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { | 728 | if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { |
| 747 | schizo_check_iommu_error(p, PCI_ERR); | 729 | schizo_check_iommu_error(pbm, PCI_ERR); |
| 748 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | 730 | pci_scan_for_target_abort(pbm, pbm->pci_bus); |
| 749 | } | 731 | } |
| 750 | if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) | 732 | if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) |
| @@ -805,12 +787,11 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
| 805 | static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) | 787 | static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) |
| 806 | { | 788 | { |
| 807 | struct pci_pbm_info *pbm = dev_id; | 789 | struct pci_pbm_info *pbm = dev_id; |
| 808 | struct pci_controller_info *p = pbm->parent; | ||
| 809 | u64 errlog; | 790 | u64 errlog; |
| 810 | 791 | ||
| 811 | errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); | 792 | errlog = upa_readq(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); |
| 812 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG, | 793 | upa_writeq(errlog & ~(SAFARI_ERRLOG_ERROUT), |
| 813 | errlog & ~(SAFARI_ERRLOG_ERROUT)); | 794 | pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); |
| 814 | 795 | ||
| 815 | if (!(errlog & BUS_ERROR_UNMAP)) { | 796 | if (!(errlog & BUS_ERROR_UNMAP)) { |
| 816 | printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", | 797 | printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", |
| @@ -821,7 +802,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) | |||
| 821 | 802 | ||
| 822 | printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", | 803 | printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", |
| 823 | pbm->name); | 804 | pbm->name); |
| 824 | schizo_check_iommu_error(p, SAFARI_ERR); | 805 | schizo_check_iommu_error(pbm, SAFARI_ERR); |
| 825 | 806 | ||
| 826 | return IRQ_HANDLED; | 807 | return IRQ_HANDLED; |
| 827 | } | 808 | } |
| @@ -863,7 +844,7 @@ static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) | |||
| 863 | */ | 844 | */ |
| 864 | static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | 845 | static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) |
| 865 | { | 846 | { |
| 866 | struct of_device *op = of_find_device_by_node(pbm->prom_node); | 847 | struct of_device *op = of_find_device_by_node(pbm->op->node); |
| 867 | u64 tmp, err_mask, err_no_mask; | 848 | u64 tmp, err_mask, err_no_mask; |
| 868 | int err; | 849 | int err; |
| 869 | 850 | ||
| @@ -910,10 +891,9 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 910 | } | 891 | } |
| 911 | 892 | ||
| 912 | /* Enable UE and CE interrupts for controller. */ | 893 | /* Enable UE and CE interrupts for controller. */ |
| 913 | schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, | 894 | upa_writeq((SCHIZO_ECCCTRL_EE | |
| 914 | (SCHIZO_ECCCTRL_EE | | 895 | SCHIZO_ECCCTRL_UE | |
| 915 | SCHIZO_ECCCTRL_UE | | 896 | SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); |
| 916 | SCHIZO_ECCCTRL_CE)); | ||
| 917 | 897 | ||
| 918 | /* Enable PCI Error interrupts and clear error | 898 | /* Enable PCI Error interrupts and clear error |
| 919 | * bits. | 899 | * bits. |
| @@ -926,10 +906,10 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 926 | 906 | ||
| 927 | err_no_mask = SCHIZO_PCICTRL_DTO_ERR; | 907 | err_no_mask = SCHIZO_PCICTRL_DTO_ERR; |
| 928 | 908 | ||
| 929 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); | 909 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); |
| 930 | tmp |= err_mask; | 910 | tmp |= err_mask; |
| 931 | tmp &= ~err_no_mask; | 911 | tmp &= ~err_no_mask; |
| 932 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); | 912 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); |
| 933 | 913 | ||
| 934 | err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | | 914 | err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | |
| 935 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | | 915 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | |
| @@ -938,7 +918,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 938 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | | 918 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | |
| 939 | SCHIZO_PCIAFSR_STTO); | 919 | SCHIZO_PCIAFSR_STTO); |
| 940 | 920 | ||
| 941 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask); | 921 | upa_writeq(err_mask, pbm->pbm_regs + SCHIZO_PCI_AFSR); |
| 942 | 922 | ||
| 943 | err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | | 923 | err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | |
| 944 | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | | 924 | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | |
| @@ -950,16 +930,16 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 950 | BUS_ERROR_APERR | BUS_ERROR_UNMAP | | 930 | BUS_ERROR_APERR | BUS_ERROR_UNMAP | |
| 951 | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); | 931 | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); |
| 952 | 932 | ||
| 953 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, | 933 | upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), |
| 954 | (SCHIZO_SAFERRCTRL_EN | err_mask)); | 934 | pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); |
| 955 | 935 | ||
| 956 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL, | 936 | upa_writeq((SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)), |
| 957 | (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); | 937 | pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL); |
| 958 | } | 938 | } |
| 959 | 939 | ||
| 960 | static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | 940 | static void schizo_register_error_handlers(struct pci_pbm_info *pbm) |
| 961 | { | 941 | { |
| 962 | struct of_device *op = of_find_device_by_node(pbm->prom_node); | 942 | struct of_device *op = of_find_device_by_node(pbm->op->node); |
| 963 | u64 tmp, err_mask, err_no_mask; | 943 | u64 tmp, err_mask, err_no_mask; |
| 964 | int err; | 944 | int err; |
| 965 | 945 | ||
| @@ -1006,10 +986,9 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 1006 | } | 986 | } |
| 1007 | 987 | ||
| 1008 | /* Enable UE and CE interrupts for controller. */ | 988 | /* Enable UE and CE interrupts for controller. */ |
| 1009 | schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, | 989 | upa_writeq((SCHIZO_ECCCTRL_EE | |
| 1010 | (SCHIZO_ECCCTRL_EE | | 990 | SCHIZO_ECCCTRL_UE | |
| 1011 | SCHIZO_ECCCTRL_UE | | 991 | SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); |
| 1012 | SCHIZO_ECCCTRL_CE)); | ||
| 1013 | 992 | ||
| 1014 | err_mask = (SCHIZO_PCICTRL_BUS_UNUS | | 993 | err_mask = (SCHIZO_PCICTRL_BUS_UNUS | |
| 1015 | SCHIZO_PCICTRL_ESLCK | | 994 | SCHIZO_PCICTRL_ESLCK | |
| @@ -1025,18 +1004,18 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 1025 | /* Enable PCI Error interrupts and clear error | 1004 | /* Enable PCI Error interrupts and clear error |
| 1026 | * bits for each PBM. | 1005 | * bits for each PBM. |
| 1027 | */ | 1006 | */ |
| 1028 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); | 1007 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); |
| 1029 | tmp |= err_mask; | 1008 | tmp |= err_mask; |
| 1030 | tmp &= ~err_no_mask; | 1009 | tmp &= ~err_no_mask; |
| 1031 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); | 1010 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); |
| 1032 | 1011 | ||
| 1033 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, | 1012 | upa_writeq((SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | |
| 1034 | (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | | 1013 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | |
| 1035 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | | 1014 | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | |
| 1036 | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | | 1015 | SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | |
| 1037 | SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | | 1016 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | |
| 1038 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | | 1017 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS), |
| 1039 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); | 1018 | pbm->pbm_regs + SCHIZO_PCI_AFSR); |
| 1040 | 1019 | ||
| 1041 | /* Make all Safari error conditions fatal except unmapped | 1020 | /* Make all Safari error conditions fatal except unmapped |
| 1042 | * errors which we make generate interrupts. | 1021 | * errors which we make generate interrupts. |
| @@ -1063,8 +1042,8 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | |||
| 1063 | BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); | 1042 | BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); |
| 1064 | #endif | 1043 | #endif |
| 1065 | 1044 | ||
| 1066 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, | 1045 | upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), |
| 1067 | (SCHIZO_SAFERRCTRL_EN | err_mask)); | 1046 | pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); |
| 1068 | } | 1047 | } |
| 1069 | 1048 | ||
| 1070 | static void pbm_config_busmastering(struct pci_pbm_info *pbm) | 1049 | static void pbm_config_busmastering(struct pci_pbm_info *pbm) |
| @@ -1084,14 +1063,15 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) | |||
| 1084 | pci_config_write8(addr, 64); | 1063 | pci_config_write8(addr, 64); |
| 1085 | } | 1064 | } |
| 1086 | 1065 | ||
| 1087 | static void __init schizo_scan_bus(struct pci_pbm_info *pbm) | 1066 | static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm, |
| 1067 | struct device *parent) | ||
| 1088 | { | 1068 | { |
| 1089 | pbm_config_busmastering(pbm); | 1069 | pbm_config_busmastering(pbm); |
| 1090 | pbm->is_66mhz_capable = | 1070 | pbm->is_66mhz_capable = |
| 1091 | (of_find_property(pbm->prom_node, "66mhz-capable", NULL) | 1071 | (of_find_property(pbm->op->node, "66mhz-capable", NULL) |
| 1092 | != NULL); | 1072 | != NULL); |
| 1093 | 1073 | ||
| 1094 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 1074 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
| 1095 | 1075 | ||
| 1096 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) | 1076 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) |
| 1097 | tomatillo_register_error_handlers(pbm); | 1077 | tomatillo_register_error_handlers(pbm); |
| @@ -1133,12 +1113,12 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) | |||
| 1133 | * streaming buffer and leave the rerun-disable | 1113 | * streaming buffer and leave the rerun-disable |
| 1134 | * setting however OBP set it. | 1114 | * setting however OBP set it. |
| 1135 | */ | 1115 | */ |
| 1136 | control = schizo_read(pbm->stc.strbuf_control); | 1116 | control = upa_readq(pbm->stc.strbuf_control); |
| 1137 | control &= ~(SCHIZO_STRBUF_CTRL_LPTR | | 1117 | control &= ~(SCHIZO_STRBUF_CTRL_LPTR | |
| 1138 | SCHIZO_STRBUF_CTRL_LENAB | | 1118 | SCHIZO_STRBUF_CTRL_LENAB | |
| 1139 | SCHIZO_STRBUF_CTRL_DENAB); | 1119 | SCHIZO_STRBUF_CTRL_DENAB); |
| 1140 | control |= SCHIZO_STRBUF_CTRL_ENAB; | 1120 | control |= SCHIZO_STRBUF_CTRL_ENAB; |
| 1141 | schizo_write(pbm->stc.strbuf_control, control); | 1121 | upa_writeq(control, pbm->stc.strbuf_control); |
| 1142 | 1122 | ||
| 1143 | pbm->stc.strbuf_enabled = 1; | 1123 | pbm->stc.strbuf_enabled = 1; |
| 1144 | } | 1124 | } |
| @@ -1150,24 +1130,17 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) | |||
| 1150 | 1130 | ||
| 1151 | static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | 1131 | static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) |
| 1152 | { | 1132 | { |
| 1153 | struct iommu *iommu = pbm->iommu; | 1133 | static const u32 vdma_default[] = { 0xc0000000, 0x40000000 }; |
| 1154 | unsigned long i, tagbase, database; | 1134 | unsigned long i, tagbase, database; |
| 1155 | struct property *prop; | 1135 | struct iommu *iommu = pbm->iommu; |
| 1156 | u32 vdma[2], dma_mask; | ||
| 1157 | int tsbsize, err; | 1136 | int tsbsize, err; |
| 1137 | const u32 *vdma; | ||
| 1138 | u32 dma_mask; | ||
| 1158 | u64 control; | 1139 | u64 control; |
| 1159 | 1140 | ||
| 1160 | prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); | 1141 | vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); |
| 1161 | if (prop) { | 1142 | if (!vdma) |
| 1162 | u32 *val = prop->value; | 1143 | vdma = vdma_default; |
| 1163 | |||
| 1164 | vdma[0] = val[0]; | ||
| 1165 | vdma[1] = val[1]; | ||
| 1166 | } else { | ||
| 1167 | /* No property, use default values. */ | ||
| 1168 | vdma[0] = 0xc0000000; | ||
| 1169 | vdma[1] = 0x40000000; | ||
| 1170 | } | ||
| 1171 | 1144 | ||
| 1172 | dma_mask = vdma[0]; | 1145 | dma_mask = vdma[0]; |
| 1173 | switch (vdma[1]) { | 1146 | switch (vdma[1]) { |
| @@ -1187,9 +1160,9 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1187 | break; | 1160 | break; |
| 1188 | 1161 | ||
| 1189 | default: | 1162 | default: |
| 1190 | prom_printf("SCHIZO: strange virtual-dma size.\n"); | 1163 | printk(KERN_ERR PFX "Strange virtual-dma size.\n"); |
| 1191 | prom_halt(); | 1164 | return -EINVAL; |
| 1192 | }; | 1165 | } |
| 1193 | 1166 | ||
| 1194 | /* Register addresses, SCHIZO has iommu ctx flushing. */ | 1167 | /* Register addresses, SCHIZO has iommu ctx flushing. */ |
| 1195 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; | 1168 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; |
| @@ -1206,15 +1179,15 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1206 | /* | 1179 | /* |
| 1207 | * Invalidate TLB Entries. | 1180 | * Invalidate TLB Entries. |
| 1208 | */ | 1181 | */ |
| 1209 | control = schizo_read(iommu->iommu_control); | 1182 | control = upa_readq(iommu->iommu_control); |
| 1210 | control |= SCHIZO_IOMMU_CTRL_DENAB; | 1183 | control |= SCHIZO_IOMMU_CTRL_DENAB; |
| 1211 | schizo_write(iommu->iommu_control, control); | 1184 | upa_writeq(control, iommu->iommu_control); |
| 1212 | 1185 | ||
| 1213 | tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; | 1186 | tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; |
| 1214 | 1187 | ||
| 1215 | for(i = 0; i < 16; i++) { | 1188 | for (i = 0; i < 16; i++) { |
| 1216 | schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); | 1189 | upa_writeq(0, pbm->pbm_regs + tagbase + (i * 8UL)); |
| 1217 | schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); | 1190 | upa_writeq(0, pbm->pbm_regs + database + (i * 8UL)); |
| 1218 | } | 1191 | } |
| 1219 | 1192 | ||
| 1220 | /* Leave diag mode enabled for full-flushing done | 1193 | /* Leave diag mode enabled for full-flushing done |
| @@ -1222,12 +1195,14 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1222 | */ | 1195 | */ |
| 1223 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, | 1196 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, |
| 1224 | pbm->numa_node); | 1197 | pbm->numa_node); |
| 1225 | if (err) | 1198 | if (err) { |
| 1199 | printk(KERN_ERR PFX "iommu_table_init() fails with %d\n", err); | ||
| 1226 | return err; | 1200 | return err; |
| 1201 | } | ||
| 1227 | 1202 | ||
| 1228 | schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); | 1203 | upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); |
| 1229 | 1204 | ||
| 1230 | control = schizo_read(iommu->iommu_control); | 1205 | control = upa_readq(iommu->iommu_control); |
| 1231 | control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); | 1206 | control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); |
| 1232 | switch (tsbsize) { | 1207 | switch (tsbsize) { |
| 1233 | case 64: | 1208 | case 64: |
| @@ -1236,10 +1211,10 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1236 | case 128: | 1211 | case 128: |
| 1237 | control |= SCHIZO_IOMMU_TSBSZ_128K; | 1212 | control |= SCHIZO_IOMMU_TSBSZ_128K; |
| 1238 | break; | 1213 | break; |
| 1239 | }; | 1214 | } |
| 1240 | 1215 | ||
| 1241 | control |= SCHIZO_IOMMU_CTRL_ENAB; | 1216 | control |= SCHIZO_IOMMU_CTRL_ENAB; |
| 1242 | schizo_write(iommu->iommu_control, control); | 1217 | upa_writeq(control, iommu->iommu_control); |
| 1243 | 1218 | ||
| 1244 | return 0; | 1219 | return 0; |
| 1245 | } | 1220 | } |
| @@ -1280,12 +1255,11 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1280 | 1255 | ||
| 1281 | static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | 1256 | static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) |
| 1282 | { | 1257 | { |
| 1283 | struct property *prop; | ||
| 1284 | u64 tmp; | 1258 | u64 tmp; |
| 1285 | 1259 | ||
| 1286 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); | 1260 | upa_writeq(5, pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY); |
| 1287 | 1261 | ||
| 1288 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); | 1262 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); |
| 1289 | 1263 | ||
| 1290 | /* Enable arbiter for all PCI slots. */ | 1264 | /* Enable arbiter for all PCI slots. */ |
| 1291 | tmp |= 0xff; | 1265 | tmp |= 0xff; |
| @@ -1294,8 +1268,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
| 1294 | pbm->chip_version >= 0x2) | 1268 | pbm->chip_version >= 0x2) |
| 1295 | tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; | 1269 | tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; |
| 1296 | 1270 | ||
| 1297 | prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL); | 1271 | if (!of_find_property(pbm->op->node, "no-bus-parking", NULL)) |
| 1298 | if (!prop) | ||
| 1299 | tmp |= SCHIZO_PCICTRL_PARK; | 1272 | tmp |= SCHIZO_PCICTRL_PARK; |
| 1300 | else | 1273 | else |
| 1301 | tmp &= ~SCHIZO_PCICTRL_PARK; | 1274 | tmp &= ~SCHIZO_PCICTRL_PARK; |
| @@ -1311,13 +1284,13 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
| 1311 | SCHIZO_PCICTRL_RDO_PREF | | 1284 | SCHIZO_PCICTRL_RDO_PREF | |
| 1312 | SCHIZO_PCICTRL_RDL_PREF); | 1285 | SCHIZO_PCICTRL_RDL_PREF); |
| 1313 | 1286 | ||
| 1314 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); | 1287 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); |
| 1315 | 1288 | ||
| 1316 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG); | 1289 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_DIAG); |
| 1317 | tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | | 1290 | tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | |
| 1318 | SCHIZO_PCIDIAG_D_RETRY | | 1291 | SCHIZO_PCIDIAG_D_RETRY | |
| 1319 | SCHIZO_PCIDIAG_D_INTSYNC); | 1292 | SCHIZO_PCIDIAG_D_INTSYNC); |
| 1320 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp); | 1293 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_DIAG); |
| 1321 | 1294 | ||
| 1322 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { | 1295 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { |
| 1323 | /* Clear prefetch lengths to workaround a bug in | 1296 | /* Clear prefetch lengths to workaround a bug in |
| @@ -1329,17 +1302,16 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
| 1329 | TOMATILLO_IOC_RDONE_CPENAB | | 1302 | TOMATILLO_IOC_RDONE_CPENAB | |
| 1330 | TOMATILLO_IOC_RDLINE_CPENAB); | 1303 | TOMATILLO_IOC_RDLINE_CPENAB); |
| 1331 | 1304 | ||
| 1332 | schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR, | 1305 | upa_writeq(tmp, pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR); |
| 1333 | tmp); | ||
| 1334 | } | 1306 | } |
| 1335 | } | 1307 | } |
| 1336 | 1308 | ||
| 1337 | static int __init schizo_pbm_init(struct pci_controller_info *p, | 1309 | static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, |
| 1338 | struct device_node *dp, u32 portid, | 1310 | struct of_device *op, u32 portid, |
| 1339 | int chip_type) | 1311 | int chip_type) |
| 1340 | { | 1312 | { |
| 1341 | const struct linux_prom64_registers *regs; | 1313 | const struct linux_prom64_registers *regs; |
| 1342 | struct pci_pbm_info *pbm; | 1314 | struct device_node *dp = op->node; |
| 1343 | const char *chipset_name; | 1315 | const char *chipset_name; |
| 1344 | int is_pbm_a, err; | 1316 | int is_pbm_a, err; |
| 1345 | 1317 | ||
| @@ -1372,25 +1344,19 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, | |||
| 1372 | regs = of_get_property(dp, "reg", NULL); | 1344 | regs = of_get_property(dp, "reg", NULL); |
| 1373 | 1345 | ||
| 1374 | is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); | 1346 | is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); |
| 1375 | if (is_pbm_a) | ||
| 1376 | pbm = &p->pbm_A; | ||
| 1377 | else | ||
| 1378 | pbm = &p->pbm_B; | ||
| 1379 | 1347 | ||
| 1380 | pbm->next = pci_pbm_root; | 1348 | pbm->next = pci_pbm_root; |
| 1381 | pci_pbm_root = pbm; | 1349 | pci_pbm_root = pbm; |
| 1382 | 1350 | ||
| 1383 | pbm->numa_node = -1; | 1351 | pbm->numa_node = -1; |
| 1384 | 1352 | ||
| 1385 | pbm->scan_bus = schizo_scan_bus; | ||
| 1386 | pbm->pci_ops = &sun4u_pci_ops; | 1353 | pbm->pci_ops = &sun4u_pci_ops; |
| 1387 | pbm->config_space_reg_bits = 8; | 1354 | pbm->config_space_reg_bits = 8; |
| 1388 | 1355 | ||
| 1389 | pbm->index = pci_num_pbms++; | 1356 | pbm->index = pci_num_pbms++; |
| 1390 | 1357 | ||
| 1391 | pbm->portid = portid; | 1358 | pbm->portid = portid; |
| 1392 | pbm->parent = p; | 1359 | pbm->op = op; |
| 1393 | pbm->prom_node = dp; | ||
| 1394 | 1360 | ||
| 1395 | pbm->chip_type = chip_type; | 1361 | pbm->chip_type = chip_type; |
| 1396 | pbm->chip_version = of_getintprop_default(dp, "version#", 0); | 1362 | pbm->chip_version = of_getintprop_default(dp, "version#", 0); |
| @@ -1420,6 +1386,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, | |||
| 1420 | 1386 | ||
| 1421 | schizo_pbm_strbuf_init(pbm); | 1387 | schizo_pbm_strbuf_init(pbm); |
| 1422 | 1388 | ||
| 1389 | schizo_scan_bus(pbm, &op->dev); | ||
| 1390 | |||
| 1423 | return 0; | 1391 | return 0; |
| 1424 | } | 1392 | } |
| 1425 | 1393 | ||
| @@ -1433,62 +1401,104 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) | |||
| 1433 | return (x == y); | 1401 | return (x == y); |
| 1434 | } | 1402 | } |
| 1435 | 1403 | ||
| 1436 | static void __init __schizo_init(struct device_node *dp, char *model_name, | 1404 | static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid, |
| 1437 | int chip_type) | 1405 | int chip_type) |
| 1438 | { | 1406 | { |
| 1439 | struct pci_controller_info *p; | 1407 | struct pci_pbm_info *pbm; |
| 1408 | |||
| 1409 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | ||
| 1410 | if (portid_compare(pbm->portid, portid, chip_type)) | ||
| 1411 | return pbm; | ||
| 1412 | } | ||
| 1413 | return NULL; | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) | ||
| 1417 | { | ||
| 1418 | struct device_node *dp = op->node; | ||
| 1440 | struct pci_pbm_info *pbm; | 1419 | struct pci_pbm_info *pbm; |
| 1441 | struct iommu *iommu; | 1420 | struct iommu *iommu; |
| 1442 | u32 portid; | 1421 | u32 portid; |
| 1422 | int err; | ||
| 1443 | 1423 | ||
| 1444 | portid = of_getintprop_default(dp, "portid", 0xff); | 1424 | portid = of_getintprop_default(dp, "portid", 0xff); |
| 1445 | 1425 | ||
| 1446 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 1426 | err = -ENOMEM; |
| 1447 | if (portid_compare(pbm->portid, portid, chip_type)) { | 1427 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
| 1448 | if (schizo_pbm_init(pbm->parent, dp, | 1428 | if (!pbm) { |
| 1449 | portid, chip_type)) | 1429 | printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); |
| 1450 | goto fatal_memory_error; | 1430 | goto out_err; |
| 1451 | return; | 1431 | } |
| 1452 | } | 1432 | |
| 1433 | pbm->sibling = schizo_find_sibling(portid, chip_type); | ||
| 1434 | |||
| 1435 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); | ||
| 1436 | if (!iommu) { | ||
| 1437 | printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); | ||
| 1438 | goto out_free_pbm; | ||
| 1453 | } | 1439 | } |
| 1454 | 1440 | ||
| 1455 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 1441 | pbm->iommu = iommu; |
| 1456 | if (!p) | ||
| 1457 | goto fatal_memory_error; | ||
| 1458 | 1442 | ||
| 1459 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1443 | if (schizo_pbm_init(pbm, op, portid, chip_type)) |
| 1460 | if (!iommu) | 1444 | goto out_free_iommu; |
| 1461 | goto fatal_memory_error; | ||
| 1462 | 1445 | ||
| 1463 | p->pbm_A.iommu = iommu; | 1446 | if (pbm->sibling) |
| 1447 | pbm->sibling->sibling = pbm; | ||
| 1464 | 1448 | ||
| 1465 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1449 | dev_set_drvdata(&op->dev, pbm); |
| 1466 | if (!iommu) | ||
| 1467 | goto fatal_memory_error; | ||
| 1468 | 1450 | ||
| 1469 | p->pbm_B.iommu = iommu; | 1451 | return 0; |
| 1470 | 1452 | ||
| 1471 | if (schizo_pbm_init(p, dp, portid, chip_type)) | 1453 | out_free_iommu: |
| 1472 | goto fatal_memory_error; | 1454 | kfree(pbm->iommu); |
| 1473 | 1455 | ||
| 1474 | return; | 1456 | out_free_pbm: |
| 1457 | kfree(pbm); | ||
| 1475 | 1458 | ||
| 1476 | fatal_memory_error: | 1459 | out_err: |
| 1477 | prom_printf("SCHIZO: Fatal memory allocation error.\n"); | 1460 | return err; |
| 1478 | prom_halt(); | ||
| 1479 | } | 1461 | } |
| 1480 | 1462 | ||
| 1481 | void __init schizo_init(struct device_node *dp, char *model_name) | 1463 | static int __devinit schizo_probe(struct of_device *op, |
| 1464 | const struct of_device_id *match) | ||
| 1482 | { | 1465 | { |
| 1483 | __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO); | 1466 | return __schizo_init(op, (unsigned long) match->data); |
| 1484 | } | 1467 | } |
| 1485 | 1468 | ||
| 1486 | void __init schizo_plus_init(struct device_node *dp, char *model_name) | 1469 | /* The ordering of this table is very important. Some Tomatillo |
| 1487 | { | 1470 | * nodes announce that they are compatible with both pci108e,a801 |
| 1488 | __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); | 1471 | * and pci108e,8001. So list the chips in reverse chronological |
| 1489 | } | 1472 | * order. |
| 1473 | */ | ||
| 1474 | static struct of_device_id __initdata schizo_match[] = { | ||
| 1475 | { | ||
| 1476 | .name = "pci", | ||
| 1477 | .compatible = "pci108e,a801", | ||
| 1478 | .data = (void *) PBM_CHIP_TYPE_TOMATILLO, | ||
| 1479 | }, | ||
| 1480 | { | ||
| 1481 | .name = "pci", | ||
| 1482 | .compatible = "pci108e,8002", | ||
| 1483 | .data = (void *) PBM_CHIP_TYPE_SCHIZO_PLUS, | ||
| 1484 | }, | ||
| 1485 | { | ||
| 1486 | .name = "pci", | ||
| 1487 | .compatible = "pci108e,8001", | ||
| 1488 | .data = (void *) PBM_CHIP_TYPE_SCHIZO, | ||
| 1489 | }, | ||
| 1490 | {}, | ||
| 1491 | }; | ||
| 1490 | 1492 | ||
| 1491 | void __init tomatillo_init(struct device_node *dp, char *model_name) | 1493 | static struct of_platform_driver schizo_driver = { |
| 1494 | .name = DRIVER_NAME, | ||
| 1495 | .match_table = schizo_match, | ||
| 1496 | .probe = schizo_probe, | ||
| 1497 | }; | ||
| 1498 | |||
| 1499 | static int __init schizo_init(void) | ||
| 1492 | { | 1500 | { |
| 1493 | __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO); | 1501 | return of_register_driver(&schizo_driver, &of_bus_type); |
| 1494 | } | 1502 | } |
| 1503 | |||
| 1504 | subsys_initcall(schizo_init); | ||
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index a104c80d319d..e86c73ec167b 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
| @@ -13,12 +13,10 @@ | |||
| 13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
| 14 | #include <linux/msi.h> | 14 | #include <linux/msi.h> |
| 15 | #include <linux/log2.h> | 15 | #include <linux/log2.h> |
| 16 | #include <linux/of_device.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/iommu.h> | 18 | #include <asm/iommu.h> |
| 18 | #include <asm/irq.h> | 19 | #include <asm/irq.h> |
| 19 | #include <asm/upa.h> | ||
| 20 | #include <asm/pstate.h> | ||
| 21 | #include <asm/oplib.h> | ||
| 22 | #include <asm/hypervisor.h> | 20 | #include <asm/hypervisor.h> |
| 23 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
| 24 | 22 | ||
| @@ -27,6 +25,9 @@ | |||
| 27 | 25 | ||
| 28 | #include "pci_sun4v.h" | 26 | #include "pci_sun4v.h" |
| 29 | 27 | ||
| 28 | #define DRIVER_NAME "pci_sun4v" | ||
| 29 | #define PFX DRIVER_NAME ": " | ||
| 30 | |||
| 30 | static unsigned long vpci_major = 1; | 31 | static unsigned long vpci_major = 1; |
| 31 | static unsigned long vpci_minor = 1; | 32 | static unsigned long vpci_minor = 1; |
| 32 | 33 | ||
| @@ -41,6 +42,7 @@ struct iommu_batch { | |||
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | static DEFINE_PER_CPU(struct iommu_batch, iommu_batch); | 44 | static DEFINE_PER_CPU(struct iommu_batch, iommu_batch); |
| 45 | static int iommu_batch_initialized; | ||
| 44 | 46 | ||
| 45 | /* Interrupts must be disabled. */ | 47 | /* Interrupts must be disabled. */ |
| 46 | static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry) | 48 | static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry) |
| @@ -542,15 +544,16 @@ static const struct dma_ops sun4v_dma_ops = { | |||
| 542 | .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu, | 544 | .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu, |
| 543 | }; | 545 | }; |
| 544 | 546 | ||
| 545 | static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm) | 547 | static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm, |
| 548 | struct device *parent) | ||
| 546 | { | 549 | { |
| 547 | struct property *prop; | 550 | struct property *prop; |
| 548 | struct device_node *dp; | 551 | struct device_node *dp; |
| 549 | 552 | ||
| 550 | dp = pbm->prom_node; | 553 | dp = pbm->op->node; |
| 551 | prop = of_find_property(dp, "66mhz-capable", NULL); | 554 | prop = of_find_property(dp, "66mhz-capable", NULL); |
| 552 | pbm->is_66mhz_capable = (prop != NULL); | 555 | pbm->is_66mhz_capable = (prop != NULL); |
| 553 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 556 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
| 554 | 557 | ||
| 555 | /* XXX register error interrupt handlers XXX */ | 558 | /* XXX register error interrupt handlers XXX */ |
| 556 | } | 559 | } |
| @@ -583,29 +586,22 @@ static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm, | |||
| 583 | return cnt; | 586 | return cnt; |
| 584 | } | 587 | } |
| 585 | 588 | ||
| 586 | static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | 589 | static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) |
| 587 | { | 590 | { |
| 591 | static const u32 vdma_default[] = { 0x80000000, 0x80000000 }; | ||
| 588 | struct iommu *iommu = pbm->iommu; | 592 | struct iommu *iommu = pbm->iommu; |
| 589 | struct property *prop; | ||
| 590 | unsigned long num_tsb_entries, sz, tsbsize; | 593 | unsigned long num_tsb_entries, sz, tsbsize; |
| 591 | u32 vdma[2], dma_mask, dma_offset; | 594 | u32 dma_mask, dma_offset; |
| 592 | 595 | const u32 *vdma; | |
| 593 | prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); | 596 | |
| 594 | if (prop) { | 597 | vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); |
| 595 | u32 *val = prop->value; | 598 | if (!vdma) |
| 596 | 599 | vdma = vdma_default; | |
| 597 | vdma[0] = val[0]; | ||
| 598 | vdma[1] = val[1]; | ||
| 599 | } else { | ||
| 600 | /* No property, use default values. */ | ||
| 601 | vdma[0] = 0x80000000; | ||
| 602 | vdma[1] = 0x80000000; | ||
| 603 | } | ||
| 604 | 600 | ||
| 605 | if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { | 601 | if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { |
| 606 | prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n", | 602 | printk(KERN_ERR PFX "Strange virtual-dma[%08x:%08x].\n", |
| 607 | vdma[0], vdma[1]); | 603 | vdma[0], vdma[1]); |
| 608 | prom_halt(); | 604 | return -EINVAL; |
| 609 | }; | 605 | }; |
| 610 | 606 | ||
| 611 | dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); | 607 | dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); |
| @@ -625,8 +621,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
| 625 | sz = (sz + 7UL) & ~7UL; | 621 | sz = (sz + 7UL) & ~7UL; |
| 626 | iommu->arena.map = kzalloc(sz, GFP_KERNEL); | 622 | iommu->arena.map = kzalloc(sz, GFP_KERNEL); |
| 627 | if (!iommu->arena.map) { | 623 | if (!iommu->arena.map) { |
| 628 | prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); | 624 | printk(KERN_ERR PFX "Error, kmalloc(arena.map) failed.\n"); |
| 629 | prom_halt(); | 625 | return -ENOMEM; |
| 630 | } | 626 | } |
| 631 | iommu->arena.limit = num_tsb_entries; | 627 | iommu->arena.limit = num_tsb_entries; |
| 632 | 628 | ||
| @@ -634,6 +630,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
| 634 | if (sz) | 630 | if (sz) |
| 635 | printk("%s: Imported %lu TSB entries from OBP\n", | 631 | printk("%s: Imported %lu TSB entries from OBP\n", |
| 636 | pbm->name, sz); | 632 | pbm->name, sz); |
| 633 | |||
| 634 | return 0; | ||
| 637 | } | 635 | } |
| 638 | 636 | ||
| 639 | #ifdef CONFIG_PCI_MSI | 637 | #ifdef CONFIG_PCI_MSI |
| @@ -890,29 +888,20 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | |||
| 890 | } | 888 | } |
| 891 | #endif /* !(CONFIG_PCI_MSI) */ | 889 | #endif /* !(CONFIG_PCI_MSI) */ |
| 892 | 890 | ||
| 893 | static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, | 891 | static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm, |
| 894 | struct device_node *dp, u32 devhandle) | 892 | struct of_device *op, u32 devhandle) |
| 895 | { | 893 | { |
| 896 | struct pci_pbm_info *pbm; | 894 | struct device_node *dp = op->node; |
| 897 | 895 | int err; | |
| 898 | if (devhandle & 0x40) | ||
| 899 | pbm = &p->pbm_B; | ||
| 900 | else | ||
| 901 | pbm = &p->pbm_A; | ||
| 902 | |||
| 903 | pbm->next = pci_pbm_root; | ||
| 904 | pci_pbm_root = pbm; | ||
| 905 | 896 | ||
| 906 | pbm->numa_node = of_node_to_nid(dp); | 897 | pbm->numa_node = of_node_to_nid(dp); |
| 907 | 898 | ||
| 908 | pbm->scan_bus = pci_sun4v_scan_bus; | ||
| 909 | pbm->pci_ops = &sun4v_pci_ops; | 899 | pbm->pci_ops = &sun4v_pci_ops; |
| 910 | pbm->config_space_reg_bits = 12; | 900 | pbm->config_space_reg_bits = 12; |
| 911 | 901 | ||
| 912 | pbm->index = pci_num_pbms++; | 902 | pbm->index = pci_num_pbms++; |
| 913 | 903 | ||
| 914 | pbm->parent = p; | 904 | pbm->op = op; |
| 915 | pbm->prom_node = dp; | ||
| 916 | 905 | ||
| 917 | pbm->devhandle = devhandle; | 906 | pbm->devhandle = devhandle; |
| 918 | 907 | ||
| @@ -924,82 +913,120 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, | |||
| 924 | pci_determine_mem_io_space(pbm); | 913 | pci_determine_mem_io_space(pbm); |
| 925 | 914 | ||
| 926 | pci_get_pbm_props(pbm); | 915 | pci_get_pbm_props(pbm); |
| 927 | pci_sun4v_iommu_init(pbm); | 916 | |
| 917 | err = pci_sun4v_iommu_init(pbm); | ||
| 918 | if (err) | ||
| 919 | return err; | ||
| 920 | |||
| 928 | pci_sun4v_msi_init(pbm); | 921 | pci_sun4v_msi_init(pbm); |
| 922 | |||
| 923 | pci_sun4v_scan_bus(pbm, &op->dev); | ||
| 924 | |||
| 925 | pbm->next = pci_pbm_root; | ||
| 926 | pci_pbm_root = pbm; | ||
| 927 | |||
| 928 | return 0; | ||
| 929 | } | 929 | } |
| 930 | 930 | ||
| 931 | void __init sun4v_pci_init(struct device_node *dp, char *model_name) | 931 | static int __devinit pci_sun4v_probe(struct of_device *op, |
| 932 | const struct of_device_id *match) | ||
| 932 | { | 933 | { |
| 934 | const struct linux_prom64_registers *regs; | ||
| 933 | static int hvapi_negotiated = 0; | 935 | static int hvapi_negotiated = 0; |
| 934 | struct pci_controller_info *p; | ||
| 935 | struct pci_pbm_info *pbm; | 936 | struct pci_pbm_info *pbm; |
| 937 | struct device_node *dp; | ||
| 936 | struct iommu *iommu; | 938 | struct iommu *iommu; |
| 937 | struct property *prop; | ||
| 938 | struct linux_prom64_registers *regs; | ||
| 939 | u32 devhandle; | 939 | u32 devhandle; |
| 940 | int i; | 940 | int i, err; |
| 941 | |||
| 942 | dp = op->node; | ||
| 941 | 943 | ||
| 942 | if (!hvapi_negotiated++) { | 944 | if (!hvapi_negotiated++) { |
| 943 | int err = sun4v_hvapi_register(HV_GRP_PCI, | 945 | err = sun4v_hvapi_register(HV_GRP_PCI, |
| 944 | vpci_major, | 946 | vpci_major, |
| 945 | &vpci_minor); | 947 | &vpci_minor); |
| 946 | 948 | ||
| 947 | if (err) { | 949 | if (err) { |
| 948 | prom_printf("SUN4V_PCI: Could not register hvapi, " | 950 | printk(KERN_ERR PFX "Could not register hvapi, " |
| 949 | "err=%d\n", err); | 951 | "err=%d\n", err); |
| 950 | prom_halt(); | 952 | return err; |
| 951 | } | 953 | } |
| 952 | printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n", | 954 | printk(KERN_INFO PFX "Registered hvapi major[%lu] minor[%lu]\n", |
| 953 | vpci_major, vpci_minor); | 955 | vpci_major, vpci_minor); |
| 954 | 956 | ||
| 955 | dma_ops = &sun4v_dma_ops; | 957 | dma_ops = &sun4v_dma_ops; |
| 956 | } | 958 | } |
| 957 | 959 | ||
| 958 | prop = of_find_property(dp, "reg", NULL); | 960 | regs = of_get_property(dp, "reg", NULL); |
| 959 | if (!prop) { | 961 | err = -ENODEV; |
| 960 | prom_printf("SUN4V_PCI: Could not find config registers\n"); | 962 | if (!regs) { |
| 961 | prom_halt(); | 963 | printk(KERN_ERR PFX "Could not find config registers\n"); |
| 964 | goto out_err; | ||
| 962 | } | 965 | } |
| 963 | regs = prop->value; | ||
| 964 | |||
| 965 | devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; | 966 | devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; |
| 966 | 967 | ||
| 967 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 968 | err = -ENOMEM; |
| 968 | if (pbm->devhandle == (devhandle ^ 0x40)) { | 969 | if (!iommu_batch_initialized) { |
| 969 | pci_sun4v_pbm_init(pbm->parent, dp, devhandle); | 970 | for_each_possible_cpu(i) { |
| 970 | return; | 971 | unsigned long page = get_zeroed_page(GFP_KERNEL); |
| 972 | |||
| 973 | if (!page) | ||
| 974 | goto out_err; | ||
| 975 | |||
| 976 | per_cpu(iommu_batch, i).pglist = (u64 *) page; | ||
| 971 | } | 977 | } |
| 978 | iommu_batch_initialized = 1; | ||
| 972 | } | 979 | } |
| 973 | 980 | ||
| 974 | for_each_possible_cpu(i) { | 981 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
| 975 | unsigned long page = get_zeroed_page(GFP_ATOMIC); | 982 | if (!pbm) { |
| 976 | 983 | printk(KERN_ERR PFX "Could not allocate pci_pbm_info\n"); | |
| 977 | if (!page) | 984 | goto out_err; |
| 978 | goto fatal_memory_error; | 985 | } |
| 979 | 986 | ||
| 980 | per_cpu(iommu_batch, i).pglist = (u64 *) page; | 987 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); |
| 988 | if (!iommu) { | ||
| 989 | printk(KERN_ERR PFX "Could not allocate pbm iommu\n"); | ||
| 990 | goto out_free_controller; | ||
| 981 | } | 991 | } |
| 982 | 992 | ||
| 983 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 993 | pbm->iommu = iommu; |
| 984 | if (!p) | ||
| 985 | goto fatal_memory_error; | ||
| 986 | 994 | ||
| 987 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 995 | err = pci_sun4v_pbm_init(pbm, op, devhandle); |
| 988 | if (!iommu) | 996 | if (err) |
| 989 | goto fatal_memory_error; | 997 | goto out_free_iommu; |
| 998 | |||
| 999 | dev_set_drvdata(&op->dev, pbm); | ||
| 1000 | |||
| 1001 | return 0; | ||
| 1002 | |||
| 1003 | out_free_iommu: | ||
| 1004 | kfree(pbm->iommu); | ||
| 990 | 1005 | ||
| 991 | p->pbm_A.iommu = iommu; | 1006 | out_free_controller: |
| 1007 | kfree(pbm); | ||
| 992 | 1008 | ||
| 993 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1009 | out_err: |
| 994 | if (!iommu) | 1010 | return err; |
| 995 | goto fatal_memory_error; | 1011 | } |
| 996 | 1012 | ||
| 997 | p->pbm_B.iommu = iommu; | 1013 | static struct of_device_id __initdata pci_sun4v_match[] = { |
| 1014 | { | ||
| 1015 | .name = "pci", | ||
| 1016 | .compatible = "SUNW,sun4v-pci", | ||
| 1017 | }, | ||
| 1018 | {}, | ||
| 1019 | }; | ||
| 998 | 1020 | ||
| 999 | pci_sun4v_pbm_init(p, dp, devhandle); | 1021 | static struct of_platform_driver pci_sun4v_driver = { |
| 1000 | return; | 1022 | .name = DRIVER_NAME, |
| 1023 | .match_table = pci_sun4v_match, | ||
| 1024 | .probe = pci_sun4v_probe, | ||
| 1025 | }; | ||
| 1001 | 1026 | ||
| 1002 | fatal_memory_error: | 1027 | static int __init pci_sun4v_init(void) |
| 1003 | prom_printf("SUN4V_PCI: Fatal memory allocation error.\n"); | 1028 | { |
| 1004 | prom_halt(); | 1029 | return of_register_driver(&pci_sun4v_driver, &of_bus_type); |
| 1005 | } | 1030 | } |
| 1031 | |||
| 1032 | subsys_initcall(pci_sun4v_init); | ||
diff --git a/arch/sparc64/kernel/pci_sun4v_asm.S b/arch/sparc64/kernel/pci_sun4v_asm.S index ecb81f389b06..e606d46c6815 100644 --- a/arch/sparc64/kernel/pci_sun4v_asm.S +++ b/arch/sparc64/kernel/pci_sun4v_asm.S | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | /* pci_sun4v_asm: Hypervisor calls for PCI support. | 1 | /* pci_sun4v_asm: Hypervisor calls for PCI support. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2006 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2006, 2008 David S. Miller <davem@davemloft.net> |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/linkage.h> | ||
| 6 | #include <asm/hypervisor.h> | 7 | #include <asm/hypervisor.h> |
| 7 | 8 | ||
| 8 | /* %o0: devhandle | 9 | /* %o0: devhandle |
| @@ -14,8 +15,7 @@ | |||
| 14 | * returns %o0: -status if status was non-zero, else | 15 | * returns %o0: -status if status was non-zero, else |
| 15 | * %o0: num pages mapped | 16 | * %o0: num pages mapped |
| 16 | */ | 17 | */ |
| 17 | .globl pci_sun4v_iommu_map | 18 | ENTRY(pci_sun4v_iommu_map) |
| 18 | pci_sun4v_iommu_map: | ||
| 19 | mov %o5, %g1 | 19 | mov %o5, %g1 |
| 20 | mov HV_FAST_PCI_IOMMU_MAP, %o5 | 20 | mov HV_FAST_PCI_IOMMU_MAP, %o5 |
| 21 | ta HV_FAST_TRAP | 21 | ta HV_FAST_TRAP |
| @@ -24,6 +24,7 @@ pci_sun4v_iommu_map: | |||
| 24 | mov %o1, %o0 | 24 | mov %o1, %o0 |
| 25 | 1: retl | 25 | 1: retl |
| 26 | nop | 26 | nop |
| 27 | ENDPROC(pci_sun4v_iommu_map) | ||
| 27 | 28 | ||
| 28 | /* %o0: devhandle | 29 | /* %o0: devhandle |
| 29 | * %o1: tsbid | 30 | * %o1: tsbid |
| @@ -31,12 +32,12 @@ pci_sun4v_iommu_map: | |||
| 31 | * | 32 | * |
| 32 | * returns %o0: num ttes demapped | 33 | * returns %o0: num ttes demapped |
| 33 | */ | 34 | */ |
| 34 | .globl pci_sun4v_iommu_demap | 35 | ENTRY(pci_sun4v_iommu_demap) |
| 35 | pci_sun4v_iommu_demap: | ||
| 36 | mov HV_FAST_PCI_IOMMU_DEMAP, %o5 | 36 | mov HV_FAST_PCI_IOMMU_DEMAP, %o5 |
| 37 | ta HV_FAST_TRAP | 37 | ta HV_FAST_TRAP |
| 38 | retl | 38 | retl |
| 39 | mov %o1, %o0 | 39 | mov %o1, %o0 |
| 40 | ENDPROC(pci_sun4v_iommu_demap) | ||
| 40 | 41 | ||
| 41 | /* %o0: devhandle | 42 | /* %o0: devhandle |
| 42 | * %o1: tsbid | 43 | * %o1: tsbid |
| @@ -45,8 +46,7 @@ pci_sun4v_iommu_demap: | |||
| 45 | * | 46 | * |
| 46 | * returns %o0: status | 47 | * returns %o0: status |
| 47 | */ | 48 | */ |
| 48 | .globl pci_sun4v_iommu_getmap | 49 | ENTRY(pci_sun4v_iommu_getmap) |
| 49 | pci_sun4v_iommu_getmap: | ||
| 50 | mov %o2, %o4 | 50 | mov %o2, %o4 |
| 51 | mov HV_FAST_PCI_IOMMU_GETMAP, %o5 | 51 | mov HV_FAST_PCI_IOMMU_GETMAP, %o5 |
| 52 | ta HV_FAST_TRAP | 52 | ta HV_FAST_TRAP |
| @@ -54,6 +54,7 @@ pci_sun4v_iommu_getmap: | |||
| 54 | stx %o2, [%o3] | 54 | stx %o2, [%o3] |
| 55 | retl | 55 | retl |
| 56 | mov %o0, %o0 | 56 | mov %o0, %o0 |
| 57 | ENDPROC(pci_sun4v_iommu_getmap) | ||
| 57 | 58 | ||
| 58 | /* %o0: devhandle | 59 | /* %o0: devhandle |
| 59 | * %o1: pci_device | 60 | * %o1: pci_device |
| @@ -65,14 +66,14 @@ pci_sun4v_iommu_getmap: | |||
| 65 | * If there is an error, the data will be returned | 66 | * If there is an error, the data will be returned |
| 66 | * as all 1's. | 67 | * as all 1's. |
| 67 | */ | 68 | */ |
| 68 | .globl pci_sun4v_config_get | 69 | ENTRY(pci_sun4v_config_get) |
| 69 | pci_sun4v_config_get: | ||
| 70 | mov HV_FAST_PCI_CONFIG_GET, %o5 | 70 | mov HV_FAST_PCI_CONFIG_GET, %o5 |
| 71 | ta HV_FAST_TRAP | 71 | ta HV_FAST_TRAP |
| 72 | brnz,a,pn %o1, 1f | 72 | brnz,a,pn %o1, 1f |
| 73 | mov -1, %o2 | 73 | mov -1, %o2 |
| 74 | 1: retl | 74 | 1: retl |
| 75 | mov %o2, %o0 | 75 | mov %o2, %o0 |
| 76 | ENDPROC(pci_sun4v_config_get) | ||
| 76 | 77 | ||
| 77 | /* %o0: devhandle | 78 | /* %o0: devhandle |
| 78 | * %o1: pci_device | 79 | * %o1: pci_device |
| @@ -85,14 +86,14 @@ pci_sun4v_config_get: | |||
| 85 | * status will be zero if the operation completed | 86 | * status will be zero if the operation completed |
| 86 | * successfully, else -1 if not | 87 | * successfully, else -1 if not |
| 87 | */ | 88 | */ |
| 88 | .globl pci_sun4v_config_put | 89 | ENTRY(pci_sun4v_config_put) |
| 89 | pci_sun4v_config_put: | ||
| 90 | mov HV_FAST_PCI_CONFIG_PUT, %o5 | 90 | mov HV_FAST_PCI_CONFIG_PUT, %o5 |
| 91 | ta HV_FAST_TRAP | 91 | ta HV_FAST_TRAP |
| 92 | brnz,a,pn %o1, 1f | 92 | brnz,a,pn %o1, 1f |
| 93 | mov -1, %o1 | 93 | mov -1, %o1 |
| 94 | 1: retl | 94 | 1: retl |
| 95 | mov %o1, %o0 | 95 | mov %o1, %o0 |
| 96 | ENDPROC(pci_sun4v_config_put) | ||
| 96 | 97 | ||
| 97 | /* %o0: devhandle | 98 | /* %o0: devhandle |
| 98 | * %o1: msiqid | 99 | * %o1: msiqid |
| @@ -104,12 +105,12 @@ pci_sun4v_config_put: | |||
| 104 | * status will be zero if the operation completed | 105 | * status will be zero if the operation completed |
| 105 | * successfully, else -1 if not | 106 | * successfully, else -1 if not |
| 106 | */ | 107 | */ |
| 107 | .globl pci_sun4v_msiq_conf | 108 | ENTRY(pci_sun4v_msiq_conf) |
| 108 | pci_sun4v_msiq_conf: | ||
| 109 | mov HV_FAST_PCI_MSIQ_CONF, %o5 | 109 | mov HV_FAST_PCI_MSIQ_CONF, %o5 |
| 110 | ta HV_FAST_TRAP | 110 | ta HV_FAST_TRAP |
| 111 | retl | 111 | retl |
| 112 | mov %o0, %o0 | 112 | mov %o0, %o0 |
| 113 | ENDPROC(pci_sun4v_msiq_conf) | ||
| 113 | 114 | ||
| 114 | /* %o0: devhandle | 115 | /* %o0: devhandle |
| 115 | * %o1: msiqid | 116 | * %o1: msiqid |
| @@ -118,8 +119,7 @@ pci_sun4v_msiq_conf: | |||
| 118 | * | 119 | * |
| 119 | * returns %o0: status | 120 | * returns %o0: status |
| 120 | */ | 121 | */ |
| 121 | .globl pci_sun4v_msiq_info | 122 | ENTRY(pci_sun4v_msiq_info) |
| 122 | pci_sun4v_msiq_info: | ||
| 123 | mov %o2, %o4 | 123 | mov %o2, %o4 |
| 124 | mov HV_FAST_PCI_MSIQ_INFO, %o5 | 124 | mov HV_FAST_PCI_MSIQ_INFO, %o5 |
| 125 | ta HV_FAST_TRAP | 125 | ta HV_FAST_TRAP |
| @@ -127,6 +127,7 @@ pci_sun4v_msiq_info: | |||
| 127 | stx %o2, [%o3] | 127 | stx %o2, [%o3] |
| 128 | retl | 128 | retl |
| 129 | mov %o0, %o0 | 129 | mov %o0, %o0 |
| 130 | ENDPROC(pci_sun4v_msiq_info) | ||
| 130 | 131 | ||
| 131 | /* %o0: devhandle | 132 | /* %o0: devhandle |
| 132 | * %o1: msiqid | 133 | * %o1: msiqid |
| @@ -134,13 +135,13 @@ pci_sun4v_msiq_info: | |||
| 134 | * | 135 | * |
| 135 | * returns %o0: status | 136 | * returns %o0: status |
| 136 | */ | 137 | */ |
| 137 | .globl pci_sun4v_msiq_getvalid | 138 | ENTRY(pci_sun4v_msiq_getvalid) |
| 138 | pci_sun4v_msiq_getvalid: | ||
| 139 | mov HV_FAST_PCI_MSIQ_GETVALID, %o5 | 139 | mov HV_FAST_PCI_MSIQ_GETVALID, %o5 |
| 140 | ta HV_FAST_TRAP | 140 | ta HV_FAST_TRAP |
| 141 | stx %o1, [%o2] | 141 | stx %o1, [%o2] |
| 142 | retl | 142 | retl |
| 143 | mov %o0, %o0 | 143 | mov %o0, %o0 |
| 144 | ENDPROC(pci_sun4v_msiq_getvalid) | ||
| 144 | 145 | ||
| 145 | /* %o0: devhandle | 146 | /* %o0: devhandle |
| 146 | * %o1: msiqid | 147 | * %o1: msiqid |
| @@ -148,12 +149,12 @@ pci_sun4v_msiq_getvalid: | |||
| 148 | * | 149 | * |
| 149 | * returns %o0: status | 150 | * returns %o0: status |
| 150 | */ | 151 | */ |
| 151 | .globl pci_sun4v_msiq_setvalid | 152 | ENTRY(pci_sun4v_msiq_setvalid) |
| 152 | pci_sun4v_msiq_setvalid: | ||
| 153 | mov HV_FAST_PCI_MSIQ_SETVALID, %o5 | 153 | mov HV_FAST_PCI_MSIQ_SETVALID, %o5 |
| 154 | ta HV_FAST_TRAP | 154 | ta HV_FAST_TRAP |
| 155 | retl | 155 | retl |
| 156 | mov %o0, %o0 | 156 | mov %o0, %o0 |
| 157 | ENDPROC(pci_sun4v_msiq_setvalid) | ||
| 157 | 158 | ||
| 158 | /* %o0: devhandle | 159 | /* %o0: devhandle |
| 159 | * %o1: msiqid | 160 | * %o1: msiqid |
| @@ -161,13 +162,13 @@ pci_sun4v_msiq_setvalid: | |||
| 161 | * | 162 | * |
| 162 | * returns %o0: status | 163 | * returns %o0: status |
| 163 | */ | 164 | */ |
| 164 | .globl pci_sun4v_msiq_getstate | 165 | ENTRY(pci_sun4v_msiq_getstate) |
| 165 | pci_sun4v_msiq_getstate: | ||
| 166 | mov HV_FAST_PCI_MSIQ_GETSTATE, %o5 | 166 | mov HV_FAST_PCI_MSIQ_GETSTATE, %o5 |
| 167 | ta HV_FAST_TRAP | 167 | ta HV_FAST_TRAP |
| 168 | stx %o1, [%o2] | 168 | stx %o1, [%o2] |
| 169 | retl | 169 | retl |
| 170 | mov %o0, %o0 | 170 | mov %o0, %o0 |
| 171 | ENDPROC(pci_sun4v_msiq_getstate) | ||
| 171 | 172 | ||
| 172 | /* %o0: devhandle | 173 | /* %o0: devhandle |
| 173 | * %o1: msiqid | 174 | * %o1: msiqid |
| @@ -175,12 +176,12 @@ pci_sun4v_msiq_getstate: | |||
| 175 | * | 176 | * |
| 176 | * returns %o0: status | 177 | * returns %o0: status |
| 177 | */ | 178 | */ |
| 178 | .globl pci_sun4v_msiq_setstate | 179 | ENTRY(pci_sun4v_msiq_setstate) |
| 179 | pci_sun4v_msiq_setstate: | ||
| 180 | mov HV_FAST_PCI_MSIQ_SETSTATE, %o5 | 180 | mov HV_FAST_PCI_MSIQ_SETSTATE, %o5 |
| 181 | ta HV_FAST_TRAP | 181 | ta HV_FAST_TRAP |
| 182 | retl | 182 | retl |
| 183 | mov %o0, %o0 | 183 | mov %o0, %o0 |
| 184 | ENDPROC(pci_sun4v_msiq_setstate) | ||
| 184 | 185 | ||
| 185 | /* %o0: devhandle | 186 | /* %o0: devhandle |
| 186 | * %o1: msiqid | 187 | * %o1: msiqid |
| @@ -188,13 +189,13 @@ pci_sun4v_msiq_setstate: | |||
| 188 | * | 189 | * |
| 189 | * returns %o0: status | 190 | * returns %o0: status |
| 190 | */ | 191 | */ |
| 191 | .globl pci_sun4v_msiq_gethead | 192 | ENTRY(pci_sun4v_msiq_gethead) |
| 192 | pci_sun4v_msiq_gethead: | ||
| 193 | mov HV_FAST_PCI_MSIQ_GETHEAD, %o5 | 193 | mov HV_FAST_PCI_MSIQ_GETHEAD, %o5 |
| 194 | ta HV_FAST_TRAP | 194 | ta HV_FAST_TRAP |
| 195 | stx %o1, [%o2] | 195 | stx %o1, [%o2] |
| 196 | retl | 196 | retl |
| 197 | mov %o0, %o0 | 197 | mov %o0, %o0 |
| 198 | ENDPROC(pci_sun4v_msiq_gethead) | ||
| 198 | 199 | ||
| 199 | /* %o0: devhandle | 200 | /* %o0: devhandle |
| 200 | * %o1: msiqid | 201 | * %o1: msiqid |
| @@ -202,12 +203,12 @@ pci_sun4v_msiq_gethead: | |||
| 202 | * | 203 | * |
| 203 | * returns %o0: status | 204 | * returns %o0: status |
| 204 | */ | 205 | */ |
| 205 | .globl pci_sun4v_msiq_sethead | 206 | ENTRY(pci_sun4v_msiq_sethead) |
| 206 | pci_sun4v_msiq_sethead: | ||
| 207 | mov HV_FAST_PCI_MSIQ_SETHEAD, %o5 | 207 | mov HV_FAST_PCI_MSIQ_SETHEAD, %o5 |
| 208 | ta HV_FAST_TRAP | 208 | ta HV_FAST_TRAP |
| 209 | retl | 209 | retl |
| 210 | mov %o0, %o0 | 210 | mov %o0, %o0 |
| 211 | ENDPROC(pci_sun4v_msiq_sethead) | ||
| 211 | 212 | ||
| 212 | /* %o0: devhandle | 213 | /* %o0: devhandle |
| 213 | * %o1: msiqid | 214 | * %o1: msiqid |
| @@ -215,13 +216,13 @@ pci_sun4v_msiq_sethead: | |||
| 215 | * | 216 | * |
| 216 | * returns %o0: status | 217 | * returns %o0: status |
| 217 | */ | 218 | */ |
| 218 | .globl pci_sun4v_msiq_gettail | 219 | ENTRY(pci_sun4v_msiq_gettail) |
| 219 | pci_sun4v_msiq_gettail: | ||
| 220 | mov HV_FAST_PCI_MSIQ_GETTAIL, %o5 | 220 | mov HV_FAST_PCI_MSIQ_GETTAIL, %o5 |
| 221 | ta HV_FAST_TRAP | 221 | ta HV_FAST_TRAP |
| 222 | stx %o1, [%o2] | 222 | stx %o1, [%o2] |
| 223 | retl | 223 | retl |
| 224 | mov %o0, %o0 | 224 | mov %o0, %o0 |
| 225 | ENDPROC(pci_sun4v_msiq_gettail) | ||
| 225 | 226 | ||
| 226 | /* %o0: devhandle | 227 | /* %o0: devhandle |
| 227 | * %o1: msinum | 228 | * %o1: msinum |
| @@ -229,13 +230,13 @@ pci_sun4v_msiq_gettail: | |||
| 229 | * | 230 | * |
| 230 | * returns %o0: status | 231 | * returns %o0: status |
| 231 | */ | 232 | */ |
| 232 | .globl pci_sun4v_msi_getvalid | 233 | ENTRY(pci_sun4v_msi_getvalid) |
| 233 | pci_sun4v_msi_getvalid: | ||
| 234 | mov HV_FAST_PCI_MSI_GETVALID, %o5 | 234 | mov HV_FAST_PCI_MSI_GETVALID, %o5 |
| 235 | ta HV_FAST_TRAP | 235 | ta HV_FAST_TRAP |
| 236 | stx %o1, [%o2] | 236 | stx %o1, [%o2] |
| 237 | retl | 237 | retl |
| 238 | mov %o0, %o0 | 238 | mov %o0, %o0 |
| 239 | ENDPROC(pci_sun4v_msi_getvalid) | ||
| 239 | 240 | ||
| 240 | /* %o0: devhandle | 241 | /* %o0: devhandle |
| 241 | * %o1: msinum | 242 | * %o1: msinum |
| @@ -243,12 +244,12 @@ pci_sun4v_msi_getvalid: | |||
| 243 | * | 244 | * |
| 244 | * returns %o0: status | 245 | * returns %o0: status |
| 245 | */ | 246 | */ |
| 246 | .globl pci_sun4v_msi_setvalid | 247 | ENTRY(pci_sun4v_msi_setvalid) |
| 247 | pci_sun4v_msi_setvalid: | ||
| 248 | mov HV_FAST_PCI_MSI_SETVALID, %o5 | 248 | mov HV_FAST_PCI_MSI_SETVALID, %o5 |
| 249 | ta HV_FAST_TRAP | 249 | ta HV_FAST_TRAP |
| 250 | retl | 250 | retl |
| 251 | mov %o0, %o0 | 251 | mov %o0, %o0 |
| 252 | ENDPROC(pci_sun4v_msi_setvalid) | ||
| 252 | 253 | ||
| 253 | /* %o0: devhandle | 254 | /* %o0: devhandle |
| 254 | * %o1: msinum | 255 | * %o1: msinum |
| @@ -256,13 +257,13 @@ pci_sun4v_msi_setvalid: | |||
| 256 | * | 257 | * |
| 257 | * returns %o0: status | 258 | * returns %o0: status |
| 258 | */ | 259 | */ |
| 259 | .globl pci_sun4v_msi_getmsiq | 260 | ENTRY(pci_sun4v_msi_getmsiq) |
| 260 | pci_sun4v_msi_getmsiq: | ||
| 261 | mov HV_FAST_PCI_MSI_GETMSIQ, %o5 | 261 | mov HV_FAST_PCI_MSI_GETMSIQ, %o5 |
| 262 | ta HV_FAST_TRAP | 262 | ta HV_FAST_TRAP |
| 263 | stx %o1, [%o2] | 263 | stx %o1, [%o2] |
| 264 | retl | 264 | retl |
| 265 | mov %o0, %o0 | 265 | mov %o0, %o0 |
| 266 | ENDPROC(pci_sun4v_msi_getmsiq) | ||
| 266 | 267 | ||
| 267 | /* %o0: devhandle | 268 | /* %o0: devhandle |
| 268 | * %o1: msinum | 269 | * %o1: msinum |
| @@ -271,12 +272,12 @@ pci_sun4v_msi_getmsiq: | |||
| 271 | * | 272 | * |
| 272 | * returns %o0: status | 273 | * returns %o0: status |
| 273 | */ | 274 | */ |
| 274 | .globl pci_sun4v_msi_setmsiq | 275 | ENTRY(pci_sun4v_msi_setmsiq) |
| 275 | pci_sun4v_msi_setmsiq: | ||
| 276 | mov HV_FAST_PCI_MSI_SETMSIQ, %o5 | 276 | mov HV_FAST_PCI_MSI_SETMSIQ, %o5 |
| 277 | ta HV_FAST_TRAP | 277 | ta HV_FAST_TRAP |
| 278 | retl | 278 | retl |
| 279 | mov %o0, %o0 | 279 | mov %o0, %o0 |
| 280 | ENDPROC(pci_sun4v_msi_setmsiq) | ||
| 280 | 281 | ||
| 281 | /* %o0: devhandle | 282 | /* %o0: devhandle |
| 282 | * %o1: msinum | 283 | * %o1: msinum |
| @@ -284,13 +285,13 @@ pci_sun4v_msi_setmsiq: | |||
| 284 | * | 285 | * |
| 285 | * returns %o0: status | 286 | * returns %o0: status |
| 286 | */ | 287 | */ |
| 287 | .globl pci_sun4v_msi_getstate | 288 | ENTRY(pci_sun4v_msi_getstate) |
| 288 | pci_sun4v_msi_getstate: | ||
| 289 | mov HV_FAST_PCI_MSI_GETSTATE, %o5 | 289 | mov HV_FAST_PCI_MSI_GETSTATE, %o5 |
| 290 | ta HV_FAST_TRAP | 290 | ta HV_FAST_TRAP |
| 291 | stx %o1, [%o2] | 291 | stx %o1, [%o2] |
| 292 | retl | 292 | retl |
| 293 | mov %o0, %o0 | 293 | mov %o0, %o0 |
| 294 | ENDPROC(pci_sun4v_msi_getstate) | ||
| 294 | 295 | ||
| 295 | /* %o0: devhandle | 296 | /* %o0: devhandle |
| 296 | * %o1: msinum | 297 | * %o1: msinum |
| @@ -298,12 +299,12 @@ pci_sun4v_msi_getstate: | |||
| 298 | * | 299 | * |
| 299 | * returns %o0: status | 300 | * returns %o0: status |
| 300 | */ | 301 | */ |
| 301 | .globl pci_sun4v_msi_setstate | 302 | ENTRY(pci_sun4v_msi_setstate) |
| 302 | pci_sun4v_msi_setstate: | ||
| 303 | mov HV_FAST_PCI_MSI_SETSTATE, %o5 | 303 | mov HV_FAST_PCI_MSI_SETSTATE, %o5 |
| 304 | ta HV_FAST_TRAP | 304 | ta HV_FAST_TRAP |
| 305 | retl | 305 | retl |
| 306 | mov %o0, %o0 | 306 | mov %o0, %o0 |
| 307 | ENDPROC(pci_sun4v_msi_setstate) | ||
| 307 | 308 | ||
| 308 | /* %o0: devhandle | 309 | /* %o0: devhandle |
| 309 | * %o1: msinum | 310 | * %o1: msinum |
| @@ -311,13 +312,13 @@ pci_sun4v_msi_setstate: | |||
| 311 | * | 312 | * |
| 312 | * returns %o0: status | 313 | * returns %o0: status |
| 313 | */ | 314 | */ |
| 314 | .globl pci_sun4v_msg_getmsiq | 315 | ENTRY(pci_sun4v_msg_getmsiq) |
| 315 | pci_sun4v_msg_getmsiq: | ||
| 316 | mov HV_FAST_PCI_MSG_GETMSIQ, %o5 | 316 | mov HV_FAST_PCI_MSG_GETMSIQ, %o5 |
| 317 | ta HV_FAST_TRAP | 317 | ta HV_FAST_TRAP |
| 318 | stx %o1, [%o2] | 318 | stx %o1, [%o2] |
| 319 | retl | 319 | retl |
| 320 | mov %o0, %o0 | 320 | mov %o0, %o0 |
| 321 | ENDPROC(pci_sun4v_msg_getmsiq) | ||
| 321 | 322 | ||
| 322 | /* %o0: devhandle | 323 | /* %o0: devhandle |
| 323 | * %o1: msinum | 324 | * %o1: msinum |
| @@ -325,12 +326,12 @@ pci_sun4v_msg_getmsiq: | |||
| 325 | * | 326 | * |
| 326 | * returns %o0: status | 327 | * returns %o0: status |
| 327 | */ | 328 | */ |
| 328 | .globl pci_sun4v_msg_setmsiq | 329 | ENTRY(pci_sun4v_msg_setmsiq) |
| 329 | pci_sun4v_msg_setmsiq: | ||
| 330 | mov HV_FAST_PCI_MSG_SETMSIQ, %o5 | 330 | mov HV_FAST_PCI_MSG_SETMSIQ, %o5 |
| 331 | ta HV_FAST_TRAP | 331 | ta HV_FAST_TRAP |
| 332 | retl | 332 | retl |
| 333 | mov %o0, %o0 | 333 | mov %o0, %o0 |
| 334 | ENDPROC(pci_sun4v_msg_setmsiq) | ||
| 334 | 335 | ||
| 335 | /* %o0: devhandle | 336 | /* %o0: devhandle |
| 336 | * %o1: msinum | 337 | * %o1: msinum |
| @@ -338,13 +339,13 @@ pci_sun4v_msg_setmsiq: | |||
| 338 | * | 339 | * |
| 339 | * returns %o0: status | 340 | * returns %o0: status |
| 340 | */ | 341 | */ |
| 341 | .globl pci_sun4v_msg_getvalid | 342 | ENTRY(pci_sun4v_msg_getvalid) |
| 342 | pci_sun4v_msg_getvalid: | ||
| 343 | mov HV_FAST_PCI_MSG_GETVALID, %o5 | 343 | mov HV_FAST_PCI_MSG_GETVALID, %o5 |
| 344 | ta HV_FAST_TRAP | 344 | ta HV_FAST_TRAP |
| 345 | stx %o1, [%o2] | 345 | stx %o1, [%o2] |
| 346 | retl | 346 | retl |
| 347 | mov %o0, %o0 | 347 | mov %o0, %o0 |
| 348 | ENDPROC(pci_sun4v_msg_getvalid) | ||
| 348 | 349 | ||
| 349 | /* %o0: devhandle | 350 | /* %o0: devhandle |
| 350 | * %o1: msinum | 351 | * %o1: msinum |
| @@ -352,10 +353,10 @@ pci_sun4v_msg_getvalid: | |||
| 352 | * | 353 | * |
| 353 | * returns %o0: status | 354 | * returns %o0: status |
| 354 | */ | 355 | */ |
| 355 | .globl pci_sun4v_msg_setvalid | 356 | ENTRY(pci_sun4v_msg_setvalid) |
| 356 | pci_sun4v_msg_setvalid: | ||
| 357 | mov HV_FAST_PCI_MSG_SETVALID, %o5 | 357 | mov HV_FAST_PCI_MSG_SETVALID, %o5 |
| 358 | ta HV_FAST_TRAP | 358 | ta HV_FAST_TRAP |
| 359 | retl | 359 | retl |
| 360 | mov %o0, %o0 | 360 | mov %o0, %o0 |
| 361 | ENDPROC(pci_sun4v_msg_setvalid) | ||
| 361 | 362 | ||
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 3bb987a6d03c..076cad7f9757 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c | |||
| @@ -1,34 +1,17 @@ | |||
| 1 | /* power.c: Power management driver. | 1 | /* power.c: Power management driver. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
| 9 | #include <linux/sched.h> | ||
| 10 | #include <linux/signal.h> | ||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
| 13 | #include <linux/pm.h> | ||
| 14 | #include <linux/syscalls.h> | ||
| 15 | #include <linux/reboot.h> | 10 | #include <linux/reboot.h> |
| 16 | #include <linux/of_device.h> | 11 | #include <linux/of_device.h> |
| 17 | 12 | ||
| 18 | #include <asm/system.h> | ||
| 19 | #include <asm/auxio.h> | ||
| 20 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
| 21 | #include <asm/io.h> | 14 | #include <asm/io.h> |
| 22 | #include <asm/sstate.h> | ||
| 23 | #include <asm/reboot.h> | ||
| 24 | |||
| 25 | #include <linux/unistd.h> | ||
| 26 | |||
| 27 | /* | ||
| 28 | * sysctl - toggle power-off restriction for serial console | ||
| 29 | * systems in machine_power_off() | ||
| 30 | */ | ||
| 31 | int scons_pwroff = 1; | ||
| 32 | 15 | ||
| 33 | static void __iomem *power_reg; | 16 | static void __iomem *power_reg; |
| 34 | 17 | ||
| @@ -40,31 +23,6 @@ static irqreturn_t power_handler(int irq, void *dev_id) | |||
| 40 | return IRQ_HANDLED; | 23 | return IRQ_HANDLED; |
| 41 | } | 24 | } |
| 42 | 25 | ||
| 43 | static void (*poweroff_method)(void) = machine_alt_power_off; | ||
| 44 | |||
| 45 | void machine_power_off(void) | ||
| 46 | { | ||
| 47 | sstate_poweroff(); | ||
| 48 | if (strcmp(of_console_device->type, "serial") || scons_pwroff) { | ||
| 49 | if (power_reg) { | ||
| 50 | /* Both register bits seem to have the | ||
| 51 | * same effect, so until I figure out | ||
| 52 | * what the difference is... | ||
| 53 | */ | ||
| 54 | writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg); | ||
| 55 | } else { | ||
| 56 | if (poweroff_method != NULL) { | ||
| 57 | poweroff_method(); | ||
| 58 | /* not reached */ | ||
| 59 | } | ||
| 60 | } | ||
| 61 | } | ||
| 62 | machine_halt(); | ||
| 63 | } | ||
| 64 | |||
| 65 | void (*pm_power_off)(void) = machine_power_off; | ||
| 66 | EXPORT_SYMBOL(pm_power_off); | ||
| 67 | |||
| 68 | static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) | 26 | static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) |
| 69 | { | 27 | { |
| 70 | if (irq == 0xffffffff) | 28 | if (irq == 0xffffffff) |
| @@ -85,8 +43,6 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id | |||
| 85 | printk(KERN_INFO "%s: Control reg at %lx\n", | 43 | printk(KERN_INFO "%s: Control reg at %lx\n", |
| 86 | op->node->name, res->start); | 44 | op->node->name, res->start); |
| 87 | 45 | ||
| 88 | poweroff_method = machine_halt; /* able to use the standard halt */ | ||
| 89 | |||
| 90 | if (has_button_interrupt(irq, op->node)) { | 46 | if (has_button_interrupt(irq, op->node)) { |
| 91 | if (request_irq(irq, | 47 | if (request_irq(irq, |
| 92 | power_handler, 0, "power", NULL) < 0) | 48 | power_handler, 0, "power", NULL) < 0) |
| @@ -96,7 +52,7 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id | |||
| 96 | return 0; | 52 | return 0; |
| 97 | } | 53 | } |
| 98 | 54 | ||
| 99 | static struct of_device_id power_match[] = { | 55 | static struct of_device_id __initdata power_match[] = { |
| 100 | { | 56 | { |
| 101 | .name = "power", | 57 | .name = "power", |
| 102 | }, | 58 | }, |
| @@ -111,8 +67,9 @@ static struct of_platform_driver power_driver = { | |||
| 111 | }, | 67 | }, |
| 112 | }; | 68 | }; |
| 113 | 69 | ||
| 114 | void __init power_init(void) | 70 | static int __init power_init(void) |
| 115 | { | 71 | { |
| 116 | of_register_driver(&power_driver, &of_platform_bus_type); | 72 | return of_register_driver(&power_driver, &of_platform_bus_type); |
| 117 | return; | ||
| 118 | } | 73 | } |
| 74 | |||
| 75 | device_initcall(power_init); | ||
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 15f4178592e7..d5e2acef9877 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/user.h> | 24 | #include <linux/user.h> |
| 25 | #include <linux/reboot.h> | ||
| 26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 27 | #include <linux/compat.h> | 26 | #include <linux/compat.h> |
| 28 | #include <linux/tick.h> | 27 | #include <linux/tick.h> |
| @@ -31,7 +30,6 @@ | |||
| 31 | #include <linux/elfcore.h> | 30 | #include <linux/elfcore.h> |
| 32 | #include <linux/sysrq.h> | 31 | #include <linux/sysrq.h> |
| 33 | 32 | ||
| 34 | #include <asm/oplib.h> | ||
| 35 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
| 36 | #include <asm/system.h> | 34 | #include <asm/system.h> |
| 37 | #include <asm/page.h> | 35 | #include <asm/page.h> |
| @@ -46,8 +44,6 @@ | |||
| 46 | #include <asm/mmu_context.h> | 44 | #include <asm/mmu_context.h> |
| 47 | #include <asm/unistd.h> | 45 | #include <asm/unistd.h> |
| 48 | #include <asm/hypervisor.h> | 46 | #include <asm/hypervisor.h> |
| 49 | #include <asm/sstate.h> | ||
| 50 | #include <asm/reboot.h> | ||
| 51 | #include <asm/syscalls.h> | 47 | #include <asm/syscalls.h> |
| 52 | #include <asm/irq_regs.h> | 48 | #include <asm/irq_regs.h> |
| 53 | #include <asm/smp.h> | 49 | #include <asm/smp.h> |
| @@ -115,35 +111,6 @@ void cpu_idle(void) | |||
| 115 | } | 111 | } |
| 116 | } | 112 | } |
| 117 | 113 | ||
| 118 | void machine_halt(void) | ||
| 119 | { | ||
| 120 | sstate_halt(); | ||
| 121 | prom_halt(); | ||
| 122 | panic("Halt failed!"); | ||
| 123 | } | ||
| 124 | |||
| 125 | void machine_alt_power_off(void) | ||
| 126 | { | ||
| 127 | sstate_poweroff(); | ||
| 128 | prom_halt_power_off(); | ||
| 129 | panic("Power-off failed!"); | ||
| 130 | } | ||
| 131 | |||
| 132 | void machine_restart(char * cmd) | ||
| 133 | { | ||
| 134 | char *p; | ||
| 135 | |||
| 136 | sstate_reboot(); | ||
| 137 | p = strchr (reboot_command, '\n'); | ||
| 138 | if (p) *p = 0; | ||
| 139 | if (cmd) | ||
| 140 | prom_reboot(cmd); | ||
| 141 | if (*reboot_command) | ||
| 142 | prom_reboot(reboot_command); | ||
| 143 | prom_reboot(""); | ||
| 144 | panic("Reboot failed!"); | ||
| 145 | } | ||
| 146 | |||
| 147 | #ifdef CONFIG_COMPAT | 114 | #ifdef CONFIG_COMPAT |
| 148 | static void show_regwindow32(struct pt_regs *regs) | 115 | static void show_regwindow32(struct pt_regs *regs) |
| 149 | { | 116 | { |
| @@ -248,7 +215,6 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | |||
| 248 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; | 215 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; |
| 249 | 216 | ||
| 250 | if (regs->tstate & TSTATE_PRIV) { | 217 | if (regs->tstate & TSTATE_PRIV) { |
| 251 | struct thread_info *tp = current_thread_info(); | ||
| 252 | struct reg_window *rw; | 218 | struct reg_window *rw; |
| 253 | 219 | ||
| 254 | rw = (struct reg_window *) | 220 | rw = (struct reg_window *) |
| @@ -304,7 +270,6 @@ void __trigger_all_cpu_backtrace(void) | |||
| 304 | 270 | ||
| 305 | for_each_online_cpu(cpu) { | 271 | for_each_online_cpu(cpu) { |
| 306 | struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; | 272 | struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; |
| 307 | struct thread_info *tp; | ||
| 308 | 273 | ||
| 309 | __global_reg_poll(gp); | 274 | __global_reg_poll(gp); |
| 310 | 275 | ||
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 3c048ac4e638..dbba82f9b142 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
| @@ -38,7 +38,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
| 38 | { | 38 | { |
| 39 | struct device_node *np; | 39 | struct device_node *np; |
| 40 | 40 | ||
| 41 | for (np = allnodes; np != 0; np = np->allnext) | 41 | for (np = allnodes; np; np = np->allnext) |
| 42 | if (np->node == handle) | 42 | if (np->node == handle) |
| 43 | break; | 43 | break; |
| 44 | 44 | ||
| @@ -59,6 +59,9 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) | |||
| 59 | } | 59 | } |
| 60 | EXPORT_SYMBOL(of_getintprop_default); | 60 | EXPORT_SYMBOL(of_getintprop_default); |
| 61 | 61 | ||
| 62 | DEFINE_MUTEX(of_set_property_mutex); | ||
| 63 | EXPORT_SYMBOL(of_set_property_mutex); | ||
| 64 | |||
| 62 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) | 65 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) |
| 63 | { | 66 | { |
| 64 | struct property **prevp; | 67 | struct property **prevp; |
| @@ -82,7 +85,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len | |||
| 82 | void *old_val = prop->value; | 85 | void *old_val = prop->value; |
| 83 | int ret; | 86 | int ret; |
| 84 | 87 | ||
| 88 | mutex_lock(&of_set_property_mutex); | ||
| 85 | ret = prom_setprop(dp->node, name, val, len); | 89 | ret = prom_setprop(dp->node, name, val, len); |
| 90 | mutex_unlock(&of_set_property_mutex); | ||
| 91 | |||
| 86 | err = -EINVAL; | 92 | err = -EINVAL; |
| 87 | if (ret >= 0) { | 93 | if (ret >= 0) { |
| 88 | prop->value = new_val; | 94 | prop->value = new_val; |
| @@ -156,55 +162,11 @@ static unsigned long psycho_pcislot_imap_offset(unsigned long ino) | |||
| 156 | return PSYCHO_IMAP_B_SLOT0 + (slot * 8); | 162 | return PSYCHO_IMAP_B_SLOT0 + (slot * 8); |
| 157 | } | 163 | } |
| 158 | 164 | ||
| 159 | #define PSYCHO_IMAP_SCSI 0x1000UL | 165 | #define PSYCHO_OBIO_IMAP_BASE 0x1000UL |
| 160 | #define PSYCHO_IMAP_ETH 0x1008UL | 166 | |
| 161 | #define PSYCHO_IMAP_BPP 0x1010UL | ||
| 162 | #define PSYCHO_IMAP_AU_REC 0x1018UL | ||
| 163 | #define PSYCHO_IMAP_AU_PLAY 0x1020UL | ||
| 164 | #define PSYCHO_IMAP_PFAIL 0x1028UL | ||
| 165 | #define PSYCHO_IMAP_KMS 0x1030UL | ||
| 166 | #define PSYCHO_IMAP_FLPY 0x1038UL | ||
| 167 | #define PSYCHO_IMAP_SHW 0x1040UL | ||
| 168 | #define PSYCHO_IMAP_KBD 0x1048UL | ||
| 169 | #define PSYCHO_IMAP_MS 0x1050UL | ||
| 170 | #define PSYCHO_IMAP_SER 0x1058UL | ||
| 171 | #define PSYCHO_IMAP_TIM0 0x1060UL | ||
| 172 | #define PSYCHO_IMAP_TIM1 0x1068UL | ||
| 173 | #define PSYCHO_IMAP_UE 0x1070UL | ||
| 174 | #define PSYCHO_IMAP_CE 0x1078UL | ||
| 175 | #define PSYCHO_IMAP_A_ERR 0x1080UL | ||
| 176 | #define PSYCHO_IMAP_B_ERR 0x1088UL | ||
| 177 | #define PSYCHO_IMAP_PMGMT 0x1090UL | ||
| 178 | #define PSYCHO_IMAP_GFX 0x1098UL | ||
| 179 | #define PSYCHO_IMAP_EUPA 0x10a0UL | ||
| 180 | |||
| 181 | static unsigned long __psycho_onboard_imap_off[] = { | ||
| 182 | /*0x20*/ PSYCHO_IMAP_SCSI, | ||
| 183 | /*0x21*/ PSYCHO_IMAP_ETH, | ||
| 184 | /*0x22*/ PSYCHO_IMAP_BPP, | ||
| 185 | /*0x23*/ PSYCHO_IMAP_AU_REC, | ||
| 186 | /*0x24*/ PSYCHO_IMAP_AU_PLAY, | ||
| 187 | /*0x25*/ PSYCHO_IMAP_PFAIL, | ||
| 188 | /*0x26*/ PSYCHO_IMAP_KMS, | ||
| 189 | /*0x27*/ PSYCHO_IMAP_FLPY, | ||
| 190 | /*0x28*/ PSYCHO_IMAP_SHW, | ||
| 191 | /*0x29*/ PSYCHO_IMAP_KBD, | ||
| 192 | /*0x2a*/ PSYCHO_IMAP_MS, | ||
| 193 | /*0x2b*/ PSYCHO_IMAP_SER, | ||
| 194 | /*0x2c*/ PSYCHO_IMAP_TIM0, | ||
| 195 | /*0x2d*/ PSYCHO_IMAP_TIM1, | ||
| 196 | /*0x2e*/ PSYCHO_IMAP_UE, | ||
| 197 | /*0x2f*/ PSYCHO_IMAP_CE, | ||
| 198 | /*0x30*/ PSYCHO_IMAP_A_ERR, | ||
| 199 | /*0x31*/ PSYCHO_IMAP_B_ERR, | ||
| 200 | /*0x32*/ PSYCHO_IMAP_PMGMT, | ||
| 201 | /*0x33*/ PSYCHO_IMAP_GFX, | ||
| 202 | /*0x34*/ PSYCHO_IMAP_EUPA, | ||
| 203 | }; | ||
| 204 | #define PSYCHO_ONBOARD_IRQ_BASE 0x20 | 167 | #define PSYCHO_ONBOARD_IRQ_BASE 0x20 |
| 205 | #define PSYCHO_ONBOARD_IRQ_LAST 0x34 | ||
| 206 | #define psycho_onboard_imap_offset(__ino) \ | 168 | #define psycho_onboard_imap_offset(__ino) \ |
| 207 | __psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE] | 169 | (PSYCHO_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3)) |
| 208 | 170 | ||
| 209 | #define PSYCHO_ICLR_A_SLOT0 0x1400UL | 171 | #define PSYCHO_ICLR_A_SLOT0 0x1400UL |
| 210 | #define PSYCHO_ICLR_SCSI 0x1800UL | 172 | #define PSYCHO_ICLR_SCSI 0x1800UL |
| @@ -228,10 +190,6 @@ static unsigned int psycho_irq_build(struct device_node *dp, | |||
| 228 | imap_off = psycho_pcislot_imap_offset(ino); | 190 | imap_off = psycho_pcislot_imap_offset(ino); |
| 229 | } else { | 191 | } else { |
| 230 | /* Onboard device */ | 192 | /* Onboard device */ |
| 231 | if (ino > PSYCHO_ONBOARD_IRQ_LAST) { | ||
| 232 | prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino); | ||
| 233 | prom_halt(); | ||
| 234 | } | ||
| 235 | imap_off = psycho_onboard_imap_offset(ino); | 193 | imap_off = psycho_onboard_imap_offset(ino); |
| 236 | } | 194 | } |
| 237 | 195 | ||
| @@ -318,23 +276,6 @@ static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) | |||
| 318 | 276 | ||
| 319 | #define SABRE_IMAP_A_SLOT0 0x0c00UL | 277 | #define SABRE_IMAP_A_SLOT0 0x0c00UL |
| 320 | #define SABRE_IMAP_B_SLOT0 0x0c20UL | 278 | #define SABRE_IMAP_B_SLOT0 0x0c20UL |
| 321 | #define SABRE_IMAP_SCSI 0x1000UL | ||
| 322 | #define SABRE_IMAP_ETH 0x1008UL | ||
| 323 | #define SABRE_IMAP_BPP 0x1010UL | ||
| 324 | #define SABRE_IMAP_AU_REC 0x1018UL | ||
| 325 | #define SABRE_IMAP_AU_PLAY 0x1020UL | ||
| 326 | #define SABRE_IMAP_PFAIL 0x1028UL | ||
| 327 | #define SABRE_IMAP_KMS 0x1030UL | ||
| 328 | #define SABRE_IMAP_FLPY 0x1038UL | ||
| 329 | #define SABRE_IMAP_SHW 0x1040UL | ||
| 330 | #define SABRE_IMAP_KBD 0x1048UL | ||
| 331 | #define SABRE_IMAP_MS 0x1050UL | ||
| 332 | #define SABRE_IMAP_SER 0x1058UL | ||
| 333 | #define SABRE_IMAP_UE 0x1070UL | ||
| 334 | #define SABRE_IMAP_CE 0x1078UL | ||
| 335 | #define SABRE_IMAP_PCIERR 0x1080UL | ||
| 336 | #define SABRE_IMAP_GFX 0x1098UL | ||
| 337 | #define SABRE_IMAP_EUPA 0x10a0UL | ||
| 338 | #define SABRE_ICLR_A_SLOT0 0x1400UL | 279 | #define SABRE_ICLR_A_SLOT0 0x1400UL |
| 339 | #define SABRE_ICLR_B_SLOT0 0x1480UL | 280 | #define SABRE_ICLR_B_SLOT0 0x1480UL |
| 340 | #define SABRE_ICLR_SCSI 0x1800UL | 281 | #define SABRE_ICLR_SCSI 0x1800UL |
| @@ -364,33 +305,10 @@ static unsigned long sabre_pcislot_imap_offset(unsigned long ino) | |||
| 364 | return SABRE_IMAP_B_SLOT0 + (slot * 8); | 305 | return SABRE_IMAP_B_SLOT0 + (slot * 8); |
| 365 | } | 306 | } |
| 366 | 307 | ||
| 367 | static unsigned long __sabre_onboard_imap_off[] = { | 308 | #define SABRE_OBIO_IMAP_BASE 0x1000UL |
| 368 | /*0x20*/ SABRE_IMAP_SCSI, | 309 | #define SABRE_ONBOARD_IRQ_BASE 0x20 |
| 369 | /*0x21*/ SABRE_IMAP_ETH, | ||
| 370 | /*0x22*/ SABRE_IMAP_BPP, | ||
| 371 | /*0x23*/ SABRE_IMAP_AU_REC, | ||
| 372 | /*0x24*/ SABRE_IMAP_AU_PLAY, | ||
| 373 | /*0x25*/ SABRE_IMAP_PFAIL, | ||
| 374 | /*0x26*/ SABRE_IMAP_KMS, | ||
| 375 | /*0x27*/ SABRE_IMAP_FLPY, | ||
| 376 | /*0x28*/ SABRE_IMAP_SHW, | ||
| 377 | /*0x29*/ SABRE_IMAP_KBD, | ||
| 378 | /*0x2a*/ SABRE_IMAP_MS, | ||
| 379 | /*0x2b*/ SABRE_IMAP_SER, | ||
| 380 | /*0x2c*/ 0 /* reserved */, | ||
| 381 | /*0x2d*/ 0 /* reserved */, | ||
| 382 | /*0x2e*/ SABRE_IMAP_UE, | ||
| 383 | /*0x2f*/ SABRE_IMAP_CE, | ||
| 384 | /*0x30*/ SABRE_IMAP_PCIERR, | ||
| 385 | /*0x31*/ 0 /* reserved */, | ||
| 386 | /*0x32*/ 0 /* reserved */, | ||
| 387 | /*0x33*/ SABRE_IMAP_GFX, | ||
| 388 | /*0x34*/ SABRE_IMAP_EUPA, | ||
| 389 | }; | ||
| 390 | #define SABRE_ONBOARD_IRQ_BASE 0x20 | ||
| 391 | #define SABRE_ONBOARD_IRQ_LAST 0x30 | ||
| 392 | #define sabre_onboard_imap_offset(__ino) \ | 310 | #define sabre_onboard_imap_offset(__ino) \ |
| 393 | __sabre_onboard_imap_off[(__ino) - SABRE_ONBOARD_IRQ_BASE] | 311 | (SABRE_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3)) |
| 394 | 312 | ||
| 395 | #define sabre_iclr_offset(ino) \ | 313 | #define sabre_iclr_offset(ino) \ |
| 396 | ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ | 314 | ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ |
| @@ -453,10 +371,6 @@ static unsigned int sabre_irq_build(struct device_node *dp, | |||
| 453 | imap_off = sabre_pcislot_imap_offset(ino); | 371 | imap_off = sabre_pcislot_imap_offset(ino); |
| 454 | } else { | 372 | } else { |
| 455 | /* onboard device */ | 373 | /* onboard device */ |
| 456 | if (ino > SABRE_ONBOARD_IRQ_LAST) { | ||
| 457 | prom_printf("sabre_irq_build: Wacky INO [%x]\n", ino); | ||
| 458 | prom_halt(); | ||
| 459 | } | ||
| 460 | imap_off = sabre_onboard_imap_offset(ino); | 374 | imap_off = sabre_onboard_imap_offset(ino); |
| 461 | } | 375 | } |
| 462 | 376 | ||
| @@ -1037,22 +951,30 @@ static void __init irq_trans_init(struct device_node *dp) | |||
| 1037 | for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { | 951 | for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { |
| 1038 | struct irq_trans *t = &pci_irq_trans_table[i]; | 952 | struct irq_trans *t = &pci_irq_trans_table[i]; |
| 1039 | 953 | ||
| 1040 | if (!strcmp(model, t->name)) | 954 | if (!strcmp(model, t->name)) { |
| 1041 | return t->init(dp); | 955 | t->init(dp); |
| 956 | return; | ||
| 957 | } | ||
| 1042 | } | 958 | } |
| 1043 | } | 959 | } |
| 1044 | #endif | 960 | #endif |
| 1045 | #ifdef CONFIG_SBUS | 961 | #ifdef CONFIG_SBUS |
| 1046 | if (!strcmp(dp->name, "sbus") || | 962 | if (!strcmp(dp->name, "sbus") || |
| 1047 | !strcmp(dp->name, "sbi")) | 963 | !strcmp(dp->name, "sbi")) { |
| 1048 | return sbus_irq_trans_init(dp); | 964 | sbus_irq_trans_init(dp); |
| 965 | return; | ||
| 966 | } | ||
| 1049 | #endif | 967 | #endif |
| 1050 | if (!strcmp(dp->name, "fhc") && | 968 | if (!strcmp(dp->name, "fhc") && |
| 1051 | !strcmp(dp->parent->name, "central")) | 969 | !strcmp(dp->parent->name, "central")) { |
| 1052 | return central_irq_trans_init(dp); | 970 | central_irq_trans_init(dp); |
| 971 | return; | ||
| 972 | } | ||
| 1053 | if (!strcmp(dp->name, "virtual-devices") || | 973 | if (!strcmp(dp->name, "virtual-devices") || |
| 1054 | !strcmp(dp->name, "niu")) | 974 | !strcmp(dp->name, "niu")) { |
| 1055 | return sun4v_vdev_irq_trans_init(dp); | 975 | sun4v_vdev_irq_trans_init(dp); |
| 976 | return; | ||
| 977 | } | ||
| 1056 | } | 978 | } |
| 1057 | 979 | ||
| 1058 | static int is_root_node(const struct device_node *dp) | 980 | static int is_root_node(const struct device_node *dp) |
| @@ -1323,32 +1245,49 @@ static void __init __build_path_component(struct device_node *dp, char *tmp_buf) | |||
| 1323 | 1245 | ||
| 1324 | if (parent != NULL) { | 1246 | if (parent != NULL) { |
| 1325 | if (!strcmp(parent->type, "pci") || | 1247 | if (!strcmp(parent->type, "pci") || |
| 1326 | !strcmp(parent->type, "pciex")) | 1248 | !strcmp(parent->type, "pciex")) { |
| 1327 | return pci_path_component(dp, tmp_buf); | 1249 | pci_path_component(dp, tmp_buf); |
| 1328 | if (!strcmp(parent->type, "sbus")) | 1250 | return; |
| 1329 | return sbus_path_component(dp, tmp_buf); | 1251 | } |
| 1330 | if (!strcmp(parent->type, "upa")) | 1252 | if (!strcmp(parent->type, "sbus")) { |
| 1331 | return upa_path_component(dp, tmp_buf); | 1253 | sbus_path_component(dp, tmp_buf); |
| 1332 | if (!strcmp(parent->type, "ebus")) | 1254 | return; |
| 1333 | return ebus_path_component(dp, tmp_buf); | 1255 | } |
| 1256 | if (!strcmp(parent->type, "upa")) { | ||
| 1257 | upa_path_component(dp, tmp_buf); | ||
| 1258 | return; | ||
| 1259 | } | ||
| 1260 | if (!strcmp(parent->type, "ebus")) { | ||
| 1261 | ebus_path_component(dp, tmp_buf); | ||
| 1262 | return; | ||
| 1263 | } | ||
| 1334 | if (!strcmp(parent->name, "usb") || | 1264 | if (!strcmp(parent->name, "usb") || |
| 1335 | !strcmp(parent->name, "hub")) | 1265 | !strcmp(parent->name, "hub")) { |
| 1336 | return usb_path_component(dp, tmp_buf); | 1266 | usb_path_component(dp, tmp_buf); |
| 1337 | if (!strcmp(parent->type, "i2c")) | 1267 | return; |
| 1338 | return i2c_path_component(dp, tmp_buf); | 1268 | } |
| 1339 | if (!strcmp(parent->type, "firewire")) | 1269 | if (!strcmp(parent->type, "i2c")) { |
| 1340 | return ieee1394_path_component(dp, tmp_buf); | 1270 | i2c_path_component(dp, tmp_buf); |
| 1341 | if (!strcmp(parent->type, "virtual-devices")) | 1271 | return; |
| 1342 | return vdev_path_component(dp, tmp_buf); | 1272 | } |
| 1343 | 1273 | if (!strcmp(parent->type, "firewire")) { | |
| 1274 | ieee1394_path_component(dp, tmp_buf); | ||
| 1275 | return; | ||
| 1276 | } | ||
| 1277 | if (!strcmp(parent->type, "virtual-devices")) { | ||
| 1278 | vdev_path_component(dp, tmp_buf); | ||
| 1279 | return; | ||
| 1280 | } | ||
| 1344 | /* "isa" is handled with platform naming */ | 1281 | /* "isa" is handled with platform naming */ |
| 1345 | } | 1282 | } |
| 1346 | 1283 | ||
| 1347 | /* Use platform naming convention. */ | 1284 | /* Use platform naming convention. */ |
| 1348 | if (tlb_type == hypervisor) | 1285 | if (tlb_type == hypervisor) { |
| 1349 | return sun4v_path_component(dp, tmp_buf); | 1286 | sun4v_path_component(dp, tmp_buf); |
| 1350 | else | 1287 | return; |
| 1351 | return sun4u_path_component(dp, tmp_buf); | 1288 | } else { |
| 1289 | sun4u_path_component(dp, tmp_buf); | ||
| 1290 | } | ||
| 1352 | } | 1291 | } |
| 1353 | 1292 | ||
| 1354 | static char * __init build_path_component(struct device_node *dp) | 1293 | static char * __init build_path_component(struct device_node *dp) |
diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c new file mode 100644 index 000000000000..790996428c14 --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.c | |||
| @@ -0,0 +1,470 @@ | |||
| 1 | /* psycho_common.c: Code common to PSYCHO and derivative PCI controllers. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | #include <linux/kernel.h> | ||
| 6 | #include <linux/interrupt.h> | ||
| 7 | |||
| 8 | #include <asm/upa.h> | ||
| 9 | |||
| 10 | #include "pci_impl.h" | ||
| 11 | #include "iommu_common.h" | ||
| 12 | #include "psycho_common.h" | ||
| 13 | |||
| 14 | #define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002UL | ||
| 15 | #define PSYCHO_STCERR_WRITE 0x0000000000000002UL | ||
| 16 | #define PSYCHO_STCERR_READ 0x0000000000000001UL | ||
| 17 | #define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL | ||
| 18 | #define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL | ||
| 19 | #define PSYCHO_STCTAG_VALID 0x0000000000000002UL | ||
| 20 | #define PSYCHO_STCTAG_WRITE 0x0000000000000001UL | ||
| 21 | #define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL | ||
| 22 | #define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL | ||
| 23 | #define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL | ||
| 24 | #define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL | ||
| 25 | #define PSYCHO_STCLINE_VALID 0x0000000000000002UL | ||
| 26 | #define PSYCHO_STCLINE_FOFN 0x0000000000000001UL | ||
| 27 | |||
| 28 | static DEFINE_SPINLOCK(stc_buf_lock); | ||
| 29 | static unsigned long stc_error_buf[128]; | ||
| 30 | static unsigned long stc_tag_buf[16]; | ||
| 31 | static unsigned long stc_line_buf[16]; | ||
| 32 | |||
| 33 | static void psycho_check_stc_error(struct pci_pbm_info *pbm) | ||
| 34 | { | ||
| 35 | unsigned long err_base, tag_base, line_base; | ||
| 36 | struct strbuf *strbuf = &pbm->stc; | ||
| 37 | u64 control; | ||
| 38 | int i; | ||
| 39 | |||
| 40 | if (!strbuf->strbuf_control) | ||
| 41 | return; | ||
| 42 | |||
| 43 | err_base = strbuf->strbuf_err_stat; | ||
| 44 | tag_base = strbuf->strbuf_tag_diag; | ||
| 45 | line_base = strbuf->strbuf_line_diag; | ||
| 46 | |||
| 47 | spin_lock(&stc_buf_lock); | ||
| 48 | |||
| 49 | /* This is __REALLY__ dangerous. When we put the streaming | ||
| 50 | * buffer into diagnostic mode to probe it's tags and error | ||
| 51 | * status, we _must_ clear all of the line tag valid bits | ||
| 52 | * before re-enabling the streaming buffer. If any dirty data | ||
| 53 | * lives in the STC when we do this, we will end up | ||
| 54 | * invalidating it before it has a chance to reach main | ||
| 55 | * memory. | ||
| 56 | */ | ||
| 57 | control = upa_readq(strbuf->strbuf_control); | ||
| 58 | upa_writeq(control | PSYCHO_STRBUF_CTRL_DENAB, strbuf->strbuf_control); | ||
| 59 | for (i = 0; i < 128; i++) { | ||
| 60 | u64 val; | ||
| 61 | |||
| 62 | val = upa_readq(err_base + (i * 8UL)); | ||
| 63 | upa_writeq(0UL, err_base + (i * 8UL)); | ||
| 64 | stc_error_buf[i] = val; | ||
| 65 | } | ||
| 66 | for (i = 0; i < 16; i++) { | ||
| 67 | stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); | ||
| 68 | stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); | ||
| 69 | upa_writeq(0UL, tag_base + (i * 8UL)); | ||
| 70 | upa_writeq(0UL, line_base + (i * 8UL)); | ||
| 71 | } | ||
| 72 | |||
| 73 | /* OK, state is logged, exit diagnostic mode. */ | ||
| 74 | upa_writeq(control, strbuf->strbuf_control); | ||
| 75 | |||
| 76 | for (i = 0; i < 16; i++) { | ||
| 77 | int j, saw_error, first, last; | ||
| 78 | |||
| 79 | saw_error = 0; | ||
| 80 | first = i * 8; | ||
| 81 | last = first + 8; | ||
| 82 | for (j = first; j < last; j++) { | ||
| 83 | u64 errval = stc_error_buf[j]; | ||
| 84 | if (errval != 0) { | ||
| 85 | saw_error++; | ||
| 86 | printk(KERN_ERR "%s: STC_ERR(%d)[wr(%d)" | ||
| 87 | "rd(%d)]\n", | ||
| 88 | pbm->name, | ||
| 89 | j, | ||
| 90 | (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, | ||
| 91 | (errval & PSYCHO_STCERR_READ) ? 1 : 0); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | if (saw_error != 0) { | ||
| 95 | u64 tagval = stc_tag_buf[i]; | ||
| 96 | u64 lineval = stc_line_buf[i]; | ||
| 97 | printk(KERN_ERR "%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)" | ||
| 98 | "V(%d)W(%d)]\n", | ||
| 99 | pbm->name, | ||
| 100 | i, | ||
| 101 | ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), | ||
| 102 | (tagval & PSYCHO_STCTAG_VPN), | ||
| 103 | ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), | ||
| 104 | ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); | ||
| 105 | printk(KERN_ERR "%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)" | ||
| 106 | "LADDR(%lx)EP(%lx)V(%d)FOFN(%d)]\n", | ||
| 107 | pbm->name, | ||
| 108 | i, | ||
| 109 | ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), | ||
| 110 | ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), | ||
| 111 | ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), | ||
| 112 | ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), | ||
| 113 | ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), | ||
| 114 | ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | spin_unlock(&stc_buf_lock); | ||
| 119 | } | ||
| 120 | |||
| 121 | #define PSYCHO_IOMMU_TAG 0xa580UL | ||
| 122 | #define PSYCHO_IOMMU_DATA 0xa600UL | ||
| 123 | |||
| 124 | static void psycho_record_iommu_tags_and_data(struct pci_pbm_info *pbm, | ||
| 125 | u64 *tag, u64 *data) | ||
| 126 | { | ||
| 127 | int i; | ||
| 128 | |||
| 129 | for (i = 0; i < 16; i++) { | ||
| 130 | unsigned long base = pbm->controller_regs; | ||
| 131 | unsigned long off = i * 8UL; | ||
| 132 | |||
| 133 | tag[i] = upa_readq(base + PSYCHO_IOMMU_TAG+off); | ||
| 134 | data[i] = upa_readq(base + PSYCHO_IOMMU_DATA+off); | ||
| 135 | |||
| 136 | /* Now clear out the entry. */ | ||
| 137 | upa_writeq(0, base + PSYCHO_IOMMU_TAG + off); | ||
| 138 | upa_writeq(0, base + PSYCHO_IOMMU_DATA + off); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | #define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) | ||
| 143 | #define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) | ||
| 144 | #define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) | ||
| 145 | #define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) | ||
| 146 | #define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) | ||
| 147 | #define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL | ||
| 148 | #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) | ||
| 149 | #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) | ||
| 150 | #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL | ||
| 151 | |||
| 152 | static void psycho_dump_iommu_tags_and_data(struct pci_pbm_info *pbm, | ||
| 153 | u64 *tag, u64 *data) | ||
| 154 | { | ||
| 155 | int i; | ||
| 156 | |||
| 157 | for (i = 0; i < 16; i++) { | ||
| 158 | u64 tag_val, data_val; | ||
| 159 | const char *type_str; | ||
| 160 | tag_val = tag[i]; | ||
| 161 | if (!(tag_val & PSYCHO_IOMMU_TAG_ERR)) | ||
| 162 | continue; | ||
| 163 | |||
| 164 | data_val = data[i]; | ||
| 165 | switch((tag_val & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { | ||
| 166 | case 0: | ||
| 167 | type_str = "Protection Error"; | ||
| 168 | break; | ||
| 169 | case 1: | ||
| 170 | type_str = "Invalid Error"; | ||
| 171 | break; | ||
| 172 | case 2: | ||
| 173 | type_str = "TimeOut Error"; | ||
| 174 | break; | ||
| 175 | case 3: | ||
| 176 | default: | ||
| 177 | type_str = "ECC Error"; | ||
| 178 | break; | ||
| 179 | } | ||
| 180 | |||
| 181 | printk(KERN_ERR "%s: IOMMU TAG(%d)[error(%s) wr(%d) " | ||
| 182 | "str(%d) sz(%dK) vpg(%08lx)]\n", | ||
| 183 | pbm->name, i, type_str, | ||
| 184 | ((tag_val & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), | ||
| 185 | ((tag_val & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), | ||
| 186 | ((tag_val & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), | ||
| 187 | (tag_val & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); | ||
| 188 | printk(KERN_ERR "%s: IOMMU DATA(%d)[valid(%d) cache(%d) " | ||
| 189 | "ppg(%016lx)]\n", | ||
| 190 | pbm->name, i, | ||
| 191 | ((data_val & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), | ||
| 192 | ((data_val & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), | ||
| 193 | (data_val & PSYCHO_IOMMU_DATA_PPAGE)<<IOMMU_PAGE_SHIFT); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | #define PSYCHO_IOMMU_CTRL_XLTESTAT 0x0000000006000000UL | ||
| 198 | #define PSYCHO_IOMMU_CTRL_XLTEERR 0x0000000001000000UL | ||
| 199 | |||
| 200 | void psycho_check_iommu_error(struct pci_pbm_info *pbm, | ||
| 201 | unsigned long afsr, | ||
| 202 | unsigned long afar, | ||
| 203 | enum psycho_error_type type) | ||
| 204 | { | ||
| 205 | u64 control, iommu_tag[16], iommu_data[16]; | ||
| 206 | struct iommu *iommu = pbm->iommu; | ||
| 207 | unsigned long flags; | ||
| 208 | |||
| 209 | spin_lock_irqsave(&iommu->lock, flags); | ||
| 210 | control = upa_readq(iommu->iommu_control); | ||
| 211 | if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { | ||
| 212 | const char *type_str; | ||
| 213 | |||
| 214 | control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; | ||
| 215 | upa_writeq(control, iommu->iommu_control); | ||
| 216 | |||
| 217 | switch ((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { | ||
| 218 | case 0: | ||
| 219 | type_str = "Protection Error"; | ||
| 220 | break; | ||
| 221 | case 1: | ||
| 222 | type_str = "Invalid Error"; | ||
| 223 | break; | ||
| 224 | case 2: | ||
| 225 | type_str = "TimeOut Error"; | ||
| 226 | break; | ||
| 227 | case 3: | ||
| 228 | default: | ||
| 229 | type_str = "ECC Error"; | ||
| 230 | break; | ||
| 231 | }; | ||
| 232 | printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", | ||
| 233 | pbm->name, type_str); | ||
| 234 | |||
| 235 | /* It is very possible for another DVMA to occur while | ||
| 236 | * we do this probe, and corrupt the system further. | ||
| 237 | * But we are so screwed at this point that we are | ||
| 238 | * likely to crash hard anyways, so get as much | ||
| 239 | * diagnostic information to the console as we can. | ||
| 240 | */ | ||
| 241 | psycho_record_iommu_tags_and_data(pbm, iommu_tag, iommu_data); | ||
| 242 | psycho_dump_iommu_tags_and_data(pbm, iommu_tag, iommu_data); | ||
| 243 | } | ||
| 244 | psycho_check_stc_error(pbm); | ||
| 245 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
| 246 | } | ||
| 247 | |||
| 248 | #define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000UL | ||
| 249 | #define PSYCHO_PCICTRL_SERR 0x0000000400000000UL | ||
| 250 | |||
| 251 | static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) | ||
| 252 | { | ||
| 253 | irqreturn_t ret = IRQ_NONE; | ||
| 254 | u64 csr, csr_error_bits; | ||
| 255 | u16 stat, *addr; | ||
| 256 | |||
| 257 | csr = upa_readq(pbm->pci_csr); | ||
| 258 | csr_error_bits = csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); | ||
| 259 | if (csr_error_bits) { | ||
| 260 | /* Clear the errors. */ | ||
| 261 | upa_writeq(csr, pbm->pci_csr); | ||
| 262 | |||
| 263 | /* Log 'em. */ | ||
| 264 | if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) | ||
| 265 | printk(KERN_ERR "%s: PCI streaming byte hole " | ||
| 266 | "error asserted.\n", pbm->name); | ||
| 267 | if (csr_error_bits & PSYCHO_PCICTRL_SERR) | ||
| 268 | printk(KERN_ERR "%s: PCI SERR signal asserted.\n", | ||
| 269 | pbm->name); | ||
| 270 | ret = IRQ_HANDLED; | ||
| 271 | } | ||
| 272 | addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, | ||
| 273 | 0, PCI_STATUS); | ||
| 274 | pci_config_read16(addr, &stat); | ||
| 275 | if (stat & (PCI_STATUS_PARITY | | ||
| 276 | PCI_STATUS_SIG_TARGET_ABORT | | ||
| 277 | PCI_STATUS_REC_TARGET_ABORT | | ||
| 278 | PCI_STATUS_REC_MASTER_ABORT | | ||
| 279 | PCI_STATUS_SIG_SYSTEM_ERROR)) { | ||
| 280 | printk(KERN_ERR "%s: PCI bus error, PCI_STATUS[%04x]\n", | ||
| 281 | pbm->name, stat); | ||
| 282 | pci_config_write16(addr, 0xffff); | ||
| 283 | ret = IRQ_HANDLED; | ||
| 284 | } | ||
| 285 | return ret; | ||
| 286 | } | ||
| 287 | |||
| 288 | #define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL | ||
| 289 | #define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL | ||
| 290 | #define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL | ||
| 291 | #define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL | ||
| 292 | #define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL | ||
| 293 | #define PSYCHO_PCIAFSR_STA 0x0400000000000000UL | ||
| 294 | #define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL | ||
| 295 | #define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL | ||
| 296 | #define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL | ||
| 297 | #define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL | ||
| 298 | #define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL | ||
| 299 | #define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL | ||
| 300 | #define PSYCHO_PCIAFSR_MID 0x000000003e000000UL | ||
| 301 | #define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL | ||
| 302 | |||
| 303 | irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | ||
| 304 | { | ||
| 305 | struct pci_pbm_info *pbm = dev_id; | ||
| 306 | u64 afsr, afar, error_bits; | ||
| 307 | int reported; | ||
| 308 | |||
| 309 | afsr = upa_readq(pbm->pci_afsr); | ||
| 310 | afar = upa_readq(pbm->pci_afar); | ||
| 311 | error_bits = afsr & | ||
| 312 | (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | | ||
| 313 | PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | | ||
| 314 | PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | | ||
| 315 | PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); | ||
| 316 | if (!error_bits) | ||
| 317 | return psycho_pcierr_intr_other(pbm); | ||
| 318 | upa_writeq(error_bits, pbm->pci_afsr); | ||
| 319 | printk(KERN_ERR "%s: PCI Error, primary error type[%s]\n", | ||
| 320 | pbm->name, | ||
| 321 | (((error_bits & PSYCHO_PCIAFSR_PMA) ? | ||
| 322 | "Master Abort" : | ||
| 323 | ((error_bits & PSYCHO_PCIAFSR_PTA) ? | ||
| 324 | "Target Abort" : | ||
| 325 | ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? | ||
| 326 | "Excessive Retries" : | ||
| 327 | ((error_bits & PSYCHO_PCIAFSR_PPERR) ? | ||
| 328 | "Parity Error" : "???")))))); | ||
| 329 | printk(KERN_ERR "%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", | ||
| 330 | pbm->name, | ||
| 331 | (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, | ||
| 332 | (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, | ||
| 333 | (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); | ||
| 334 | printk(KERN_ERR "%s: PCI AFAR [%016lx]\n", pbm->name, afar); | ||
| 335 | printk(KERN_ERR "%s: PCI Secondary errors [", pbm->name); | ||
| 336 | reported = 0; | ||
| 337 | if (afsr & PSYCHO_PCIAFSR_SMA) { | ||
| 338 | reported++; | ||
| 339 | printk("(Master Abort)"); | ||
| 340 | } | ||
| 341 | if (afsr & PSYCHO_PCIAFSR_STA) { | ||
| 342 | reported++; | ||
| 343 | printk("(Target Abort)"); | ||
| 344 | } | ||
| 345 | if (afsr & PSYCHO_PCIAFSR_SRTRY) { | ||
| 346 | reported++; | ||
| 347 | printk("(Excessive Retries)"); | ||
| 348 | } | ||
| 349 | if (afsr & PSYCHO_PCIAFSR_SPERR) { | ||
| 350 | reported++; | ||
| 351 | printk("(Parity Error)"); | ||
| 352 | } | ||
| 353 | if (!reported) | ||
| 354 | printk("(none)"); | ||
| 355 | printk("]\n"); | ||
| 356 | |||
| 357 | if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { | ||
| 358 | psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); | ||
| 359 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | ||
| 360 | } | ||
| 361 | if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) | ||
| 362 | pci_scan_for_master_abort(pbm, pbm->pci_bus); | ||
| 363 | |||
| 364 | if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) | ||
| 365 | pci_scan_for_parity_error(pbm, pbm->pci_bus); | ||
| 366 | |||
| 367 | return IRQ_HANDLED; | ||
| 368 | } | ||
| 369 | |||
| 370 | static void psycho_iommu_flush(struct pci_pbm_info *pbm) | ||
| 371 | { | ||
| 372 | int i; | ||
| 373 | |||
| 374 | for (i = 0; i < 16; i++) { | ||
| 375 | unsigned long off = i * 8; | ||
| 376 | |||
| 377 | upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_TAG + off); | ||
| 378 | upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_DATA + off); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | #define PSYCHO_IOMMU_CONTROL 0x0200UL | ||
| 383 | #define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL | ||
| 384 | #define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000UL | ||
| 385 | #define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000UL | ||
| 386 | #define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000UL | ||
| 387 | #define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000UL | ||
| 388 | #define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000UL | ||
| 389 | #define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000UL | ||
| 390 | #define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000UL | ||
| 391 | #define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000UL | ||
| 392 | #define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL | ||
| 393 | #define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002UL | ||
| 394 | #define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001UL | ||
| 395 | #define PSYCHO_IOMMU_FLUSH 0x0210UL | ||
| 396 | #define PSYCHO_IOMMU_TSBBASE 0x0208UL | ||
| 397 | |||
| 398 | int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, | ||
| 399 | u32 dvma_offset, u32 dma_mask, | ||
| 400 | unsigned long write_complete_offset) | ||
| 401 | { | ||
| 402 | struct iommu *iommu = pbm->iommu; | ||
| 403 | u64 control; | ||
| 404 | int err; | ||
| 405 | |||
| 406 | iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; | ||
| 407 | iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; | ||
| 408 | iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; | ||
| 409 | iommu->iommu_tags = pbm->controller_regs + PSYCHO_IOMMU_TAG; | ||
| 410 | iommu->write_complete_reg = (pbm->controller_regs + | ||
| 411 | write_complete_offset); | ||
| 412 | |||
| 413 | iommu->iommu_ctxflush = 0; | ||
| 414 | |||
| 415 | control = upa_readq(iommu->iommu_control); | ||
| 416 | control |= PSYCHO_IOMMU_CTRL_DENAB; | ||
| 417 | upa_writeq(control, iommu->iommu_control); | ||
| 418 | |||
| 419 | psycho_iommu_flush(pbm); | ||
| 420 | |||
| 421 | /* Leave diag mode enabled for full-flushing done in pci_iommu.c */ | ||
| 422 | err = iommu_table_init(iommu, tsbsize * 1024 * 8, | ||
| 423 | dvma_offset, dma_mask, pbm->numa_node); | ||
| 424 | if (err) | ||
| 425 | return err; | ||
| 426 | |||
| 427 | upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); | ||
| 428 | |||
| 429 | control = upa_readq(iommu->iommu_control); | ||
| 430 | control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); | ||
| 431 | control |= PSYCHO_IOMMU_CTRL_ENAB; | ||
| 432 | |||
| 433 | switch (tsbsize) { | ||
| 434 | case 64: | ||
| 435 | control |= PSYCHO_IOMMU_TSBSZ_64K; | ||
| 436 | break; | ||
| 437 | case 128: | ||
| 438 | control |= PSYCHO_IOMMU_TSBSZ_128K; | ||
| 439 | break; | ||
| 440 | default: | ||
| 441 | return -EINVAL; | ||
| 442 | } | ||
| 443 | |||
| 444 | upa_writeq(control, iommu->iommu_control); | ||
| 445 | |||
| 446 | return 0; | ||
| 447 | |||
| 448 | } | ||
| 449 | |||
| 450 | void psycho_pbm_init_common(struct pci_pbm_info *pbm, struct of_device *op, | ||
| 451 | const char *chip_name, int chip_type) | ||
| 452 | { | ||
| 453 | struct device_node *dp = op->node; | ||
| 454 | |||
| 455 | pbm->name = dp->full_name; | ||
| 456 | pbm->numa_node = -1; | ||
| 457 | pbm->chip_type = chip_type; | ||
| 458 | pbm->chip_version = of_getintprop_default(dp, "version#", 0); | ||
| 459 | pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); | ||
| 460 | pbm->op = op; | ||
| 461 | pbm->pci_ops = &sun4u_pci_ops; | ||
| 462 | pbm->config_space_reg_bits = 8; | ||
| 463 | pbm->index = pci_num_pbms++; | ||
| 464 | pci_get_pbm_props(pbm); | ||
| 465 | pci_determine_mem_io_space(pbm); | ||
| 466 | |||
| 467 | printk(KERN_INFO "%s: %s PCI Bus Module ver[%x:%x]\n", | ||
| 468 | pbm->name, chip_name, | ||
| 469 | pbm->chip_version, pbm->chip_revision); | ||
| 470 | } | ||
diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h new file mode 100644 index 000000000000..092c278ef28d --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | #ifndef _PSYCHO_COMMON_H | ||
| 2 | #define _PSYCHO_COMMON_H | ||
| 3 | |||
| 4 | /* U2P Programmer's Manual, page 13-55, configuration space | ||
| 5 | * address format: | ||
| 6 | * | ||
| 7 | * 32 24 23 16 15 11 10 8 7 2 1 0 | ||
| 8 | * --------------------------------------------------------- | ||
| 9 | * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | | ||
| 10 | * --------------------------------------------------------- | ||
| 11 | */ | ||
| 12 | #define PSYCHO_CONFIG_BASE(PBM) \ | ||
| 13 | ((PBM)->config_space | (1UL << 24)) | ||
| 14 | #define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG) \ | ||
| 15 | (((unsigned long)(BUS) << 16) | \ | ||
| 16 | ((unsigned long)(DEVFN) << 8) | \ | ||
| 17 | ((unsigned long)(REG))) | ||
| 18 | |||
| 19 | static inline void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, | ||
| 20 | unsigned char bus, | ||
| 21 | unsigned int devfn, | ||
| 22 | int where) | ||
| 23 | { | ||
| 24 | return (void *) | ||
| 25 | (PSYCHO_CONFIG_BASE(pbm) | | ||
| 26 | PSYCHO_CONFIG_ENCODE(bus, devfn, where)); | ||
| 27 | } | ||
| 28 | |||
| 29 | enum psycho_error_type { | ||
| 30 | UE_ERR, CE_ERR, PCI_ERR | ||
| 31 | }; | ||
| 32 | |||
| 33 | extern void psycho_check_iommu_error(struct pci_pbm_info *pbm, | ||
| 34 | unsigned long afsr, | ||
| 35 | unsigned long afar, | ||
| 36 | enum psycho_error_type type); | ||
| 37 | |||
| 38 | extern irqreturn_t psycho_pcierr_intr(int irq, void *dev_id); | ||
| 39 | |||
| 40 | extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, | ||
| 41 | u32 dvma_offset, u32 dma_mask, | ||
| 42 | unsigned long write_complete_offset); | ||
| 43 | |||
| 44 | extern void psycho_pbm_init_common(struct pci_pbm_info *pbm, | ||
| 45 | struct of_device *op, | ||
| 46 | const char *chip_name, int chip_type); | ||
| 47 | |||
| 48 | #endif /* _PSYCHO_COMMON_H */ | ||
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index bd578cc4856d..f43adbc773ca 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c | |||
| @@ -443,7 +443,7 @@ static const struct user_regset sparc64_regsets[] = { | |||
| 443 | */ | 443 | */ |
| 444 | [REGSET_GENERAL] = { | 444 | [REGSET_GENERAL] = { |
| 445 | .core_note_type = NT_PRSTATUS, | 445 | .core_note_type = NT_PRSTATUS, |
| 446 | .n = 36 * sizeof(u64), | 446 | .n = 36, |
| 447 | .size = sizeof(u64), .align = sizeof(u64), | 447 | .size = sizeof(u64), .align = sizeof(u64), |
| 448 | .get = genregs64_get, .set = genregs64_set | 448 | .get = genregs64_get, .set = genregs64_set |
| 449 | }, | 449 | }, |
| @@ -455,7 +455,7 @@ static const struct user_regset sparc64_regsets[] = { | |||
| 455 | */ | 455 | */ |
| 456 | [REGSET_FP] = { | 456 | [REGSET_FP] = { |
| 457 | .core_note_type = NT_PRFPREG, | 457 | .core_note_type = NT_PRFPREG, |
| 458 | .n = 35 * sizeof(u64), | 458 | .n = 35, |
| 459 | .size = sizeof(u64), .align = sizeof(u64), | 459 | .size = sizeof(u64), .align = sizeof(u64), |
| 460 | .get = fpregs64_get, .set = fpregs64_set | 460 | .get = fpregs64_get, .set = fpregs64_set |
| 461 | }, | 461 | }, |
| @@ -801,7 +801,7 @@ static const struct user_regset sparc32_regsets[] = { | |||
| 801 | */ | 801 | */ |
| 802 | [REGSET_GENERAL] = { | 802 | [REGSET_GENERAL] = { |
| 803 | .core_note_type = NT_PRSTATUS, | 803 | .core_note_type = NT_PRSTATUS, |
| 804 | .n = 38 * sizeof(u32), | 804 | .n = 38, |
| 805 | .size = sizeof(u32), .align = sizeof(u32), | 805 | .size = sizeof(u32), .align = sizeof(u32), |
| 806 | .get = genregs32_get, .set = genregs32_set | 806 | .get = genregs32_get, .set = genregs32_set |
| 807 | }, | 807 | }, |
| @@ -817,7 +817,7 @@ static const struct user_regset sparc32_regsets[] = { | |||
| 817 | */ | 817 | */ |
| 818 | [REGSET_FP] = { | 818 | [REGSET_FP] = { |
| 819 | .core_note_type = NT_PRFPREG, | 819 | .core_note_type = NT_PRFPREG, |
| 820 | .n = 99 * sizeof(u32), | 820 | .n = 99, |
| 821 | .size = sizeof(u32), .align = sizeof(u32), | 821 | .size = sizeof(u32), .align = sizeof(u32), |
| 822 | .get = fpregs32_get, .set = fpregs32_set | 822 | .get = fpregs32_get, .set = fpregs32_set |
| 823 | }, | 823 | }, |
| @@ -1050,31 +1050,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 1050 | return ret; | 1050 | return ret; |
| 1051 | } | 1051 | } |
| 1052 | 1052 | ||
| 1053 | asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) | 1053 | asmlinkage int syscall_trace_enter(struct pt_regs *regs) |
| 1054 | { | 1054 | { |
| 1055 | int ret = 0; | 1055 | int ret = 0; |
| 1056 | 1056 | ||
| 1057 | /* do the secure computing check first */ | 1057 | /* do the secure computing check first */ |
| 1058 | secure_computing(regs->u_regs[UREG_G1]); | 1058 | secure_computing(regs->u_regs[UREG_G1]); |
| 1059 | 1059 | ||
| 1060 | if (unlikely(current->audit_context) && syscall_exit_p) { | 1060 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
| 1061 | unsigned long tstate = regs->tstate; | 1061 | ret = tracehook_report_syscall_entry(regs); |
| 1062 | int result = AUDITSC_SUCCESS; | ||
| 1063 | |||
| 1064 | if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) | ||
| 1065 | result = AUDITSC_FAILURE; | ||
| 1066 | |||
| 1067 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | if (test_thread_flag(TIF_SYSCALL_TRACE)) { | ||
| 1071 | if (syscall_exit_p) | ||
| 1072 | tracehook_report_syscall_exit(regs, 0); | ||
| 1073 | else | ||
| 1074 | ret = tracehook_report_syscall_entry(regs); | ||
| 1075 | } | ||
| 1076 | 1062 | ||
| 1077 | if (unlikely(current->audit_context) && !syscall_exit_p && !ret) | 1063 | if (unlikely(current->audit_context) && !ret) |
| 1078 | audit_syscall_entry((test_thread_flag(TIF_32BIT) ? | 1064 | audit_syscall_entry((test_thread_flag(TIF_32BIT) ? |
| 1079 | AUDIT_ARCH_SPARC : | 1065 | AUDIT_ARCH_SPARC : |
| 1080 | AUDIT_ARCH_SPARC64), | 1066 | AUDIT_ARCH_SPARC64), |
| @@ -1086,3 +1072,19 @@ asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) | |||
| 1086 | 1072 | ||
| 1087 | return ret; | 1073 | return ret; |
| 1088 | } | 1074 | } |
| 1075 | |||
| 1076 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | ||
| 1077 | { | ||
| 1078 | if (unlikely(current->audit_context)) { | ||
| 1079 | unsigned long tstate = regs->tstate; | ||
| 1080 | int result = AUDITSC_SUCCESS; | ||
| 1081 | |||
| 1082 | if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) | ||
| 1083 | result = AUDITSC_FAILURE; | ||
| 1084 | |||
| 1085 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
| 1089 | tracehook_report_syscall_exit(regs, 0); | ||
| 1090 | } | ||
diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c new file mode 100644 index 000000000000..ef89d3d69748 --- /dev/null +++ b/arch/sparc64/kernel/reboot.c | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* reboot.c: reboot/shutdown/halt/poweroff handling | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | #include <linux/kernel.h> | ||
| 6 | #include <linux/reboot.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/pm.h> | ||
| 9 | |||
| 10 | #include <asm/system.h> | ||
| 11 | #include <asm/oplib.h> | ||
| 12 | #include <asm/prom.h> | ||
| 13 | |||
| 14 | /* sysctl - toggle power-off restriction for serial console | ||
| 15 | * systems in machine_power_off() | ||
| 16 | */ | ||
| 17 | int scons_pwroff = 1; | ||
| 18 | |||
| 19 | /* This isn't actually used, it exists merely to satisfy the | ||
| 20 | * reference in kernel/sys.c | ||
| 21 | */ | ||
| 22 | void (*pm_power_off)(void) = machine_power_off; | ||
| 23 | EXPORT_SYMBOL(pm_power_off); | ||
| 24 | |||
| 25 | void machine_power_off(void) | ||
| 26 | { | ||
| 27 | if (strcmp(of_console_device->type, "serial") || scons_pwroff) | ||
| 28 | prom_halt_power_off(); | ||
| 29 | |||
| 30 | prom_halt(); | ||
| 31 | } | ||
| 32 | |||
| 33 | void machine_halt(void) | ||
| 34 | { | ||
| 35 | prom_halt(); | ||
| 36 | panic("Halt failed!"); | ||
| 37 | } | ||
| 38 | |||
| 39 | void machine_restart(char *cmd) | ||
| 40 | { | ||
| 41 | char *p; | ||
| 42 | |||
| 43 | p = strchr(reboot_command, '\n'); | ||
| 44 | if (p) | ||
| 45 | *p = 0; | ||
| 46 | if (cmd) | ||
| 47 | prom_reboot(cmd); | ||
| 48 | if (*reboot_command) | ||
| 49 | prom_reboot(reboot_command); | ||
| 50 | prom_reboot(""); | ||
| 51 | panic("Reboot failed!"); | ||
| 52 | } | ||
| 53 | |||
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index e33a8a660e9e..2ead310066d1 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
| @@ -11,15 +11,17 @@ | |||
| 11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 14 | #include <linux/of.h> | ||
| 15 | #include <linux/of_device.h> | ||
| 14 | 16 | ||
| 15 | #include <asm/page.h> | 17 | #include <asm/page.h> |
| 16 | #include <asm/sbus.h> | ||
| 17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
| 18 | #include <asm/upa.h> | 19 | #include <asm/upa.h> |
| 19 | #include <asm/cache.h> | 20 | #include <asm/cache.h> |
| 20 | #include <asm/dma.h> | 21 | #include <asm/dma.h> |
| 21 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
| 22 | #include <asm/prom.h> | 23 | #include <asm/prom.h> |
| 24 | #include <asm/oplib.h> | ||
| 23 | #include <asm/starfire.h> | 25 | #include <asm/starfire.h> |
| 24 | 26 | ||
| 25 | #include "iommu_common.h" | 27 | #include "iommu_common.h" |
| @@ -52,13 +54,23 @@ | |||
| 52 | #define STRBUF_TAG_VALID 0x02UL | 54 | #define STRBUF_TAG_VALID 0x02UL |
| 53 | 55 | ||
| 54 | /* Enable 64-bit DVMA mode for the given device. */ | 56 | /* Enable 64-bit DVMA mode for the given device. */ |
| 55 | void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) | 57 | void sbus_set_sbus64(struct device *dev, int bursts) |
| 56 | { | 58 | { |
| 57 | struct iommu *iommu = sdev->ofdev.dev.archdata.iommu; | 59 | struct iommu *iommu = dev->archdata.iommu; |
| 58 | int slot = sdev->slot; | 60 | struct of_device *op = to_of_device(dev); |
| 61 | const struct linux_prom_registers *regs; | ||
| 59 | unsigned long cfg_reg; | 62 | unsigned long cfg_reg; |
| 63 | int slot; | ||
| 60 | u64 val; | 64 | u64 val; |
| 61 | 65 | ||
| 66 | regs = of_get_property(op->node, "reg", NULL); | ||
| 67 | if (!regs) { | ||
| 68 | printk(KERN_ERR "sbus_set_sbus64: Cannot find regs for %s\n", | ||
| 69 | op->node->full_name); | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | slot = regs->which_io; | ||
| 73 | |||
| 62 | cfg_reg = iommu->write_complete_reg; | 74 | cfg_reg = iommu->write_complete_reg; |
| 63 | switch (slot) { | 75 | switch (slot) { |
| 64 | case 0: | 76 | case 0: |
| @@ -191,10 +203,9 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap) | |||
| 191 | return imap + diff; | 203 | return imap + diff; |
| 192 | } | 204 | } |
| 193 | 205 | ||
| 194 | unsigned int sbus_build_irq(void *buscookie, unsigned int ino) | 206 | static unsigned int sbus_build_irq(struct of_device *op, unsigned int ino) |
| 195 | { | 207 | { |
| 196 | struct sbus_bus *sbus = (struct sbus_bus *)buscookie; | 208 | struct iommu *iommu = op->dev.archdata.iommu; |
| 197 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | ||
| 198 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 209 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
| 199 | unsigned long imap, iclr; | 210 | unsigned long imap, iclr; |
| 200 | int sbus_level = 0; | 211 | int sbus_level = 0; |
| @@ -255,12 +266,12 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) | |||
| 255 | #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ | 266 | #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ |
| 256 | static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | 267 | static irqreturn_t sysio_ue_handler(int irq, void *dev_id) |
| 257 | { | 268 | { |
| 258 | struct sbus_bus *sbus = dev_id; | 269 | struct of_device *op = dev_id; |
| 259 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 270 | struct iommu *iommu = op->dev.archdata.iommu; |
| 260 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 271 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
| 261 | unsigned long afsr_reg, afar_reg; | 272 | unsigned long afsr_reg, afar_reg; |
| 262 | unsigned long afsr, afar, error_bits; | 273 | unsigned long afsr, afar, error_bits; |
| 263 | int reported; | 274 | int reported, portid; |
| 264 | 275 | ||
| 265 | afsr_reg = reg_base + SYSIO_UE_AFSR; | 276 | afsr_reg = reg_base + SYSIO_UE_AFSR; |
| 266 | afar_reg = reg_base + SYSIO_UE_AFAR; | 277 | afar_reg = reg_base + SYSIO_UE_AFAR; |
| @@ -275,9 +286,11 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
| 275 | SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); | 286 | SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); |
| 276 | upa_writeq(error_bits, afsr_reg); | 287 | upa_writeq(error_bits, afsr_reg); |
| 277 | 288 | ||
| 289 | portid = of_getintprop_default(op->node, "portid", -1); | ||
| 290 | |||
| 278 | /* Log the error. */ | 291 | /* Log the error. */ |
| 279 | printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", | 292 | printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", |
| 280 | sbus->portid, | 293 | portid, |
| 281 | (((error_bits & SYSIO_UEAFSR_PPIO) ? | 294 | (((error_bits & SYSIO_UEAFSR_PPIO) ? |
| 282 | "PIO" : | 295 | "PIO" : |
| 283 | ((error_bits & SYSIO_UEAFSR_PDRD) ? | 296 | ((error_bits & SYSIO_UEAFSR_PDRD) ? |
| @@ -285,12 +298,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
| 285 | ((error_bits & SYSIO_UEAFSR_PDWR) ? | 298 | ((error_bits & SYSIO_UEAFSR_PDWR) ? |
| 286 | "DVMA Write" : "???"))))); | 299 | "DVMA Write" : "???"))))); |
| 287 | printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", | 300 | printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", |
| 288 | sbus->portid, | 301 | portid, |
| 289 | (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, | 302 | (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, |
| 290 | (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, | 303 | (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, |
| 291 | (afsr & SYSIO_UEAFSR_MID) >> 37UL); | 304 | (afsr & SYSIO_UEAFSR_MID) >> 37UL); |
| 292 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 305 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
| 293 | printk("SYSIO[%x]: Secondary UE errors [", sbus->portid); | 306 | printk("SYSIO[%x]: Secondary UE errors [", portid); |
| 294 | reported = 0; | 307 | reported = 0; |
| 295 | if (afsr & SYSIO_UEAFSR_SPIO) { | 308 | if (afsr & SYSIO_UEAFSR_SPIO) { |
| 296 | reported++; | 309 | reported++; |
| @@ -327,12 +340,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
| 327 | #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ | 340 | #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ |
| 328 | static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | 341 | static irqreturn_t sysio_ce_handler(int irq, void *dev_id) |
| 329 | { | 342 | { |
| 330 | struct sbus_bus *sbus = dev_id; | 343 | struct of_device *op = dev_id; |
| 331 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 344 | struct iommu *iommu = op->dev.archdata.iommu; |
| 332 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 345 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
| 333 | unsigned long afsr_reg, afar_reg; | 346 | unsigned long afsr_reg, afar_reg; |
| 334 | unsigned long afsr, afar, error_bits; | 347 | unsigned long afsr, afar, error_bits; |
| 335 | int reported; | 348 | int reported, portid; |
| 336 | 349 | ||
| 337 | afsr_reg = reg_base + SYSIO_CE_AFSR; | 350 | afsr_reg = reg_base + SYSIO_CE_AFSR; |
| 338 | afar_reg = reg_base + SYSIO_CE_AFAR; | 351 | afar_reg = reg_base + SYSIO_CE_AFAR; |
| @@ -347,8 +360,10 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
| 347 | SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); | 360 | SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); |
| 348 | upa_writeq(error_bits, afsr_reg); | 361 | upa_writeq(error_bits, afsr_reg); |
| 349 | 362 | ||
| 363 | portid = of_getintprop_default(op->node, "portid", -1); | ||
| 364 | |||
| 350 | printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", | 365 | printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", |
| 351 | sbus->portid, | 366 | portid, |
| 352 | (((error_bits & SYSIO_CEAFSR_PPIO) ? | 367 | (((error_bits & SYSIO_CEAFSR_PPIO) ? |
| 353 | "PIO" : | 368 | "PIO" : |
| 354 | ((error_bits & SYSIO_CEAFSR_PDRD) ? | 369 | ((error_bits & SYSIO_CEAFSR_PDRD) ? |
| @@ -360,14 +375,14 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
| 360 | * XXX UDB CE trap handler does... -DaveM | 375 | * XXX UDB CE trap handler does... -DaveM |
| 361 | */ | 376 | */ |
| 362 | printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", | 377 | printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", |
| 363 | sbus->portid, | 378 | portid, |
| 364 | (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, | 379 | (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, |
| 365 | (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, | 380 | (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, |
| 366 | (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, | 381 | (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, |
| 367 | (afsr & SYSIO_CEAFSR_MID) >> 37UL); | 382 | (afsr & SYSIO_CEAFSR_MID) >> 37UL); |
| 368 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 383 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
| 369 | 384 | ||
| 370 | printk("SYSIO[%x]: Secondary CE errors [", sbus->portid); | 385 | printk("SYSIO[%x]: Secondary CE errors [", portid); |
| 371 | reported = 0; | 386 | reported = 0; |
| 372 | if (afsr & SYSIO_CEAFSR_SPIO) { | 387 | if (afsr & SYSIO_CEAFSR_SPIO) { |
| 373 | reported++; | 388 | reported++; |
| @@ -404,11 +419,11 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
| 404 | #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ | 419 | #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ |
| 405 | static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | 420 | static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) |
| 406 | { | 421 | { |
| 407 | struct sbus_bus *sbus = dev_id; | 422 | struct of_device *op = dev_id; |
| 408 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 423 | struct iommu *iommu = op->dev.archdata.iommu; |
| 409 | unsigned long afsr_reg, afar_reg, reg_base; | 424 | unsigned long afsr_reg, afar_reg, reg_base; |
| 410 | unsigned long afsr, afar, error_bits; | 425 | unsigned long afsr, afar, error_bits; |
| 411 | int reported; | 426 | int reported, portid; |
| 412 | 427 | ||
| 413 | reg_base = iommu->write_complete_reg - 0x2000UL; | 428 | reg_base = iommu->write_complete_reg - 0x2000UL; |
| 414 | afsr_reg = reg_base + SYSIO_SBUS_AFSR; | 429 | afsr_reg = reg_base + SYSIO_SBUS_AFSR; |
| @@ -423,9 +438,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
| 423 | SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); | 438 | SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); |
| 424 | upa_writeq(error_bits, afsr_reg); | 439 | upa_writeq(error_bits, afsr_reg); |
| 425 | 440 | ||
| 441 | portid = of_getintprop_default(op->node, "portid", -1); | ||
| 442 | |||
| 426 | /* Log the error. */ | 443 | /* Log the error. */ |
| 427 | printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", | 444 | printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", |
| 428 | sbus->portid, | 445 | portid, |
| 429 | (((error_bits & SYSIO_SBAFSR_PLE) ? | 446 | (((error_bits & SYSIO_SBAFSR_PLE) ? |
| 430 | "Late PIO Error" : | 447 | "Late PIO Error" : |
| 431 | ((error_bits & SYSIO_SBAFSR_PTO) ? | 448 | ((error_bits & SYSIO_SBAFSR_PTO) ? |
| @@ -434,11 +451,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
| 434 | "Error Ack" : "???")))), | 451 | "Error Ack" : "???")))), |
| 435 | (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); | 452 | (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); |
| 436 | printk("SYSIO[%x]: size[%lx] MID[%lx]\n", | 453 | printk("SYSIO[%x]: size[%lx] MID[%lx]\n", |
| 437 | sbus->portid, | 454 | portid, |
| 438 | (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, | 455 | (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, |
| 439 | (afsr & SYSIO_SBAFSR_MID) >> 37UL); | 456 | (afsr & SYSIO_SBAFSR_MID) >> 37UL); |
| 440 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 457 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
| 441 | printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid); | 458 | printk("SYSIO[%x]: Secondary SBUS errors [", portid); |
| 442 | reported = 0; | 459 | reported = 0; |
| 443 | if (afsr & SYSIO_SBAFSR_SLE) { | 460 | if (afsr & SYSIO_SBAFSR_SLE) { |
| 444 | reported++; | 461 | reported++; |
| @@ -470,34 +487,37 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
| 470 | #define SYSIO_CE_INO 0x35 | 487 | #define SYSIO_CE_INO 0x35 |
| 471 | #define SYSIO_SBUSERR_INO 0x36 | 488 | #define SYSIO_SBUSERR_INO 0x36 |
| 472 | 489 | ||
| 473 | static void __init sysio_register_error_handlers(struct sbus_bus *sbus) | 490 | static void __init sysio_register_error_handlers(struct of_device *op) |
| 474 | { | 491 | { |
| 475 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 492 | struct iommu *iommu = op->dev.archdata.iommu; |
| 476 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 493 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
| 477 | unsigned int irq; | 494 | unsigned int irq; |
| 478 | u64 control; | 495 | u64 control; |
| 496 | int portid; | ||
| 497 | |||
| 498 | portid = of_getintprop_default(op->node, "portid", -1); | ||
| 479 | 499 | ||
| 480 | irq = sbus_build_irq(sbus, SYSIO_UE_INO); | 500 | irq = sbus_build_irq(op, SYSIO_UE_INO); |
| 481 | if (request_irq(irq, sysio_ue_handler, 0, | 501 | if (request_irq(irq, sysio_ue_handler, 0, |
| 482 | "SYSIO_UE", sbus) < 0) { | 502 | "SYSIO_UE", op) < 0) { |
| 483 | prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", | 503 | prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", |
| 484 | sbus->portid); | 504 | portid); |
| 485 | prom_halt(); | 505 | prom_halt(); |
| 486 | } | 506 | } |
| 487 | 507 | ||
| 488 | irq = sbus_build_irq(sbus, SYSIO_CE_INO); | 508 | irq = sbus_build_irq(op, SYSIO_CE_INO); |
| 489 | if (request_irq(irq, sysio_ce_handler, 0, | 509 | if (request_irq(irq, sysio_ce_handler, 0, |
| 490 | "SYSIO_CE", sbus) < 0) { | 510 | "SYSIO_CE", op) < 0) { |
| 491 | prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", | 511 | prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", |
| 492 | sbus->portid); | 512 | portid); |
| 493 | prom_halt(); | 513 | prom_halt(); |
| 494 | } | 514 | } |
| 495 | 515 | ||
| 496 | irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); | 516 | irq = sbus_build_irq(op, SYSIO_SBUSERR_INO); |
| 497 | if (request_irq(irq, sysio_sbus_error_handler, 0, | 517 | if (request_irq(irq, sysio_sbus_error_handler, 0, |
| 498 | "SYSIO_SBERR", sbus) < 0) { | 518 | "SYSIO_SBERR", op) < 0) { |
| 499 | prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", | 519 | prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", |
| 500 | sbus->portid); | 520 | portid); |
| 501 | prom_halt(); | 521 | prom_halt(); |
| 502 | } | 522 | } |
| 503 | 523 | ||
| @@ -513,19 +533,15 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) | |||
| 513 | } | 533 | } |
| 514 | 534 | ||
| 515 | /* Boot time initialization. */ | 535 | /* Boot time initialization. */ |
| 516 | static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | 536 | static void __init sbus_iommu_init(struct of_device *op) |
| 517 | { | 537 | { |
| 518 | const struct linux_prom64_registers *pr; | 538 | const struct linux_prom64_registers *pr; |
| 519 | struct device_node *dp; | 539 | struct device_node *dp = op->node; |
| 520 | struct iommu *iommu; | 540 | struct iommu *iommu; |
| 521 | struct strbuf *strbuf; | 541 | struct strbuf *strbuf; |
| 522 | unsigned long regs, reg_base; | 542 | unsigned long regs, reg_base; |
| 543 | int i, portid; | ||
| 523 | u64 control; | 544 | u64 control; |
| 524 | int i; | ||
| 525 | |||
| 526 | dp = of_find_node_by_phandle(__node); | ||
| 527 | |||
| 528 | sbus->portid = of_getintprop_default(dp, "upa-portid", -1); | ||
| 529 | 545 | ||
| 530 | pr = of_get_property(dp, "reg", NULL); | 546 | pr = of_get_property(dp, "reg", NULL); |
| 531 | if (!pr) { | 547 | if (!pr) { |
| @@ -542,9 +558,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
| 542 | if (!strbuf) | 558 | if (!strbuf) |
| 543 | goto fatal_memory_error; | 559 | goto fatal_memory_error; |
| 544 | 560 | ||
| 545 | sbus->ofdev.dev.archdata.iommu = iommu; | 561 | op->dev.archdata.iommu = iommu; |
| 546 | sbus->ofdev.dev.archdata.stc = strbuf; | 562 | op->dev.archdata.stc = strbuf; |
| 547 | sbus->ofdev.dev.archdata.numa_node = -1; | 563 | op->dev.archdata.numa_node = -1; |
| 548 | 564 | ||
| 549 | reg_base = regs + SYSIO_IOMMUREG_BASE; | 565 | reg_base = regs + SYSIO_IOMMUREG_BASE; |
| 550 | iommu->iommu_control = reg_base + IOMMU_CONTROL; | 566 | iommu->iommu_control = reg_base + IOMMU_CONTROL; |
| @@ -572,8 +588,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
| 572 | */ | 588 | */ |
| 573 | iommu->write_complete_reg = regs + 0x2000UL; | 589 | iommu->write_complete_reg = regs + 0x2000UL; |
| 574 | 590 | ||
| 575 | printk("SYSIO: UPA portID %x, at %016lx\n", | 591 | portid = of_getintprop_default(op->node, "portid", -1); |
| 576 | sbus->portid, regs); | 592 | printk(KERN_INFO "SYSIO: UPA portID %x, at %016lx\n", |
| 593 | portid, regs); | ||
| 577 | 594 | ||
| 578 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ | 595 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ |
| 579 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) | 596 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) |
| @@ -631,56 +648,27 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
| 631 | 648 | ||
| 632 | /* Now some Xfire specific grot... */ | 649 | /* Now some Xfire specific grot... */ |
| 633 | if (this_is_starfire) | 650 | if (this_is_starfire) |
| 634 | starfire_hookup(sbus->portid); | 651 | starfire_hookup(portid); |
| 635 | 652 | ||
| 636 | sysio_register_error_handlers(sbus); | 653 | sysio_register_error_handlers(op); |
| 637 | return; | 654 | return; |
| 638 | 655 | ||
| 639 | fatal_memory_error: | 656 | fatal_memory_error: |
| 640 | prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); | 657 | prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); |
| 641 | } | 658 | } |
| 642 | 659 | ||
| 643 | void sbus_fill_device_irq(struct sbus_dev *sdev) | 660 | static int __init sbus_init(void) |
| 644 | { | 661 | { |
| 645 | struct device_node *dp = of_find_node_by_phandle(sdev->prom_node); | 662 | struct device_node *dp; |
| 646 | const struct linux_prom_irqs *irqs; | ||
| 647 | |||
| 648 | irqs = of_get_property(dp, "interrupts", NULL); | ||
| 649 | if (!irqs) { | ||
| 650 | sdev->irqs[0] = 0; | ||
| 651 | sdev->num_irqs = 0; | ||
| 652 | } else { | ||
| 653 | unsigned int pri = irqs[0].pri; | ||
| 654 | 663 | ||
| 655 | sdev->num_irqs = 1; | 664 | for_each_node_by_name(dp, "sbus") { |
| 656 | if (pri < 0x20) | 665 | struct of_device *op = of_find_device_by_node(dp); |
| 657 | pri += sdev->slot * 8; | ||
| 658 | 666 | ||
| 659 | sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); | 667 | sbus_iommu_init(op); |
| 668 | of_propagate_archdata(op); | ||
| 660 | } | 669 | } |
| 661 | } | ||
| 662 | 670 | ||
| 663 | void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) | ||
| 664 | { | ||
| 665 | } | ||
| 666 | |||
| 667 | void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) | ||
| 668 | { | ||
| 669 | sbus_iommu_init(dp->node, sbus); | ||
| 670 | } | ||
| 671 | |||
| 672 | void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) | ||
| 673 | { | ||
| 674 | } | ||
| 675 | |||
| 676 | int __init sbus_arch_preinit(void) | ||
| 677 | { | ||
| 678 | return 0; | 671 | return 0; |
| 679 | } | 672 | } |
| 680 | 673 | ||
| 681 | void __init sbus_arch_postinit(void) | 674 | subsys_initcall(sbus_init); |
| 682 | { | ||
| 683 | extern void firetruck_init(void); | ||
| 684 | |||
| 685 | firetruck_init(); | ||
| 686 | } | ||
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 743ccad61c60..2be166c544ca 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
| @@ -80,8 +80,6 @@ void smp_bogo(struct seq_file *m) | |||
| 80 | i, cpu_data(i).clock_tick); | 80 | i, cpu_data(i).clock_tick); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock); | ||
| 84 | |||
| 85 | extern void setup_sparc64_timer(void); | 83 | extern void setup_sparc64_timer(void); |
| 86 | 84 | ||
| 87 | static volatile unsigned long callin_flag = 0; | 85 | static volatile unsigned long callin_flag = 0; |
| @@ -120,9 +118,9 @@ void __cpuinit smp_callin(void) | |||
| 120 | while (!cpu_isset(cpuid, smp_commenced_mask)) | 118 | while (!cpu_isset(cpuid, smp_commenced_mask)) |
| 121 | rmb(); | 119 | rmb(); |
| 122 | 120 | ||
| 123 | spin_lock(&call_lock); | 121 | ipi_call_lock(); |
| 124 | cpu_set(cpuid, cpu_online_map); | 122 | cpu_set(cpuid, cpu_online_map); |
| 125 | spin_unlock(&call_lock); | 123 | ipi_call_unlock(); |
| 126 | 124 | ||
| 127 | /* idle thread is expected to have preempt disabled */ | 125 | /* idle thread is expected to have preempt disabled */ |
| 128 | preempt_disable(); | 126 | preempt_disable(); |
| @@ -1305,10 +1303,6 @@ int __cpu_disable(void) | |||
| 1305 | c->core_id = 0; | 1303 | c->core_id = 0; |
| 1306 | c->proc_id = -1; | 1304 | c->proc_id = -1; |
| 1307 | 1305 | ||
| 1308 | spin_lock(&call_lock); | ||
| 1309 | cpu_clear(cpu, cpu_online_map); | ||
| 1310 | spin_unlock(&call_lock); | ||
| 1311 | |||
| 1312 | smp_wmb(); | 1306 | smp_wmb(); |
| 1313 | 1307 | ||
| 1314 | /* Make sure no interrupts point to this cpu. */ | 1308 | /* Make sure no interrupts point to this cpu. */ |
| @@ -1318,6 +1312,10 @@ int __cpu_disable(void) | |||
| 1318 | mdelay(1); | 1312 | mdelay(1); |
| 1319 | local_irq_disable(); | 1313 | local_irq_disable(); |
| 1320 | 1314 | ||
| 1315 | ipi_call_lock(); | ||
| 1316 | cpu_clear(cpu, cpu_online_map); | ||
| 1317 | ipi_call_unlock(); | ||
| 1318 | |||
| 1321 | return 0; | 1319 | return 0; |
| 1322 | } | 1320 | } |
| 1323 | 1321 | ||
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 0804f71df6cb..30bba8b0a3b0 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <asm/elf.h> | 36 | #include <asm/elf.h> |
| 37 | #include <asm/head.h> | 37 | #include <asm/head.h> |
| 38 | #include <asm/smp.h> | 38 | #include <asm/smp.h> |
| 39 | #include <asm/mostek.h> | ||
| 40 | #include <asm/ptrace.h> | 39 | #include <asm/ptrace.h> |
| 41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 42 | #include <asm/checksum.h> | 41 | #include <asm/checksum.h> |
| @@ -44,12 +43,8 @@ | |||
| 44 | #include <asm/pgalloc.h> | 43 | #include <asm/pgalloc.h> |
| 45 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
| 46 | #ifdef CONFIG_SBUS | 45 | #ifdef CONFIG_SBUS |
| 47 | #include <asm/sbus.h> | ||
| 48 | #include <asm/dma.h> | 46 | #include <asm/dma.h> |
| 49 | #endif | 47 | #endif |
| 50 | #ifdef CONFIG_PCI | ||
| 51 | #include <asm/ebus.h> | ||
| 52 | #endif | ||
| 53 | #include <asm/ns87303.h> | 48 | #include <asm/ns87303.h> |
| 54 | #include <asm/timer.h> | 49 | #include <asm/timer.h> |
| 55 | #include <asm/cpudata.h> | 50 | #include <asm/cpudata.h> |
| @@ -68,7 +63,6 @@ extern void *__memscan_zero(void *, size_t); | |||
| 68 | extern void *__memscan_generic(void *, int, size_t); | 63 | extern void *__memscan_generic(void *, int, size_t); |
| 69 | extern int __memcmp(const void *, const void *, __kernel_size_t); | 64 | extern int __memcmp(const void *, const void *, __kernel_size_t); |
| 70 | extern __kernel_size_t strlen(const char *); | 65 | extern __kernel_size_t strlen(const char *); |
| 71 | extern void syscall_trace(struct pt_regs *, int); | ||
| 72 | extern void sys_sigsuspend(void); | 66 | extern void sys_sigsuspend(void); |
| 73 | extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); | 67 | extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); |
| 74 | extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); | 68 | extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); |
| @@ -154,26 +148,12 @@ EXPORT_SYMBOL(flush_dcache_page); | |||
| 154 | EXPORT_SYMBOL(__flush_dcache_range); | 148 | EXPORT_SYMBOL(__flush_dcache_range); |
| 155 | #endif | 149 | #endif |
| 156 | 150 | ||
| 157 | EXPORT_SYMBOL(mostek_lock); | ||
| 158 | EXPORT_SYMBOL(mstk48t02_regs); | ||
| 159 | #ifdef CONFIG_SUN_AUXIO | 151 | #ifdef CONFIG_SUN_AUXIO |
| 160 | EXPORT_SYMBOL(auxio_set_led); | 152 | EXPORT_SYMBOL(auxio_set_led); |
| 161 | EXPORT_SYMBOL(auxio_set_lte); | 153 | EXPORT_SYMBOL(auxio_set_lte); |
| 162 | #endif | 154 | #endif |
| 163 | #ifdef CONFIG_SBUS | 155 | #ifdef CONFIG_SBUS |
| 164 | EXPORT_SYMBOL(sbus_root); | ||
| 165 | EXPORT_SYMBOL(dma_chain); | ||
| 166 | EXPORT_SYMBOL(sbus_set_sbus64); | 156 | EXPORT_SYMBOL(sbus_set_sbus64); |
| 167 | EXPORT_SYMBOL(sbus_alloc_consistent); | ||
| 168 | EXPORT_SYMBOL(sbus_free_consistent); | ||
| 169 | EXPORT_SYMBOL(sbus_map_single); | ||
| 170 | EXPORT_SYMBOL(sbus_unmap_single); | ||
| 171 | EXPORT_SYMBOL(sbus_map_sg); | ||
| 172 | EXPORT_SYMBOL(sbus_unmap_sg); | ||
| 173 | EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); | ||
| 174 | EXPORT_SYMBOL(sbus_dma_sync_single_for_device); | ||
| 175 | EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); | ||
| 176 | EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); | ||
| 177 | #endif | 157 | #endif |
| 178 | EXPORT_SYMBOL(outsb); | 158 | EXPORT_SYMBOL(outsb); |
| 179 | EXPORT_SYMBOL(outsw); | 159 | EXPORT_SYMBOL(outsw); |
| @@ -182,7 +162,6 @@ EXPORT_SYMBOL(insb); | |||
| 182 | EXPORT_SYMBOL(insw); | 162 | EXPORT_SYMBOL(insw); |
| 183 | EXPORT_SYMBOL(insl); | 163 | EXPORT_SYMBOL(insl); |
| 184 | #ifdef CONFIG_PCI | 164 | #ifdef CONFIG_PCI |
| 185 | EXPORT_SYMBOL(ebus_chain); | ||
| 186 | EXPORT_SYMBOL(pci_alloc_consistent); | 165 | EXPORT_SYMBOL(pci_alloc_consistent); |
| 187 | EXPORT_SYMBOL(pci_free_consistent); | 166 | EXPORT_SYMBOL(pci_free_consistent); |
| 188 | EXPORT_SYMBOL(pci_map_single); | 167 | EXPORT_SYMBOL(pci_map_single); |
| @@ -300,3 +279,5 @@ EXPORT_SYMBOL(xor_niagara_2); | |||
| 300 | EXPORT_SYMBOL(xor_niagara_3); | 279 | EXPORT_SYMBOL(xor_niagara_3); |
| 301 | EXPORT_SYMBOL(xor_niagara_4); | 280 | EXPORT_SYMBOL(xor_niagara_4); |
| 302 | EXPORT_SYMBOL(xor_niagara_5); | 281 | EXPORT_SYMBOL(xor_niagara_5); |
| 282 | |||
| 283 | EXPORT_SYMBOL_GPL(real_hard_smp_processor_id); | ||
diff --git a/arch/sparc64/kernel/sstate.c b/arch/sparc64/kernel/sstate.c index 5b6e75b7f052..8cdbe5946b43 100644 --- a/arch/sparc64/kernel/sstate.c +++ b/arch/sparc64/kernel/sstate.c | |||
| @@ -1,14 +1,15 @@ | |||
| 1 | /* sstate.c: System soft state support. | 1 | /* sstate.c: System soft state support. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 7 | #include <linux/notifier.h> | 7 | #include <linux/notifier.h> |
| 8 | #include <linux/reboot.h> | ||
| 8 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 9 | 10 | ||
| 10 | #include <asm/hypervisor.h> | 11 | #include <asm/hypervisor.h> |
| 11 | #include <asm/sstate.h> | 12 | #include <asm/spitfire.h> |
| 12 | #include <asm/oplib.h> | 13 | #include <asm/oplib.h> |
| 13 | #include <asm/head.h> | 14 | #include <asm/head.h> |
| 14 | #include <asm/io.h> | 15 | #include <asm/io.h> |
| @@ -50,31 +51,34 @@ static const char rebooting_msg[32] __attribute__((aligned(32))) = | |||
| 50 | static const char panicing_msg[32] __attribute__((aligned(32))) = | 51 | static const char panicing_msg[32] __attribute__((aligned(32))) = |
| 51 | "Linux panicing"; | 52 | "Linux panicing"; |
| 52 | 53 | ||
| 53 | void sstate_booting(void) | 54 | static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused) |
| 54 | { | 55 | { |
| 55 | do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); | 56 | const char *msg; |
| 56 | } | ||
| 57 | 57 | ||
| 58 | void sstate_running(void) | 58 | switch (type) { |
| 59 | { | 59 | case SYS_DOWN: |
| 60 | do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); | 60 | default: |
| 61 | } | 61 | msg = rebooting_msg; |
| 62 | break; | ||
| 62 | 63 | ||
| 63 | void sstate_halt(void) | 64 | case SYS_HALT: |
| 64 | { | 65 | msg = halting_msg; |
| 65 | do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg); | 66 | break; |
| 66 | } | ||
| 67 | 67 | ||
| 68 | void sstate_poweroff(void) | 68 | case SYS_POWER_OFF: |
| 69 | { | 69 | msg = poweroff_msg; |
| 70 | do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg); | 70 | break; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | void sstate_reboot(void) | 73 | do_set_sstate(HV_SOFT_STATE_TRANSITION, msg); |
| 74 | { | 74 | |
| 75 | do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg); | 75 | return NOTIFY_OK; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | static struct notifier_block sstate_reboot_notifier = { | ||
| 79 | .notifier_call = sstate_reboot_call, | ||
| 80 | }; | ||
| 81 | |||
| 78 | static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) | 82 | static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) |
| 79 | { | 83 | { |
| 80 | do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg); | 84 | do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg); |
| @@ -87,18 +91,37 @@ static struct notifier_block sstate_panic_block = { | |||
| 87 | .priority = INT_MAX, | 91 | .priority = INT_MAX, |
| 88 | }; | 92 | }; |
| 89 | 93 | ||
| 90 | void __init sun4v_sstate_init(void) | 94 | static int __init sstate_init(void) |
| 91 | { | 95 | { |
| 92 | unsigned long major, minor; | 96 | unsigned long major, minor; |
| 93 | 97 | ||
| 98 | if (tlb_type != hypervisor) | ||
| 99 | return 0; | ||
| 100 | |||
| 94 | major = 1; | 101 | major = 1; |
| 95 | minor = 0; | 102 | minor = 0; |
| 96 | if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) | 103 | if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) |
| 97 | return; | 104 | return 0; |
| 98 | 105 | ||
| 99 | hv_supports_soft_state = 1; | 106 | hv_supports_soft_state = 1; |
| 100 | 107 | ||
| 101 | prom_sun4v_guest_soft_state(); | 108 | prom_sun4v_guest_soft_state(); |
| 109 | |||
| 110 | do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); | ||
| 111 | |||
| 102 | atomic_notifier_chain_register(&panic_notifier_list, | 112 | atomic_notifier_chain_register(&panic_notifier_list, |
| 103 | &sstate_panic_block); | 113 | &sstate_panic_block); |
| 114 | register_reboot_notifier(&sstate_reboot_notifier); | ||
| 115 | |||
| 116 | return 0; | ||
| 104 | } | 117 | } |
| 118 | |||
| 119 | core_initcall(sstate_init); | ||
| 120 | |||
| 121 | static int __init sstate_running(void) | ||
| 122 | { | ||
| 123 | do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); | ||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | late_initcall(sstate_running); | ||
diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c index 7461581b3bb9..060d0f3a6151 100644 --- a/arch/sparc64/kernel/starfire.c +++ b/arch/sparc64/kernel/starfire.c | |||
| @@ -28,11 +28,6 @@ void check_if_starfire(void) | |||
| 28 | this_is_starfire = 1; | 28 | this_is_starfire = 1; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | void starfire_cpu_setup(void) | ||
| 32 | { | ||
| 33 | /* Currently, nothing to do. */ | ||
| 34 | } | ||
| 35 | |||
| 36 | int starfire_hard_smp_processor_id(void) | 31 | int starfire_hard_smp_processor_id(void) |
| 37 | { | 32 | { |
| 38 | return upa_readl(0x1fff40000d0UL); | 33 | return upa_readl(0x1fff40000d0UL); |
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 3d118531baff..3320c9d0075f 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c | |||
| @@ -575,14 +575,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, | |||
| 575 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); | 575 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | /* These are here just in case some old sparc32 binary calls it. */ | ||
| 579 | asmlinkage long sys32_pause(void) | ||
| 580 | { | ||
| 581 | current->state = TASK_INTERRUPTIBLE; | ||
| 582 | schedule(); | ||
| 583 | return -ERESTARTNOHAND; | ||
| 584 | } | ||
| 585 | |||
| 586 | asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, | 578 | asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, |
| 587 | char __user *ubuf, | 579 | char __user *ubuf, |
| 588 | compat_size_t count, | 580 | compat_size_t count, |
diff --git a/arch/sparc64/kernel/syscalls.S b/arch/sparc64/kernel/syscalls.S index a2f24270ed8a..7a6786a71363 100644 --- a/arch/sparc64/kernel/syscalls.S +++ b/arch/sparc64/kernel/syscalls.S | |||
| @@ -65,9 +65,8 @@ sys32_rt_sigreturn: | |||
| 65 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 | 65 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 |
| 66 | be,pt %icc, rtrap | 66 | be,pt %icc, rtrap |
| 67 | nop | 67 | nop |
| 68 | add %sp, PTREGS_OFF, %o0 | 68 | call syscall_trace_leave |
| 69 | call syscall_trace | 69 | add %sp, PTREGS_OFF, %o0 |
| 70 | mov 1, %o1 | ||
| 71 | ba,pt %xcc, rtrap | 70 | ba,pt %xcc, rtrap |
| 72 | nop | 71 | nop |
| 73 | 72 | ||
| @@ -159,9 +158,8 @@ linux_sparc_ni_syscall: | |||
| 159 | or %l7, %lo(sys_ni_syscall), %l7 | 158 | or %l7, %lo(sys_ni_syscall), %l7 |
| 160 | 159 | ||
| 161 | linux_syscall_trace32: | 160 | linux_syscall_trace32: |
| 162 | add %sp, PTREGS_OFF, %o0 | 161 | call syscall_trace_enter |
| 163 | call syscall_trace | 162 | add %sp, PTREGS_OFF, %o0 |
| 164 | clr %o1 | ||
| 165 | brnz,pn %o0, 3f | 163 | brnz,pn %o0, 3f |
| 166 | mov -ENOSYS, %o0 | 164 | mov -ENOSYS, %o0 |
| 167 | srl %i0, 0, %o0 | 165 | srl %i0, 0, %o0 |
| @@ -172,9 +170,8 @@ linux_syscall_trace32: | |||
| 172 | srl %i3, 0, %o3 | 170 | srl %i3, 0, %o3 |
| 173 | 171 | ||
| 174 | linux_syscall_trace: | 172 | linux_syscall_trace: |
| 175 | add %sp, PTREGS_OFF, %o0 | 173 | call syscall_trace_enter |
| 176 | call syscall_trace | 174 | add %sp, PTREGS_OFF, %o0 |
| 177 | clr %o1 | ||
| 178 | brnz,pn %o0, 3f | 175 | brnz,pn %o0, 3f |
| 179 | mov -ENOSYS, %o0 | 176 | mov -ENOSYS, %o0 |
| 180 | mov %i0, %o0 | 177 | mov %i0, %o0 |
| @@ -275,9 +272,8 @@ ret_sys_call: | |||
| 275 | b,pt %xcc, rtrap | 272 | b,pt %xcc, rtrap |
| 276 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] | 273 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] |
| 277 | linux_syscall_trace2: | 274 | linux_syscall_trace2: |
| 278 | add %sp, PTREGS_OFF, %o0 | 275 | call syscall_trace_leave |
| 279 | call syscall_trace | 276 | add %sp, PTREGS_OFF, %o0 |
| 280 | mov 1, %o1 | ||
| 281 | stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] | 277 | stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] |
| 282 | ba,pt %xcc, rtrap | 278 | ba,pt %xcc, rtrap |
| 283 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] | 279 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] |
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 0fdbf3ba956e..5daee4b04dd5 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S | |||
| @@ -23,7 +23,7 @@ sys_call_table32: | |||
| 23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod | 23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod |
| 24 | /*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek | 24 | /*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek |
| 25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 | 25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 |
| 26 | /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause | 26 | /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause |
| 27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice | 27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice |
| 28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile | 28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile |
| 29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid | 29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index cc16fdcf98af..80d71a5ce1e3 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
| @@ -30,13 +30,14 @@ | |||
| 30 | #include <linux/percpu.h> | 30 | #include <linux/percpu.h> |
| 31 | #include <linux/miscdevice.h> | 31 | #include <linux/miscdevice.h> |
| 32 | #include <linux/rtc.h> | 32 | #include <linux/rtc.h> |
| 33 | #include <linux/rtc/m48t59.h> | ||
| 33 | #include <linux/kernel_stat.h> | 34 | #include <linux/kernel_stat.h> |
| 34 | #include <linux/clockchips.h> | 35 | #include <linux/clockchips.h> |
| 35 | #include <linux/clocksource.h> | 36 | #include <linux/clocksource.h> |
| 36 | #include <linux/of_device.h> | 37 | #include <linux/of_device.h> |
| 38 | #include <linux/platform_device.h> | ||
| 37 | 39 | ||
| 38 | #include <asm/oplib.h> | 40 | #include <asm/oplib.h> |
| 39 | #include <asm/mostek.h> | ||
| 40 | #include <asm/timer.h> | 41 | #include <asm/timer.h> |
| 41 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
| 42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| @@ -50,18 +51,7 @@ | |||
| 50 | 51 | ||
| 51 | #include "entry.h" | 52 | #include "entry.h" |
| 52 | 53 | ||
| 53 | DEFINE_SPINLOCK(mostek_lock); | ||
| 54 | DEFINE_SPINLOCK(rtc_lock); | 54 | DEFINE_SPINLOCK(rtc_lock); |
| 55 | void __iomem *mstk48t02_regs = NULL; | ||
| 56 | #ifdef CONFIG_PCI | ||
| 57 | unsigned long ds1287_regs = 0UL; | ||
| 58 | static void __iomem *bq4802_regs; | ||
| 59 | #endif | ||
| 60 | |||
| 61 | static void __iomem *mstk48t08_regs; | ||
| 62 | static void __iomem *mstk48t59_regs; | ||
| 63 | |||
| 64 | static int set_rtc_mmss(unsigned long); | ||
| 65 | 55 | ||
| 66 | #define TICK_PRIV_BIT (1UL << 63) | 56 | #define TICK_PRIV_BIT (1UL << 63) |
| 67 | #define TICKCMP_IRQ_BIT (1UL << 63) | 57 | #define TICKCMP_IRQ_BIT (1UL << 63) |
| @@ -405,313 +395,167 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; | |||
| 405 | 395 | ||
| 406 | int update_persistent_clock(struct timespec now) | 396 | int update_persistent_clock(struct timespec now) |
| 407 | { | 397 | { |
| 408 | return set_rtc_mmss(now.tv_sec); | 398 | struct rtc_device *rtc = rtc_class_open("rtc0"); |
| 409 | } | 399 | int err = -1; |
| 410 | 400 | ||
| 411 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ | 401 | if (rtc) { |
| 412 | static void __init kick_start_clock(void) | 402 | err = rtc_set_mmss(rtc, now.tv_sec); |
| 413 | { | 403 | rtc_class_close(rtc); |
| 414 | void __iomem *regs = mstk48t02_regs; | ||
| 415 | u8 sec, tmp; | ||
| 416 | int i, count; | ||
| 417 | |||
| 418 | prom_printf("CLOCK: Clock was stopped. Kick start "); | ||
| 419 | |||
| 420 | spin_lock_irq(&mostek_lock); | ||
| 421 | |||
| 422 | /* Turn on the kick start bit to start the oscillator. */ | ||
| 423 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 424 | tmp |= MSTK_CREG_WRITE; | ||
| 425 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 426 | tmp = mostek_read(regs + MOSTEK_SEC); | ||
| 427 | tmp &= ~MSTK_STOP; | ||
| 428 | mostek_write(regs + MOSTEK_SEC, tmp); | ||
| 429 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
| 430 | tmp |= MSTK_KICK_START; | ||
| 431 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
| 432 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 433 | tmp &= ~MSTK_CREG_WRITE; | ||
| 434 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 435 | |||
| 436 | spin_unlock_irq(&mostek_lock); | ||
| 437 | |||
| 438 | /* Delay to allow the clock oscillator to start. */ | ||
| 439 | sec = MSTK_REG_SEC(regs); | ||
| 440 | for (i = 0; i < 3; i++) { | ||
| 441 | while (sec == MSTK_REG_SEC(regs)) | ||
| 442 | for (count = 0; count < 100000; count++) | ||
| 443 | /* nothing */ ; | ||
| 444 | prom_printf("."); | ||
| 445 | sec = MSTK_REG_SEC(regs); | ||
| 446 | } | ||
| 447 | prom_printf("\n"); | ||
| 448 | |||
| 449 | spin_lock_irq(&mostek_lock); | ||
| 450 | |||
| 451 | /* Turn off kick start and set a "valid" time and date. */ | ||
| 452 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 453 | tmp |= MSTK_CREG_WRITE; | ||
| 454 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 455 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
| 456 | tmp &= ~MSTK_KICK_START; | ||
| 457 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
| 458 | MSTK_SET_REG_SEC(regs,0); | ||
| 459 | MSTK_SET_REG_MIN(regs,0); | ||
| 460 | MSTK_SET_REG_HOUR(regs,0); | ||
| 461 | MSTK_SET_REG_DOW(regs,5); | ||
| 462 | MSTK_SET_REG_DOM(regs,1); | ||
| 463 | MSTK_SET_REG_MONTH(regs,8); | ||
| 464 | MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); | ||
| 465 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 466 | tmp &= ~MSTK_CREG_WRITE; | ||
| 467 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 468 | |||
| 469 | spin_unlock_irq(&mostek_lock); | ||
| 470 | |||
| 471 | /* Ensure the kick start bit is off. If it isn't, turn it off. */ | ||
| 472 | while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) { | ||
| 473 | prom_printf("CLOCK: Kick start still on!\n"); | ||
| 474 | |||
| 475 | spin_lock_irq(&mostek_lock); | ||
| 476 | |||
| 477 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 478 | tmp |= MSTK_CREG_WRITE; | ||
| 479 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 480 | |||
| 481 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
| 482 | tmp &= ~MSTK_KICK_START; | ||
| 483 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
| 484 | |||
| 485 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 486 | tmp &= ~MSTK_CREG_WRITE; | ||
| 487 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 488 | |||
| 489 | spin_unlock_irq(&mostek_lock); | ||
| 490 | } | 404 | } |
| 491 | 405 | ||
| 492 | prom_printf("CLOCK: Kick start procedure successful.\n"); | 406 | return err; |
| 493 | } | 407 | } |
| 494 | 408 | ||
| 495 | /* Return nonzero if the clock chip battery is low. */ | 409 | unsigned long cmos_regs; |
| 496 | static int __init has_low_battery(void) | 410 | EXPORT_SYMBOL(cmos_regs); |
| 497 | { | ||
| 498 | void __iomem *regs = mstk48t02_regs; | ||
| 499 | u8 data1, data2; | ||
| 500 | |||
| 501 | spin_lock_irq(&mostek_lock); | ||
| 502 | 411 | ||
| 503 | data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */ | 412 | static struct resource rtc_cmos_resource; |
| 504 | mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */ | ||
| 505 | data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */ | ||
| 506 | mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */ | ||
| 507 | 413 | ||
| 508 | spin_unlock_irq(&mostek_lock); | 414 | static struct platform_device rtc_cmos_device = { |
| 509 | 415 | .name = "rtc_cmos", | |
| 510 | return (data1 == data2); /* Was the write blocked? */ | 416 | .id = -1, |
| 511 | } | 417 | .resource = &rtc_cmos_resource, |
| 418 | .num_resources = 1, | ||
| 419 | }; | ||
| 512 | 420 | ||
| 513 | static void __init mostek_set_system_time(void __iomem *mregs) | 421 | static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) |
| 514 | { | 422 | { |
| 515 | unsigned int year, mon, day, hour, min, sec; | 423 | struct resource *r; |
| 516 | u8 tmp; | ||
| 517 | |||
| 518 | spin_lock_irq(&mostek_lock); | ||
| 519 | 424 | ||
| 520 | /* Traditional Mostek chip. */ | 425 | printk(KERN_INFO "%s: RTC regs at 0x%lx\n", |
| 521 | tmp = mostek_read(mregs + MOSTEK_CREG); | 426 | op->node->full_name, op->resource[0].start); |
| 522 | tmp |= MSTK_CREG_READ; | ||
| 523 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
| 524 | 427 | ||
| 525 | sec = MSTK_REG_SEC(mregs); | 428 | /* The CMOS RTC driver only accepts IORESOURCE_IO, so cons |
| 526 | min = MSTK_REG_MIN(mregs); | 429 | * up a fake resource so that the probe works for all cases. |
| 527 | hour = MSTK_REG_HOUR(mregs); | 430 | * When the RTC is behind an ISA bus it will have IORESOURCE_IO |
| 528 | day = MSTK_REG_DOM(mregs); | 431 | * already, whereas when it's behind EBUS is will be IORESOURCE_MEM. |
| 529 | mon = MSTK_REG_MONTH(mregs); | 432 | */ |
| 530 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); | ||
| 531 | |||
| 532 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
| 533 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
| 534 | set_normalized_timespec(&wall_to_monotonic, | ||
| 535 | -xtime.tv_sec, -xtime.tv_nsec); | ||
| 536 | 433 | ||
| 537 | tmp = mostek_read(mregs + MOSTEK_CREG); | 434 | r = &rtc_cmos_resource; |
| 538 | tmp &= ~MSTK_CREG_READ; | 435 | r->flags = IORESOURCE_IO; |
| 539 | mostek_write(mregs + MOSTEK_CREG, tmp); | 436 | r->name = op->resource[0].name; |
| 437 | r->start = op->resource[0].start; | ||
| 438 | r->end = op->resource[0].end; | ||
| 540 | 439 | ||
| 541 | spin_unlock_irq(&mostek_lock); | 440 | cmos_regs = op->resource[0].start; |
| 441 | return platform_device_register(&rtc_cmos_device); | ||
| 542 | } | 442 | } |
| 543 | 443 | ||
| 544 | /* Probe for the real time clock chip. */ | 444 | static struct of_device_id __initdata rtc_match[] = { |
| 545 | static void __init set_system_time(void) | 445 | { |
| 546 | { | 446 | .name = "rtc", |
| 547 | unsigned int year, mon, day, hour, min, sec; | 447 | .compatible = "m5819", |
| 548 | void __iomem *mregs = mstk48t02_regs; | 448 | }, |
| 549 | #ifdef CONFIG_PCI | 449 | { |
| 550 | unsigned long dregs = ds1287_regs; | 450 | .name = "rtc", |
| 551 | void __iomem *bregs = bq4802_regs; | 451 | .compatible = "isa-m5819p", |
| 552 | #else | 452 | }, |
| 553 | unsigned long dregs = 0UL; | 453 | { |
| 554 | void __iomem *bregs = 0UL; | 454 | .name = "rtc", |
| 555 | #endif | 455 | .compatible = "isa-m5823p", |
| 556 | 456 | }, | |
| 557 | if (!mregs && !dregs && !bregs) { | 457 | { |
| 558 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | 458 | .name = "rtc", |
| 559 | prom_halt(); | 459 | .compatible = "ds1287", |
| 560 | } | 460 | }, |
| 561 | 461 | {}, | |
| 562 | if (mregs) { | 462 | }; |
| 563 | mostek_set_system_time(mregs); | ||
| 564 | return; | ||
| 565 | } | ||
| 566 | |||
| 567 | if (bregs) { | ||
| 568 | unsigned char val = readb(bregs + 0x0e); | ||
| 569 | unsigned int century; | ||
| 570 | 463 | ||
| 571 | /* BQ4802 RTC chip. */ | 464 | static struct of_platform_driver rtc_driver = { |
| 465 | .match_table = rtc_match, | ||
| 466 | .probe = rtc_probe, | ||
| 467 | .driver = { | ||
| 468 | .name = "rtc", | ||
| 469 | }, | ||
| 470 | }; | ||
| 572 | 471 | ||
| 573 | writeb(val | 0x08, bregs + 0x0e); | 472 | static struct platform_device rtc_bq4802_device = { |
| 473 | .name = "rtc-bq4802", | ||
| 474 | .id = -1, | ||
| 475 | .num_resources = 1, | ||
| 476 | }; | ||
| 574 | 477 | ||
| 575 | sec = readb(bregs + 0x00); | 478 | static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) |
| 576 | min = readb(bregs + 0x02); | 479 | { |
| 577 | hour = readb(bregs + 0x04); | ||
| 578 | day = readb(bregs + 0x06); | ||
| 579 | mon = readb(bregs + 0x09); | ||
| 580 | year = readb(bregs + 0x0a); | ||
| 581 | century = readb(bregs + 0x0f); | ||
| 582 | 480 | ||
| 583 | writeb(val, bregs + 0x0e); | 481 | printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n", |
| 482 | op->node->full_name, op->resource[0].start); | ||
| 584 | 483 | ||
| 585 | BCD_TO_BIN(sec); | 484 | rtc_bq4802_device.resource = &op->resource[0]; |
| 586 | BCD_TO_BIN(min); | 485 | return platform_device_register(&rtc_bq4802_device); |
| 587 | BCD_TO_BIN(hour); | 486 | } |
| 588 | BCD_TO_BIN(day); | ||
| 589 | BCD_TO_BIN(mon); | ||
| 590 | BCD_TO_BIN(year); | ||
| 591 | BCD_TO_BIN(century); | ||
| 592 | 487 | ||
| 593 | year += (century * 100); | 488 | static struct of_device_id __initdata bq4802_match[] = { |
| 594 | } else { | 489 | { |
| 595 | /* Dallas 12887 RTC chip. */ | 490 | .name = "rtc", |
| 596 | 491 | .compatible = "bq4802", | |
| 597 | do { | 492 | }, |
| 598 | sec = CMOS_READ(RTC_SECONDS); | 493 | }; |
| 599 | min = CMOS_READ(RTC_MINUTES); | ||
| 600 | hour = CMOS_READ(RTC_HOURS); | ||
| 601 | day = CMOS_READ(RTC_DAY_OF_MONTH); | ||
| 602 | mon = CMOS_READ(RTC_MONTH); | ||
| 603 | year = CMOS_READ(RTC_YEAR); | ||
| 604 | } while (sec != CMOS_READ(RTC_SECONDS)); | ||
| 605 | |||
| 606 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
| 607 | BCD_TO_BIN(sec); | ||
| 608 | BCD_TO_BIN(min); | ||
| 609 | BCD_TO_BIN(hour); | ||
| 610 | BCD_TO_BIN(day); | ||
| 611 | BCD_TO_BIN(mon); | ||
| 612 | BCD_TO_BIN(year); | ||
| 613 | } | ||
| 614 | if ((year += 1900) < 1970) | ||
| 615 | year += 100; | ||
| 616 | } | ||
| 617 | 494 | ||
| 618 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | 495 | static struct of_platform_driver bq4802_driver = { |
| 619 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 496 | .match_table = bq4802_match, |
| 620 | set_normalized_timespec(&wall_to_monotonic, | 497 | .probe = bq4802_probe, |
| 621 | -xtime.tv_sec, -xtime.tv_nsec); | 498 | .driver = { |
| 622 | } | 499 | .name = "bq4802", |
| 500 | }, | ||
| 501 | }; | ||
| 623 | 502 | ||
| 624 | /* davem suggests we keep this within the 4M locked kernel image */ | 503 | static unsigned char mostek_read_byte(struct device *dev, u32 ofs) |
| 625 | static u32 starfire_get_time(void) | ||
| 626 | { | 504 | { |
| 627 | static char obp_gettod[32]; | 505 | struct platform_device *pdev = to_platform_device(dev); |
| 628 | static u32 unix_tod; | 506 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; |
| 507 | void __iomem *regs; | ||
| 508 | unsigned char val; | ||
| 629 | 509 | ||
| 630 | sprintf(obp_gettod, "h# %08x unix-gettod", | 510 | regs = (void __iomem *) pdev->resource[0].start; |
| 631 | (unsigned int) (long) &unix_tod); | 511 | val = readb(regs + ofs); |
| 632 | prom_feval(obp_gettod); | ||
| 633 | 512 | ||
| 634 | return unix_tod; | 513 | /* the year 0 is 1968 */ |
| 514 | if (ofs == pdata->offset + M48T59_YEAR) { | ||
| 515 | val += 0x68; | ||
| 516 | if ((val & 0xf) > 9) | ||
| 517 | val += 6; | ||
| 518 | } | ||
| 519 | return val; | ||
| 635 | } | 520 | } |
| 636 | 521 | ||
| 637 | static int starfire_set_time(u32 val) | 522 | static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) |
| 638 | { | 523 | { |
| 639 | /* Do nothing, time is set using the service processor | 524 | struct platform_device *pdev = to_platform_device(dev); |
| 640 | * console on this platform. | 525 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; |
| 641 | */ | 526 | void __iomem *regs; |
| 642 | return 0; | ||
| 643 | } | ||
| 644 | 527 | ||
| 645 | static u32 hypervisor_get_time(void) | 528 | regs = (void __iomem *) pdev->resource[0].start; |
| 646 | { | 529 | if (ofs == pdata->offset + M48T59_YEAR) { |
| 647 | unsigned long ret, time; | 530 | if (val < 0x68) |
| 648 | int retries = 10000; | 531 | val += 0x32; |
| 649 | 532 | else | |
| 650 | retry: | 533 | val -= 0x68; |
| 651 | ret = sun4v_tod_get(&time); | 534 | if ((val & 0xf) > 9) |
| 652 | if (ret == HV_EOK) | 535 | val += 6; |
| 653 | return time; | 536 | if ((val & 0xf0) > 0x9A) |
| 654 | if (ret == HV_EWOULDBLOCK) { | 537 | val += 0x60; |
| 655 | if (--retries > 0) { | ||
| 656 | udelay(100); | ||
| 657 | goto retry; | ||
| 658 | } | ||
| 659 | printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); | ||
| 660 | return 0; | ||
| 661 | } | 538 | } |
| 662 | printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); | 539 | writeb(val, regs + ofs); |
| 663 | return 0; | ||
| 664 | } | 540 | } |
| 665 | 541 | ||
| 666 | static int hypervisor_set_time(u32 secs) | 542 | static struct m48t59_plat_data m48t59_data = { |
| 667 | { | 543 | .read_byte = mostek_read_byte, |
| 668 | unsigned long ret; | 544 | .write_byte = mostek_write_byte, |
| 669 | int retries = 10000; | 545 | }; |
| 670 | |||
| 671 | retry: | ||
| 672 | ret = sun4v_tod_set(secs); | ||
| 673 | if (ret == HV_EOK) | ||
| 674 | return 0; | ||
| 675 | if (ret == HV_EWOULDBLOCK) { | ||
| 676 | if (--retries > 0) { | ||
| 677 | udelay(100); | ||
| 678 | goto retry; | ||
| 679 | } | ||
| 680 | printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); | ||
| 681 | return -EAGAIN; | ||
| 682 | } | ||
| 683 | printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); | ||
| 684 | return -EOPNOTSUPP; | ||
| 685 | } | ||
| 686 | 546 | ||
| 687 | static int __init clock_model_matches(const char *model) | 547 | static struct platform_device m48t59_rtc = { |
| 688 | { | 548 | .name = "rtc-m48t59", |
| 689 | if (strcmp(model, "mk48t02") && | 549 | .id = 0, |
| 690 | strcmp(model, "mk48t08") && | 550 | .num_resources = 1, |
| 691 | strcmp(model, "mk48t59") && | 551 | .dev = { |
| 692 | strcmp(model, "m5819") && | 552 | .platform_data = &m48t59_data, |
| 693 | strcmp(model, "m5819p") && | 553 | }, |
| 694 | strcmp(model, "m5823") && | 554 | }; |
| 695 | strcmp(model, "ds1287") && | ||
| 696 | strcmp(model, "bq4802")) | ||
| 697 | return 0; | ||
| 698 | |||
| 699 | return 1; | ||
| 700 | } | ||
| 701 | 555 | ||
| 702 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) | 556 | static int __devinit mostek_probe(struct of_device *op, const struct of_device_id *match) |
| 703 | { | 557 | { |
| 704 | struct device_node *dp = op->node; | 558 | struct device_node *dp = op->node; |
| 705 | const char *model = of_get_property(dp, "model", NULL); | ||
| 706 | const char *compat = of_get_property(dp, "compatible", NULL); | ||
| 707 | unsigned long size, flags; | ||
| 708 | void __iomem *regs; | ||
| 709 | |||
| 710 | if (!model) | ||
| 711 | model = compat; | ||
| 712 | |||
| 713 | if (!model || !clock_model_matches(model)) | ||
| 714 | return -ENODEV; | ||
| 715 | 559 | ||
| 716 | /* On an Enterprise system there can be multiple mostek clocks. | 560 | /* On an Enterprise system there can be multiple mostek clocks. |
| 717 | * We should only match the one that is on the central FHC bus. | 561 | * We should only match the one that is on the central FHC bus. |
| @@ -720,88 +564,51 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id | |||
| 720 | strcmp(dp->parent->parent->name, "central") != 0) | 564 | strcmp(dp->parent->parent->name, "central") != 0) |
| 721 | return -ENODEV; | 565 | return -ENODEV; |
| 722 | 566 | ||
| 723 | size = (op->resource[0].end - op->resource[0].start) + 1; | 567 | printk(KERN_INFO "%s: Mostek regs at 0x%lx\n", |
| 724 | regs = of_ioremap(&op->resource[0], 0, size, "clock"); | 568 | dp->full_name, op->resource[0].start); |
| 725 | if (!regs) | ||
| 726 | return -ENOMEM; | ||
| 727 | |||
| 728 | #ifdef CONFIG_PCI | ||
| 729 | if (!strcmp(model, "ds1287") || | ||
| 730 | !strcmp(model, "m5819") || | ||
| 731 | !strcmp(model, "m5819p") || | ||
| 732 | !strcmp(model, "m5823")) { | ||
| 733 | ds1287_regs = (unsigned long) regs; | ||
| 734 | } else if (!strcmp(model, "bq4802")) { | ||
| 735 | bq4802_regs = regs; | ||
| 736 | } else | ||
| 737 | #endif | ||
| 738 | if (model[5] == '0' && model[6] == '2') { | ||
| 739 | mstk48t02_regs = regs; | ||
| 740 | } else if(model[5] == '0' && model[6] == '8') { | ||
| 741 | mstk48t08_regs = regs; | ||
| 742 | mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; | ||
| 743 | } else { | ||
| 744 | mstk48t59_regs = regs; | ||
| 745 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
| 746 | } | ||
| 747 | |||
| 748 | printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); | ||
| 749 | |||
| 750 | local_irq_save(flags); | ||
| 751 | |||
| 752 | if (mstk48t02_regs != NULL) { | ||
| 753 | /* Report a low battery voltage condition. */ | ||
| 754 | if (has_low_battery()) | ||
| 755 | prom_printf("NVRAM: Low battery voltage!\n"); | ||
| 756 | |||
| 757 | /* Kick start the clock if it is completely stopped. */ | ||
| 758 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | ||
| 759 | kick_start_clock(); | ||
| 760 | } | ||
| 761 | |||
| 762 | set_system_time(); | ||
| 763 | |||
| 764 | local_irq_restore(flags); | ||
| 765 | 569 | ||
| 766 | return 0; | 570 | m48t59_rtc.resource = &op->resource[0]; |
| 571 | return platform_device_register(&m48t59_rtc); | ||
| 767 | } | 572 | } |
| 768 | 573 | ||
| 769 | static struct of_device_id clock_match[] = { | 574 | static struct of_device_id __initdata mostek_match[] = { |
| 770 | { | 575 | { |
| 771 | .name = "eeprom", | 576 | .name = "eeprom", |
| 772 | }, | 577 | }, |
| 773 | { | ||
| 774 | .name = "rtc", | ||
| 775 | }, | ||
| 776 | {}, | 578 | {}, |
| 777 | }; | 579 | }; |
| 778 | 580 | ||
| 779 | static struct of_platform_driver clock_driver = { | 581 | static struct of_platform_driver mostek_driver = { |
| 780 | .match_table = clock_match, | 582 | .match_table = mostek_match, |
| 781 | .probe = clock_probe, | 583 | .probe = mostek_probe, |
| 782 | .driver = { | 584 | .driver = { |
| 783 | .name = "clock", | 585 | .name = "mostek", |
| 784 | }, | 586 | }, |
| 785 | }; | 587 | }; |
| 786 | 588 | ||
| 589 | static struct platform_device rtc_sun4v_device = { | ||
| 590 | .name = "rtc-sun4v", | ||
| 591 | .id = -1, | ||
| 592 | }; | ||
| 593 | |||
| 594 | static struct platform_device rtc_starfire_device = { | ||
| 595 | .name = "rtc-starfire", | ||
| 596 | .id = -1, | ||
| 597 | }; | ||
| 598 | |||
| 787 | static int __init clock_init(void) | 599 | static int __init clock_init(void) |
| 788 | { | 600 | { |
| 789 | if (this_is_starfire) { | 601 | if (this_is_starfire) |
| 790 | xtime.tv_sec = starfire_get_time(); | 602 | return platform_device_register(&rtc_starfire_device); |
| 791 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 603 | |
| 792 | set_normalized_timespec(&wall_to_monotonic, | 604 | if (tlb_type == hypervisor) |
| 793 | -xtime.tv_sec, -xtime.tv_nsec); | 605 | return platform_device_register(&rtc_sun4v_device); |
| 794 | return 0; | 606 | |
| 795 | } | 607 | (void) of_register_driver(&rtc_driver, &of_platform_bus_type); |
| 796 | if (tlb_type == hypervisor) { | 608 | (void) of_register_driver(&mostek_driver, &of_platform_bus_type); |
| 797 | xtime.tv_sec = hypervisor_get_time(); | 609 | (void) of_register_driver(&bq4802_driver, &of_platform_bus_type); |
| 798 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
| 799 | set_normalized_timespec(&wall_to_monotonic, | ||
| 800 | -xtime.tv_sec, -xtime.tv_nsec); | ||
| 801 | return 0; | ||
| 802 | } | ||
| 803 | 610 | ||
| 804 | return of_register_driver(&clock_driver, &of_platform_bus_type); | 611 | return 0; |
| 805 | } | 612 | } |
| 806 | 613 | ||
| 807 | /* Must be after subsys_initcall() so that busses are probed. Must | 614 | /* Must be after subsys_initcall() so that busses are probed. Must |
| @@ -814,7 +621,7 @@ fs_initcall(clock_init); | |||
| 814 | static unsigned long sparc64_init_timers(void) | 621 | static unsigned long sparc64_init_timers(void) |
| 815 | { | 622 | { |
| 816 | struct device_node *dp; | 623 | struct device_node *dp; |
| 817 | unsigned long clock; | 624 | unsigned long freq; |
| 818 | 625 | ||
| 819 | dp = of_find_node_by_path("/"); | 626 | dp = of_find_node_by_path("/"); |
| 820 | if (tlb_type == spitfire) { | 627 | if (tlb_type == spitfire) { |
| @@ -827,17 +634,17 @@ static unsigned long sparc64_init_timers(void) | |||
| 827 | if (manuf == 0x17 && impl == 0x13) { | 634 | if (manuf == 0x17 && impl == 0x13) { |
| 828 | /* Hummingbird, aka Ultra-IIe */ | 635 | /* Hummingbird, aka Ultra-IIe */ |
| 829 | tick_ops = &hbtick_operations; | 636 | tick_ops = &hbtick_operations; |
| 830 | clock = of_getintprop_default(dp, "stick-frequency", 0); | 637 | freq = of_getintprop_default(dp, "stick-frequency", 0); |
| 831 | } else { | 638 | } else { |
| 832 | tick_ops = &tick_operations; | 639 | tick_ops = &tick_operations; |
| 833 | clock = local_cpu_data().clock_tick; | 640 | freq = local_cpu_data().clock_tick; |
| 834 | } | 641 | } |
| 835 | } else { | 642 | } else { |
| 836 | tick_ops = &stick_operations; | 643 | tick_ops = &stick_operations; |
| 837 | clock = of_getintprop_default(dp, "stick-frequency", 0); | 644 | freq = of_getintprop_default(dp, "stick-frequency", 0); |
| 838 | } | 645 | } |
| 839 | 646 | ||
| 840 | return clock; | 647 | return freq; |
| 841 | } | 648 | } |
| 842 | 649 | ||
| 843 | struct freq_table { | 650 | struct freq_table { |
| @@ -1029,16 +836,16 @@ EXPORT_SYMBOL(udelay); | |||
| 1029 | 836 | ||
| 1030 | void __init time_init(void) | 837 | void __init time_init(void) |
| 1031 | { | 838 | { |
| 1032 | unsigned long clock = sparc64_init_timers(); | 839 | unsigned long freq = sparc64_init_timers(); |
| 1033 | 840 | ||
| 1034 | tb_ticks_per_usec = clock / USEC_PER_SEC; | 841 | tb_ticks_per_usec = freq / USEC_PER_SEC; |
| 1035 | 842 | ||
| 1036 | timer_ticks_per_nsec_quotient = | 843 | timer_ticks_per_nsec_quotient = |
| 1037 | clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT); | 844 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); |
| 1038 | 845 | ||
| 1039 | clocksource_tick.name = tick_ops->name; | 846 | clocksource_tick.name = tick_ops->name; |
| 1040 | clocksource_tick.mult = | 847 | clocksource_tick.mult = |
| 1041 | clocksource_hz2mult(clock, | 848 | clocksource_hz2mult(freq, |
| 1042 | clocksource_tick.shift); | 849 | clocksource_tick.shift); |
| 1043 | clocksource_tick.read = tick_ops->get_tick; | 850 | clocksource_tick.read = tick_ops->get_tick; |
| 1044 | 851 | ||
| @@ -1049,7 +856,7 @@ void __init time_init(void) | |||
| 1049 | 856 | ||
| 1050 | sparc64_clockevent.name = tick_ops->name; | 857 | sparc64_clockevent.name = tick_ops->name; |
| 1051 | 858 | ||
| 1052 | setup_clockevent_multiplier(clock); | 859 | setup_clockevent_multiplier(freq); |
| 1053 | 860 | ||
| 1054 | sparc64_clockevent.max_delta_ns = | 861 | sparc64_clockevent.max_delta_ns = |
| 1055 | clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); | 862 | clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); |
| @@ -1070,672 +877,8 @@ unsigned long long sched_clock(void) | |||
| 1070 | >> SPARC64_NSEC_PER_CYC_SHIFT; | 877 | >> SPARC64_NSEC_PER_CYC_SHIFT; |
| 1071 | } | 878 | } |
| 1072 | 879 | ||
| 1073 | static int set_rtc_mmss(unsigned long nowtime) | ||
| 1074 | { | ||
| 1075 | int real_seconds, real_minutes, chip_minutes; | ||
| 1076 | void __iomem *mregs = mstk48t02_regs; | ||
| 1077 | #ifdef CONFIG_PCI | ||
| 1078 | unsigned long dregs = ds1287_regs; | ||
| 1079 | void __iomem *bregs = bq4802_regs; | ||
| 1080 | #else | ||
| 1081 | unsigned long dregs = 0UL; | ||
| 1082 | void __iomem *bregs = 0UL; | ||
| 1083 | #endif | ||
| 1084 | unsigned long flags; | ||
| 1085 | u8 tmp; | ||
| 1086 | |||
| 1087 | /* | ||
| 1088 | * Not having a register set can lead to trouble. | ||
| 1089 | * Also starfire doesn't have a tod clock. | ||
| 1090 | */ | ||
| 1091 | if (!mregs && !dregs && !bregs) | ||
| 1092 | return -1; | ||
| 1093 | |||
| 1094 | if (mregs) { | ||
| 1095 | spin_lock_irqsave(&mostek_lock, flags); | ||
| 1096 | |||
| 1097 | /* Read the current RTC minutes. */ | ||
| 1098 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
| 1099 | tmp |= MSTK_CREG_READ; | ||
| 1100 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
| 1101 | |||
| 1102 | chip_minutes = MSTK_REG_MIN(mregs); | ||
| 1103 | |||
| 1104 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
| 1105 | tmp &= ~MSTK_CREG_READ; | ||
| 1106 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
| 1107 | |||
| 1108 | /* | ||
| 1109 | * since we're only adjusting minutes and seconds, | ||
| 1110 | * don't interfere with hour overflow. This avoids | ||
| 1111 | * messing with unknown time zones but requires your | ||
| 1112 | * RTC not to be off by more than 15 minutes | ||
| 1113 | */ | ||
| 1114 | real_seconds = nowtime % 60; | ||
| 1115 | real_minutes = nowtime / 60; | ||
| 1116 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
| 1117 | real_minutes += 30; /* correct for half hour time zone */ | ||
| 1118 | real_minutes %= 60; | ||
| 1119 | |||
| 1120 | if (abs(real_minutes - chip_minutes) < 30) { | ||
| 1121 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
| 1122 | tmp |= MSTK_CREG_WRITE; | ||
| 1123 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
| 1124 | |||
| 1125 | MSTK_SET_REG_SEC(mregs,real_seconds); | ||
| 1126 | MSTK_SET_REG_MIN(mregs,real_minutes); | ||
| 1127 | |||
| 1128 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
| 1129 | tmp &= ~MSTK_CREG_WRITE; | ||
| 1130 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
| 1131 | |||
| 1132 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
| 1133 | |||
| 1134 | return 0; | ||
| 1135 | } else { | ||
| 1136 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
| 1137 | |||
| 1138 | return -1; | ||
| 1139 | } | ||
| 1140 | } else if (bregs) { | ||
| 1141 | int retval = 0; | ||
| 1142 | unsigned char val = readb(bregs + 0x0e); | ||
| 1143 | |||
| 1144 | /* BQ4802 RTC chip. */ | ||
| 1145 | |||
| 1146 | writeb(val | 0x08, bregs + 0x0e); | ||
| 1147 | |||
| 1148 | chip_minutes = readb(bregs + 0x02); | ||
| 1149 | BCD_TO_BIN(chip_minutes); | ||
| 1150 | real_seconds = nowtime % 60; | ||
| 1151 | real_minutes = nowtime / 60; | ||
| 1152 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
| 1153 | real_minutes += 30; | ||
| 1154 | real_minutes %= 60; | ||
| 1155 | |||
| 1156 | if (abs(real_minutes - chip_minutes) < 30) { | ||
| 1157 | BIN_TO_BCD(real_seconds); | ||
| 1158 | BIN_TO_BCD(real_minutes); | ||
| 1159 | writeb(real_seconds, bregs + 0x00); | ||
| 1160 | writeb(real_minutes, bregs + 0x02); | ||
| 1161 | } else { | ||
| 1162 | printk(KERN_WARNING | ||
| 1163 | "set_rtc_mmss: can't update from %d to %d\n", | ||
| 1164 | chip_minutes, real_minutes); | ||
| 1165 | retval = -1; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | writeb(val, bregs + 0x0e); | ||
| 1169 | |||
| 1170 | return retval; | ||
| 1171 | } else { | ||
| 1172 | int retval = 0; | ||
| 1173 | unsigned char save_control, save_freq_select; | ||
| 1174 | |||
| 1175 | /* Stolen from arch/i386/kernel/time.c, see there for | ||
| 1176 | * credits and descriptive comments. | ||
| 1177 | */ | ||
| 1178 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 1179 | save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ | ||
| 1180 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
| 1181 | |||
| 1182 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ | ||
| 1183 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
| 1184 | |||
| 1185 | chip_minutes = CMOS_READ(RTC_MINUTES); | ||
| 1186 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
| 1187 | BCD_TO_BIN(chip_minutes); | ||
| 1188 | real_seconds = nowtime % 60; | ||
| 1189 | real_minutes = nowtime / 60; | ||
| 1190 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
| 1191 | real_minutes += 30; | ||
| 1192 | real_minutes %= 60; | ||
| 1193 | |||
| 1194 | if (abs(real_minutes - chip_minutes) < 30) { | ||
| 1195 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
| 1196 | BIN_TO_BCD(real_seconds); | ||
| 1197 | BIN_TO_BCD(real_minutes); | ||
| 1198 | } | ||
| 1199 | CMOS_WRITE(real_seconds,RTC_SECONDS); | ||
| 1200 | CMOS_WRITE(real_minutes,RTC_MINUTES); | ||
| 1201 | } else { | ||
| 1202 | printk(KERN_WARNING | ||
| 1203 | "set_rtc_mmss: can't update from %d to %d\n", | ||
| 1204 | chip_minutes, real_minutes); | ||
| 1205 | retval = -1; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
| 1209 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
| 1210 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 1211 | |||
| 1212 | return retval; | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ | ||
| 1217 | static unsigned char mini_rtc_status; /* bitmapped status byte. */ | ||
| 1218 | |||
| 1219 | #define FEBRUARY 2 | ||
| 1220 | #define STARTOFTIME 1970 | ||
| 1221 | #define SECDAY 86400L | ||
| 1222 | #define SECYR (SECDAY * 365) | ||
| 1223 | #define leapyear(year) ((year) % 4 == 0 && \ | ||
| 1224 | ((year) % 100 != 0 || (year) % 400 == 0)) | ||
| 1225 | #define days_in_year(a) (leapyear(a) ? 366 : 365) | ||
| 1226 | #define days_in_month(a) (month_days[(a) - 1]) | ||
| 1227 | |||
| 1228 | static int month_days[12] = { | ||
| 1229 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | ||
| 1230 | }; | ||
| 1231 | |||
| 1232 | /* | ||
| 1233 | * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) | ||
| 1234 | */ | ||
| 1235 | static void GregorianDay(struct rtc_time * tm) | ||
| 1236 | { | ||
| 1237 | int leapsToDate; | ||
| 1238 | int lastYear; | ||
| 1239 | int day; | ||
| 1240 | int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; | ||
| 1241 | |||
| 1242 | lastYear = tm->tm_year - 1; | ||
| 1243 | |||
| 1244 | /* | ||
| 1245 | * Number of leap corrections to apply up to end of last year | ||
| 1246 | */ | ||
| 1247 | leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400; | ||
| 1248 | |||
| 1249 | /* | ||
| 1250 | * This year is a leap year if it is divisible by 4 except when it is | ||
| 1251 | * divisible by 100 unless it is divisible by 400 | ||
| 1252 | * | ||
| 1253 | * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was | ||
| 1254 | */ | ||
| 1255 | day = tm->tm_mon > 2 && leapyear(tm->tm_year); | ||
| 1256 | |||
| 1257 | day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + | ||
| 1258 | tm->tm_mday; | ||
| 1259 | |||
| 1260 | tm->tm_wday = day % 7; | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | static void to_tm(int tim, struct rtc_time *tm) | ||
| 1264 | { | ||
| 1265 | register int i; | ||
| 1266 | register long hms, day; | ||
| 1267 | |||
| 1268 | day = tim / SECDAY; | ||
| 1269 | hms = tim % SECDAY; | ||
| 1270 | |||
| 1271 | /* Hours, minutes, seconds are easy */ | ||
| 1272 | tm->tm_hour = hms / 3600; | ||
| 1273 | tm->tm_min = (hms % 3600) / 60; | ||
| 1274 | tm->tm_sec = (hms % 3600) % 60; | ||
| 1275 | |||
| 1276 | /* Number of years in days */ | ||
| 1277 | for (i = STARTOFTIME; day >= days_in_year(i); i++) | ||
| 1278 | day -= days_in_year(i); | ||
| 1279 | tm->tm_year = i; | ||
| 1280 | |||
| 1281 | /* Number of months in days left */ | ||
| 1282 | if (leapyear(tm->tm_year)) | ||
| 1283 | days_in_month(FEBRUARY) = 29; | ||
| 1284 | for (i = 1; day >= days_in_month(i); i++) | ||
| 1285 | day -= days_in_month(i); | ||
| 1286 | days_in_month(FEBRUARY) = 28; | ||
| 1287 | tm->tm_mon = i; | ||
| 1288 | |||
| 1289 | /* Days are what is left over (+1) from all that. */ | ||
| 1290 | tm->tm_mday = day + 1; | ||
| 1291 | |||
| 1292 | /* | ||
| 1293 | * Determine the day of week | ||
| 1294 | */ | ||
| 1295 | GregorianDay(tm); | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | /* Both Starfire and SUN4V give us seconds since Jan 1st, 1970, | ||
| 1299 | * aka Unix time. So we have to convert to/from rtc_time. | ||
| 1300 | */ | ||
| 1301 | static void starfire_get_rtc_time(struct rtc_time *time) | ||
| 1302 | { | ||
| 1303 | u32 seconds = starfire_get_time(); | ||
| 1304 | |||
| 1305 | to_tm(seconds, time); | ||
| 1306 | time->tm_year -= 1900; | ||
| 1307 | time->tm_mon -= 1; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | static int starfire_set_rtc_time(struct rtc_time *time) | ||
| 1311 | { | ||
| 1312 | u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, | ||
| 1313 | time->tm_mday, time->tm_hour, | ||
| 1314 | time->tm_min, time->tm_sec); | ||
| 1315 | |||
| 1316 | return starfire_set_time(seconds); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | static void hypervisor_get_rtc_time(struct rtc_time *time) | ||
| 1320 | { | ||
| 1321 | u32 seconds = hypervisor_get_time(); | ||
| 1322 | |||
| 1323 | to_tm(seconds, time); | ||
| 1324 | time->tm_year -= 1900; | ||
| 1325 | time->tm_mon -= 1; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | static int hypervisor_set_rtc_time(struct rtc_time *time) | ||
| 1329 | { | ||
| 1330 | u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, | ||
| 1331 | time->tm_mday, time->tm_hour, | ||
| 1332 | time->tm_min, time->tm_sec); | ||
| 1333 | |||
| 1334 | return hypervisor_set_time(seconds); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | #ifdef CONFIG_PCI | ||
| 1338 | static void bq4802_get_rtc_time(struct rtc_time *time) | ||
| 1339 | { | ||
| 1340 | unsigned char val = readb(bq4802_regs + 0x0e); | ||
| 1341 | unsigned int century; | ||
| 1342 | |||
| 1343 | writeb(val | 0x08, bq4802_regs + 0x0e); | ||
| 1344 | |||
| 1345 | time->tm_sec = readb(bq4802_regs + 0x00); | ||
| 1346 | time->tm_min = readb(bq4802_regs + 0x02); | ||
| 1347 | time->tm_hour = readb(bq4802_regs + 0x04); | ||
| 1348 | time->tm_mday = readb(bq4802_regs + 0x06); | ||
| 1349 | time->tm_mon = readb(bq4802_regs + 0x09); | ||
| 1350 | time->tm_year = readb(bq4802_regs + 0x0a); | ||
| 1351 | time->tm_wday = readb(bq4802_regs + 0x08); | ||
| 1352 | century = readb(bq4802_regs + 0x0f); | ||
| 1353 | |||
| 1354 | writeb(val, bq4802_regs + 0x0e); | ||
| 1355 | |||
| 1356 | BCD_TO_BIN(time->tm_sec); | ||
| 1357 | BCD_TO_BIN(time->tm_min); | ||
| 1358 | BCD_TO_BIN(time->tm_hour); | ||
| 1359 | BCD_TO_BIN(time->tm_mday); | ||
| 1360 | BCD_TO_BIN(time->tm_mon); | ||
| 1361 | BCD_TO_BIN(time->tm_year); | ||
| 1362 | BCD_TO_BIN(time->tm_wday); | ||
| 1363 | BCD_TO_BIN(century); | ||
| 1364 | |||
| 1365 | time->tm_year += (century * 100); | ||
| 1366 | time->tm_year -= 1900; | ||
| 1367 | |||
| 1368 | time->tm_mon--; | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static int bq4802_set_rtc_time(struct rtc_time *time) | ||
| 1372 | { | ||
| 1373 | unsigned char val = readb(bq4802_regs + 0x0e); | ||
| 1374 | unsigned char sec, min, hrs, day, mon, yrs, century; | ||
| 1375 | unsigned int year; | ||
| 1376 | |||
| 1377 | year = time->tm_year + 1900; | ||
| 1378 | century = year / 100; | ||
| 1379 | yrs = year % 100; | ||
| 1380 | |||
| 1381 | mon = time->tm_mon + 1; /* tm_mon starts at zero */ | ||
| 1382 | day = time->tm_mday; | ||
| 1383 | hrs = time->tm_hour; | ||
| 1384 | min = time->tm_min; | ||
| 1385 | sec = time->tm_sec; | ||
| 1386 | |||
| 1387 | BIN_TO_BCD(sec); | ||
| 1388 | BIN_TO_BCD(min); | ||
| 1389 | BIN_TO_BCD(hrs); | ||
| 1390 | BIN_TO_BCD(day); | ||
| 1391 | BIN_TO_BCD(mon); | ||
| 1392 | BIN_TO_BCD(yrs); | ||
| 1393 | BIN_TO_BCD(century); | ||
| 1394 | |||
| 1395 | writeb(val | 0x08, bq4802_regs + 0x0e); | ||
| 1396 | |||
| 1397 | writeb(sec, bq4802_regs + 0x00); | ||
| 1398 | writeb(min, bq4802_regs + 0x02); | ||
| 1399 | writeb(hrs, bq4802_regs + 0x04); | ||
| 1400 | writeb(day, bq4802_regs + 0x06); | ||
| 1401 | writeb(mon, bq4802_regs + 0x09); | ||
| 1402 | writeb(yrs, bq4802_regs + 0x0a); | ||
| 1403 | writeb(century, bq4802_regs + 0x0f); | ||
| 1404 | |||
| 1405 | writeb(val, bq4802_regs + 0x0e); | ||
| 1406 | |||
| 1407 | return 0; | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | static void cmos_get_rtc_time(struct rtc_time *rtc_tm) | ||
| 1411 | { | ||
| 1412 | unsigned char ctrl; | ||
| 1413 | |||
| 1414 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | ||
| 1415 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | ||
| 1416 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); | ||
| 1417 | rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); | ||
| 1418 | rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); | ||
| 1419 | rtc_tm->tm_year = CMOS_READ(RTC_YEAR); | ||
| 1420 | rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); | ||
| 1421 | |||
| 1422 | ctrl = CMOS_READ(RTC_CONTROL); | ||
| 1423 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
| 1424 | BCD_TO_BIN(rtc_tm->tm_sec); | ||
| 1425 | BCD_TO_BIN(rtc_tm->tm_min); | ||
| 1426 | BCD_TO_BIN(rtc_tm->tm_hour); | ||
| 1427 | BCD_TO_BIN(rtc_tm->tm_mday); | ||
| 1428 | BCD_TO_BIN(rtc_tm->tm_mon); | ||
| 1429 | BCD_TO_BIN(rtc_tm->tm_year); | ||
| 1430 | BCD_TO_BIN(rtc_tm->tm_wday); | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | if (rtc_tm->tm_year <= 69) | ||
| 1434 | rtc_tm->tm_year += 100; | ||
| 1435 | |||
| 1436 | rtc_tm->tm_mon--; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | static int cmos_set_rtc_time(struct rtc_time *rtc_tm) | ||
| 1440 | { | ||
| 1441 | unsigned char mon, day, hrs, min, sec; | ||
| 1442 | unsigned char save_control, save_freq_select; | ||
| 1443 | unsigned int yrs; | ||
| 1444 | |||
| 1445 | yrs = rtc_tm->tm_year; | ||
| 1446 | mon = rtc_tm->tm_mon + 1; | ||
| 1447 | day = rtc_tm->tm_mday; | ||
| 1448 | hrs = rtc_tm->tm_hour; | ||
| 1449 | min = rtc_tm->tm_min; | ||
| 1450 | sec = rtc_tm->tm_sec; | ||
| 1451 | |||
| 1452 | if (yrs >= 100) | ||
| 1453 | yrs -= 100; | ||
| 1454 | |||
| 1455 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
| 1456 | BIN_TO_BCD(sec); | ||
| 1457 | BIN_TO_BCD(min); | ||
| 1458 | BIN_TO_BCD(hrs); | ||
| 1459 | BIN_TO_BCD(day); | ||
| 1460 | BIN_TO_BCD(mon); | ||
| 1461 | BIN_TO_BCD(yrs); | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | save_control = CMOS_READ(RTC_CONTROL); | ||
| 1465 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
| 1466 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | ||
| 1467 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
| 1468 | |||
| 1469 | CMOS_WRITE(yrs, RTC_YEAR); | ||
| 1470 | CMOS_WRITE(mon, RTC_MONTH); | ||
| 1471 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); | ||
| 1472 | CMOS_WRITE(hrs, RTC_HOURS); | ||
| 1473 | CMOS_WRITE(min, RTC_MINUTES); | ||
| 1474 | CMOS_WRITE(sec, RTC_SECONDS); | ||
| 1475 | |||
| 1476 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
| 1477 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
| 1478 | |||
| 1479 | return 0; | ||
| 1480 | } | ||
| 1481 | #endif /* CONFIG_PCI */ | ||
| 1482 | |||
| 1483 | static void mostek_get_rtc_time(struct rtc_time *rtc_tm) | ||
| 1484 | { | ||
| 1485 | void __iomem *regs = mstk48t02_regs; | ||
| 1486 | u8 tmp; | ||
| 1487 | |||
| 1488 | spin_lock_irq(&mostek_lock); | ||
| 1489 | |||
| 1490 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 1491 | tmp |= MSTK_CREG_READ; | ||
| 1492 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 1493 | |||
| 1494 | rtc_tm->tm_sec = MSTK_REG_SEC(regs); | ||
| 1495 | rtc_tm->tm_min = MSTK_REG_MIN(regs); | ||
| 1496 | rtc_tm->tm_hour = MSTK_REG_HOUR(regs); | ||
| 1497 | rtc_tm->tm_mday = MSTK_REG_DOM(regs); | ||
| 1498 | rtc_tm->tm_mon = MSTK_REG_MONTH(regs); | ||
| 1499 | rtc_tm->tm_year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); | ||
| 1500 | rtc_tm->tm_wday = MSTK_REG_DOW(regs); | ||
| 1501 | |||
| 1502 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 1503 | tmp &= ~MSTK_CREG_READ; | ||
| 1504 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 1505 | |||
| 1506 | spin_unlock_irq(&mostek_lock); | ||
| 1507 | |||
| 1508 | rtc_tm->tm_mon--; | ||
| 1509 | rtc_tm->tm_wday--; | ||
| 1510 | rtc_tm->tm_year -= 1900; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | static int mostek_set_rtc_time(struct rtc_time *rtc_tm) | ||
| 1514 | { | ||
| 1515 | unsigned char mon, day, hrs, min, sec, wday; | ||
| 1516 | void __iomem *regs = mstk48t02_regs; | ||
| 1517 | unsigned int yrs; | ||
| 1518 | u8 tmp; | ||
| 1519 | |||
| 1520 | yrs = rtc_tm->tm_year + 1900; | ||
| 1521 | mon = rtc_tm->tm_mon + 1; | ||
| 1522 | day = rtc_tm->tm_mday; | ||
| 1523 | wday = rtc_tm->tm_wday + 1; | ||
| 1524 | hrs = rtc_tm->tm_hour; | ||
| 1525 | min = rtc_tm->tm_min; | ||
| 1526 | sec = rtc_tm->tm_sec; | ||
| 1527 | |||
| 1528 | spin_lock_irq(&mostek_lock); | ||
| 1529 | |||
| 1530 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 1531 | tmp |= MSTK_CREG_WRITE; | ||
| 1532 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 1533 | |||
| 1534 | MSTK_SET_REG_SEC(regs, sec); | ||
| 1535 | MSTK_SET_REG_MIN(regs, min); | ||
| 1536 | MSTK_SET_REG_HOUR(regs, hrs); | ||
| 1537 | MSTK_SET_REG_DOW(regs, wday); | ||
| 1538 | MSTK_SET_REG_DOM(regs, day); | ||
| 1539 | MSTK_SET_REG_MONTH(regs, mon); | ||
| 1540 | MSTK_SET_REG_YEAR(regs, yrs - MSTK_YEAR_ZERO); | ||
| 1541 | |||
| 1542 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 1543 | tmp &= ~MSTK_CREG_WRITE; | ||
| 1544 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 1545 | |||
| 1546 | spin_unlock_irq(&mostek_lock); | ||
| 1547 | |||
| 1548 | return 0; | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | struct mini_rtc_ops { | ||
| 1552 | void (*get_rtc_time)(struct rtc_time *); | ||
| 1553 | int (*set_rtc_time)(struct rtc_time *); | ||
| 1554 | }; | ||
| 1555 | |||
| 1556 | static struct mini_rtc_ops starfire_rtc_ops = { | ||
| 1557 | .get_rtc_time = starfire_get_rtc_time, | ||
| 1558 | .set_rtc_time = starfire_set_rtc_time, | ||
| 1559 | }; | ||
| 1560 | |||
| 1561 | static struct mini_rtc_ops hypervisor_rtc_ops = { | ||
| 1562 | .get_rtc_time = hypervisor_get_rtc_time, | ||
| 1563 | .set_rtc_time = hypervisor_set_rtc_time, | ||
| 1564 | }; | ||
| 1565 | |||
| 1566 | #ifdef CONFIG_PCI | ||
| 1567 | static struct mini_rtc_ops bq4802_rtc_ops = { | ||
| 1568 | .get_rtc_time = bq4802_get_rtc_time, | ||
| 1569 | .set_rtc_time = bq4802_set_rtc_time, | ||
| 1570 | }; | ||
| 1571 | |||
| 1572 | static struct mini_rtc_ops cmos_rtc_ops = { | ||
| 1573 | .get_rtc_time = cmos_get_rtc_time, | ||
| 1574 | .set_rtc_time = cmos_set_rtc_time, | ||
| 1575 | }; | ||
| 1576 | #endif /* CONFIG_PCI */ | ||
| 1577 | |||
| 1578 | static struct mini_rtc_ops mostek_rtc_ops = { | ||
| 1579 | .get_rtc_time = mostek_get_rtc_time, | ||
| 1580 | .set_rtc_time = mostek_set_rtc_time, | ||
| 1581 | }; | ||
| 1582 | |||
| 1583 | static struct mini_rtc_ops *mini_rtc_ops; | ||
| 1584 | |||
| 1585 | static inline void mini_get_rtc_time(struct rtc_time *time) | ||
| 1586 | { | ||
| 1587 | unsigned long flags; | ||
| 1588 | |||
| 1589 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 1590 | mini_rtc_ops->get_rtc_time(time); | ||
| 1591 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | static inline int mini_set_rtc_time(struct rtc_time *time) | ||
| 1595 | { | ||
| 1596 | unsigned long flags; | ||
| 1597 | int err; | ||
| 1598 | |||
| 1599 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 1600 | err = mini_rtc_ops->set_rtc_time(time); | ||
| 1601 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 1602 | |||
| 1603 | return err; | ||
| 1604 | } | ||
| 1605 | |||
| 1606 | static int mini_rtc_ioctl(struct inode *inode, struct file *file, | ||
| 1607 | unsigned int cmd, unsigned long arg) | ||
| 1608 | { | ||
| 1609 | struct rtc_time wtime; | ||
| 1610 | void __user *argp = (void __user *)arg; | ||
| 1611 | |||
| 1612 | switch (cmd) { | ||
| 1613 | |||
| 1614 | case RTC_PLL_GET: | ||
| 1615 | return -EINVAL; | ||
| 1616 | |||
| 1617 | case RTC_PLL_SET: | ||
| 1618 | return -EINVAL; | ||
| 1619 | |||
| 1620 | case RTC_UIE_OFF: /* disable ints from RTC updates. */ | ||
| 1621 | return 0; | ||
| 1622 | |||
| 1623 | case RTC_UIE_ON: /* enable ints for RTC updates. */ | ||
| 1624 | return -EINVAL; | ||
| 1625 | |||
| 1626 | case RTC_RD_TIME: /* Read the time/date from RTC */ | ||
| 1627 | /* this doesn't get week-day, who cares */ | ||
| 1628 | memset(&wtime, 0, sizeof(wtime)); | ||
| 1629 | mini_get_rtc_time(&wtime); | ||
| 1630 | |||
| 1631 | return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0; | ||
| 1632 | |||
| 1633 | case RTC_SET_TIME: /* Set the RTC */ | ||
| 1634 | { | ||
| 1635 | int year, days; | ||
| 1636 | |||
| 1637 | if (!capable(CAP_SYS_TIME)) | ||
| 1638 | return -EACCES; | ||
| 1639 | |||
| 1640 | if (copy_from_user(&wtime, argp, sizeof(wtime))) | ||
| 1641 | return -EFAULT; | ||
| 1642 | |||
| 1643 | year = wtime.tm_year + 1900; | ||
| 1644 | days = month_days[wtime.tm_mon] + | ||
| 1645 | ((wtime.tm_mon == 1) && leapyear(year)); | ||
| 1646 | |||
| 1647 | if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || | ||
| 1648 | (wtime.tm_mday < 1)) | ||
| 1649 | return -EINVAL; | ||
| 1650 | |||
| 1651 | if (wtime.tm_mday < 0 || wtime.tm_mday > days) | ||
| 1652 | return -EINVAL; | ||
| 1653 | |||
| 1654 | if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || | ||
| 1655 | wtime.tm_min < 0 || wtime.tm_min >= 60 || | ||
| 1656 | wtime.tm_sec < 0 || wtime.tm_sec >= 60) | ||
| 1657 | return -EINVAL; | ||
| 1658 | |||
| 1659 | return mini_set_rtc_time(&wtime); | ||
| 1660 | } | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | return -EINVAL; | ||
| 1664 | } | ||
| 1665 | |||
| 1666 | static int mini_rtc_open(struct inode *inode, struct file *file) | ||
| 1667 | { | ||
| 1668 | lock_kernel(); | ||
| 1669 | if (mini_rtc_status & RTC_IS_OPEN) { | ||
| 1670 | unlock_kernel(); | ||
| 1671 | return -EBUSY; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | mini_rtc_status |= RTC_IS_OPEN; | ||
| 1675 | unlock_kernel(); | ||
| 1676 | |||
| 1677 | return 0; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | static int mini_rtc_release(struct inode *inode, struct file *file) | ||
| 1681 | { | ||
| 1682 | mini_rtc_status &= ~RTC_IS_OPEN; | ||
| 1683 | return 0; | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | |||
| 1687 | static const struct file_operations mini_rtc_fops = { | ||
| 1688 | .owner = THIS_MODULE, | ||
| 1689 | .ioctl = mini_rtc_ioctl, | ||
| 1690 | .open = mini_rtc_open, | ||
| 1691 | .release = mini_rtc_release, | ||
| 1692 | }; | ||
| 1693 | |||
| 1694 | static struct miscdevice rtc_mini_dev = | ||
| 1695 | { | ||
| 1696 | .minor = RTC_MINOR, | ||
| 1697 | .name = "rtc", | ||
| 1698 | .fops = &mini_rtc_fops, | ||
| 1699 | }; | ||
| 1700 | |||
| 1701 | static int __init rtc_mini_init(void) | ||
| 1702 | { | ||
| 1703 | int retval; | ||
| 1704 | |||
| 1705 | if (tlb_type == hypervisor) | ||
| 1706 | mini_rtc_ops = &hypervisor_rtc_ops; | ||
| 1707 | else if (this_is_starfire) | ||
| 1708 | mini_rtc_ops = &starfire_rtc_ops; | ||
| 1709 | #ifdef CONFIG_PCI | ||
| 1710 | else if (bq4802_regs) | ||
| 1711 | mini_rtc_ops = &bq4802_rtc_ops; | ||
| 1712 | else if (ds1287_regs) | ||
| 1713 | mini_rtc_ops = &cmos_rtc_ops; | ||
| 1714 | #endif /* CONFIG_PCI */ | ||
| 1715 | else if (mstk48t02_regs) | ||
| 1716 | mini_rtc_ops = &mostek_rtc_ops; | ||
| 1717 | else | ||
| 1718 | return -ENODEV; | ||
| 1719 | |||
| 1720 | printk(KERN_INFO "Mini RTC Driver\n"); | ||
| 1721 | |||
| 1722 | retval = misc_register(&rtc_mini_dev); | ||
| 1723 | if (retval < 0) | ||
| 1724 | return retval; | ||
| 1725 | |||
| 1726 | return 0; | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | static void __exit rtc_mini_exit(void) | ||
| 1730 | { | ||
| 1731 | misc_deregister(&rtc_mini_dev); | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | int __devinit read_current_timer(unsigned long *timer_val) | 880 | int __devinit read_current_timer(unsigned long *timer_val) |
| 1735 | { | 881 | { |
| 1736 | *timer_val = tick_ops->get_tick(); | 882 | *timer_val = tick_ops->get_tick(); |
| 1737 | return 0; | 883 | return 0; |
| 1738 | } | 884 | } |
| 1739 | |||
| 1740 | module_init(rtc_mini_init); | ||
| 1741 | module_exit(rtc_mini_exit); | ||
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 3d924121c796..81ccd22e78d4 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
| 13 | #include <linux/linkage.h> | ||
| 13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 14 | #include <linux/signal.h> | 15 | #include <linux/signal.h> |
| 15 | #include <linux/smp.h> | 16 | #include <linux/smp.h> |
| @@ -37,6 +38,7 @@ | |||
| 37 | #include <asm/timer.h> | 38 | #include <asm/timer.h> |
| 38 | #include <asm/head.h> | 39 | #include <asm/head.h> |
| 39 | #include <asm/prom.h> | 40 | #include <asm/prom.h> |
| 41 | #include <asm/memctrl.h> | ||
| 40 | 42 | ||
| 41 | #include "entry.h" | 43 | #include "entry.h" |
| 42 | #include "kstack.h" | 44 | #include "kstack.h" |
| @@ -128,6 +130,56 @@ void do_BUG(const char *file, int line) | |||
| 128 | } | 130 | } |
| 129 | #endif | 131 | #endif |
| 130 | 132 | ||
| 133 | static DEFINE_SPINLOCK(dimm_handler_lock); | ||
| 134 | static dimm_printer_t dimm_handler; | ||
| 135 | |||
| 136 | static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen) | ||
| 137 | { | ||
| 138 | unsigned long flags; | ||
| 139 | int ret = -ENODEV; | ||
| 140 | |||
| 141 | spin_lock_irqsave(&dimm_handler_lock, flags); | ||
| 142 | if (dimm_handler) { | ||
| 143 | ret = dimm_handler(synd_code, paddr, buf, buflen); | ||
| 144 | } else if (tlb_type == spitfire) { | ||
| 145 | if (prom_getunumber(synd_code, paddr, buf, buflen) == -1) | ||
| 146 | ret = -EINVAL; | ||
| 147 | else | ||
| 148 | ret = 0; | ||
| 149 | } else | ||
| 150 | ret = -ENODEV; | ||
| 151 | spin_unlock_irqrestore(&dimm_handler_lock, flags); | ||
| 152 | |||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | |||
| 156 | int register_dimm_printer(dimm_printer_t func) | ||
| 157 | { | ||
| 158 | unsigned long flags; | ||
| 159 | int ret = 0; | ||
| 160 | |||
| 161 | spin_lock_irqsave(&dimm_handler_lock, flags); | ||
| 162 | if (!dimm_handler) | ||
| 163 | dimm_handler = func; | ||
| 164 | else | ||
| 165 | ret = -EEXIST; | ||
| 166 | spin_unlock_irqrestore(&dimm_handler_lock, flags); | ||
| 167 | |||
| 168 | return ret; | ||
| 169 | } | ||
| 170 | EXPORT_SYMBOL_GPL(register_dimm_printer); | ||
| 171 | |||
| 172 | void unregister_dimm_printer(dimm_printer_t func) | ||
| 173 | { | ||
| 174 | unsigned long flags; | ||
| 175 | |||
| 176 | spin_lock_irqsave(&dimm_handler_lock, flags); | ||
| 177 | if (dimm_handler == func) | ||
| 178 | dimm_handler = NULL; | ||
| 179 | spin_unlock_irqrestore(&dimm_handler_lock, flags); | ||
| 180 | } | ||
| 181 | EXPORT_SYMBOL_GPL(unregister_dimm_printer); | ||
| 182 | |||
| 131 | void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 183 | void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) |
| 132 | { | 184 | { |
| 133 | siginfo_t info; | 185 | siginfo_t info; |
| @@ -290,10 +342,7 @@ void sun4v_data_access_exception_tl1(struct pt_regs *regs, unsigned long addr, u | |||
| 290 | } | 342 | } |
| 291 | 343 | ||
| 292 | #ifdef CONFIG_PCI | 344 | #ifdef CONFIG_PCI |
| 293 | /* This is really pathetic... */ | 345 | #include "pci_impl.h" |
| 294 | extern volatile int pci_poke_in_progress; | ||
| 295 | extern volatile int pci_poke_cpu; | ||
| 296 | extern volatile int pci_poke_faulted; | ||
| 297 | #endif | 346 | #endif |
| 298 | 347 | ||
| 299 | /* When access exceptions happen, we must do this. */ | 348 | /* When access exceptions happen, we must do this. */ |
| @@ -375,8 +424,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un | |||
| 375 | 424 | ||
| 376 | if (udbl & bit) { | 425 | if (udbl & bit) { |
| 377 | scode = ecc_syndrome_table[udbl & 0xff]; | 426 | scode = ecc_syndrome_table[udbl & 0xff]; |
| 378 | if (prom_getunumber(scode, afar, | 427 | if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) |
| 379 | memmod_str, sizeof(memmod_str)) == -1) | ||
| 380 | p = syndrome_unknown; | 428 | p = syndrome_unknown; |
| 381 | else | 429 | else |
| 382 | p = memmod_str; | 430 | p = memmod_str; |
| @@ -387,8 +435,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un | |||
| 387 | 435 | ||
| 388 | if (udbh & bit) { | 436 | if (udbh & bit) { |
| 389 | scode = ecc_syndrome_table[udbh & 0xff]; | 437 | scode = ecc_syndrome_table[udbh & 0xff]; |
| 390 | if (prom_getunumber(scode, afar, | 438 | if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) |
| 391 | memmod_str, sizeof(memmod_str)) == -1) | ||
| 392 | p = syndrome_unknown; | 439 | p = syndrome_unknown; |
| 393 | else | 440 | else |
| 394 | p = memmod_str; | 441 | p = memmod_str; |
| @@ -1061,8 +1108,6 @@ static const char *cheetah_get_string(unsigned long bit) | |||
| 1061 | return "???"; | 1108 | return "???"; |
| 1062 | } | 1109 | } |
| 1063 | 1110 | ||
| 1064 | extern int chmc_getunumber(int, unsigned long, char *, int); | ||
| 1065 | |||
| 1066 | static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, | 1111 | static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, |
| 1067 | unsigned long afsr, unsigned long afar, int recoverable) | 1112 | unsigned long afsr, unsigned long afar, int recoverable) |
| 1068 | { | 1113 | { |
| @@ -1104,7 +1149,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in | |||
| 1104 | 1149 | ||
| 1105 | syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; | 1150 | syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; |
| 1106 | syndrome = cheetah_ecc_syntab[syndrome]; | 1151 | syndrome = cheetah_ecc_syntab[syndrome]; |
| 1107 | ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); | 1152 | ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); |
| 1108 | if (ret != -1) | 1153 | if (ret != -1) |
| 1109 | printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", | 1154 | printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", |
| 1110 | (recoverable ? KERN_WARNING : KERN_CRIT), | 1155 | (recoverable ? KERN_WARNING : KERN_CRIT), |
| @@ -1115,7 +1160,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in | |||
| 1115 | 1160 | ||
| 1116 | syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; | 1161 | syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; |
| 1117 | syndrome = cheetah_mtag_syntab[syndrome]; | 1162 | syndrome = cheetah_mtag_syntab[syndrome]; |
| 1118 | ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); | 1163 | ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); |
| 1119 | if (ret != -1) | 1164 | if (ret != -1) |
| 1120 | printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", | 1165 | printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", |
| 1121 | (recoverable ? KERN_WARNING : KERN_CRIT), | 1166 | (recoverable ? KERN_WARNING : KERN_CRIT), |
| @@ -2223,7 +2268,6 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
| 2223 | 2268 | ||
| 2224 | extern int handle_popc(u32 insn, struct pt_regs *regs); | 2269 | extern int handle_popc(u32 insn, struct pt_regs *regs); |
| 2225 | extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); | 2270 | extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); |
| 2226 | extern int vis_emul(struct pt_regs *, unsigned int); | ||
| 2227 | 2271 | ||
| 2228 | void do_illegal_instruction(struct pt_regs *regs) | 2272 | void do_illegal_instruction(struct pt_regs *regs) |
| 2229 | { | 2273 | { |
| @@ -2453,7 +2497,7 @@ struct trap_per_cpu trap_block[NR_CPUS]; | |||
| 2453 | /* This can get invoked before sched_init() so play it super safe | 2497 | /* This can get invoked before sched_init() so play it super safe |
| 2454 | * and use hard_smp_processor_id(). | 2498 | * and use hard_smp_processor_id(). |
| 2455 | */ | 2499 | */ |
| 2456 | void init_cur_cpu_trap(struct thread_info *t) | 2500 | void notrace init_cur_cpu_trap(struct thread_info *t) |
| 2457 | { | 2501 | { |
| 2458 | int cpu = hard_smp_processor_id(); | 2502 | int cpu = hard_smp_processor_id(); |
| 2459 | struct trap_per_cpu *p = &trap_block[cpu]; | 2503 | struct trap_per_cpu *p = &trap_block[cpu]; |
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index a490077891a4..92b1f8ec01de 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c | |||
| @@ -152,7 +152,7 @@ show_pciobppath_attr(struct device *dev, struct device_attribute *attr, | |||
| 152 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, | 152 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, |
| 153 | show_pciobppath_attr, NULL); | 153 | show_pciobppath_attr, NULL); |
| 154 | 154 | ||
| 155 | struct device_node *cdev_node; | 155 | static struct device_node *cdev_node; |
| 156 | 156 | ||
| 157 | static struct vio_dev *root_vdev; | 157 | static struct vio_dev *root_vdev; |
| 158 | static u64 cdev_cfg_handle; | 158 | static u64 cdev_cfg_handle; |
| @@ -371,9 +371,9 @@ static struct mdesc_notifier_client vio_ds_notifier = { | |||
| 371 | .node_name = "domain-services-port", | 371 | .node_name = "domain-services-port", |
| 372 | }; | 372 | }; |
| 373 | 373 | ||
| 374 | const char *channel_devices_node = "channel-devices"; | 374 | static const char *channel_devices_node = "channel-devices"; |
| 375 | const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; | 375 | static const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; |
| 376 | const char *cfg_handle_prop = "cfg-handle"; | 376 | static const char *cfg_handle_prop = "cfg-handle"; |
| 377 | 377 | ||
| 378 | static int __init vio_init(void) | 378 | static int __init vio_init(void) |
| 379 | { | 379 | { |
diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc64/kernel/visemul.c index c3fd64706b53..9e05cb5cb855 100644 --- a/arch/sparc64/kernel/visemul.c +++ b/arch/sparc64/kernel/visemul.c | |||
| @@ -243,7 +243,7 @@ static inline unsigned int *fps_regaddr(struct fpustate *f, | |||
| 243 | struct edge_tab { | 243 | struct edge_tab { |
| 244 | u16 left, right; | 244 | u16 left, right; |
| 245 | }; | 245 | }; |
| 246 | struct edge_tab edge8_tab[8] = { | 246 | static struct edge_tab edge8_tab[8] = { |
| 247 | { 0xff, 0x80 }, | 247 | { 0xff, 0x80 }, |
| 248 | { 0x7f, 0xc0 }, | 248 | { 0x7f, 0xc0 }, |
| 249 | { 0x3f, 0xe0 }, | 249 | { 0x3f, 0xe0 }, |
| @@ -253,7 +253,7 @@ struct edge_tab edge8_tab[8] = { | |||
| 253 | { 0x03, 0xfe }, | 253 | { 0x03, 0xfe }, |
| 254 | { 0x01, 0xff }, | 254 | { 0x01, 0xff }, |
| 255 | }; | 255 | }; |
| 256 | struct edge_tab edge8_tab_l[8] = { | 256 | static struct edge_tab edge8_tab_l[8] = { |
| 257 | { 0xff, 0x01 }, | 257 | { 0xff, 0x01 }, |
| 258 | { 0xfe, 0x03 }, | 258 | { 0xfe, 0x03 }, |
| 259 | { 0xfc, 0x07 }, | 259 | { 0xfc, 0x07 }, |
| @@ -263,23 +263,23 @@ struct edge_tab edge8_tab_l[8] = { | |||
| 263 | { 0xc0, 0x7f }, | 263 | { 0xc0, 0x7f }, |
| 264 | { 0x80, 0xff }, | 264 | { 0x80, 0xff }, |
| 265 | }; | 265 | }; |
| 266 | struct edge_tab edge16_tab[4] = { | 266 | static struct edge_tab edge16_tab[4] = { |
| 267 | { 0xf, 0x8 }, | 267 | { 0xf, 0x8 }, |
| 268 | { 0x7, 0xc }, | 268 | { 0x7, 0xc }, |
| 269 | { 0x3, 0xe }, | 269 | { 0x3, 0xe }, |
| 270 | { 0x1, 0xf }, | 270 | { 0x1, 0xf }, |
| 271 | }; | 271 | }; |
| 272 | struct edge_tab edge16_tab_l[4] = { | 272 | static struct edge_tab edge16_tab_l[4] = { |
| 273 | { 0xf, 0x1 }, | 273 | { 0xf, 0x1 }, |
| 274 | { 0xe, 0x3 }, | 274 | { 0xe, 0x3 }, |
| 275 | { 0xc, 0x7 }, | 275 | { 0xc, 0x7 }, |
| 276 | { 0x8, 0xf }, | 276 | { 0x8, 0xf }, |
| 277 | }; | 277 | }; |
| 278 | struct edge_tab edge32_tab[2] = { | 278 | static struct edge_tab edge32_tab[2] = { |
| 279 | { 0x3, 0x2 }, | 279 | { 0x3, 0x2 }, |
| 280 | { 0x1, 0x3 }, | 280 | { 0x1, 0x3 }, |
| 281 | }; | 281 | }; |
| 282 | struct edge_tab edge32_tab_l[2] = { | 282 | static struct edge_tab edge32_tab_l[2] = { |
| 283 | { 0x3, 0x1 }, | 283 | { 0x3, 0x1 }, |
| 284 | { 0x2, 0x3 }, | 284 | { 0x2, 0x3 }, |
| 285 | }; | 285 | }; |
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index ea7d7ae76bc2..a9e474bf6385 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c | |||
| @@ -51,43 +51,6 @@ static inline int notify_page_fault(struct pt_regs *regs) | |||
| 51 | } | 51 | } |
| 52 | #endif | 52 | #endif |
| 53 | 53 | ||
| 54 | /* | ||
| 55 | * To debug kernel to catch accesses to certain virtual/physical addresses. | ||
| 56 | * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. | ||
| 57 | * flags = VM_READ watches memread accesses, flags = VM_WRITE watches memwrite accesses. | ||
| 58 | * Caller passes in a 64bit aligned addr, with mask set to the bytes that need to be | ||
| 59 | * watched. This is only useful on a single cpu machine for now. After the watchpoint | ||
| 60 | * is detected, the process causing it will be killed, thus preventing an infinite loop. | ||
| 61 | */ | ||
| 62 | void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode) | ||
| 63 | { | ||
| 64 | unsigned long lsubits; | ||
| 65 | |||
| 66 | __asm__ __volatile__("ldxa [%%g0] %1, %0" | ||
| 67 | : "=r" (lsubits) | ||
| 68 | : "i" (ASI_LSU_CONTROL)); | ||
| 69 | lsubits &= ~(LSU_CONTROL_PM | LSU_CONTROL_VM | | ||
| 70 | LSU_CONTROL_PR | LSU_CONTROL_VR | | ||
| 71 | LSU_CONTROL_PW | LSU_CONTROL_VW); | ||
| 72 | |||
| 73 | __asm__ __volatile__("stxa %0, [%1] %2\n\t" | ||
| 74 | "membar #Sync" | ||
| 75 | : /* no outputs */ | ||
| 76 | : "r" (addr), "r" (mode ? VIRT_WATCHPOINT : PHYS_WATCHPOINT), | ||
| 77 | "i" (ASI_DMMU)); | ||
| 78 | |||
| 79 | lsubits |= ((unsigned long)mask << (mode ? 25 : 33)); | ||
| 80 | if (flags & VM_READ) | ||
| 81 | lsubits |= (mode ? LSU_CONTROL_VR : LSU_CONTROL_PR); | ||
| 82 | if (flags & VM_WRITE) | ||
| 83 | lsubits |= (mode ? LSU_CONTROL_VW : LSU_CONTROL_PW); | ||
| 84 | __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" | ||
| 85 | "membar #Sync" | ||
| 86 | : /* no outputs */ | ||
| 87 | : "r" (lsubits), "i" (ASI_LSU_CONTROL) | ||
| 88 | : "memory"); | ||
| 89 | } | ||
| 90 | |||
| 91 | static void __kprobes unhandled_fault(unsigned long address, | 54 | static void __kprobes unhandled_fault(unsigned long address, |
| 92 | struct task_struct *tsk, | 55 | struct task_struct *tsk, |
| 93 | struct pt_regs *regs) | 56 | struct pt_regs *regs) |
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index a41df7bef035..3c10daf8fc01 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
| @@ -46,15 +46,11 @@ | |||
| 46 | #include <asm/tsb.h> | 46 | #include <asm/tsb.h> |
| 47 | #include <asm/hypervisor.h> | 47 | #include <asm/hypervisor.h> |
| 48 | #include <asm/prom.h> | 48 | #include <asm/prom.h> |
| 49 | #include <asm/sstate.h> | ||
| 50 | #include <asm/mdesc.h> | 49 | #include <asm/mdesc.h> |
| 51 | #include <asm/cpudata.h> | 50 | #include <asm/cpudata.h> |
| 52 | #include <asm/irq.h> | 51 | #include <asm/irq.h> |
| 53 | 52 | ||
| 54 | #define MAX_PHYS_ADDRESS (1UL << 42UL) | 53 | #include "init.h" |
| 55 | #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) | ||
| 56 | #define KPTE_BITMAP_BYTES \ | ||
| 57 | ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8) | ||
| 58 | 54 | ||
| 59 | unsigned long kern_linear_pte_xor[2] __read_mostly; | 55 | unsigned long kern_linear_pte_xor[2] __read_mostly; |
| 60 | 56 | ||
| @@ -416,17 +412,9 @@ void mmu_info(struct seq_file *m) | |||
| 416 | #endif /* CONFIG_DEBUG_DCFLUSH */ | 412 | #endif /* CONFIG_DEBUG_DCFLUSH */ |
| 417 | } | 413 | } |
| 418 | 414 | ||
| 419 | struct linux_prom_translation { | ||
| 420 | unsigned long virt; | ||
| 421 | unsigned long size; | ||
| 422 | unsigned long data; | ||
| 423 | }; | ||
| 424 | |||
| 425 | /* Exported for kernel TLB miss handling in ktlb.S */ | ||
| 426 | struct linux_prom_translation prom_trans[512] __read_mostly; | 415 | struct linux_prom_translation prom_trans[512] __read_mostly; |
| 427 | unsigned int prom_trans_ents __read_mostly; | 416 | unsigned int prom_trans_ents __read_mostly; |
| 428 | 417 | ||
| 429 | /* Exported for SMP bootup purposes. */ | ||
| 430 | unsigned long kern_locked_tte_data; | 418 | unsigned long kern_locked_tte_data; |
| 431 | 419 | ||
| 432 | /* The obp translations are saved based on 8k pagesize, since obp can | 420 | /* The obp translations are saved based on 8k pagesize, since obp can |
| @@ -938,6 +926,10 @@ int of_node_to_nid(struct device_node *dp) | |||
| 938 | int count, nid; | 926 | int count, nid; |
| 939 | u64 grp; | 927 | u64 grp; |
| 940 | 928 | ||
| 929 | /* This is the right thing to do on currently supported | ||
| 930 | * SUN4U NUMA platforms as well, as the PCI controller does | ||
| 931 | * not sit behind any particular memory controller. | ||
| 932 | */ | ||
| 941 | if (!mlgroups) | 933 | if (!mlgroups) |
| 942 | return -1; | 934 | return -1; |
| 943 | 935 | ||
| @@ -1206,8 +1198,44 @@ out: | |||
| 1206 | return err; | 1198 | return err; |
| 1207 | } | 1199 | } |
| 1208 | 1200 | ||
| 1201 | static int __init numa_parse_jbus(void) | ||
| 1202 | { | ||
| 1203 | unsigned long cpu, index; | ||
| 1204 | |||
| 1205 | /* NUMA node id is encoded in bits 36 and higher, and there is | ||
| 1206 | * a 1-to-1 mapping from CPU ID to NUMA node ID. | ||
| 1207 | */ | ||
| 1208 | index = 0; | ||
| 1209 | for_each_present_cpu(cpu) { | ||
| 1210 | numa_cpu_lookup_table[cpu] = index; | ||
| 1211 | numa_cpumask_lookup_table[index] = cpumask_of_cpu(cpu); | ||
| 1212 | node_masks[index].mask = ~((1UL << 36UL) - 1UL); | ||
| 1213 | node_masks[index].val = cpu << 36UL; | ||
| 1214 | |||
| 1215 | index++; | ||
| 1216 | } | ||
| 1217 | num_node_masks = index; | ||
| 1218 | |||
| 1219 | add_node_ranges(); | ||
| 1220 | |||
| 1221 | for (index = 0; index < num_node_masks; index++) { | ||
| 1222 | allocate_node_data(index); | ||
| 1223 | node_set_online(index); | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | return 0; | ||
| 1227 | } | ||
| 1228 | |||
| 1209 | static int __init numa_parse_sun4u(void) | 1229 | static int __init numa_parse_sun4u(void) |
| 1210 | { | 1230 | { |
| 1231 | if (tlb_type == cheetah || tlb_type == cheetah_plus) { | ||
| 1232 | unsigned long ver; | ||
| 1233 | |||
| 1234 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); | ||
| 1235 | if ((ver >> 32UL) == __JALAPENO_ID || | ||
| 1236 | (ver >> 32UL) == __SERRANO_ID) | ||
| 1237 | return numa_parse_jbus(); | ||
| 1238 | } | ||
| 1211 | return -1; | 1239 | return -1; |
| 1212 | } | 1240 | } |
| 1213 | 1241 | ||
| @@ -1633,8 +1661,6 @@ void __cpuinit sun4v_ktsb_register(void) | |||
| 1633 | 1661 | ||
| 1634 | /* paging_init() sets up the page tables */ | 1662 | /* paging_init() sets up the page tables */ |
| 1635 | 1663 | ||
| 1636 | extern void central_probe(void); | ||
| 1637 | |||
| 1638 | static unsigned long last_valid_pfn; | 1664 | static unsigned long last_valid_pfn; |
| 1639 | pgd_t swapper_pg_dir[2048]; | 1665 | pgd_t swapper_pg_dir[2048]; |
| 1640 | 1666 | ||
| @@ -1679,8 +1705,6 @@ void __init paging_init(void) | |||
| 1679 | kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; | 1705 | kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; |
| 1680 | kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; | 1706 | kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; |
| 1681 | 1707 | ||
| 1682 | sstate_booting(); | ||
| 1683 | |||
| 1684 | /* Invalidate both kernel TSBs. */ | 1708 | /* Invalidate both kernel TSBs. */ |
| 1685 | memset(swapper_tsb, 0x40, sizeof(swapper_tsb)); | 1709 | memset(swapper_tsb, 0x40, sizeof(swapper_tsb)); |
| 1686 | #ifndef CONFIG_DEBUG_PAGEALLOC | 1710 | #ifndef CONFIG_DEBUG_PAGEALLOC |
| @@ -1803,9 +1827,6 @@ void __init paging_init(void) | |||
| 1803 | } | 1827 | } |
| 1804 | 1828 | ||
| 1805 | printk("Booting Linux...\n"); | 1829 | printk("Booting Linux...\n"); |
| 1806 | |||
| 1807 | central_probe(); | ||
| 1808 | cpu_probe(); | ||
| 1809 | } | 1830 | } |
| 1810 | 1831 | ||
| 1811 | int __init page_in_phys_avail(unsigned long paddr) | 1832 | int __init page_in_phys_avail(unsigned long paddr) |
| @@ -2032,7 +2053,6 @@ pgprot_t PAGE_COPY __read_mostly; | |||
| 2032 | pgprot_t PAGE_SHARED __read_mostly; | 2053 | pgprot_t PAGE_SHARED __read_mostly; |
| 2033 | EXPORT_SYMBOL(PAGE_SHARED); | 2054 | EXPORT_SYMBOL(PAGE_SHARED); |
| 2034 | 2055 | ||
| 2035 | pgprot_t PAGE_EXEC __read_mostly; | ||
| 2036 | unsigned long pg_iobits __read_mostly; | 2056 | unsigned long pg_iobits __read_mostly; |
| 2037 | 2057 | ||
| 2038 | unsigned long _PAGE_IE __read_mostly; | 2058 | unsigned long _PAGE_IE __read_mostly; |
| @@ -2045,14 +2065,6 @@ unsigned long _PAGE_CACHE __read_mostly; | |||
| 2045 | EXPORT_SYMBOL(_PAGE_CACHE); | 2065 | EXPORT_SYMBOL(_PAGE_CACHE); |
| 2046 | 2066 | ||
| 2047 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | 2067 | #ifdef CONFIG_SPARSEMEM_VMEMMAP |
| 2048 | |||
| 2049 | #define VMEMMAP_CHUNK_SHIFT 22 | ||
| 2050 | #define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) | ||
| 2051 | #define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) | ||
| 2052 | #define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) | ||
| 2053 | |||
| 2054 | #define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ | ||
| 2055 | sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) | ||
| 2056 | unsigned long vmemmap_table[VMEMMAP_SIZE]; | 2068 | unsigned long vmemmap_table[VMEMMAP_SIZE]; |
| 2057 | 2069 | ||
| 2058 | int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) | 2070 | int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) |
| @@ -2136,7 +2148,6 @@ static void __init sun4u_pgprot_init(void) | |||
| 2136 | _PAGE_CACHE_4U | _PAGE_P_4U | | 2148 | _PAGE_CACHE_4U | _PAGE_P_4U | |
| 2137 | __ACCESS_BITS_4U | __DIRTY_BITS_4U | | 2149 | __ACCESS_BITS_4U | __DIRTY_BITS_4U | |
| 2138 | _PAGE_EXEC_4U | _PAGE_L_4U); | 2150 | _PAGE_EXEC_4U | _PAGE_L_4U); |
| 2139 | PAGE_EXEC = __pgprot(_PAGE_EXEC_4U); | ||
| 2140 | 2151 | ||
| 2141 | _PAGE_IE = _PAGE_IE_4U; | 2152 | _PAGE_IE = _PAGE_IE_4U; |
| 2142 | _PAGE_E = _PAGE_E_4U; | 2153 | _PAGE_E = _PAGE_E_4U; |
| @@ -2147,10 +2158,10 @@ static void __init sun4u_pgprot_init(void) | |||
| 2147 | 2158 | ||
| 2148 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2159 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 2149 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4U) ^ | 2160 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4U) ^ |
| 2150 | 0xfffff80000000000; | 2161 | 0xfffff80000000000UL; |
| 2151 | #else | 2162 | #else |
| 2152 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ | 2163 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ |
| 2153 | 0xfffff80000000000; | 2164 | 0xfffff80000000000UL; |
| 2154 | #endif | 2165 | #endif |
| 2155 | kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U | | 2166 | kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U | |
| 2156 | _PAGE_P_4U | _PAGE_W_4U); | 2167 | _PAGE_P_4U | _PAGE_W_4U); |
| @@ -2188,7 +2199,6 @@ static void __init sun4v_pgprot_init(void) | |||
| 2188 | __ACCESS_BITS_4V | __DIRTY_BITS_4V | | 2199 | __ACCESS_BITS_4V | __DIRTY_BITS_4V | |
| 2189 | _PAGE_EXEC_4V); | 2200 | _PAGE_EXEC_4V); |
| 2190 | PAGE_KERNEL_LOCKED = PAGE_KERNEL; | 2201 | PAGE_KERNEL_LOCKED = PAGE_KERNEL; |
| 2191 | PAGE_EXEC = __pgprot(_PAGE_EXEC_4V); | ||
| 2192 | 2202 | ||
| 2193 | _PAGE_IE = _PAGE_IE_4V; | 2203 | _PAGE_IE = _PAGE_IE_4V; |
| 2194 | _PAGE_E = _PAGE_E_4V; | 2204 | _PAGE_E = _PAGE_E_4V; |
| @@ -2196,20 +2206,20 @@ static void __init sun4v_pgprot_init(void) | |||
| 2196 | 2206 | ||
| 2197 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2207 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 2198 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ | 2208 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ |
| 2199 | 0xfffff80000000000; | 2209 | 0xfffff80000000000UL; |
| 2200 | #else | 2210 | #else |
| 2201 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ | 2211 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ |
| 2202 | 0xfffff80000000000; | 2212 | 0xfffff80000000000UL; |
| 2203 | #endif | 2213 | #endif |
| 2204 | kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | | 2214 | kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | |
| 2205 | _PAGE_P_4V | _PAGE_W_4V); | 2215 | _PAGE_P_4V | _PAGE_W_4V); |
| 2206 | 2216 | ||
| 2207 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2217 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 2208 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ | 2218 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ |
| 2209 | 0xfffff80000000000; | 2219 | 0xfffff80000000000UL; |
| 2210 | #else | 2220 | #else |
| 2211 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ | 2221 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ |
| 2212 | 0xfffff80000000000; | 2222 | 0xfffff80000000000UL; |
| 2213 | #endif | 2223 | #endif |
| 2214 | kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | | 2224 | kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | |
| 2215 | _PAGE_P_4V | _PAGE_W_4V); | 2225 | _PAGE_P_4V | _PAGE_W_4V); |
diff --git a/arch/sparc64/mm/init.h b/arch/sparc64/mm/init.h new file mode 100644 index 000000000000..16063870a489 --- /dev/null +++ b/arch/sparc64/mm/init.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #ifndef _SPARC64_MM_INIT_H | ||
| 2 | #define _SPARC64_MM_INIT_H | ||
| 3 | |||
| 4 | /* Most of the symbols in this file are defined in init.c and | ||
| 5 | * marked non-static so that assembler code can get at them. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #define MAX_PHYS_ADDRESS (1UL << 42UL) | ||
| 9 | #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) | ||
| 10 | #define KPTE_BITMAP_BYTES \ | ||
| 11 | ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8) | ||
| 12 | |||
| 13 | extern unsigned long kern_linear_pte_xor[2]; | ||
| 14 | extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; | ||
| 15 | extern unsigned int sparc64_highest_unlocked_tlb_ent; | ||
| 16 | extern unsigned long sparc64_kern_pri_context; | ||
| 17 | extern unsigned long sparc64_kern_pri_nuc_bits; | ||
| 18 | extern unsigned long sparc64_kern_sec_context; | ||
| 19 | extern void mmu_info(struct seq_file *m); | ||
| 20 | |||
| 21 | struct linux_prom_translation { | ||
| 22 | unsigned long virt; | ||
| 23 | unsigned long size; | ||
| 24 | unsigned long data; | ||
| 25 | }; | ||
| 26 | |||
| 27 | /* Exported for kernel TLB miss handling in ktlb.S */ | ||
| 28 | extern struct linux_prom_translation prom_trans[512]; | ||
| 29 | extern unsigned int prom_trans_ents; | ||
| 30 | |||
| 31 | /* Exported for SMP bootup purposes. */ | ||
| 32 | extern unsigned long kern_locked_tte_data; | ||
| 33 | |||
| 34 | extern void prom_world(int enter); | ||
| 35 | |||
| 36 | extern void free_initmem(void); | ||
| 37 | |||
| 38 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
| 39 | #define VMEMMAP_CHUNK_SHIFT 22 | ||
| 40 | #define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) | ||
| 41 | #define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) | ||
| 42 | #define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) | ||
| 43 | |||
| 44 | #define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ | ||
| 45 | sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) | ||
| 46 | extern unsigned long vmemmap_table[VMEMMAP_SIZE]; | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #endif /* _SPARC64_MM_INIT_H */ | ||
diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c index ae24919cba7c..d8f21e24a82f 100644 --- a/arch/sparc64/mm/tlb.c +++ b/arch/sparc64/mm/tlb.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | /* Heavily inspired by the ppc64 code. */ | 20 | /* Heavily inspired by the ppc64 code. */ |
| 21 | 21 | ||
| 22 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; | 22 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
| 23 | 23 | ||
| 24 | void flush_tlb_pending(void) | 24 | void flush_tlb_pending(void) |
| 25 | { | 25 | { |
