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 146 const struct bcma_host_ops bcma_host_soc_ops = { 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 } 184