1ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens/* 2ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * Broadcom specific AMBA 3ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * System on Chip (SoC) Host 4ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * 5ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * Licensed under the GNU/GPL. See COPYING for details. 6ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens */ 7ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 8ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include "bcma_private.h" 9ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include "scan.h" 10ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include <linux/bcma/bcma.h> 11ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include <linux/bcma/bcma_soc.h> 12ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 13ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset) 14ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 15ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return readb(core->io_addr + offset); 16ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 17ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 18ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset) 19ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 20ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return readw(core->io_addr + offset); 21ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 22ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 23ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset) 24ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 25ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return readl(core->io_addr + offset); 26ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 27ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 28ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_write8(struct bcma_device *core, u16 offset, 29ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens u8 value) 30ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 31ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens writeb(value, core->io_addr + offset); 32ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 33ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 34ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_write16(struct bcma_device *core, u16 offset, 35ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens u16 value) 36ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 37ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens writew(value, core->io_addr + offset); 38ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 39ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 40ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_write32(struct bcma_device *core, u16 offset, 41ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens u32 value) 42ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 43ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens writel(value, core->io_addr + offset); 44ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 45ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 46ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#ifdef CONFIG_BCMA_BLOCKIO 47ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_block_read(struct bcma_device *core, void *buffer, 48ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens size_t count, u16 offset, u8 reg_width) 49ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 50ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens void __iomem *addr = core->io_addr + offset; 51ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 52ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens switch (reg_width) { 53ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens case sizeof(u8): { 54ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens u8 *buf = buffer; 55ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 56ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens while (count) { 57ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens *buf = __raw_readb(addr); 58ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens buf++; 59ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens count--; 60ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 61ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens break; 62ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 63ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens case sizeof(u16): { 64ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens __le16 *buf = buffer; 65ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 66ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens WARN_ON(count & 1); 67ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens while (count) { 68ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens *buf = (__force __le16)__raw_readw(addr); 69ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens buf++; 70ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens count -= 2; 71ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 72ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens break; 73ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 74ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens case sizeof(u32): { 75ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens __le32 *buf = buffer; 76ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 77ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens WARN_ON(count & 3); 78ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens while (count) { 79ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens *buf = (__force __le32)__raw_readl(addr); 80ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens buf++; 81ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens count -= 4; 82ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 83ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens break; 84ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 85ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens default: 86ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens WARN_ON(1); 87ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 88ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 89ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 90ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_block_write(struct bcma_device *core, 91ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens const void *buffer, 92ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens size_t count, u16 offset, u8 reg_width) 93ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 94ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens void __iomem *addr = core->io_addr + offset; 95ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 96ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens switch (reg_width) { 97ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens case sizeof(u8): { 98ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens const u8 *buf = buffer; 99ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 100ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens while (count) { 101ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens __raw_writeb(*buf, addr); 102ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens buf++; 103ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens count--; 104ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 105ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens break; 106ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 107ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens case sizeof(u16): { 108ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens const __le16 *buf = buffer; 109ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 110ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens WARN_ON(count & 1); 111ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens while (count) { 112ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens __raw_writew((__force u16)(*buf), addr); 113ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens buf++; 114ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens count -= 2; 115ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 116ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens break; 117ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 118ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens case sizeof(u32): { 119ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens const __le32 *buf = buffer; 120ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 121ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens WARN_ON(count & 3); 122ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens while (count) { 123ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens __raw_writel((__force u32)(*buf), addr); 124ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens buf++; 125ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens count -= 4; 126ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 127ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens break; 128ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 129ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens default: 130ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens WARN_ON(1); 131ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens } 132ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 133ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#endif /* CONFIG_BCMA_BLOCKIO */ 134ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 135ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset) 136ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 137ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return readl(core->io_wrap + offset); 138ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 139ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 140ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset, 141ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens u32 value) 142ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 143ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens writel(value, core->io_wrap + offset); 144ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 145ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 146ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensconst struct bcma_host_ops bcma_host_soc_ops = { 147ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .read8 = bcma_host_soc_read8, 148ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .read16 = bcma_host_soc_read16, 149ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .read32 = bcma_host_soc_read32, 150ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .write8 = bcma_host_soc_write8, 151ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .write16 = bcma_host_soc_write16, 152ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .write32 = bcma_host_soc_write32, 153ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#ifdef CONFIG_BCMA_BLOCKIO 154ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .block_read = bcma_host_soc_block_read, 155ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .block_write = bcma_host_soc_block_write, 156ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#endif 157ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .aread32 = bcma_host_soc_aread32, 158ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens .awrite32 = bcma_host_soc_awrite32, 159ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}; 160ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 161ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensint __init bcma_host_soc_register(struct bcma_soc *soc) 162ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{ 163ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens struct bcma_bus *bus = &soc->bus; 164ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens int err; 165ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 166ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens /* iomap only first core. We have to read some register on this core 167ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * to scan the bus. 168ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens */ 169ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1); 170ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (!bus->mmio) 171ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return -ENOMEM; 172ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 173ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens /* Host specific */ 174ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens bus->hosttype = BCMA_HOSTTYPE_SOC; 175ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens bus->ops = &bcma_host_soc_ops; 176ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 177ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens /* Register */ 178ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips); 179ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens if (err) 180ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens iounmap(bus->mmio); 181ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens 182ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens return err; 183ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens} 184