/* * SCOM backend for WSP * * Copyright 2010 Benjamin Herrenschmidt, 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. */ #include <linux/cpumask.h> #include <linux/io.h> #include <linux/of.h> #include <linux/spinlock.h> #include <linux/types.h> #include <asm/cputhreads.h> #include <asm/reg_a2.h> #include <asm/scom.h> #include <asm/udbg.h> #include "wsp.h" static scom_map_t wsp_scom_map(struct device_node *dev, u64 reg, u64 count) { struct resource r; u64 xscom_addr; if (!of_get_property(dev, "scom-controller", NULL)) { pr_err("%s: device %s is not a SCOM controller\n", __func__, dev->full_name); return SCOM_MAP_INVALID; } if (of_address_to_resource(dev, 0, &r)) { pr_debug("Failed to find SCOM controller address\n"); return 0; } /* Transform the SCOM address into an XSCOM offset */ xscom_addr = ((reg & 0x7f000000) >> 1) | ((reg & 0xfffff) << 3); return (scom_map_t)ioremap(r.start + xscom_addr, count << 3); } static void wsp_scom_unmap(scom_map_t map) { iounmap((void *)map); } static u64 wsp_scom_read(scom_map_t map, u32 reg) { u64 __iomem *addr = (u64 __iomem *)map; return in_be64(addr + reg); } static void wsp_scom_write(scom_map_t map, u32 reg, u64 value) { u64 __iomem *addr = (u64 __iomem *)map; return out_be64(addr + reg, value); } static const struct scom_controller wsp_scom_controller = { .map = wsp_scom_map, .unmap = wsp_scom_unmap, .read = wsp_scom_read, .write = wsp_scom_write }; void scom_init_wsp(void) { scom_init(&wsp_scom_controller); }