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