···11+/*22+ * BPA Internal Interrupt Controller33+ *44+ * (C) Copyright IBM Deutschland Entwicklung GmbH 200555+ *66+ * Author: Arnd Bergmann <arndb@de.ibm.com>77+ *88+ * This program is free software; you can redistribute it and/or modify99+ * it under the terms of the GNU General Public License as published by1010+ * the Free Software Foundation; either version 2, or (at your option)1111+ * any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful,1414+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1515+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616+ * GNU General Public License for more details.1717+ *1818+ * You should have received a copy of the GNU General Public License1919+ * along with this program; if not, write to the Free Software2020+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2121+ */2222+2323+#include <linux/config.h>2424+#include <linux/interrupt.h>2525+#include <linux/irq.h>2626+#include <linux/percpu.h>2727+#include <linux/types.h>2828+2929+#include <asm/io.h>3030+#include <asm/pgtable.h>3131+#include <asm/prom.h>3232+#include <asm/ptrace.h>3333+3434+#include "bpa_iic.h"3535+3636+struct iic_pending_bits {3737+ u32 data;3838+ u8 flags;3939+ u8 class;4040+ u8 source;4141+ u8 prio;4242+};4343+4444+enum iic_pending_flags {4545+ IIC_VALID = 0x80,4646+ IIC_IPI = 0x40,4747+};4848+4949+struct iic_regs {5050+ struct iic_pending_bits pending;5151+ struct iic_pending_bits pending_destr;5252+ u64 generate;5353+ u64 prio;5454+};5555+5656+struct iic {5757+ struct iic_regs __iomem *regs;5858+};5959+6060+static DEFINE_PER_CPU(struct iic, iic);6161+6262+void iic_local_enable(void)6363+{6464+ out_be64(&__get_cpu_var(iic).regs->prio, 0xff);6565+}6666+6767+void iic_local_disable(void)6868+{6969+ out_be64(&__get_cpu_var(iic).regs->prio, 0x0);7070+}7171+7272+static unsigned int iic_startup(unsigned int irq)7373+{7474+ return 0;7575+}7676+7777+static void iic_enable(unsigned int irq)7878+{7979+ iic_local_enable();8080+}8181+8282+static void iic_disable(unsigned int irq)8383+{8484+}8585+8686+static void iic_end(unsigned int irq)8787+{8888+ iic_local_enable();8989+}9090+9191+static struct hw_interrupt_type iic_pic = {9292+ .typename = " BPA-IIC ",9393+ .startup = iic_startup,9494+ .enable = iic_enable,9595+ .disable = iic_disable,9696+ .end = iic_end,9797+};9898+9999+static int iic_external_get_irq(struct iic_pending_bits pending)100100+{101101+ int irq;102102+ unsigned char node, unit;103103+104104+ node = pending.source >> 4;105105+ unit = pending.source & 0xf;106106+ irq = -1;107107+108108+ /*109109+ * This mapping is specific to the Broadband110110+ * Engine. We might need to get the numbers111111+ * from the device tree to support future CPUs.112112+ */113113+ switch (unit) {114114+ case 0x00:115115+ case 0x0b:116116+ /*117117+ * One of these units can be connected118118+ * to an external interrupt controller.119119+ */120120+ if (pending.prio > 0x3f ||121121+ pending.class != 2)122122+ break;123123+ irq = IIC_EXT_OFFSET124124+ + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)125125+ + node * IIC_NODE_STRIDE;126126+ break;127127+ case 0x01 ... 0x04:128128+ case 0x07 ... 0x0a:129129+ /*130130+ * These units are connected to the SPEs131131+ */132132+ if (pending.class > 2)133133+ break;134134+ irq = IIC_SPE_OFFSET135135+ + pending.class * IIC_CLASS_STRIDE136136+ + node * IIC_NODE_STRIDE137137+ + unit;138138+ break;139139+ }140140+ if (irq == -1)141141+ printk(KERN_WARNING "Unexpected interrupt class %02x, "142142+ "source %02x, prio %02x, cpu %02x\n", pending.class,143143+ pending.source, pending.prio, smp_processor_id());144144+ return irq;145145+}146146+147147+/* Get an IRQ number from the pending state register of the IIC */148148+int iic_get_irq(struct pt_regs *regs)149149+{150150+ struct iic *iic;151151+ int irq;152152+ struct iic_pending_bits pending;153153+154154+ iic = &__get_cpu_var(iic);155155+ *(unsigned long *) &pending = 156156+ in_be64((unsigned long __iomem *) &iic->regs->pending_destr);157157+158158+ irq = -1;159159+ if (pending.flags & IIC_VALID) {160160+ if (pending.flags & IIC_IPI) {161161+ irq = IIC_IPI_OFFSET + (pending.prio >> 4);162162+/*163163+ if (irq > 0x80)164164+ printk(KERN_WARNING "Unexpected IPI prio %02x"165165+ "on CPU %02x\n", pending.prio,166166+ smp_processor_id());167167+*/168168+ } else {169169+ irq = iic_external_get_irq(pending);170170+ }171171+ }172172+ return irq;173173+}174174+175175+static struct iic_regs __iomem *find_iic(int cpu)176176+{177177+ struct device_node *np;178178+ int nodeid = cpu / 2;179179+ unsigned long regs;180180+ struct iic_regs __iomem *iic_regs;181181+182182+ for (np = of_find_node_by_type(NULL, "cpu");183183+ np;184184+ np = of_find_node_by_type(np, "cpu")) {185185+ if (nodeid == *(int *)get_property(np, "node-id", NULL))186186+ break;187187+ }188188+189189+ if (!np) {190190+ printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);191191+ iic_regs = NULL;192192+ } else {193193+ regs = *(long *)get_property(np, "iic", NULL);194194+195195+ /* hack until we have decided on the devtree info */196196+ regs += 0x400;197197+ if (cpu & 1)198198+ regs += 0x20;199199+200200+ printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);201201+ iic_regs = __ioremap(regs, sizeof(struct iic_regs),202202+ _PAGE_NO_CACHE);203203+ }204204+ return iic_regs;205205+}206206+207207+#ifdef CONFIG_SMP208208+void iic_setup_cpu(void)209209+{210210+ out_be64(&__get_cpu_var(iic).regs->prio, 0xff);211211+}212212+213213+void iic_cause_IPI(int cpu, int mesg)214214+{215215+ out_be64(&per_cpu(iic, cpu).regs->generate, mesg);216216+}217217+218218+static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)219219+{220220+221221+ smp_message_recv(irq - IIC_IPI_OFFSET, regs);222222+ return IRQ_HANDLED;223223+}224224+225225+static void iic_request_ipi(int irq, const char *name)226226+{227227+ /* IPIs are marked SA_INTERRUPT as they must run with irqs228228+ * disabled */229229+ get_irq_desc(irq)->handler = &iic_pic;230230+ get_irq_desc(irq)->status |= IRQ_PER_CPU;231231+ request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL);232232+}233233+234234+void iic_request_IPIs(void)235235+{236236+ iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call");237237+ iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched");238238+#ifdef CONFIG_DEBUGGER239239+ iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug");240240+#endif /* CONFIG_DEBUGGER */241241+}242242+#endif /* CONFIG_SMP */243243+244244+static void iic_setup_spe_handlers(void)245245+{246246+ int be, isrc;247247+248248+ /* Assume two threads per BE are present */249249+ for (be=0; be < num_present_cpus() / 2; be++) {250250+ for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {251251+ int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;252252+ get_irq_desc(irq)->handler = &iic_pic;253253+ }254254+ }255255+}256256+257257+void iic_init_IRQ(void)258258+{259259+ int cpu, irq_offset;260260+ struct iic *iic;261261+262262+ irq_offset = 0;263263+ for_each_cpu(cpu) {264264+ iic = &per_cpu(iic, cpu);265265+ iic->regs = find_iic(cpu);266266+ if (iic->regs)267267+ out_be64(&iic->regs->prio, 0xff);268268+ }269269+ iic_setup_spe_handlers();270270+}
+62
arch/ppc64/kernel/bpa_iic.h
···11+#ifndef ASM_BPA_IIC_H22+#define ASM_BPA_IIC_H33+#ifdef __KERNEL__44+/*55+ * Mapping of IIC pending bits into per-node66+ * interrupt numbers.77+ *88+ * IRQ FF CC SS PP FF CC SS PP Description99+ *1010+ * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge1111+ * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge1212+ * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 01313+ * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 11414+ * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 21515+ * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI1616+ *1717+ * F flags1818+ * C class1919+ * S source2020+ * P Priority2121+ * + node number2222+ * * don't care2323+ *2424+ * A node consists of a Broadband Engine and an optional2525+ * south bridge device providing a maximum of 64 IRQs.2626+ * The south bridge may be connected to either IOIF02727+ * or IOIF1.2828+ * Each SPE is represented as three IRQ lines, one per2929+ * interrupt class.3030+ * 16 IRQ numbers are reserved for inter processor3131+ * interruptions, although these are only used in the3232+ * range of the first node.3333+ *3434+ * This scheme needs 128 IRQ numbers per BIF node ID,3535+ * which means that with the total of 512 lines3636+ * available, we can have a maximum of four nodes.3737+ */3838+3939+enum {4040+ IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */4141+ IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */4242+ IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */4343+ IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */4444+ IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */4545+ IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */4646+ IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */4747+};4848+4949+extern void iic_init_IRQ(void);5050+extern int iic_get_irq(struct pt_regs *regs);5151+extern void iic_cause_IPI(int cpu, int mesg);5252+extern void iic_request_IPIs(void);5353+extern void iic_setup_cpu(void);5454+extern void iic_local_enable(void);5555+extern void iic_local_disable(void);5656+5757+5858+extern void spider_init_IRQ(void);5959+extern int spider_get_irq(unsigned long int_pending);6060+6161+#endif6262+#endif /* ASM_BPA_IIC_H */
+377
arch/ppc64/kernel/bpa_iommu.c
···11+/*22+ * IOMMU implementation for Broadband Processor Architecture33+ * We just establish a linear mapping at boot by setting all the44+ * IOPT cache entries in the CPU.55+ * The mapping functions should be identical to pci_direct_iommu, 66+ * except for the handling of the high order bit that is required77+ * by the Spider bridge. These should be split into a separate88+ * file at the point where we get a different bridge chip.99+ *1010+ * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH,1111+ * Arnd Bergmann <arndb@de.ibm.com>1212+ *1313+ * Based on linear mapping1414+ * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)1515+ *1616+ * This program is free software; you can redistribute it and/or1717+ * modify it under the terms of the GNU General Public License1818+ * as published by the Free Software Foundation; either version1919+ * 2 of the License, or (at your option) any later version.2020+ */2121+2222+#undef DEBUG2323+2424+#include <linux/kernel.h>2525+#include <linux/pci.h>2626+#include <linux/delay.h>2727+#include <linux/string.h>2828+#include <linux/init.h>2929+#include <linux/bootmem.h>3030+#include <linux/mm.h>3131+#include <linux/dma-mapping.h>3232+3333+#include <asm/sections.h>3434+#include <asm/iommu.h>3535+#include <asm/io.h>3636+#include <asm/prom.h>3737+#include <asm/pci-bridge.h>3838+#include <asm/machdep.h>3939+#include <asm/pmac_feature.h>4040+#include <asm/abs_addr.h>4141+#include <asm/system.h>4242+4343+#include "pci.h"4444+#include "bpa_iommu.h"4545+4646+static inline unsigned long 4747+get_iopt_entry(unsigned long real_address, unsigned long ioid,4848+ unsigned long prot)4949+{5050+ return (prot & IOPT_PROT_MASK)5151+ | (IOPT_COHERENT)5252+ | (IOPT_ORDER_VC)5353+ | (real_address & IOPT_RPN_MASK)5454+ | (ioid & IOPT_IOID_MASK);5555+}5656+5757+typedef struct {5858+ unsigned long val;5959+} ioste;6060+6161+static inline ioste6262+mk_ioste(unsigned long val)6363+{6464+ ioste ioste = { .val = val, };6565+ return ioste;6666+}6767+6868+static inline ioste6969+get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size)7070+{7171+ unsigned long ps;7272+ unsigned long iostep;7373+ unsigned long nnpt;7474+ unsigned long shift;7575+7676+ switch (page_size) {7777+ case 0x1000000:7878+ ps = IOST_PS_16M;7979+ nnpt = 0; /* one page per segment */8080+ shift = 5; /* segment has 16 iopt entries */8181+ break;8282+8383+ case 0x100000:8484+ ps = IOST_PS_1M;8585+ nnpt = 0; /* one page per segment */8686+ shift = 1; /* segment has 256 iopt entries */8787+ break;8888+8989+ case 0x10000:9090+ ps = IOST_PS_64K;9191+ nnpt = 0x07; /* 8 pages per io page table */9292+ shift = 0; /* all entries are used */9393+ break;9494+9595+ case 0x1000:9696+ ps = IOST_PS_4K;9797+ nnpt = 0x7f; /* 128 pages per io page table */9898+ shift = 0; /* all entries are used */9999+ break;100100+101101+ default: /* not a known compile time constant */102102+ BUILD_BUG_ON(1);103103+ break;104104+ }105105+106106+ iostep = iopt_base +107107+ /* need 8 bytes per iopte */108108+ (((io_address / page_size * 8)109109+ /* align io page tables on 4k page boundaries */110110+ << shift) 111111+ /* nnpt+1 pages go into each iopt */112112+ & ~(nnpt << 12));113113+114114+ nnpt++; /* this seems to work, but the documentation is not clear115115+ about wether we put nnpt or nnpt-1 into the ioste bits.116116+ In theory, this can't work for 4k pages. */117117+ return mk_ioste(IOST_VALID_MASK118118+ | (iostep & IOST_PT_BASE_MASK)119119+ | ((nnpt << 5) & IOST_NNPT_MASK)120120+ | (ps & IOST_PS_MASK));121121+}122122+123123+/* compute the address of an io pte */124124+static inline unsigned long125125+get_ioptep(ioste iost_entry, unsigned long io_address)126126+{127127+ unsigned long iopt_base;128128+ unsigned long page_size;129129+ unsigned long page_number;130130+ unsigned long iopt_offset;131131+132132+ iopt_base = iost_entry.val & IOST_PT_BASE_MASK;133133+ page_size = iost_entry.val & IOST_PS_MASK;134134+135135+ /* decode page size to compute page number */136136+ page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size);137137+ /* page number is an offset into the io page table */138138+ iopt_offset = (page_number << 3) & 0x7fff8ul;139139+ return iopt_base + iopt_offset;140140+}141141+142142+/* compute the tag field of the iopt cache entry */143143+static inline unsigned long144144+get_ioc_tag(ioste iost_entry, unsigned long io_address)145145+{146146+ unsigned long iopte = get_ioptep(iost_entry, io_address);147147+148148+ return IOPT_VALID_MASK149149+ | ((iopte & 0x00000000000000ff8ul) >> 3)150150+ | ((iopte & 0x0000003fffffc0000ul) >> 9);151151+}152152+153153+/* compute the hashed 6 bit index for the 4-way associative pte cache */154154+static inline unsigned long155155+get_ioc_hash(ioste iost_entry, unsigned long io_address)156156+{157157+ unsigned long iopte = get_ioptep(iost_entry, io_address);158158+159159+ return ((iopte & 0x000000000000001f8ul) >> 3)160160+ ^ ((iopte & 0x00000000000020000ul) >> 17)161161+ ^ ((iopte & 0x00000000000010000ul) >> 15)162162+ ^ ((iopte & 0x00000000000008000ul) >> 13)163163+ ^ ((iopte & 0x00000000000004000ul) >> 11)164164+ ^ ((iopte & 0x00000000000002000ul) >> 9)165165+ ^ ((iopte & 0x00000000000001000ul) >> 7);166166+}167167+168168+/* same as above, but pretend that we have a simpler 1-way associative169169+ pte cache with an 8 bit index */170170+static inline unsigned long171171+get_ioc_hash_1way(ioste iost_entry, unsigned long io_address)172172+{173173+ unsigned long iopte = get_ioptep(iost_entry, io_address);174174+175175+ return ((iopte & 0x000000000000001f8ul) >> 3)176176+ ^ ((iopte & 0x00000000000020000ul) >> 17)177177+ ^ ((iopte & 0x00000000000010000ul) >> 15)178178+ ^ ((iopte & 0x00000000000008000ul) >> 13)179179+ ^ ((iopte & 0x00000000000004000ul) >> 11)180180+ ^ ((iopte & 0x00000000000002000ul) >> 9)181181+ ^ ((iopte & 0x00000000000001000ul) >> 7)182182+ ^ ((iopte & 0x0000000000000c000ul) >> 8);183183+}184184+185185+static inline ioste186186+get_iost_cache(void __iomem *base, unsigned long index)187187+{188188+ unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);189189+ return mk_ioste(in_be64(&p[index]));190190+}191191+192192+static inline void193193+set_iost_cache(void __iomem *base, unsigned long index, ioste ste)194194+{195195+ unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);196196+ pr_debug("ioste %02lx was %016lx, store %016lx", index,197197+ get_iost_cache(base, index).val, ste.val);198198+ out_be64(&p[index], ste.val);199199+ pr_debug(" now %016lx\n", get_iost_cache(base, index).val);200200+}201201+202202+static inline unsigned long203203+get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag)204204+{205205+ unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR);206206+ unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG); 207207+208208+ *tag = tags[index];209209+ rmb();210210+ return *p;211211+}212212+213213+static inline void214214+set_iopt_cache(void __iomem *base, unsigned long index,215215+ unsigned long tag, unsigned long val)216216+{217217+ unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR;218218+ unsigned long __iomem *p = base + IOC_PT_CACHE_REG;219219+ pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n",220220+ index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag);221221+222222+ out_be64(p, val);223223+ out_be64(&tags[index], tag);224224+}225225+226226+static inline void227227+set_iost_origin(void __iomem *base)228228+{229229+ unsigned long __iomem *p = base + IOC_ST_ORIGIN;230230+ unsigned long origin = IOSTO_ENABLE | IOSTO_SW;231231+232232+ pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin);233233+ out_be64(p, origin);234234+}235235+236236+static inline void237237+set_iocmd_config(void __iomem *base)238238+{239239+ unsigned long __iomem *p = base + 0xc00;240240+ unsigned long conf;241241+242242+ conf = in_be64(p);243243+ pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE);244244+ out_be64(p, conf | IOCMD_CONF_TE);245245+}246246+247247+/* FIXME: get these from the device tree */248248+#define ioc_base 0x20000511000ull249249+#define ioc_mmio_base 0x20000510000ull250250+#define ioid 0x48a251251+#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */252252+#define io_page_size 0x1000000253253+254254+static unsigned long map_iopt_entry(unsigned long address)255255+{256256+ switch (address >> 20) {257257+ case 0x600:258258+ address = 0x24020000000ull; /* spider i/o */259259+ break;260260+ default:261261+ address += iopt_phys_offset;262262+ break;263263+ }264264+265265+ return get_iopt_entry(address, ioid, IOPT_PROT_RW);266266+}267267+268268+static void iommu_bus_setup_null(struct pci_bus *b) { }269269+static void iommu_dev_setup_null(struct pci_dev *d) { }270270+271271+/* initialize the iommu to support a simple linear mapping272272+ * for each DMA window used by any device. For now, we273273+ * happen to know that there is only one DMA window in use,274274+ * starting at iopt_phys_offset. */275275+static void bpa_map_iommu(void)276276+{277277+ unsigned long address;278278+ void __iomem *base;279279+ ioste ioste;280280+ unsigned long index;281281+282282+ base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE);283283+ pr_debug("%lx mapped to %p\n", ioc_base, base);284284+ set_iocmd_config(base);285285+ iounmap(base);286286+287287+ base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE);288288+ pr_debug("%lx mapped to %p\n", ioc_mmio_base, base);289289+290290+ set_iost_origin(base);291291+292292+ for (address = 0; address < 0x100000000ul; address += io_page_size) {293293+ ioste = get_iost_entry(0x10000000000ul, address, io_page_size);294294+ if ((address & 0xfffffff) == 0) /* segment start */295295+ set_iost_cache(base, address >> 28, ioste);296296+ index = get_ioc_hash_1way(ioste, address);297297+ pr_debug("addr %08lx, index %02lx, ioste %016lx\n",298298+ address, index, ioste.val);299299+ set_iopt_cache(base,300300+ get_ioc_hash_1way(ioste, address),301301+ get_ioc_tag(ioste, address),302302+ map_iopt_entry(address));303303+ }304304+ iounmap(base);305305+}306306+307307+308308+static void *bpa_alloc_coherent(struct device *hwdev, size_t size,309309+ dma_addr_t *dma_handle, unsigned int __nocast flag)310310+{311311+ void *ret;312312+313313+ ret = (void *)__get_free_pages(flag, get_order(size));314314+ if (ret != NULL) {315315+ memset(ret, 0, size);316316+ *dma_handle = virt_to_abs(ret) | BPA_DMA_VALID;317317+ }318318+ return ret;319319+}320320+321321+static void bpa_free_coherent(struct device *hwdev, size_t size,322322+ void *vaddr, dma_addr_t dma_handle)323323+{324324+ free_pages((unsigned long)vaddr, get_order(size));325325+}326326+327327+static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr,328328+ size_t size, enum dma_data_direction direction)329329+{330330+ return virt_to_abs(ptr) | BPA_DMA_VALID;331331+}332332+333333+static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr,334334+ size_t size, enum dma_data_direction direction)335335+{336336+}337337+338338+static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg,339339+ int nents, enum dma_data_direction direction)340340+{341341+ int i;342342+343343+ for (i = 0; i < nents; i++, sg++) {344344+ sg->dma_address = (page_to_phys(sg->page) + sg->offset)345345+ | BPA_DMA_VALID;346346+ sg->dma_length = sg->length;347347+ }348348+349349+ return nents;350350+}351351+352352+static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg,353353+ int nents, enum dma_data_direction direction)354354+{355355+}356356+357357+static int bpa_dma_supported(struct device *dev, u64 mask)358358+{359359+ return mask < 0x100000000ull;360360+}361361+362362+void bpa_init_iommu(void)363363+{364364+ bpa_map_iommu();365365+366366+ /* Direct I/O, IOMMU off */367367+ ppc_md.iommu_dev_setup = iommu_dev_setup_null;368368+ ppc_md.iommu_bus_setup = iommu_bus_setup_null;369369+370370+ pci_dma_ops.alloc_coherent = bpa_alloc_coherent;371371+ pci_dma_ops.free_coherent = bpa_free_coherent;372372+ pci_dma_ops.map_single = bpa_map_single;373373+ pci_dma_ops.unmap_single = bpa_unmap_single;374374+ pci_dma_ops.map_sg = bpa_map_sg;375375+ pci_dma_ops.unmap_sg = bpa_unmap_sg;376376+ pci_dma_ops.dma_supported = bpa_dma_supported;377377+}
+65
arch/ppc64/kernel/bpa_iommu.h
···11+#ifndef BPA_IOMMU_H22+#define BPA_IOMMU_H33+44+/* some constants */55+enum {66+ /* segment table entries */77+ IOST_VALID_MASK = 0x8000000000000000ul,88+ IOST_TAG_MASK = 0x3000000000000000ul,99+ IOST_PT_BASE_MASK = 0x000003fffffff000ul,1010+ IOST_NNPT_MASK = 0x0000000000000fe0ul,1111+ IOST_PS_MASK = 0x000000000000000ful,1212+1313+ IOST_PS_4K = 0x1,1414+ IOST_PS_64K = 0x3,1515+ IOST_PS_1M = 0x5,1616+ IOST_PS_16M = 0x7,1717+1818+ /* iopt tag register */1919+ IOPT_VALID_MASK = 0x0000000200000000ul,2020+ IOPT_TAG_MASK = 0x00000001fffffffful,2121+2222+ /* iopt cache register */2323+ IOPT_PROT_MASK = 0xc000000000000000ul,2424+ IOPT_PROT_NONE = 0x0000000000000000ul,2525+ IOPT_PROT_READ = 0x4000000000000000ul,2626+ IOPT_PROT_WRITE = 0x8000000000000000ul,2727+ IOPT_PROT_RW = 0xc000000000000000ul,2828+ IOPT_COHERENT = 0x2000000000000000ul,2929+3030+ IOPT_ORDER_MASK = 0x1800000000000000ul,3131+ /* order access to same IOID/VC on same address */3232+ IOPT_ORDER_ADDR = 0x0800000000000000ul,3333+ /* similar, but only after a write access */3434+ IOPT_ORDER_WRITES = 0x1000000000000000ul,3535+ /* Order all accesses to same IOID/VC */3636+ IOPT_ORDER_VC = 0x1800000000000000ul,3737+3838+ IOPT_RPN_MASK = 0x000003fffffff000ul,3939+ IOPT_HINT_MASK = 0x0000000000000800ul,4040+ IOPT_IOID_MASK = 0x00000000000007fful,4141+4242+ IOSTO_ENABLE = 0x8000000000000000ul,4343+ IOSTO_ORIGIN = 0x000003fffffff000ul,4444+ IOSTO_HW = 0x0000000000000800ul,4545+ IOSTO_SW = 0x0000000000000400ul,4646+4747+ IOCMD_CONF_TE = 0x0000800000000000ul,4848+4949+ /* memory mapped registers */5050+ IOC_PT_CACHE_DIR = 0x000,5151+ IOC_ST_CACHE_DIR = 0x800,5252+ IOC_PT_CACHE_REG = 0x910,5353+ IOC_ST_ORIGIN = 0x918,5454+ IOC_CONF = 0x930,5555+5656+ /* The high bit needs to be set on every DMA address,5757+ only 2GB are addressable */5858+ BPA_DMA_VALID = 0x80000000,5959+ BPA_DMA_MASK = 0x7fffffff,6060+};6161+6262+6363+void bpa_init_iommu(void);6464+6565+#endif
+118
arch/ppc64/kernel/bpa_nvram.c
···11+/*22+ * NVRAM for CPBW33+ *44+ * (C) Copyright IBM Corp. 200555+ *66+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>77+ *88+ * This program is free software; you can redistribute it and/or modify99+ * it under the terms of the GNU General Public License as published by1010+ * the Free Software Foundation; either version 2, or (at your option)1111+ * any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful,1414+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1515+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616+ * GNU General Public License for more details.1717+ *1818+ * You should have received a copy of the GNU General Public License1919+ * along with this program; if not, write to the Free Software2020+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2121+ */2222+2323+#include <linux/fs.h>2424+#include <linux/init.h>2525+#include <linux/kernel.h>2626+#include <linux/spinlock.h>2727+#include <linux/types.h>2828+2929+#include <asm/machdep.h>3030+#include <asm/nvram.h>3131+#include <asm/prom.h>3232+3333+static void __iomem *bpa_nvram_start;3434+static long bpa_nvram_len;3535+static spinlock_t bpa_nvram_lock = SPIN_LOCK_UNLOCKED;3636+3737+static ssize_t bpa_nvram_read(char *buf, size_t count, loff_t *index)3838+{3939+ unsigned long flags;4040+4141+ if (*index >= bpa_nvram_len)4242+ return 0;4343+ if (*index + count > bpa_nvram_len)4444+ count = bpa_nvram_len - *index;4545+4646+ spin_lock_irqsave(&bpa_nvram_lock, flags);4747+4848+ memcpy_fromio(buf, bpa_nvram_start + *index, count);4949+5050+ spin_unlock_irqrestore(&bpa_nvram_lock, flags);5151+5252+ *index += count;5353+ return count;5454+}5555+5656+static ssize_t bpa_nvram_write(char *buf, size_t count, loff_t *index)5757+{5858+ unsigned long flags;5959+6060+ if (*index >= bpa_nvram_len)6161+ return 0;6262+ if (*index + count > bpa_nvram_len)6363+ count = bpa_nvram_len - *index;6464+6565+ spin_lock_irqsave(&bpa_nvram_lock, flags);6666+6767+ memcpy_toio(bpa_nvram_start + *index, buf, count);6868+6969+ spin_unlock_irqrestore(&bpa_nvram_lock, flags);7070+7171+ *index += count;7272+ return count;7373+}7474+7575+static ssize_t bpa_nvram_get_size(void)7676+{7777+ return bpa_nvram_len;7878+}7979+8080+int __init bpa_nvram_init(void)8181+{8282+ struct device_node *nvram_node;8383+ unsigned long *buffer;8484+ int proplen;8585+ unsigned long nvram_addr;8686+ int ret;8787+8888+ ret = -ENODEV;8989+ nvram_node = of_find_node_by_type(NULL, "nvram");9090+ if (!nvram_node)9191+ goto out;9292+9393+ ret = -EIO;9494+ buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen);9595+ if (proplen != 2*sizeof(unsigned long))9696+ goto out;9797+9898+ ret = -ENODEV;9999+ nvram_addr = buffer[0];100100+ bpa_nvram_len = buffer[1];101101+ if ( (!bpa_nvram_len) || (!nvram_addr) )102102+ goto out;103103+104104+ bpa_nvram_start = ioremap(nvram_addr, bpa_nvram_len);105105+ if (!bpa_nvram_start)106106+ goto out;107107+108108+ printk(KERN_INFO "BPA NVRAM, %luk mapped to %p\n",109109+ bpa_nvram_len >> 10, bpa_nvram_start);110110+111111+ ppc_md.nvram_read = bpa_nvram_read;112112+ ppc_md.nvram_write = bpa_nvram_write;113113+ ppc_md.nvram_size = bpa_nvram_get_size;114114+115115+out:116116+ of_node_put(nvram_node);117117+ return ret;118118+}
+140
arch/ppc64/kernel/bpa_setup.c
···11+/*22+ * linux/arch/ppc/kernel/bpa_setup.c33+ *44+ * Copyright (C) 1995 Linus Torvalds55+ * Adapted from 'alpha' version by Gary Thomas66+ * Modified by Cort Dougan (cort@cs.nmt.edu)77+ * Modified by PPC64 Team, IBM Corp88+ * Modified by BPA Team, IBM Deutschland Entwicklung GmbH99+ *1010+ * This program is free software; you can redistribute it and/or1111+ * modify it under the terms of the GNU General Public License1212+ * as published by the Free Software Foundation; either version1313+ * 2 of the License, or (at your option) any later version.1414+ */1515+#undef DEBUG1616+1717+#include <linux/config.h>1818+#include <linux/sched.h>1919+#include <linux/kernel.h>2020+#include <linux/mm.h>2121+#include <linux/stddef.h>2222+#include <linux/unistd.h>2323+#include <linux/slab.h>2424+#include <linux/user.h>2525+#include <linux/reboot.h>2626+#include <linux/init.h>2727+#include <linux/delay.h>2828+#include <linux/irq.h>2929+#include <linux/seq_file.h>3030+#include <linux/root_dev.h>3131+#include <linux/console.h>3232+3333+#include <asm/mmu.h>3434+#include <asm/processor.h>3535+#include <asm/io.h>3636+#include <asm/pgtable.h>3737+#include <asm/prom.h>3838+#include <asm/rtas.h>3939+#include <asm/pci-bridge.h>4040+#include <asm/iommu.h>4141+#include <asm/dma.h>4242+#include <asm/machdep.h>4343+#include <asm/time.h>4444+#include <asm/nvram.h>4545+#include <asm/cputable.h>4646+4747+#include "pci.h"4848+#include "bpa_iic.h"4949+#include "bpa_iommu.h"5050+5151+#ifdef DEBUG5252+#define DBG(fmt...) udbg_printf(fmt)5353+#else5454+#define DBG(fmt...)5555+#endif5656+5757+void bpa_get_cpuinfo(struct seq_file *m)5858+{5959+ struct device_node *root;6060+ const char *model = "";6161+6262+ root = of_find_node_by_path("/");6363+ if (root)6464+ model = get_property(root, "model", NULL);6565+ seq_printf(m, "machine\t\t: BPA %s\n", model);6666+ of_node_put(root);6767+}6868+6969+static void bpa_progress(char *s, unsigned short hex)7070+{7171+ printk("*** %04x : %s\n", hex, s ? s : "");7272+}7373+7474+static void __init bpa_setup_arch(void)7575+{7676+ ppc_md.init_IRQ = iic_init_IRQ;7777+ ppc_md.get_irq = iic_get_irq;7878+7979+#ifdef CONFIG_SMP8080+ smp_init_pSeries();8181+#endif8282+8383+ /* init to some ~sane value until calibrate_delay() runs */8484+ loops_per_jiffy = 50000000;8585+8686+ if (ROOT_DEV == 0) {8787+ printk("No ramdisk, default root is /dev/hda2\n");8888+ ROOT_DEV = Root_HDA2;8989+ }9090+9191+ /* Find and initialize PCI host bridges */9292+ init_pci_config_tokens();9393+ find_and_init_phbs();9494+ spider_init_IRQ();9595+#ifdef CONFIG_DUMMY_CONSOLE9696+ conswitchp = &dummy_con;9797+#endif9898+9999+ bpa_nvram_init();100100+}101101+102102+/*103103+ * Early initialization. Relocation is on but do not reference unbolted pages104104+ */105105+static void __init bpa_init_early(void)106106+{107107+ DBG(" -> bpa_init_early()\n");108108+109109+ hpte_init_native();110110+111111+ bpa_init_iommu();112112+113113+ ppc64_interrupt_controller = IC_BPA_IIC;114114+115115+ DBG(" <- bpa_init_early()\n");116116+}117117+118118+119119+static int __init bpa_probe(int platform)120120+{121121+ if (platform != PLATFORM_BPA)122122+ return 0;123123+124124+ return 1;125125+}126126+127127+struct machdep_calls __initdata bpa_md = {128128+ .probe = bpa_probe,129129+ .setup_arch = bpa_setup_arch,130130+ .init_early = bpa_init_early,131131+ .get_cpuinfo = bpa_get_cpuinfo,132132+ .restart = rtas_restart,133133+ .power_off = rtas_power_off,134134+ .halt = rtas_halt,135135+ .get_boot_time = rtas_get_boot_time,136136+ .get_rtc_time = rtas_get_rtc_time,137137+ .set_rtc_time = rtas_set_rtc_time,138138+ .calibrate_decr = generic_calibrate_decr,139139+ .progress = bpa_progress,140140+};
+15-1
arch/ppc64/kernel/cpu_setup_power4.S
···73737474_GLOBAL(__setup_cpu_power4)7575 blr7676-7676+7777+_GLOBAL(__setup_cpu_be)7878+ /* Set large page sizes LP=0: 16MB, LP=1: 64KB */7979+ addi r3, 0, 08080+ ori r3, r3, HID6_LB8181+ sldi r3, r3, 328282+ nor r3, r3, r38383+ mfspr r4, SPRN_HID68484+ and r4, r4, r38585+ addi r3, 0, 0x020008686+ sldi r3, r3, 328787+ or r4, r4, r38888+ mtspr SPRN_HID6, r48989+ blr9090+7791_GLOBAL(__setup_cpu_ppc970)7892 mfspr r0,SPRN_HID07993 li r11,5 /* clear DOZE and SLEEP */
+11
arch/ppc64/kernel/cputable.c
···3434extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);3535extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);3636extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);3737+extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);373838393940/* We only set the altivec features if the kernel was compiled with altivec···161160 COMMON_USER_PPC64,162161 128, 128,163162 __setup_cpu_power4,163163+ COMMON_PPC64_FW164164+ },165165+ { /* BE DD1.x */166166+ 0xffff0000, 0x00700000, "Broadband Engine",167167+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |168168+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |169169+ CPU_FTR_SMT,170170+ COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,171171+ 128, 128,172172+ __setup_cpu_be,164173 COMMON_PPC64_FW165174 },166175 { /* default match */
···4242#define DBG(x...)4343#endif44444545-extern void setup_default_decr(void);4645extern void GregorianDay(struct rtc_time * tm);47464848-extern unsigned long ppc_tb_freq;4949-extern unsigned long ppc_proc_freq;5047static int maple_rtc_addr;51485249static int maple_clock_read(int addr)···173176 maple_get_rtc_time(tm);174177}175178176176-/* XXX FIXME: Some sane defaults: 125 MHz timebase, 1GHz processor */177177-#define DEFAULT_TB_FREQ 125000000UL178178-#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)179179-180180-void __init maple_calibrate_decr(void)181181-{182182- struct device_node *cpu;183183- struct div_result divres;184184- unsigned int *fp = NULL;185185-186186- /*187187- * The cpu node should have a timebase-frequency property188188- * to tell us the rate at which the decrementer counts.189189- */190190- cpu = of_find_node_by_type(NULL, "cpu");191191-192192- ppc_tb_freq = DEFAULT_TB_FREQ;193193- if (cpu != 0)194194- fp = (unsigned int *)get_property(cpu, "timebase-frequency", NULL);195195- if (fp != NULL)196196- ppc_tb_freq = *fp;197197- else198198- printk(KERN_ERR "WARNING: Estimating decrementer frequency (not found)\n");199199- fp = NULL;200200- ppc_proc_freq = DEFAULT_PROC_FREQ;201201- if (cpu != 0)202202- fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);203203- if (fp != NULL)204204- ppc_proc_freq = *fp;205205- else206206- printk(KERN_ERR "WARNING: Estimating processor frequency (not found)\n");207207-208208- of_node_put(cpu);209209-210210- printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",211211- ppc_tb_freq/1000000, ppc_tb_freq%1000000);212212- printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",213213- ppc_proc_freq/1000000, ppc_proc_freq%1000000);214214-215215- tb_ticks_per_jiffy = ppc_tb_freq / HZ;216216- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;217217- tb_ticks_per_usec = ppc_tb_freq / 1000000;218218- tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);219219- div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);220220- tb_to_xs = divres.result_low;221221-222222- setup_default_decr();223223-}
+3
arch/ppc64/kernel/mpic.h
···265265extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);266266/* This one gets to the primary mpic */267267extern int mpic_get_irq(struct pt_regs *regs);268268+269269+/* global mpic for pSeries */270270+extern struct mpic *pSeries_mpic;
+19-478
arch/ppc64/kernel/pSeries_pci.c
···11/*22- * pSeries_pci.c22+ * arch/ppc64/kernel/pSeries_pci.c33 *44 * Copyright (C) 2001 Dave Engebretsen, IBM Corporation55 * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM66 *77 * pSeries specific routines for PCI.88 * 99- * Based on code from pci.c and chrp_pci.c1010- *119 * This program is free software; you can redistribute it and/or modify1210 * it under the terms of the GNU General Public License as published by1311 * the Free Software Foundation; either version 2 of the License, or···2123 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2224 */23252626+#include <linux/init.h>2727+#include <linux/ioport.h>2428#include <linux/kernel.h>2525-#include <linux/threads.h>2629#include <linux/pci.h>2730#include <linux/string.h>2828-#include <linux/init.h>2929-#include <linux/bootmem.h>30313131-#include <asm/io.h>3232-#include <asm/pgtable.h>3333-#include <asm/irq.h>3434-#include <asm/prom.h>3535-#include <asm/machdep.h>3632#include <asm/pci-bridge.h>3737-#include <asm/iommu.h>3838-#include <asm/rtas.h>3333+#include <asm/prom.h>39344040-#include "mpic.h"4135#include "pci.h"42364343-/* RTAS tokens */4444-static int read_pci_config;4545-static int write_pci_config;4646-static int ibm_read_pci_config;4747-static int ibm_write_pci_config;4848-4949-static int s7a_workaround;5050-5151-extern struct mpic *pSeries_mpic;5252-5353-static int config_access_valid(struct device_node *dn, int where)5454-{5555- if (where < 256)5656- return 1;5757- if (where < 4096 && dn->pci_ext_config_space)5858- return 1;5959-6060- return 0;6161-}6262-6363-static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)6464-{6565- int returnval = -1;6666- unsigned long buid, addr;6767- int ret;6868-6969- if (!dn)7070- return PCIBIOS_DEVICE_NOT_FOUND;7171- if (!config_access_valid(dn, where))7272- return PCIBIOS_BAD_REGISTER_NUMBER;7373-7474- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |7575- (dn->devfn << 8) | (where & 0xff);7676- buid = dn->phb->buid;7777- if (buid) {7878- ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,7979- addr, buid >> 32, buid & 0xffffffff, size);8080- } else {8181- ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);8282- }8383- *val = returnval;8484-8585- if (ret)8686- return PCIBIOS_DEVICE_NOT_FOUND;8787-8888- if (returnval == EEH_IO_ERROR_VALUE(size)8989- && eeh_dn_check_failure (dn, NULL))9090- return PCIBIOS_DEVICE_NOT_FOUND;9191-9292- return PCIBIOS_SUCCESSFUL;9393-}9494-9595-static int rtas_pci_read_config(struct pci_bus *bus,9696- unsigned int devfn,9797- int where, int size, u32 *val)9898-{9999- struct device_node *busdn, *dn;100100-101101- if (bus->self)102102- busdn = pci_device_to_OF_node(bus->self);103103- else104104- busdn = bus->sysdata; /* must be a phb */105105-106106- /* Search only direct children of the bus */107107- for (dn = busdn->child; dn; dn = dn->sibling)108108- if (dn->devfn == devfn)109109- return rtas_read_config(dn, where, size, val);110110- return PCIBIOS_DEVICE_NOT_FOUND;111111-}112112-113113-static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)114114-{115115- unsigned long buid, addr;116116- int ret;117117-118118- if (!dn)119119- return PCIBIOS_DEVICE_NOT_FOUND;120120- if (!config_access_valid(dn, where))121121- return PCIBIOS_BAD_REGISTER_NUMBER;122122-123123- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |124124- (dn->devfn << 8) | (where & 0xff);125125- buid = dn->phb->buid;126126- if (buid) {127127- ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);128128- } else {129129- ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);130130- }131131-132132- if (ret)133133- return PCIBIOS_DEVICE_NOT_FOUND;134134-135135- return PCIBIOS_SUCCESSFUL;136136-}137137-138138-static int rtas_pci_write_config(struct pci_bus *bus,139139- unsigned int devfn,140140- int where, int size, u32 val)141141-{142142- struct device_node *busdn, *dn;143143-144144- if (bus->self)145145- busdn = pci_device_to_OF_node(bus->self);146146- else147147- busdn = bus->sysdata; /* must be a phb */148148-149149- /* Search only direct children of the bus */150150- for (dn = busdn->child; dn; dn = dn->sibling)151151- if (dn->devfn == devfn)152152- return rtas_write_config(dn, where, size, val);153153- return PCIBIOS_DEVICE_NOT_FOUND;154154-}155155-156156-struct pci_ops rtas_pci_ops = {157157- rtas_pci_read_config,158158- rtas_pci_write_config159159-};160160-161161-int is_python(struct device_node *dev)162162-{163163- char *model = (char *)get_property(dev, "model", NULL);164164-165165- if (model && strstr(model, "Python"))166166- return 1;167167-168168- return 0;169169-}170170-171171-static int get_phb_reg_prop(struct device_node *dev,172172- unsigned int addr_size_words,173173- struct reg_property64 *reg)174174-{175175- unsigned int *ui_ptr = NULL, len;176176-177177- /* Found a PHB, now figure out where his registers are mapped. */178178- ui_ptr = (unsigned int *)get_property(dev, "reg", &len);179179- if (ui_ptr == NULL)180180- return 1;181181-182182- if (addr_size_words == 1) {183183- reg->address = ((struct reg_property32 *)ui_ptr)->address;184184- reg->size = ((struct reg_property32 *)ui_ptr)->size;185185- } else {186186- *reg = *((struct reg_property64 *)ui_ptr);187187- }188188-189189- return 0;190190-}191191-192192-static void python_countermeasures(struct device_node *dev,193193- unsigned int addr_size_words)194194-{195195- struct reg_property64 reg_struct;196196- void __iomem *chip_regs;197197- volatile u32 val;198198-199199- if (get_phb_reg_prop(dev, addr_size_words, ®_struct))200200- return;201201-202202- /* Python's register file is 1 MB in size. */203203- chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);204204-205205- /* 206206- * Firmware doesn't always clear this bit which is critical207207- * for good performance - Anton208208- */209209-210210-#define PRG_CL_RESET_VALID 0x00010000211211-212212- val = in_be32(chip_regs + 0xf6030);213213- if (val & PRG_CL_RESET_VALID) {214214- printk(KERN_INFO "Python workaround: ");215215- val &= ~PRG_CL_RESET_VALID;216216- out_be32(chip_regs + 0xf6030, val);217217- /*218218- * We must read it back for changes to219219- * take effect220220- */221221- val = in_be32(chip_regs + 0xf6030);222222- printk("reg0: %x\n", val);223223- }224224-225225- iounmap(chip_regs);226226-}227227-228228-void __init init_pci_config_tokens (void)229229-{230230- read_pci_config = rtas_token("read-pci-config");231231- write_pci_config = rtas_token("write-pci-config");232232- ibm_read_pci_config = rtas_token("ibm,read-pci-config");233233- ibm_write_pci_config = rtas_token("ibm,write-pci-config");234234-}235235-236236-unsigned long __devinit get_phb_buid (struct device_node *phb)237237-{238238- int addr_cells;239239- unsigned int *buid_vals;240240- unsigned int len;241241- unsigned long buid;242242-243243- if (ibm_read_pci_config == -1) return 0;244244-245245- /* PHB's will always be children of the root node,246246- * or so it is promised by the current firmware. */247247- if (phb->parent == NULL)248248- return 0;249249- if (phb->parent->parent)250250- return 0;251251-252252- buid_vals = (unsigned int *) get_property(phb, "reg", &len);253253- if (buid_vals == NULL)254254- return 0;255255-256256- addr_cells = prom_n_addr_cells(phb);257257- if (addr_cells == 1) {258258- buid = (unsigned long) buid_vals[0];259259- } else {260260- buid = (((unsigned long)buid_vals[0]) << 32UL) |261261- (((unsigned long)buid_vals[1]) & 0xffffffff);262262- }263263- return buid;264264-}265265-266266-static int phb_set_bus_ranges(struct device_node *dev,267267- struct pci_controller *phb)268268-{269269- int *bus_range;270270- unsigned int len;271271-272272- bus_range = (int *) get_property(dev, "bus-range", &len);273273- if (bus_range == NULL || len < 2 * sizeof(int)) {274274- return 1;275275- }276276-277277- phb->first_busno = bus_range[0];278278- phb->last_busno = bus_range[1];279279-280280- return 0;281281-}282282-283283-static int __devinit setup_phb(struct device_node *dev,284284- struct pci_controller *phb,285285- unsigned int addr_size_words)286286-{287287- pci_setup_pci_controller(phb);288288-289289- if (is_python(dev))290290- python_countermeasures(dev, addr_size_words);291291-292292- if (phb_set_bus_ranges(dev, phb))293293- return 1;294294-295295- phb->arch_data = dev;296296- phb->ops = &rtas_pci_ops;297297- phb->buid = get_phb_buid(dev);298298-299299- return 0;300300-}301301-302302-static void __devinit add_linux_pci_domain(struct device_node *dev,303303- struct pci_controller *phb,304304- struct property *of_prop)305305-{306306- memset(of_prop, 0, sizeof(struct property));307307- of_prop->name = "linux,pci-domain";308308- of_prop->length = sizeof(phb->global_number);309309- of_prop->value = (unsigned char *)&of_prop[1];310310- memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));311311- prom_add_property(dev, of_prop);312312-}313313-314314-static struct pci_controller * __init alloc_phb(struct device_node *dev,315315- unsigned int addr_size_words)316316-{317317- struct pci_controller *phb;318318- struct property *of_prop;319319-320320- phb = alloc_bootmem(sizeof(struct pci_controller));321321- if (phb == NULL)322322- return NULL;323323-324324- of_prop = alloc_bootmem(sizeof(struct property) +325325- sizeof(phb->global_number));326326- if (!of_prop)327327- return NULL;328328-329329- if (setup_phb(dev, phb, addr_size_words))330330- return NULL;331331-332332- add_linux_pci_domain(dev, phb, of_prop);333333-334334- return phb;335335-}336336-337337-static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)338338-{339339- struct pci_controller *phb;340340-341341- phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),342342- GFP_KERNEL);343343- if (phb == NULL)344344- return NULL;345345-346346- if (setup_phb(dev, phb, addr_size_words))347347- return NULL;348348-349349- phb->is_dynamic = 1;350350-351351- /* TODO: linux,pci-domain? */352352-353353- return phb;354354-}355355-356356-unsigned long __init find_and_init_phbs(void)357357-{358358- struct device_node *node;359359- struct pci_controller *phb;360360- unsigned int root_size_cells = 0;361361- unsigned int index;362362- unsigned int *opprop = NULL;363363- struct device_node *root = of_find_node_by_path("/");364364-365365- if (ppc64_interrupt_controller == IC_OPEN_PIC) {366366- opprop = (unsigned int *)get_property(root,367367- "platform-open-pic", NULL);368368- }369369-370370- root_size_cells = prom_n_size_cells(root);371371-372372- index = 0;373373-374374- for (node = of_get_next_child(root, NULL);375375- node != NULL;376376- node = of_get_next_child(root, node)) {377377- if (node->type == NULL || strcmp(node->type, "pci") != 0)378378- continue;379379-380380- phb = alloc_phb(node, root_size_cells);381381- if (!phb)382382- continue;383383-384384- pci_process_bridge_OF_ranges(phb, node);385385- pci_setup_phb_io(phb, index == 0);386386-387387- if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {388388- int addr = root_size_cells * (index + 2) - 1;389389- mpic_assign_isu(pSeries_mpic, index, opprop[addr]);390390- }391391-392392- index++;393393- }394394-395395- of_node_put(root);396396- pci_devs_phb_init();397397-398398- /*399399- * pci_probe_only and pci_assign_all_buses can be set via properties400400- * in chosen.401401- */402402- if (of_chosen) {403403- int *prop;404404-405405- prop = (int *)get_property(of_chosen, "linux,pci-probe-only",406406- NULL);407407- if (prop)408408- pci_probe_only = *prop;409409-410410- prop = (int *)get_property(of_chosen,411411- "linux,pci-assign-all-buses", NULL);412412- if (prop)413413- pci_assign_all_buses = *prop;414414- }415415-416416- return 0;417417-}418418-419419-struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)420420-{421421- struct device_node *root = of_find_node_by_path("/");422422- unsigned int root_size_cells = 0;423423- struct pci_controller *phb;424424- struct pci_bus *bus;425425- int primary;426426-427427- root_size_cells = prom_n_size_cells(root);428428-429429- primary = list_empty(&hose_list);430430- phb = alloc_phb_dynamic(dn, root_size_cells);431431- if (!phb)432432- return NULL;433433-434434- pci_process_bridge_OF_ranges(phb, dn);435435-436436- pci_setup_phb_io_dynamic(phb, primary);437437- of_node_put(root);438438-439439- pci_devs_phb_init_dynamic(phb);440440- phb->last_busno = 0xff;441441- bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data);442442- phb->bus = bus;443443- phb->last_busno = bus->subordinate;444444-445445- return phb;446446-}447447-EXPORT_SYMBOL(init_phb_dynamic);3737+static int __initdata s7a_workaround = -1;4483844939#if 045040void pcibios_name_device(struct pci_dev *dev)···60474DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);61475#endif624766363-static void check_s7a(void)477477+static void __init check_s7a(void)64478{65479 struct device_node *root;66480 char *model;67481482482+ s7a_workaround = 0;68483 root = of_find_node_by_path("/");69484 if (root) {70485 model = get_property(root, "model", NULL);···75488 }76489}774907878-/* RPA-specific bits for removing PHBs */7979-int pcibios_remove_root_bus(struct pci_controller *phb)491491+void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)80492{8181- struct pci_bus *b = phb->bus;8282- struct resource *res;8383- int rc, i;493493+ struct pci_dev *dev;844948585- res = b->resource[0];8686- if (!res->flags) {8787- printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,8888- b->name);8989- return 1;9090- }9191-9292- rc = unmap_bus_range(b);9393- if (rc) {9494- printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",9595- __FUNCTION__, b->name);9696- return 1;9797- }9898-9999- if (release_resource(res)) {100100- printk(KERN_ERR "%s: failed to release IO on bus %s\n",101101- __FUNCTION__, b->name);102102- return 1;103103- }104104-105105- for (i = 1; i < 3; ++i) {106106- res = b->resource[i];107107- if (!res->flags && i == 0) {108108- printk(KERN_ERR "%s: no MEM resource for PHB %s\n",109109- __FUNCTION__, b->name);110110- return 1;111111- }112112- if (res->flags && release_resource(res)) {113113- printk(KERN_ERR114114- "%s: failed to release IO %d on bus %s\n",115115- __FUNCTION__, i, b->name);116116- return 1;495495+ if (s7a_workaround < 0)496496+ check_s7a();497497+ list_for_each_entry(dev, &bus->devices, bus_list) {498498+ pci_read_irq_line(dev);499499+ if (s7a_workaround) {500500+ if (dev->irq > 16) {501501+ dev->irq -= 3;502502+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,503503+ dev->irq);504504+ }117505 }118506 }119119-120120- list_del(&phb->list_node);121121- if (phb->is_dynamic)122122- kfree(phb);123123-124124- return 0;125507}126126-EXPORT_SYMBOL(pcibios_remove_root_bus);127508128509static void __init pSeries_request_regions(void)129510{···108553109554void __init pSeries_final_fixup(void)110555{111111- struct pci_dev *dev = NULL;112112-113113- check_s7a();114114-115115- for_each_pci_dev(dev) {116116- pci_read_irq_line(dev);117117- if (s7a_workaround) {118118- if (dev->irq > 16) {119119- dev->irq -= 3;120120- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);121121- }122122- }123123- }124124-125556 phbs_remap_io();126557 pSeries_request_regions();127558
+6-178
arch/ppc64/kernel/pSeries_setup.c
···7171#define DBG(fmt...)7272#endif73737474-extern void pSeries_final_fixup(void);7575-7676-extern void pSeries_get_boot_time(struct rtc_time *rtc_time);7777-extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);7878-extern int pSeries_set_rtc_time(struct rtc_time *rtc_time);7974extern void find_udbg_vterm(void);8075extern void system_reset_fwnmi(void); /* from head.S */8176extern void machine_check_fwnmi(void); /* from head.S */···7883 unsigned int *default_speed);79848085int fwnmi_active; /* TRUE if an FWNMI handler is present */8181-8282-extern unsigned long ppc_proc_freq;8383-extern unsigned long ppc_tb_freq;84868587extern void pSeries_system_reset_exception(struct pt_regs *regs);8688extern int pSeries_machine_check_exception(struct pt_regs *regs);···373381}374382375383376376-static void pSeries_progress(char *s, unsigned short hex)377377-{378378- struct device_node *root;379379- int width, *p;380380- char *os;381381- static int display_character, set_indicator;382382- static int max_width;383383- static DEFINE_SPINLOCK(progress_lock);384384- static int pending_newline = 0; /* did last write end with unprinted newline? */385385-386386- if (!rtas.base)387387- return;388388-389389- if (max_width == 0) {390390- if ((root = find_path_device("/rtas")) &&391391- (p = (unsigned int *)get_property(root,392392- "ibm,display-line-length",393393- NULL)))394394- max_width = *p;395395- else396396- max_width = 0x10;397397- display_character = rtas_token("display-character");398398- set_indicator = rtas_token("set-indicator");399399- }400400-401401- if (display_character == RTAS_UNKNOWN_SERVICE) {402402- /* use hex display if available */403403- if (set_indicator != RTAS_UNKNOWN_SERVICE)404404- rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);405405- return;406406- }407407-408408- spin_lock(&progress_lock);409409-410410- /*411411- * Last write ended with newline, but we didn't print it since412412- * it would just clear the bottom line of output. Print it now413413- * instead.414414- *415415- * If no newline is pending, print a CR to start output at the416416- * beginning of the line.417417- */418418- if (pending_newline) {419419- rtas_call(display_character, 1, 1, NULL, '\r');420420- rtas_call(display_character, 1, 1, NULL, '\n');421421- pending_newline = 0;422422- } else {423423- rtas_call(display_character, 1, 1, NULL, '\r');424424- }425425-426426- width = max_width;427427- os = s;428428- while (*os) {429429- if (*os == '\n' || *os == '\r') {430430- /* Blank to end of line. */431431- while (width-- > 0)432432- rtas_call(display_character, 1, 1, NULL, ' ');433433-434434- /* If newline is the last character, save it435435- * until next call to avoid bumping up the436436- * display output.437437- */438438- if (*os == '\n' && !os[1]) {439439- pending_newline = 1;440440- spin_unlock(&progress_lock);441441- return;442442- }443443-444444- /* RTAS wants CR-LF, not just LF */445445-446446- if (*os == '\n') {447447- rtas_call(display_character, 1, 1, NULL, '\r');448448- rtas_call(display_character, 1, 1, NULL, '\n');449449- } else {450450- /* CR might be used to re-draw a line, so we'll451451- * leave it alone and not add LF.452452- */453453- rtas_call(display_character, 1, 1, NULL, *os);454454- }455455-456456- width = max_width;457457- } else {458458- width--;459459- rtas_call(display_character, 1, 1, NULL, *os);460460- }461461-462462- os++;463463-464464- /* if we overwrite the screen length */465465- if (width <= 0)466466- while ((*os != 0) && (*os != '\n') && (*os != '\r'))467467- os++;468468- }469469-470470- /* Blank to end of line. */471471- while (width-- > 0)472472- rtas_call(display_character, 1, 1, NULL, ' ');473473-474474- spin_unlock(&progress_lock);475475-}476476-477477-extern void setup_default_decr(void);478478-479479-/* Some sane defaults: 125 MHz timebase, 1GHz processor */480480-#define DEFAULT_TB_FREQ 125000000UL481481-#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)482482-483483-static void __init pSeries_calibrate_decr(void)484484-{485485- struct device_node *cpu;486486- struct div_result divres;487487- unsigned int *fp;488488- int node_found;489489-490490- /*491491- * The cpu node should have a timebase-frequency property492492- * to tell us the rate at which the decrementer counts.493493- */494494- cpu = of_find_node_by_type(NULL, "cpu");495495-496496- ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */497497- node_found = 0;498498- if (cpu != 0) {499499- fp = (unsigned int *)get_property(cpu, "timebase-frequency",500500- NULL);501501- if (fp != 0) {502502- node_found = 1;503503- ppc_tb_freq = *fp;504504- }505505- }506506- if (!node_found)507507- printk(KERN_ERR "WARNING: Estimating decrementer frequency "508508- "(not found)\n");509509-510510- ppc_proc_freq = DEFAULT_PROC_FREQ;511511- node_found = 0;512512- if (cpu != 0) {513513- fp = (unsigned int *)get_property(cpu, "clock-frequency",514514- NULL);515515- if (fp != 0) {516516- node_found = 1;517517- ppc_proc_freq = *fp;518518- }519519- }520520- if (!node_found)521521- printk(KERN_ERR "WARNING: Estimating processor frequency "522522- "(not found)\n");523523-524524- of_node_put(cpu);525525-526526- printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",527527- ppc_tb_freq/1000000, ppc_tb_freq%1000000);528528- printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",529529- ppc_proc_freq/1000000, ppc_proc_freq%1000000);530530-531531- tb_ticks_per_jiffy = ppc_tb_freq / HZ;532532- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;533533- tb_ticks_per_usec = ppc_tb_freq / 1000000;534534- tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);535535- div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);536536- tb_to_xs = divres.result_low;537537-538538- setup_default_decr();539539-}540540-541384static int pSeries_check_legacy_ioport(unsigned int baseport)542385{543386 struct device_node *np;···423596 .get_cpuinfo = pSeries_get_cpuinfo,424597 .log_error = pSeries_log_error,425598 .pcibios_fixup = pSeries_final_fixup,599599+ .irq_bus_setup = pSeries_irq_bus_setup,426600 .restart = rtas_restart,427601 .power_off = rtas_power_off,428602 .halt = rtas_halt,429603 .panic = rtas_os_term,430604 .cpu_die = pSeries_mach_cpu_die,431431- .get_boot_time = pSeries_get_boot_time,432432- .get_rtc_time = pSeries_get_rtc_time,433433- .set_rtc_time = pSeries_set_rtc_time,434434- .calibrate_decr = pSeries_calibrate_decr,435435- .progress = pSeries_progress,605605+ .get_boot_time = rtas_get_boot_time,606606+ .get_rtc_time = rtas_get_rtc_time,607607+ .set_rtc_time = rtas_set_rtc_time,608608+ .calibrate_decr = generic_calibrate_decr,609609+ .progress = rtas_progress,436610 .check_legacy_ioport = pSeries_check_legacy_ioport,437611 .system_reset_exception = pSeries_system_reset_exception,438612 .machine_check_exception = pSeries_machine_check_exception,
+64-5
arch/ppc64/kernel/pSeries_smp.c
···11/*22- * SMP support for pSeries machines.22+ * SMP support for pSeries and BPA machines.33 *44 * Dave Engebretsen, Peter Bergner, and55 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com···4747#include <asm/pSeries_reconfig.h>48484949#include "mpic.h"5050+#include "bpa_iic.h"50515152#ifdef DEBUG5253#define DBG(fmt...) udbg_printf(fmt)···287286 return 1;288287}289288289289+#ifdef CONFIG_XICS290290static inline void smp_xics_do_message(int cpu, int msg)291291{292292 set_bit(msg, &xics_ipi_message[cpu].value);···329327 cpu_clear(cpu, of_spin_map);330328331329}330330+#endif /* CONFIG_XICS */331331+#ifdef CONFIG_BPA_IIC332332+static void smp_iic_message_pass(int target, int msg)333333+{334334+ unsigned int i;335335+336336+ if (target < NR_CPUS) {337337+ iic_cause_IPI(target, msg);338338+ } else {339339+ for_each_online_cpu(i) {340340+ if (target == MSG_ALL_BUT_SELF341341+ && i == smp_processor_id())342342+ continue;343343+ iic_cause_IPI(i, msg);344344+ }345345+ }346346+}347347+348348+static int __init smp_iic_probe(void)349349+{350350+ iic_request_IPIs();351351+352352+ return cpus_weight(cpu_possible_map);353353+}354354+355355+static void __devinit smp_iic_setup_cpu(int cpu)356356+{357357+ if (cpu != boot_cpuid)358358+ iic_setup_cpu();359359+}360360+#endif /* CONFIG_BPA_IIC */332361333362static DEFINE_SPINLOCK(timebase_lock);334363static unsigned long timebase = 0;···414381415382 return 1;416383}417417-384384+#ifdef CONFIG_MPIC418385static struct smp_ops_t pSeries_mpic_smp_ops = {419386 .message_pass = smp_mpic_message_pass,420387 .probe = smp_mpic_probe,421388 .kick_cpu = smp_pSeries_kick_cpu,422389 .setup_cpu = smp_mpic_setup_cpu,423390};424424-391391+#endif392392+#ifdef CONFIG_XICS425393static struct smp_ops_t pSeries_xics_smp_ops = {426394 .message_pass = smp_xics_message_pass,427395 .probe = smp_xics_probe,···430396 .setup_cpu = smp_xics_setup_cpu,431397 .cpu_bootable = smp_pSeries_cpu_bootable,432398};399399+#endif400400+#ifdef CONFIG_BPA_IIC401401+static struct smp_ops_t bpa_iic_smp_ops = {402402+ .message_pass = smp_iic_message_pass,403403+ .probe = smp_iic_probe,404404+ .kick_cpu = smp_pSeries_kick_cpu,405405+ .setup_cpu = smp_iic_setup_cpu,406406+ .cpu_bootable = smp_pSeries_cpu_bootable,407407+};408408+#endif433409434410/* This is called very early */435411void __init smp_init_pSeries(void)···448404449405 DBG(" -> smp_init_pSeries()\n");450406451451- if (ppc64_interrupt_controller == IC_OPEN_PIC)407407+ switch (ppc64_interrupt_controller) {408408+#ifdef CONFIG_MPIC409409+ case IC_OPEN_PIC:452410 smp_ops = &pSeries_mpic_smp_ops;453453- else411411+ break;412412+#endif413413+#ifdef CONFIG_XICS414414+ case IC_PPC_XIC:454415 smp_ops = &pSeries_xics_smp_ops;416416+ break;417417+#endif418418+#ifdef CONFIG_BPA_IIC419419+ case IC_BPA_IIC:420420+ smp_ops = &bpa_iic_smp_ops;421421+ break;422422+#endif423423+ default:424424+ panic("Invalid interrupt controller");425425+ }455426456427#ifdef CONFIG_HOTPLUG_CPU457428 smp_ops->cpu_disable = pSeries_cpu_disable;
+3
arch/ppc64/kernel/pci.c
···902902 list_for_each_entry(dev, &bus->devices, bus_list)903903 ppc_md.iommu_dev_setup(dev);904904905905+ if (ppc_md.irq_bus_setup)906906+ ppc_md.irq_bus_setup(bus);907907+905908 if (!pci_probe_only)906909 return;907910
+5-1
arch/ppc64/kernel/pci.h
···4040void pci_addr_cache_insert_device(struct pci_dev *dev);4141void pci_addr_cache_remove_device(struct pci_dev *dev);42424343-/* From pSeries_pci.h */4343+/* From rtas_pci.h */4444void init_pci_config_tokens (void);4545unsigned long get_phb_buid (struct device_node *);4646+4747+/* From pSeries_pci.h */4848+extern void pSeries_final_fixup(void);4949+extern void pSeries_irq_bus_setup(struct pci_bus *bus);46504751extern unsigned long pci_probe_only;4852extern unsigned long pci_assign_all_buses;
+1-7
arch/ppc64/kernel/pmac_time.c
···4040#define DBG(x...)4141#endif42424343-extern void setup_default_decr(void);4444-4545-extern unsigned long ppc_tb_freq;4646-extern unsigned long ppc_proc_freq;4747-4843/* Apparently the RTC stores seconds since 1 Jan 1904 */4944#define RTC_OFFSET 20828448005045···156161157162/*158163 * Query the OF and get the decr frequency.159159- * This was taken from the pmac time_init() when merging the prep/pmac160160- * time functions.164164+ * FIXME: merge this with generic_calibrate_decr161165 */162166void __init pmac_calibrate_decr(void)163167{
+1-1
arch/ppc64/kernel/proc_ppc64.c
···5353 if (!root)5454 return 1;55555656- if (!(systemcfg->platform & PLATFORM_PSERIES))5656+ if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_BPA)))5757 return 0;58585959 if (!proc_mkdir("rtas", root))
+2-2
arch/ppc64/kernel/prom_init.c
···19151915 prom_send_capabilities();1916191619171917 /*19181918- * On pSeries, copy the CPU hold code19181918+ * On pSeries and BPA, copy the CPU hold code19191919 */19201920- if (RELOC(of_platform) & PLATFORM_PSERIES)19201920+ if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_BPA))19211921 copy_and_flush(0, KERNELBASE - offset, 0x100, 0);1922192219231923 /*
+2-2
arch/ppc64/kernel/rtas-proc.c
···371371 /* Lets see if the user passed hexdigits */372372 hex = simple_strtoul(progress_led, NULL, 10);373373374374- ppc_md.progress ((char *)progress_led, hex);374374+ rtas_progress ((char *)progress_led, hex);375375 return count;376376377377 /* clear the line */378378- /* ppc_md.progress(" ", 0xffff);*/378378+ /* rtas_progress(" ", 0xffff);*/379379}380380/* ****************************************************************** */381381static int ppc_rtas_progress_show(struct seq_file *m, void *v)
+119-2
arch/ppc64/kernel/rtas.c
···9191 }9292}93939494+void9595+rtas_progress(char *s, unsigned short hex)9696+{9797+ struct device_node *root;9898+ int width, *p;9999+ char *os;100100+ static int display_character, set_indicator;101101+ static int display_width, display_lines, *row_width, form_feed;102102+ static DEFINE_SPINLOCK(progress_lock);103103+ static int current_line;104104+ static int pending_newline = 0; /* did last write end with unprinted newline? */105105+106106+ if (!rtas.base)107107+ return;108108+109109+ if (display_width == 0) {110110+ display_width = 0x10;111111+ if ((root = find_path_device("/rtas"))) {112112+ if ((p = (unsigned int *)get_property(root,113113+ "ibm,display-line-length", NULL)))114114+ display_width = *p;115115+ if ((p = (unsigned int *)get_property(root,116116+ "ibm,form-feed", NULL)))117117+ form_feed = *p;118118+ if ((p = (unsigned int *)get_property(root,119119+ "ibm,display-number-of-lines", NULL)))120120+ display_lines = *p;121121+ row_width = (unsigned int *)get_property(root,122122+ "ibm,display-truncation-length", NULL);123123+ }124124+ display_character = rtas_token("display-character");125125+ set_indicator = rtas_token("set-indicator");126126+ }127127+128128+ if (display_character == RTAS_UNKNOWN_SERVICE) {129129+ /* use hex display if available */130130+ if (set_indicator != RTAS_UNKNOWN_SERVICE)131131+ rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);132132+ return;133133+ }134134+135135+ spin_lock(&progress_lock);136136+137137+ /*138138+ * Last write ended with newline, but we didn't print it since139139+ * it would just clear the bottom line of output. Print it now140140+ * instead.141141+ *142142+ * If no newline is pending and form feed is supported, clear the143143+ * display with a form feed; otherwise, print a CR to start output144144+ * at the beginning of the line.145145+ */146146+ if (pending_newline) {147147+ rtas_call(display_character, 1, 1, NULL, '\r');148148+ rtas_call(display_character, 1, 1, NULL, '\n');149149+ pending_newline = 0;150150+ } else {151151+ current_line = 0;152152+ if (form_feed)153153+ rtas_call(display_character, 1, 1, NULL,154154+ (char)form_feed);155155+ else156156+ rtas_call(display_character, 1, 1, NULL, '\r');157157+ }158158+159159+ if (row_width)160160+ width = row_width[current_line];161161+ else162162+ width = display_width;163163+ os = s;164164+ while (*os) {165165+ if (*os == '\n' || *os == '\r') {166166+ /* If newline is the last character, save it167167+ * until next call to avoid bumping up the168168+ * display output.169169+ */170170+ if (*os == '\n' && !os[1]) {171171+ pending_newline = 1;172172+ current_line++;173173+ if (current_line > display_lines-1)174174+ current_line = display_lines-1;175175+ spin_unlock(&progress_lock);176176+ return;177177+ }178178+179179+ /* RTAS wants CR-LF, not just LF */180180+181181+ if (*os == '\n') {182182+ rtas_call(display_character, 1, 1, NULL, '\r');183183+ rtas_call(display_character, 1, 1, NULL, '\n');184184+ } else {185185+ /* CR might be used to re-draw a line, so we'll186186+ * leave it alone and not add LF.187187+ */188188+ rtas_call(display_character, 1, 1, NULL, *os);189189+ }190190+191191+ if (row_width)192192+ width = row_width[current_line];193193+ else194194+ width = display_width;195195+ } else {196196+ width--;197197+ rtas_call(display_character, 1, 1, NULL, *os);198198+ }199199+200200+ os++;201201+202202+ /* if we overwrite the screen length */203203+ if (width <= 0)204204+ while ((*os != 0) && (*os != '\n') && (*os != '\r'))205205+ os++;206206+ }207207+208208+ spin_unlock(&progress_lock);209209+}210210+94211int95212rtas_token(const char *service)96213{···542425543426 printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);544427 printk(KERN_ALERT "FLASH: performing flash and reboot\n");545545- ppc_md.progress("Flashing \n", 0x0);546546- ppc_md.progress("Please Wait... ", 0x0);428428+ rtas_progress("Flashing \n", 0x0);429429+ rtas_progress("Please Wait... ", 0x0);547430 printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");548431 status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);549432 switch (status) { /* should only get "bad" status */
+495
arch/ppc64/kernel/rtas_pci.c
···11+/*22+ * arch/ppc64/kernel/rtas_pci.c33+ *44+ * Copyright (C) 2001 Dave Engebretsen, IBM Corporation55+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM66+ *77+ * RTAS specific routines for PCI.88+ * 99+ * Based on code from pci.c, chrp_pci.c and pSeries_pci.c1010+ *1111+ * This program is free software; you can redistribute it and/or modify1212+ * it under the terms of the GNU General Public License as published by1313+ * the Free Software Foundation; either version 2 of the License, or1414+ * (at your option) any later version.1515+ * 1616+ * This program is distributed in the hope that it will be useful,1717+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1818+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1919+ * GNU General Public License for more details.2020+ * 2121+ * You should have received a copy of the GNU General Public License2222+ * along with this program; if not, write to the Free Software2323+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2424+ */2525+2626+#include <linux/kernel.h>2727+#include <linux/threads.h>2828+#include <linux/pci.h>2929+#include <linux/string.h>3030+#include <linux/init.h>3131+#include <linux/bootmem.h>3232+3333+#include <asm/io.h>3434+#include <asm/pgtable.h>3535+#include <asm/irq.h>3636+#include <asm/prom.h>3737+#include <asm/machdep.h>3838+#include <asm/pci-bridge.h>3939+#include <asm/iommu.h>4040+#include <asm/rtas.h>4141+4242+#include "mpic.h"4343+#include "pci.h"4444+4545+/* RTAS tokens */4646+static int read_pci_config;4747+static int write_pci_config;4848+static int ibm_read_pci_config;4949+static int ibm_write_pci_config;5050+5151+static int config_access_valid(struct device_node *dn, int where)5252+{5353+ if (where < 256)5454+ return 1;5555+ if (where < 4096 && dn->pci_ext_config_space)5656+ return 1;5757+5858+ return 0;5959+}6060+6161+static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)6262+{6363+ int returnval = -1;6464+ unsigned long buid, addr;6565+ int ret;6666+6767+ if (!dn)6868+ return PCIBIOS_DEVICE_NOT_FOUND;6969+ if (!config_access_valid(dn, where))7070+ return PCIBIOS_BAD_REGISTER_NUMBER;7171+7272+ addr = ((where & 0xf00) << 20) | (dn->busno << 16) |7373+ (dn->devfn << 8) | (where & 0xff);7474+ buid = dn->phb->buid;7575+ if (buid) {7676+ ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,7777+ addr, buid >> 32, buid & 0xffffffff, size);7878+ } else {7979+ ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);8080+ }8181+ *val = returnval;8282+8383+ if (ret)8484+ return PCIBIOS_DEVICE_NOT_FOUND;8585+8686+ if (returnval == EEH_IO_ERROR_VALUE(size)8787+ && eeh_dn_check_failure (dn, NULL))8888+ return PCIBIOS_DEVICE_NOT_FOUND;8989+9090+ return PCIBIOS_SUCCESSFUL;9191+}9292+9393+static int rtas_pci_read_config(struct pci_bus *bus,9494+ unsigned int devfn,9595+ int where, int size, u32 *val)9696+{9797+ struct device_node *busdn, *dn;9898+9999+ if (bus->self)100100+ busdn = pci_device_to_OF_node(bus->self);101101+ else102102+ busdn = bus->sysdata; /* must be a phb */103103+104104+ /* Search only direct children of the bus */105105+ for (dn = busdn->child; dn; dn = dn->sibling)106106+ if (dn->devfn == devfn)107107+ return rtas_read_config(dn, where, size, val);108108+ return PCIBIOS_DEVICE_NOT_FOUND;109109+}110110+111111+static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)112112+{113113+ unsigned long buid, addr;114114+ int ret;115115+116116+ if (!dn)117117+ return PCIBIOS_DEVICE_NOT_FOUND;118118+ if (!config_access_valid(dn, where))119119+ return PCIBIOS_BAD_REGISTER_NUMBER;120120+121121+ addr = ((where & 0xf00) << 20) | (dn->busno << 16) |122122+ (dn->devfn << 8) | (where & 0xff);123123+ buid = dn->phb->buid;124124+ if (buid) {125125+ ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);126126+ } else {127127+ ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);128128+ }129129+130130+ if (ret)131131+ return PCIBIOS_DEVICE_NOT_FOUND;132132+133133+ return PCIBIOS_SUCCESSFUL;134134+}135135+136136+static int rtas_pci_write_config(struct pci_bus *bus,137137+ unsigned int devfn,138138+ int where, int size, u32 val)139139+{140140+ struct device_node *busdn, *dn;141141+142142+ if (bus->self)143143+ busdn = pci_device_to_OF_node(bus->self);144144+ else145145+ busdn = bus->sysdata; /* must be a phb */146146+147147+ /* Search only direct children of the bus */148148+ for (dn = busdn->child; dn; dn = dn->sibling)149149+ if (dn->devfn == devfn)150150+ return rtas_write_config(dn, where, size, val);151151+ return PCIBIOS_DEVICE_NOT_FOUND;152152+}153153+154154+struct pci_ops rtas_pci_ops = {155155+ rtas_pci_read_config,156156+ rtas_pci_write_config157157+};158158+159159+int is_python(struct device_node *dev)160160+{161161+ char *model = (char *)get_property(dev, "model", NULL);162162+163163+ if (model && strstr(model, "Python"))164164+ return 1;165165+166166+ return 0;167167+}168168+169169+static int get_phb_reg_prop(struct device_node *dev,170170+ unsigned int addr_size_words,171171+ struct reg_property64 *reg)172172+{173173+ unsigned int *ui_ptr = NULL, len;174174+175175+ /* Found a PHB, now figure out where his registers are mapped. */176176+ ui_ptr = (unsigned int *)get_property(dev, "reg", &len);177177+ if (ui_ptr == NULL)178178+ return 1;179179+180180+ if (addr_size_words == 1) {181181+ reg->address = ((struct reg_property32 *)ui_ptr)->address;182182+ reg->size = ((struct reg_property32 *)ui_ptr)->size;183183+ } else {184184+ *reg = *((struct reg_property64 *)ui_ptr);185185+ }186186+187187+ return 0;188188+}189189+190190+static void python_countermeasures(struct device_node *dev,191191+ unsigned int addr_size_words)192192+{193193+ struct reg_property64 reg_struct;194194+ void __iomem *chip_regs;195195+ volatile u32 val;196196+197197+ if (get_phb_reg_prop(dev, addr_size_words, ®_struct))198198+ return;199199+200200+ /* Python's register file is 1 MB in size. */201201+ chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);202202+203203+ /* 204204+ * Firmware doesn't always clear this bit which is critical205205+ * for good performance - Anton206206+ */207207+208208+#define PRG_CL_RESET_VALID 0x00010000209209+210210+ val = in_be32(chip_regs + 0xf6030);211211+ if (val & PRG_CL_RESET_VALID) {212212+ printk(KERN_INFO "Python workaround: ");213213+ val &= ~PRG_CL_RESET_VALID;214214+ out_be32(chip_regs + 0xf6030, val);215215+ /*216216+ * We must read it back for changes to217217+ * take effect218218+ */219219+ val = in_be32(chip_regs + 0xf6030);220220+ printk("reg0: %x\n", val);221221+ }222222+223223+ iounmap(chip_regs);224224+}225225+226226+void __init init_pci_config_tokens (void)227227+{228228+ read_pci_config = rtas_token("read-pci-config");229229+ write_pci_config = rtas_token("write-pci-config");230230+ ibm_read_pci_config = rtas_token("ibm,read-pci-config");231231+ ibm_write_pci_config = rtas_token("ibm,write-pci-config");232232+}233233+234234+unsigned long __devinit get_phb_buid (struct device_node *phb)235235+{236236+ int addr_cells;237237+ unsigned int *buid_vals;238238+ unsigned int len;239239+ unsigned long buid;240240+241241+ if (ibm_read_pci_config == -1) return 0;242242+243243+ /* PHB's will always be children of the root node,244244+ * or so it is promised by the current firmware. */245245+ if (phb->parent == NULL)246246+ return 0;247247+ if (phb->parent->parent)248248+ return 0;249249+250250+ buid_vals = (unsigned int *) get_property(phb, "reg", &len);251251+ if (buid_vals == NULL)252252+ return 0;253253+254254+ addr_cells = prom_n_addr_cells(phb);255255+ if (addr_cells == 1) {256256+ buid = (unsigned long) buid_vals[0];257257+ } else {258258+ buid = (((unsigned long)buid_vals[0]) << 32UL) |259259+ (((unsigned long)buid_vals[1]) & 0xffffffff);260260+ }261261+ return buid;262262+}263263+264264+static int phb_set_bus_ranges(struct device_node *dev,265265+ struct pci_controller *phb)266266+{267267+ int *bus_range;268268+ unsigned int len;269269+270270+ bus_range = (int *) get_property(dev, "bus-range", &len);271271+ if (bus_range == NULL || len < 2 * sizeof(int)) {272272+ return 1;273273+ }274274+275275+ phb->first_busno = bus_range[0];276276+ phb->last_busno = bus_range[1];277277+278278+ return 0;279279+}280280+281281+static int __devinit setup_phb(struct device_node *dev,282282+ struct pci_controller *phb,283283+ unsigned int addr_size_words)284284+{285285+ pci_setup_pci_controller(phb);286286+287287+ if (is_python(dev))288288+ python_countermeasures(dev, addr_size_words);289289+290290+ if (phb_set_bus_ranges(dev, phb))291291+ return 1;292292+293293+ phb->arch_data = dev;294294+ phb->ops = &rtas_pci_ops;295295+ phb->buid = get_phb_buid(dev);296296+297297+ return 0;298298+}299299+300300+static void __devinit add_linux_pci_domain(struct device_node *dev,301301+ struct pci_controller *phb,302302+ struct property *of_prop)303303+{304304+ memset(of_prop, 0, sizeof(struct property));305305+ of_prop->name = "linux,pci-domain";306306+ of_prop->length = sizeof(phb->global_number);307307+ of_prop->value = (unsigned char *)&of_prop[1];308308+ memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));309309+ prom_add_property(dev, of_prop);310310+}311311+312312+static struct pci_controller * __init alloc_phb(struct device_node *dev,313313+ unsigned int addr_size_words)314314+{315315+ struct pci_controller *phb;316316+ struct property *of_prop;317317+318318+ phb = alloc_bootmem(sizeof(struct pci_controller));319319+ if (phb == NULL)320320+ return NULL;321321+322322+ of_prop = alloc_bootmem(sizeof(struct property) +323323+ sizeof(phb->global_number));324324+ if (!of_prop)325325+ return NULL;326326+327327+ if (setup_phb(dev, phb, addr_size_words))328328+ return NULL;329329+330330+ add_linux_pci_domain(dev, phb, of_prop);331331+332332+ return phb;333333+}334334+335335+static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)336336+{337337+ struct pci_controller *phb;338338+339339+ phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),340340+ GFP_KERNEL);341341+ if (phb == NULL)342342+ return NULL;343343+344344+ if (setup_phb(dev, phb, addr_size_words))345345+ return NULL;346346+347347+ phb->is_dynamic = 1;348348+349349+ /* TODO: linux,pci-domain? */350350+351351+ return phb;352352+}353353+354354+unsigned long __init find_and_init_phbs(void)355355+{356356+ struct device_node *node;357357+ struct pci_controller *phb;358358+ unsigned int root_size_cells = 0;359359+ unsigned int index;360360+ unsigned int *opprop = NULL;361361+ struct device_node *root = of_find_node_by_path("/");362362+363363+ if (ppc64_interrupt_controller == IC_OPEN_PIC) {364364+ opprop = (unsigned int *)get_property(root,365365+ "platform-open-pic", NULL);366366+ }367367+368368+ root_size_cells = prom_n_size_cells(root);369369+370370+ index = 0;371371+372372+ for (node = of_get_next_child(root, NULL);373373+ node != NULL;374374+ node = of_get_next_child(root, node)) {375375+ if (node->type == NULL || strcmp(node->type, "pci") != 0)376376+ continue;377377+378378+ phb = alloc_phb(node, root_size_cells);379379+ if (!phb)380380+ continue;381381+382382+ pci_process_bridge_OF_ranges(phb, node);383383+ pci_setup_phb_io(phb, index == 0);384384+#ifdef CONFIG_PPC_PSERIES385385+ if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {386386+ int addr = root_size_cells * (index + 2) - 1;387387+ mpic_assign_isu(pSeries_mpic, index, opprop[addr]);388388+ }389389+#endif390390+ index++;391391+ }392392+393393+ of_node_put(root);394394+ pci_devs_phb_init();395395+396396+ /*397397+ * pci_probe_only and pci_assign_all_buses can be set via properties398398+ * in chosen.399399+ */400400+ if (of_chosen) {401401+ int *prop;402402+403403+ prop = (int *)get_property(of_chosen, "linux,pci-probe-only",404404+ NULL);405405+ if (prop)406406+ pci_probe_only = *prop;407407+408408+ prop = (int *)get_property(of_chosen,409409+ "linux,pci-assign-all-buses", NULL);410410+ if (prop)411411+ pci_assign_all_buses = *prop;412412+ }413413+414414+ return 0;415415+}416416+417417+struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)418418+{419419+ struct device_node *root = of_find_node_by_path("/");420420+ unsigned int root_size_cells = 0;421421+ struct pci_controller *phb;422422+ struct pci_bus *bus;423423+ int primary;424424+425425+ root_size_cells = prom_n_size_cells(root);426426+427427+ primary = list_empty(&hose_list);428428+ phb = alloc_phb_dynamic(dn, root_size_cells);429429+ if (!phb)430430+ return NULL;431431+432432+ pci_process_bridge_OF_ranges(phb, dn);433433+434434+ pci_setup_phb_io_dynamic(phb, primary);435435+ of_node_put(root);436436+437437+ pci_devs_phb_init_dynamic(phb);438438+ phb->last_busno = 0xff;439439+ bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data);440440+ phb->bus = bus;441441+ phb->last_busno = bus->subordinate;442442+443443+ return phb;444444+}445445+EXPORT_SYMBOL(init_phb_dynamic);446446+447447+/* RPA-specific bits for removing PHBs */448448+int pcibios_remove_root_bus(struct pci_controller *phb)449449+{450450+ struct pci_bus *b = phb->bus;451451+ struct resource *res;452452+ int rc, i;453453+454454+ res = b->resource[0];455455+ if (!res->flags) {456456+ printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,457457+ b->name);458458+ return 1;459459+ }460460+461461+ rc = unmap_bus_range(b);462462+ if (rc) {463463+ printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",464464+ __FUNCTION__, b->name);465465+ return 1;466466+ }467467+468468+ if (release_resource(res)) {469469+ printk(KERN_ERR "%s: failed to release IO on bus %s\n",470470+ __FUNCTION__, b->name);471471+ return 1;472472+ }473473+474474+ for (i = 1; i < 3; ++i) {475475+ res = b->resource[i];476476+ if (!res->flags && i == 0) {477477+ printk(KERN_ERR "%s: no MEM resource for PHB %s\n",478478+ __FUNCTION__, b->name);479479+ return 1;480480+ }481481+ if (res->flags && release_resource(res)) {482482+ printk(KERN_ERR483483+ "%s: failed to release IO %d on bus %s\n",484484+ __FUNCTION__, i, b->name);485485+ return 1;486486+ }487487+ }488488+489489+ list_del(&phb->list_node);490490+ if (phb->is_dynamic)491491+ kfree(phb);492492+493493+ return 0;494494+}495495+EXPORT_SYMBOL(pcibios_remove_root_bus);
+3-3
arch/ppc64/kernel/rtc.c
···301301#ifdef CONFIG_PPC_RTAS302302#define MAX_RTC_WAIT 5000 /* 5 sec */303303#define RTAS_CLOCK_BUSY (-2)304304-void pSeries_get_boot_time(struct rtc_time *rtc_tm)304304+void rtas_get_boot_time(struct rtc_time *rtc_tm)305305{306306 int ret[8];307307 int error, wait_time;···336336 * and if a delay is needed to read the clock. In this case we just337337 * silently return without updating rtc_tm.338338 */339339-void pSeries_get_rtc_time(struct rtc_time *rtc_tm)339339+void rtas_get_rtc_time(struct rtc_time *rtc_tm)340340{341341 int ret[8];342342 int error, wait_time;···371371 rtc_tm->tm_year = ret[0] - 1900;372372}373373374374-int pSeries_set_rtc_time(struct rtc_time *tm)374374+int rtas_set_rtc_time(struct rtc_time *tm)375375{376376 int error, wait_time;377377 unsigned long max_wait_tb;
+26-7
arch/ppc64/kernel/setup.c
···344344extern struct machdep_calls pSeries_md;345345extern struct machdep_calls pmac_md;346346extern struct machdep_calls maple_md;347347+extern struct machdep_calls bpa_md;347348348349/* Ultimately, stuff them in an elf section like initcalls... */349350static struct machdep_calls __initdata *machines[] = {···357356#ifdef CONFIG_PPC_MAPLE358357 &maple_md,359358#endif /* CONFIG_PPC_MAPLE */359359+#ifdef CONFIG_PPC_BPA360360+ &bpa_md,361361+#endif360362 NULL361363};362364···683679 if (ppc_md.nvram_sync)684680 ppc_md.nvram_sync();685681 ppc_md.restart(cmd);682682+#ifdef CONFIG_SMP683683+ smp_send_stop();684684+#endif685685+ printk(KERN_EMERG "System Halted, OK to turn off power\n");686686+ local_irq_disable();687687+ while (1) ;686688}687689688690EXPORT_SYMBOL(machine_restart);···698688 if (ppc_md.nvram_sync)699689 ppc_md.nvram_sync();700690 ppc_md.power_off();691691+#ifdef CONFIG_SMP692692+ smp_send_stop();693693+#endif694694+ printk(KERN_EMERG "System Halted, OK to turn off power\n");695695+ local_irq_disable();696696+ while (1) ;701697}702698703699EXPORT_SYMBOL(machine_power_off);···713697 if (ppc_md.nvram_sync)714698 ppc_md.nvram_sync();715699 ppc_md.halt();700700+#ifdef CONFIG_SMP701701+ smp_send_stop();702702+#endif703703+ printk(KERN_EMERG "System Halted, OK to turn off power\n");704704+ local_irq_disable();705705+ while (1) ;716706}717707718708EXPORT_SYMBOL(machine_halt);719719-720720-unsigned long ppc_proc_freq;721721-unsigned long ppc_tb_freq;722709723710static int ppc64_panic_event(struct notifier_block *this,724711 unsigned long event, void *ptr)···10991080static void ppc64_do_msg(unsigned int src, const char *msg)11001081{11011082 if (ppc_md.progress) {11021102- char buf[32];10831083+ char buf[128];1103108411041104- sprintf(buf, "%08x \n", src);10851085+ sprintf(buf, "%08X\n", src);11051086 ppc_md.progress(buf, 0);11061106- sprintf(buf, "%-16s", msg);10871087+ snprintf(buf, 128, "%s", msg);11071088 ppc_md.progress(buf, 0);11081089 }11091090}···11371118}1138111911391120/* This should only be called on processor 0 during calibrate decr */11401140-void setup_default_decr(void)11211121+void __init setup_default_decr(void)11411122{11421123 struct paca_struct *lpaca = get_paca();11431124
+2-2
arch/ppc64/kernel/smp.c
···71717272int smt_enabled_at_boot = 1;73737474-#ifdef CONFIG_PPC_MULTIPLATFORM7474+#ifdef CONFIG_MPIC7575void smp_mpic_message_pass(int target, int msg)7676{7777 /* make sure we're sending something that translates to an IPI */···128128 smp_mb();129129}130130131131-#endif /* CONFIG_PPC_MULTIPLATFORM */131131+#endif /* CONFIG_MPIC */132132133133static void __init smp_space_timers(unsigned int max_cpus)134134{
+191
arch/ppc64/kernel/spider-pic.c
···11+/*22+ * External Interrupt Controller on Spider South Bridge33+ *44+ * (C) Copyright IBM Deutschland Entwicklung GmbH 200555+ *66+ * Author: Arnd Bergmann <arndb@de.ibm.com>77+ *88+ * This program is free software; you can redistribute it and/or modify99+ * it under the terms of the GNU General Public License as published by1010+ * the Free Software Foundation; either version 2, or (at your option)1111+ * any later version.1212+ *1313+ * This program is distributed in the hope that it will be useful,1414+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1515+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616+ * GNU General Public License for more details.1717+ *1818+ * You should have received a copy of the GNU General Public License1919+ * along with this program; if not, write to the Free Software2020+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2121+ */2222+2323+#include <linux/interrupt.h>2424+#include <linux/irq.h>2525+2626+#include <asm/pgtable.h>2727+#include <asm/prom.h>2828+#include <asm/io.h>2929+3030+#include "bpa_iic.h"3131+3232+/* register layout taken from Spider spec, table 7.4-4 */3333+enum {3434+ TIR_DEN = 0x004, /* Detection Enable Register */3535+ TIR_MSK = 0x084, /* Mask Level Register */3636+ TIR_EDC = 0x0c0, /* Edge Detection Clear Register */3737+ TIR_PNDA = 0x100, /* Pending Register A */3838+ TIR_PNDB = 0x104, /* Pending Register B */3939+ TIR_CS = 0x144, /* Current Status Register */4040+ TIR_LCSA = 0x150, /* Level Current Status Register A */4141+ TIR_LCSB = 0x154, /* Level Current Status Register B */4242+ TIR_LCSC = 0x158, /* Level Current Status Register C */4343+ TIR_LCSD = 0x15c, /* Level Current Status Register D */4444+ TIR_CFGA = 0x200, /* Setting Register A0 */4545+ TIR_CFGB = 0x204, /* Setting Register B0 */4646+ /* 0x208 ... 0x3ff Setting Register An/Bn */4747+ TIR_PPNDA = 0x400, /* Packet Pending Register A */4848+ TIR_PPNDB = 0x404, /* Packet Pending Register B */4949+ TIR_PIERA = 0x408, /* Packet Output Error Register A */5050+ TIR_PIERB = 0x40c, /* Packet Output Error Register B */5151+ TIR_PIEN = 0x444, /* Packet Output Enable Register */5252+ TIR_PIPND = 0x454, /* Packet Output Pending Register */5353+ TIRDID = 0x484, /* Spider Device ID Register */5454+ REISTIM = 0x500, /* Reissue Command Timeout Time Setting */5555+ REISTIMEN = 0x504, /* Reissue Command Timeout Setting */5656+ REISWAITEN = 0x508, /* Reissue Wait Control*/5757+};5858+5959+static void __iomem *spider_pics[4];6060+6161+static void __iomem *spider_get_pic(int irq)6262+{6363+ int node = irq / IIC_NODE_STRIDE;6464+ irq %= IIC_NODE_STRIDE;6565+6666+ if (irq >= IIC_EXT_OFFSET &&6767+ irq < IIC_EXT_OFFSET + IIC_NUM_EXT &&6868+ spider_pics)6969+ return spider_pics[node];7070+ return NULL;7171+}7272+7373+static int spider_get_nr(unsigned int irq)7474+{7575+ return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET;7676+}7777+7878+static void __iomem *spider_get_irq_config(int irq)7979+{8080+ void __iomem *pic;8181+ pic = spider_get_pic(irq);8282+ return pic + TIR_CFGA + 8 * spider_get_nr(irq);8383+}8484+8585+static void spider_enable_irq(unsigned int irq)8686+{8787+ void __iomem *cfg = spider_get_irq_config(irq);8888+ irq = spider_get_nr(irq);8989+9090+ out_be32(cfg, in_be32(cfg) | 0x3107000eu);9191+ out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);9292+}9393+9494+static void spider_disable_irq(unsigned int irq)9595+{9696+ void __iomem *cfg = spider_get_irq_config(irq);9797+ irq = spider_get_nr(irq);9898+9999+ out_be32(cfg, in_be32(cfg) & ~0x30000000u);100100+}101101+102102+static unsigned int spider_startup_irq(unsigned int irq)103103+{104104+ spider_enable_irq(irq);105105+ return 0;106106+}107107+108108+static void spider_shutdown_irq(unsigned int irq)109109+{110110+ spider_disable_irq(irq);111111+}112112+113113+static void spider_end_irq(unsigned int irq)114114+{115115+ spider_enable_irq(irq);116116+}117117+118118+static void spider_ack_irq(unsigned int irq)119119+{120120+ spider_disable_irq(irq);121121+ iic_local_enable();122122+}123123+124124+static struct hw_interrupt_type spider_pic = {125125+ .typename = " SPIDER ",126126+ .startup = spider_startup_irq,127127+ .shutdown = spider_shutdown_irq,128128+ .enable = spider_enable_irq,129129+ .disable = spider_disable_irq,130130+ .ack = spider_ack_irq,131131+ .end = spider_end_irq,132132+};133133+134134+135135+int spider_get_irq(unsigned long int_pending)136136+{137137+ void __iomem *regs = spider_get_pic(int_pending);138138+ unsigned long cs;139139+ int irq;140140+141141+ cs = in_be32(regs + TIR_CS);142142+143143+ irq = cs >> 24;144144+ if (irq != 63)145145+ return irq;146146+147147+ return -1;148148+}149149+150150+void spider_init_IRQ(void)151151+{152152+ int node;153153+ struct device_node *dn;154154+ unsigned int *property;155155+ long spiderpic;156156+ int n;157157+158158+/* FIXME: detect multiple PICs as soon as the device tree has them */159159+ for (node = 0; node < 1; node++) {160160+ dn = of_find_node_by_path("/");161161+ n = prom_n_addr_cells(dn);162162+ property = (unsigned int *) get_property(dn,163163+ "platform-spider-pic", NULL);164164+165165+ if (!property)166166+ continue;167167+ for (spiderpic = 0; n > 0; --n)168168+ spiderpic = (spiderpic << 32) + *property++;169169+ printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);170170+ spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);171171+ for (n = 0; n < IIC_NUM_EXT; n++) {172172+ int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;173173+ get_irq_desc(irq)->handler = &spider_pic;174174+175175+ /* do not mask any interrupts because of level */176176+ out_be32(spider_pics[node] + TIR_MSK, 0x0);177177+178178+ /* disable edge detection clear */179179+ /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */180180+181181+ /* enable interrupt packets to be output */182182+ out_be32(spider_pics[node] + TIR_PIEN,183183+ in_be32(spider_pics[node] + TIR_PIEN) | 0x1);184184+185185+ /* Enable the interrupt detection enable bit. Do this last! */186186+ out_be32(spider_pics[node] + TIR_DEN,187187+ in_be32(spider_pics[node] +TIR_DEN) | 0x1);188188+189189+ }190190+ }191191+}
+63
arch/ppc64/kernel/time.c
···107107108108static unsigned adjusting_time = 0;109109110110+unsigned long ppc_proc_freq;111111+unsigned long ppc_tb_freq;112112+110113static __inline__ void timer_check_rtc(void)111114{112115 /*···474471}475472476473EXPORT_SYMBOL(do_settimeofday);474474+475475+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA)476476+void __init generic_calibrate_decr(void)477477+{478478+ struct device_node *cpu;479479+ struct div_result divres;480480+ unsigned int *fp;481481+ int node_found;482482+483483+ /*484484+ * The cpu node should have a timebase-frequency property485485+ * to tell us the rate at which the decrementer counts.486486+ */487487+ cpu = of_find_node_by_type(NULL, "cpu");488488+489489+ ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */490490+ node_found = 0;491491+ if (cpu != 0) {492492+ fp = (unsigned int *)get_property(cpu, "timebase-frequency",493493+ NULL);494494+ if (fp != 0) {495495+ node_found = 1;496496+ ppc_tb_freq = *fp;497497+ }498498+ }499499+ if (!node_found)500500+ printk(KERN_ERR "WARNING: Estimating decrementer frequency "501501+ "(not found)\n");502502+503503+ ppc_proc_freq = DEFAULT_PROC_FREQ;504504+ node_found = 0;505505+ if (cpu != 0) {506506+ fp = (unsigned int *)get_property(cpu, "clock-frequency",507507+ NULL);508508+ if (fp != 0) {509509+ node_found = 1;510510+ ppc_proc_freq = *fp;511511+ }512512+ }513513+ if (!node_found)514514+ printk(KERN_ERR "WARNING: Estimating processor frequency "515515+ "(not found)\n");516516+517517+ of_node_put(cpu);518518+519519+ printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",520520+ ppc_tb_freq/1000000, ppc_tb_freq%1000000);521521+ printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",522522+ ppc_proc_freq/1000000, ppc_proc_freq%1000000);523523+524524+ tb_ticks_per_jiffy = ppc_tb_freq / HZ;525525+ tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;526526+ tb_ticks_per_usec = ppc_tb_freq / 1000000;527527+ tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);528528+ div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);529529+ tb_to_xs = divres.result_low;530530+531531+ setup_default_decr();532532+}533533+#endif477534478535void __init time_init(void)479536{
···414414 machines. The watchdog timeout period is normally one minute but415415 can be changed with a boot-time parameter.416416417417+# ppc64 RTAS watchdog418418+config WATCHDOG_RTAS419419+ tristate "RTAS watchdog"420420+ depends on WATCHDOG && PPC_RTAS421421+ help422422+ This driver adds watchdog support for the RTAS watchdog.423423+424424+ To compile this driver as a module, choose M here. The module425425+ will be called wdrtas.426426+417427#418428# ISA-based Watchdog Cards419429#
+1
drivers/char/watchdog/Makefile
···3333obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o3434obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o3535obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o3636+obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o36373738# Only one watchdog can succeed. We probe the hardware watchdog3839# drivers first, then the softdog driver. This means if your hardware
+696
drivers/char/watchdog/wdrtas.c
···11+/*22+ * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as33+ * RTAS calls are available44+ */55+66+/*77+ * RTAS watchdog driver88+ *99+ * (C) Copyright IBM Corp. 20051010+ * device driver to exploit watchdog RTAS functions1111+ *1212+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>1313+ *1414+ * This program is free software; you can redistribute it and/or modify1515+ * it under the terms of the GNU General Public License as published by1616+ * the Free Software Foundation; either version 2, or (at your option)1717+ * any later version.1818+ *1919+ * This program is distributed in the hope that it will be useful,2020+ * but WITHOUT ANY WARRANTY; without even the implied warranty of2121+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the2222+ * GNU General Public License for more details.2323+ *2424+ * You should have received a copy of the GNU General Public License2525+ * along with this program; if not, write to the Free Software2626+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2727+ */2828+2929+#include <linux/config.h>3030+#include <linux/fs.h>3131+#include <linux/init.h>3232+#include <linux/kernel.h>3333+#include <linux/miscdevice.h>3434+#include <linux/module.h>3535+#include <linux/notifier.h>3636+#include <linux/reboot.h>3737+#include <linux/types.h>3838+#include <linux/watchdog.h>3939+4040+#include <asm/rtas.h>4141+#include <asm/uaccess.h>4242+4343+#define WDRTAS_MAGIC_CHAR 424444+#define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \4545+ WDIOF_MAGICCLOSE)4646+4747+MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");4848+MODULE_DESCRIPTION("RTAS watchdog driver");4949+MODULE_LICENSE("GPL");5050+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);5151+MODULE_ALIAS_MISCDEV(TEMP_MINOR);5252+5353+#ifdef CONFIG_WATCHDOG_NOWAYOUT5454+static int wdrtas_nowayout = 1;5555+#else5656+static int wdrtas_nowayout = 0;5757+#endif5858+5959+static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);6060+static char wdrtas_expect_close = 0;6161+6262+static int wdrtas_interval;6363+6464+#define WDRTAS_THERMAL_SENSOR 36565+static int wdrtas_token_get_sensor_state;6666+#define WDRTAS_SURVEILLANCE_IND 90006767+static int wdrtas_token_set_indicator;6868+#define WDRTAS_SP_SPI 286969+static int wdrtas_token_get_sp;7070+static int wdrtas_token_event_scan;7171+7272+#define WDRTAS_DEFAULT_INTERVAL 3007373+7474+#define WDRTAS_LOGBUFFER_LEN 1287575+static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];7676+7777+7878+/*** watchdog access functions */7979+8080+/**8181+ * wdrtas_set_interval - sets the watchdog interval8282+ * @interval: new interval8383+ *8484+ * returns 0 on success, <0 on failures8585+ *8686+ * wdrtas_set_interval sets the watchdog keepalive interval by calling the8787+ * RTAS function set-indicator (surveillance). The unit of interval is8888+ * seconds.8989+ */9090+static int9191+wdrtas_set_interval(int interval)9292+{9393+ long result;9494+ static int print_msg = 10;9595+9696+ /* rtas uses minutes */9797+ interval = (interval + 59) / 60;9898+9999+ result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,100100+ WDRTAS_SURVEILLANCE_IND, 0, interval);101101+ if ( (result < 0) && (print_msg) ) {102102+ printk(KERN_ERR "wdrtas: setting the watchdog to %i "103103+ "timeout failed: %li\n", interval, result);104104+ print_msg--;105105+ }106106+107107+ return result;108108+}109109+110110+/**111111+ * wdrtas_get_interval - returns the current watchdog interval112112+ * @fallback_value: value (in seconds) to use, if the RTAS call fails113113+ *114114+ * returns the interval115115+ *116116+ * wdrtas_get_interval returns the current watchdog keepalive interval117117+ * as reported by the RTAS function ibm,get-system-parameter. The unit118118+ * of the return value is seconds.119119+ */120120+static int121121+wdrtas_get_interval(int fallback_value)122122+{123123+ long result;124124+ char value[4];125125+126126+ result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,127127+ WDRTAS_SP_SPI, (void *)__pa(&value), 4);128128+ if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||129129+ (result < 0) ) {130130+ printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "131131+ "timeout (%li). Continuing\n", result);132132+ return fallback_value;133133+ }134134+135135+ /* rtas uses minutes */136136+ return ((int)value[2]) * 60;137137+}138138+139139+/**140140+ * wdrtas_timer_start - starts watchdog141141+ *142142+ * wdrtas_timer_start starts the watchdog by calling the RTAS function143143+ * set-interval (surveillance)144144+ */145145+static void146146+wdrtas_timer_start(void)147147+{148148+ wdrtas_set_interval(wdrtas_interval);149149+}150150+151151+/**152152+ * wdrtas_timer_stop - stops watchdog153153+ *154154+ * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function155155+ * set-interval (surveillance)156156+ */157157+static void158158+wdrtas_timer_stop(void)159159+{160160+ wdrtas_set_interval(0);161161+}162162+163163+/**164164+ * wdrtas_log_scanned_event - logs an event we received during keepalive165165+ *166166+ * wdrtas_log_scanned_event prints a message to the log buffer dumping167167+ * the results of the last event-scan call168168+ */169169+static void170170+wdrtas_log_scanned_event(void)171171+{172172+ int i;173173+174174+ for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)175175+ printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "176176+ "%02x %02x %02x %02x %02x %02x %02x %02x "177177+ "%02x %02x %02x %02x %02x %02x %02x %02x\n",178178+ (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),179179+ wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], 180180+ wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], 181181+ wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], 182182+ wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], 183183+ wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], 184184+ wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], 185185+ wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], 186186+ wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);187187+}188188+189189+/**190190+ * wdrtas_timer_keepalive - resets watchdog timer to keep system alive191191+ *192192+ * wdrtas_timer_keepalive restarts the watchdog timer by calling the193193+ * RTAS function event-scan and repeats these calls as long as there are194194+ * events available. All events will be dumped.195195+ */196196+static void197197+wdrtas_timer_keepalive(void)198198+{199199+ long result;200200+201201+ do {202202+ result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,203203+ RTAS_EVENT_SCAN_ALL_EVENTS, 0,204204+ (void *)__pa(wdrtas_logbuffer),205205+ WDRTAS_LOGBUFFER_LEN);206206+ if (result < 0)207207+ printk(KERN_ERR "wdrtas: event-scan failed: %li\n",208208+ result);209209+ if (result == 0)210210+ wdrtas_log_scanned_event();211211+ } while (result == 0);212212+}213213+214214+/**215215+ * wdrtas_get_temperature - returns current temperature216216+ *217217+ * returns temperature or <0 on failures218218+ *219219+ * wdrtas_get_temperature returns the current temperature in Fahrenheit. It220220+ * uses the RTAS call get-sensor-state, token 3 to do so221221+ */222222+static int223223+wdrtas_get_temperature(void)224224+{225225+ long result;226226+ int temperature = 0;227227+228228+ result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,229229+ (void *)__pa(&temperature),230230+ WDRTAS_THERMAL_SENSOR, 0);231231+232232+ if (result < 0)233233+ printk(KERN_WARNING "wdrtas: reading the thermal sensor "234234+ "faild: %li\n", result);235235+ else236236+ temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */237237+238238+ return temperature;239239+}240240+241241+/**242242+ * wdrtas_get_status - returns the status of the watchdog243243+ *244244+ * returns a bitmask of defines WDIOF_... as defined in245245+ * include/linux/watchdog.h246246+ */247247+static int248248+wdrtas_get_status(void)249249+{250250+ return 0; /* TODO */251251+}252252+253253+/**254254+ * wdrtas_get_boot_status - returns the reason for the last boot255255+ *256256+ * returns a bitmask of defines WDIOF_... as defined in257257+ * include/linux/watchdog.h, indicating why the watchdog rebooted the system258258+ */259259+static int260260+wdrtas_get_boot_status(void)261261+{262262+ return 0; /* TODO */263263+}264264+265265+/*** watchdog API and operations stuff */266266+267267+/* wdrtas_write - called when watchdog device is written to268268+ * @file: file structure269269+ * @buf: user buffer with data270270+ * @len: amount to data written271271+ * @ppos: position in file272272+ *273273+ * returns the number of successfully processed characters, which is always274274+ * the number of bytes passed to this function275275+ *276276+ * wdrtas_write processes all the data given to it and looks for the magic277277+ * character 'V'. This character allows the watchdog device to be closed278278+ * properly.279279+ */280280+static ssize_t281281+wdrtas_write(struct file *file, const char __user *buf,282282+ size_t len, loff_t *ppos)283283+{284284+ int i;285285+ char c;286286+287287+ if (!len)288288+ goto out;289289+290290+ if (!wdrtas_nowayout) {291291+ wdrtas_expect_close = 0;292292+ /* look for 'V' */293293+ for (i = 0; i < len; i++) {294294+ if (get_user(c, buf + i))295295+ return -EFAULT;296296+ /* allow to close device */297297+ if (c == 'V')298298+ wdrtas_expect_close = WDRTAS_MAGIC_CHAR;299299+ }300300+ }301301+302302+ wdrtas_timer_keepalive();303303+304304+out:305305+ return len;306306+}307307+308308+/**309309+ * wdrtas_ioctl - ioctl function for the watchdog device310310+ * @inode: inode structure311311+ * @file: file structure312312+ * @cmd: command for ioctl313313+ * @arg: argument pointer314314+ *315315+ * returns 0 on success, <0 on failure316316+ *317317+ * wdrtas_ioctl implements the watchdog API ioctls318318+ */319319+static int320320+wdrtas_ioctl(struct inode *inode, struct file *file,321321+ unsigned int cmd, unsigned long arg)322322+{323323+ int __user *argp = (void *)arg;324324+ int i;325325+ static struct watchdog_info wdinfo = {326326+ .options = WDRTAS_SUPPORTED_MASK,327327+ .firmware_version = 0,328328+ .identity = "wdrtas"329329+ };330330+331331+ switch (cmd) {332332+ case WDIOC_GETSUPPORT:333333+ if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))334334+ return -EFAULT;335335+ return 0;336336+337337+ case WDIOC_GETSTATUS:338338+ i = wdrtas_get_status();339339+ return put_user(i, argp);340340+341341+ case WDIOC_GETBOOTSTATUS:342342+ i = wdrtas_get_boot_status();343343+ return put_user(i, argp);344344+345345+ case WDIOC_GETTEMP:346346+ if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)347347+ return -EOPNOTSUPP;348348+349349+ i = wdrtas_get_temperature();350350+ return put_user(i, argp);351351+352352+ case WDIOC_SETOPTIONS:353353+ if (get_user(i, argp))354354+ return -EFAULT;355355+ if (i & WDIOS_DISABLECARD)356356+ wdrtas_timer_stop();357357+ if (i & WDIOS_ENABLECARD) {358358+ wdrtas_timer_keepalive();359359+ wdrtas_timer_start();360360+ }361361+ if (i & WDIOS_TEMPPANIC) {362362+ /* not implemented. Done by H8 */363363+ }364364+ return 0;365365+366366+ case WDIOC_KEEPALIVE:367367+ wdrtas_timer_keepalive();368368+ return 0;369369+370370+ case WDIOC_SETTIMEOUT:371371+ if (get_user(i, argp))372372+ return -EFAULT;373373+374374+ if (wdrtas_set_interval(i))375375+ return -EINVAL;376376+377377+ wdrtas_timer_keepalive();378378+379379+ if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)380380+ wdrtas_interval = i;381381+ else382382+ wdrtas_interval = wdrtas_get_interval(i);383383+ /* fallthrough */384384+385385+ case WDIOC_GETTIMEOUT:386386+ return put_user(wdrtas_interval, argp);387387+388388+ default:389389+ return -ENOIOCTLCMD;390390+ }391391+}392392+393393+/**394394+ * wdrtas_open - open function of watchdog device395395+ * @inode: inode structure396396+ * @file: file structure397397+ *398398+ * returns 0 on success, -EBUSY if the file has been opened already, <0 on399399+ * other failures400400+ *401401+ * function called when watchdog device is opened402402+ */403403+static int404404+wdrtas_open(struct inode *inode, struct file *file)405405+{406406+ /* only open once */407407+ if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {408408+ atomic_dec(&wdrtas_miscdev_open);409409+ return -EBUSY;410410+ }411411+412412+ wdrtas_timer_start();413413+ wdrtas_timer_keepalive();414414+415415+ return nonseekable_open(inode, file);416416+}417417+418418+/**419419+ * wdrtas_close - close function of watchdog device420420+ * @inode: inode structure421421+ * @file: file structure422422+ *423423+ * returns 0 on success424424+ *425425+ * close function. Always succeeds426426+ */427427+static int428428+wdrtas_close(struct inode *inode, struct file *file)429429+{430430+ /* only stop watchdog, if this was announced using 'V' before */431431+ if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)432432+ wdrtas_timer_stop();433433+ else {434434+ printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "435435+ "not stopped.\n");436436+ wdrtas_timer_keepalive();437437+ }438438+439439+ wdrtas_expect_close = 0;440440+ atomic_dec(&wdrtas_miscdev_open);441441+ return 0;442442+}443443+444444+/**445445+ * wdrtas_temp_read - gives back the temperature in fahrenheit446446+ * @file: file structure447447+ * @buf: user buffer448448+ * @count: number of bytes to be read449449+ * @ppos: position in file450450+ *451451+ * returns always 1 or -EFAULT in case of user space copy failures, <0 on452452+ * other failures453453+ *454454+ * wdrtas_temp_read gives the temperature to the users by copying this455455+ * value as one byte into the user space buffer. The unit is Fahrenheit...456456+ */457457+static ssize_t458458+wdrtas_temp_read(struct file *file, char __user *buf,459459+ size_t count, loff_t *ppos)460460+{461461+ int temperature = 0;462462+463463+ temperature = wdrtas_get_temperature();464464+ if (temperature < 0)465465+ return temperature;466466+467467+ if (copy_to_user(buf, &temperature, 1))468468+ return -EFAULT;469469+470470+ return 1;471471+}472472+473473+/**474474+ * wdrtas_temp_open - open function of temperature device475475+ * @inode: inode structure476476+ * @file: file structure477477+ *478478+ * returns 0 on success, <0 on failure479479+ *480480+ * function called when temperature device is opened481481+ */482482+static int483483+wdrtas_temp_open(struct inode *inode, struct file *file)484484+{485485+ return nonseekable_open(inode, file);486486+}487487+488488+/**489489+ * wdrtas_temp_close - close function of temperature device490490+ * @inode: inode structure491491+ * @file: file structure492492+ *493493+ * returns 0 on success494494+ *495495+ * close function. Always succeeds496496+ */497497+static int498498+wdrtas_temp_close(struct inode *inode, struct file *file)499499+{500500+ return 0;501501+}502502+503503+/**504504+ * wdrtas_reboot - reboot notifier function505505+ * @nb: notifier block structure506506+ * @code: reboot code507507+ * @ptr: unused508508+ *509509+ * returns NOTIFY_DONE510510+ *511511+ * wdrtas_reboot stops the watchdog in case of a reboot512512+ */513513+static int514514+wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)515515+{516516+ if ( (code==SYS_DOWN) || (code==SYS_HALT) )517517+ wdrtas_timer_stop();518518+519519+ return NOTIFY_DONE;520520+}521521+522522+/*** initialization stuff */523523+524524+static struct file_operations wdrtas_fops = {525525+ .owner = THIS_MODULE,526526+ .llseek = no_llseek,527527+ .write = wdrtas_write,528528+ .ioctl = wdrtas_ioctl,529529+ .open = wdrtas_open,530530+ .release = wdrtas_close,531531+};532532+533533+static struct miscdevice wdrtas_miscdev = {534534+ .minor = WATCHDOG_MINOR,535535+ .name = "watchdog",536536+ .fops = &wdrtas_fops,537537+};538538+539539+static struct file_operations wdrtas_temp_fops = {540540+ .owner = THIS_MODULE,541541+ .llseek = no_llseek,542542+ .read = wdrtas_temp_read,543543+ .open = wdrtas_temp_open,544544+ .release = wdrtas_temp_close,545545+};546546+547547+static struct miscdevice wdrtas_tempdev = {548548+ .minor = TEMP_MINOR,549549+ .name = "temperature",550550+ .fops = &wdrtas_temp_fops,551551+};552552+553553+static struct notifier_block wdrtas_notifier = {554554+ .notifier_call = wdrtas_reboot,555555+};556556+557557+/**558558+ * wdrtas_get_tokens - reads in RTAS tokens559559+ *560560+ * returns 0 on succes, <0 on failure561561+ *562562+ * wdrtas_get_tokens reads in the tokens for the RTAS calls used in563563+ * this watchdog driver. It tolerates, if "get-sensor-state" and564564+ * "ibm,get-system-parameter" are not available.565565+ */566566+static int567567+wdrtas_get_tokens(void)568568+{569569+ wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");570570+ if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {571571+ printk(KERN_WARNING "wdrtas: couldn't get token for "572572+ "get-sensor-state. Trying to continue without "573573+ "temperature support.\n");574574+ }575575+576576+ wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");577577+ if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {578578+ printk(KERN_WARNING "wdrtas: couldn't get token for "579579+ "ibm,get-system-parameter. Trying to continue with "580580+ "a default timeout value of %i seconds.\n",581581+ WDRTAS_DEFAULT_INTERVAL);582582+ }583583+584584+ wdrtas_token_set_indicator = rtas_token("set-indicator");585585+ if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {586586+ printk(KERN_ERR "wdrtas: couldn't get token for "587587+ "set-indicator. Terminating watchdog code.\n");588588+ return -EIO;589589+ }590590+591591+ wdrtas_token_event_scan = rtas_token("event-scan");592592+ if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {593593+ printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "594594+ "Terminating watchdog code.\n");595595+ return -EIO;596596+ }597597+598598+ return 0;599599+}600600+601601+/**602602+ * wdrtas_unregister_devs - unregisters the misc dev handlers603603+ *604604+ * wdrtas_register_devs unregisters the watchdog and temperature watchdog605605+ * misc devs606606+ */607607+static void608608+wdrtas_unregister_devs(void)609609+{610610+ misc_deregister(&wdrtas_miscdev);611611+ if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)612612+ misc_deregister(&wdrtas_tempdev);613613+}614614+615615+/**616616+ * wdrtas_register_devs - registers the misc dev handlers617617+ *618618+ * returns 0 on succes, <0 on failure619619+ *620620+ * wdrtas_register_devs registers the watchdog and temperature watchdog621621+ * misc devs622622+ */623623+static int624624+wdrtas_register_devs(void)625625+{626626+ int result;627627+628628+ result = misc_register(&wdrtas_miscdev);629629+ if (result) {630630+ printk(KERN_ERR "wdrtas: couldn't register watchdog misc "631631+ "device. Terminating watchdog code.\n");632632+ return result;633633+ }634634+635635+ if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {636636+ result = misc_register(&wdrtas_tempdev);637637+ if (result) {638638+ printk(KERN_WARNING "wdrtas: couldn't register "639639+ "watchdog temperature misc device. Continuing "640640+ "without temperature support.\n");641641+ wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;642642+ }643643+ }644644+645645+ return 0;646646+}647647+648648+/**649649+ * wdrtas_init - init function of the watchdog driver650650+ *651651+ * returns 0 on succes, <0 on failure652652+ *653653+ * registers the file handlers and the reboot notifier654654+ */655655+static int __init656656+wdrtas_init(void)657657+{658658+ if (wdrtas_get_tokens())659659+ return -ENODEV;660660+661661+ if (wdrtas_register_devs())662662+ return -ENODEV;663663+664664+ if (register_reboot_notifier(&wdrtas_notifier)) {665665+ printk(KERN_ERR "wdrtas: could not register reboot notifier. "666666+ "Terminating watchdog code.\n");667667+ wdrtas_unregister_devs();668668+ return -ENODEV;669669+ }670670+671671+ if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)672672+ wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;673673+ else674674+ wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);675675+676676+ return 0;677677+}678678+679679+/**680680+ * wdrtas_exit - exit function of the watchdog driver681681+ *682682+ * unregisters the file handlers and the reboot notifier683683+ */684684+static void __exit685685+wdrtas_exit(void)686686+{687687+ if (!wdrtas_nowayout)688688+ wdrtas_timer_stop();689689+690690+ wdrtas_unregister_devs();691691+692692+ unregister_reboot_notifier(&wdrtas_notifier);693693+}694694+695695+module_init(wdrtas_init);696696+module_exit(wdrtas_exit);
···70707171extern int pSeries_nvram_init(void);7272extern int pmac_nvram_init(void);7373+extern int bpa_nvram_init(void);73747475/* PowerMac specific nvram stuffs */7576
+13-2
include/asm-ppc64/processor.h
···138138#define SPRN_NIADORM 0x3F3 /* Hardware Implementation Register 2 */139139#define SPRN_HID4 0x3F4 /* 970 HID4 */140140#define SPRN_HID5 0x3F6 /* 970 HID5 */141141-#define SPRN_TSC 0x3FD /* Thread switch control */142142-#define SPRN_TST 0x3FC /* Thread switch timeout */141141+#define SPRN_HID6 0x3F9 /* BE HID 6 */142142+#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */143143+#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */144144+#define SPRN_TSCR 0x399 /* Thread switch control on BE */145145+#define SPRN_TTR 0x39A /* Thread switch timeout on BE */146146+#define TSCR_DEC_ENABLE 0x200000 /* Decrementer Interrupt */147147+#define TSCR_EE_ENABLE 0x100000 /* External Interrupt */148148+#define TSCR_EE_BOOST 0x080000 /* External Interrupt Boost */149149+#define SPRN_TSC 0x3FD /* Thread switch control on others */150150+#define SPRN_TST 0x3FC /* Thread switch timeout on others */143151#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */144152#define SPRN_LR 0x008 /* Link Register */145153#define SPRN_PIR 0x3FF /* Processor Identification Register */···267259#define PV_970FX 0x003C268260#define PV_630 0x0040269261#define PV_630p 0x0041262262+#define PV_BE 0x0070270263271264/* Platforms supported by PPC64 */272265#define PLATFORM_PSERIES 0x0100···276267#define PLATFORM_LPAR 0x0001277268#define PLATFORM_POWERMAC 0x0400278269#define PLATFORM_MAPLE 0x0500270270+#define PLATFORM_BPA 0x1000279271280272/* Compatibility with drivers coming from PPC32 world */281273#define _machine (systemcfg->platform)···288278#define IC_INVALID 0289279#define IC_OPEN_PIC 1290280#define IC_PPC_XIC 2281281+#define IC_BPA_IIC 3291282292283#define XGLUE(a,b) a##b293284#define GLUE(a,b) XGLUE(a,b)
+6
include/asm-ppc64/rtas.h
···186186extern int rtas_get_power_level(int powerdomain, int *level);187187extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);188188extern int rtas_set_indicator(int indicator, int index, int new_value);189189+extern void rtas_progress(char *s, unsigned short hex);189190extern void rtas_initialize(void);191191+192192+struct rtc_time;193193+extern void rtas_get_boot_time(struct rtc_time *rtc_time);194194+extern void rtas_get_rtc_time(struct rtc_time *rtc_time);195195+extern int rtas_set_rtc_time(struct rtc_time *rtc_time);190196191197/* Given an RTAS status code of 9900..9905 compute the hinted delay */192198unsigned int rtas_extended_busy_delay_time(int status);
···3434extern void to_tm(int tim, struct rtc_time * tm);3535extern time_t last_rtc_update;36363737+void generic_calibrate_decr(void);3838+void setup_default_decr(void);3939+4040+/* Some sane defaults: 125 MHz timebase, 1GHz processor */4141+extern unsigned long ppc_proc_freq;4242+#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)4343+extern unsigned long ppc_tb_freq;4444+#define DEFAULT_TB_FREQ 125000000UL4545+3746/*3847 * By putting all of this stuff into a single struct we 3948 * reduce the number of cache lines touched by do_gettimeofday.