Subject: powerpc: axon: DCR support This patch adds Axon DCR support for: - dcr_{read/write} - Axon specific DCR read/write - supports up to two DCR controllers - provides of_translate_dcr_address for MMIO address translation Signed-off-by: Shaun Wetzstein Signed-off-by: Arnd Bergmann Index: linux-2.6/arch/powerpc/platforms/cell/Makefile =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/Makefile +++ linux-2.6/arch/powerpc/platforms/cell/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ cbe_regs.o spider-pic.o pervasive.o \ - pmu.o axon.o + pmu.o axon.o axon_dcr.o obj-$(CONFIG_CBE_RAS) += ras.o obj-$(CONFIG_CBE_THERM) += cbe_thermal.o Index: linux-2.6/arch/powerpc/platforms/cell/axon_dcr.c =================================================================== --- /dev/null +++ linux-2.6/arch/powerpc/platforms/cell/axon_dcr.c @@ -0,0 +1,162 @@ +/* + * AXON DCR support + * + * Copyright (C) 2006 Shaun Wetzstein (shaun@vnet.ibm.com) + * IBM, Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#undef DEBUG + +#include +#include +#include +#include + +#include +#include + +/* cache the translated base addresses */ +#define MAX_AXON_DCR_NR 2 +static struct { + __iomem __be32 * base; + u64 addr; +} axon_dcr_ctlr[MAX_AXON_DCR_NR]; + +static int __init axon_dcr_init(void) +{ + struct device_node * axon; + struct device_node * dcr; + const u64 * prop; + u64 addr; + + int idx = 0; + for (axon = NULL; (axon = of_find_node_by_name(axon, "axon"));) { + for (dcr = axon; (dcr = of_find_node_by_name(dcr, "dcr"));) { + prop = get_property(dcr,"dcr-mmio-space", NULL); + if (prop == NULL) { + printk(KERN_ERR + "%s: No dcr-mmio-space property!\n", + dcr->full_name); + continue; + } + + addr = of_translate_address(dcr, (u32 *)prop); + if (addr != OF_BAD_ADDR) { + axon_dcr_ctlr[idx].addr = addr; + axon_dcr_ctlr[idx].base = ioremap(addr, prop[1]); + if (!axon_dcr_ctlr[idx].base) { + printk(KERN_ERR + "DCR%d: unable to map MMIO" + " range %lx, size %lx\n", + idx, addr, prop[1]); + continue; + } + + printk(KERN_INFO + "Axon-DCR%d: %lx -> %p, size: %lx\n", + idx, addr, axon_dcr_ctlr[idx].base, prop[1]); + idx++; + } + } + } + + return 0; +} +arch_initcall(axon_dcr_init); + +static struct device_node * find_parent_dcr_node(struct device_node * node) +{ + struct device_node *ctlr; + const u32 *prop; + + ctlr = node; + while (ctlr != NULL) { + prop = get_property(ctlr, "dcr-parent", NULL); + if (prop) + goto found; + + if (strcmp(ctlr->name, "axon") == 0) + break; + + ctlr = of_get_parent(ctlr); + } + + printk(KERN_ERR "%s: Unable to find dcr-parent property!\n", + node->name); + + return NULL; + +found: + ctlr = of_find_node_by_phandle(*prop); + if (ctlr == NULL) { + printk(KERN_ERR + "%s: Invalid dcr-parent property (phandle=%d)!\n", + ctlr->name, *prop); + return NULL; + } + + return ctlr; +} + +u64 of_translate_dcr_address(struct device_node *node, const u32 *addr) +{ + struct device_node * ctlr = find_parent_dcr_node(node); + + if (ctlr != NULL) { + const u32 * prop = get_property(ctlr, "dcr-mmio-space", NULL); + if (prop) { + u64 result = of_translate_address(ctlr, prop); + if (result != OF_BAD_ADDR) { + if (addr != NULL) + result |= ((u64)*addr) << 4; + return result; + } + } + } + + return OF_BAD_ADDR; +} +EXPORT_SYMBOL(of_translate_dcr_address); + +void *dcr_find_controller(struct device_node * node) +{ + u64 addr = of_translate_dcr_address(node, NULL); + + if (addr != OF_BAD_ADDR) { + int i; + for (i=0; i