1 /* 2 * Sonics Silicon Backplane SoC host related functions. 3 * Subsystem core 4 * 5 * Copyright 2005, Broadcom Corporation 6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 7 * 8 * Licensed under the GNU/GPL. See COPYING for details. 9 */ 10 11 #include <linux/ssb/ssb.h> 12 13 #include "ssb_private.h" 14 15 static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset) 16 { 17 struct ssb_bus *bus = dev->bus; 18 19 offset += dev->core_index * SSB_CORE_SIZE; 20 return readb(bus->mmio + offset); 21 } 22 23 static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset) 24 { 25 struct ssb_bus *bus = dev->bus; 26 27 offset += dev->core_index * SSB_CORE_SIZE; 28 return readw(bus->mmio + offset); 29 } 30 31 static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset) 32 { 33 struct ssb_bus *bus = dev->bus; 34 35 offset += dev->core_index * SSB_CORE_SIZE; 36 return readl(bus->mmio + offset); 37 } 38 39 #ifdef CONFIG_SSB_BLOCKIO 40 static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer, 41 size_t count, u16 offset, u8 reg_width) 42 { 43 struct ssb_bus *bus = dev->bus; 44 void __iomem *addr; 45 46 offset += dev->core_index * SSB_CORE_SIZE; 47 addr = bus->mmio + offset; 48 49 switch (reg_width) { 50 case sizeof(u8): { 51 u8 *buf = buffer; 52 53 while (count) { 54 *buf = __raw_readb(addr); 55 buf++; 56 count--; 57 } 58 break; 59 } 60 case sizeof(u16): { 61 __le16 *buf = buffer; 62 63 SSB_WARN_ON(count & 1); 64 while (count) { 65 *buf = (__force __le16)__raw_readw(addr); 66 buf++; 67 count -= 2; 68 } 69 break; 70 } 71 case sizeof(u32): { 72 __le32 *buf = buffer; 73 74 SSB_WARN_ON(count & 3); 75 while (count) { 76 *buf = (__force __le32)__raw_readl(addr); 77 buf++; 78 count -= 4; 79 } 80 break; 81 } 82 default: 83 SSB_WARN_ON(1); 84 } 85 } 86 #endif /* CONFIG_SSB_BLOCKIO */ 87 88 static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value) 89 { 90 struct ssb_bus *bus = dev->bus; 91 92 offset += dev->core_index * SSB_CORE_SIZE; 93 writeb(value, bus->mmio + offset); 94 } 95 96 static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value) 97 { 98 struct ssb_bus *bus = dev->bus; 99 100 offset += dev->core_index * SSB_CORE_SIZE; 101 writew(value, bus->mmio + offset); 102 } 103 104 static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value) 105 { 106 struct ssb_bus *bus = dev->bus; 107 108 offset += dev->core_index * SSB_CORE_SIZE; 109 writel(value, bus->mmio + offset); 110 } 111 112 #ifdef CONFIG_SSB_BLOCKIO 113 static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer, 114 size_t count, u16 offset, u8 reg_width) 115 { 116 struct ssb_bus *bus = dev->bus; 117 void __iomem *addr; 118 119 offset += dev->core_index * SSB_CORE_SIZE; 120 addr = bus->mmio + offset; 121 122 switch (reg_width) { 123 case sizeof(u8): { 124 const u8 *buf = buffer; 125 126 while (count) { 127 __raw_writeb(*buf, addr); 128 buf++; 129 count--; 130 } 131 break; 132 } 133 case sizeof(u16): { 134 const __le16 *buf = buffer; 135 136 SSB_WARN_ON(count & 1); 137 while (count) { 138 __raw_writew((__force u16)(*buf), addr); 139 buf++; 140 count -= 2; 141 } 142 break; 143 } 144 case sizeof(u32): { 145 const __le32 *buf = buffer; 146 147 SSB_WARN_ON(count & 3); 148 while (count) { 149 __raw_writel((__force u32)(*buf), addr); 150 buf++; 151 count -= 4; 152 } 153 break; 154 } 155 default: 156 SSB_WARN_ON(1); 157 } 158 } 159 #endif /* CONFIG_SSB_BLOCKIO */ 160 161 /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ 162 const struct ssb_bus_ops ssb_host_soc_ops = { 163 .read8 = ssb_host_soc_read8, 164 .read16 = ssb_host_soc_read16, 165 .read32 = ssb_host_soc_read32, 166 .write8 = ssb_host_soc_write8, 167 .write16 = ssb_host_soc_write16, 168 .write32 = ssb_host_soc_write32, 169 #ifdef CONFIG_SSB_BLOCKIO 170 .block_read = ssb_host_soc_block_read, 171 .block_write = ssb_host_soc_block_write, 172 #endif 173 }; 174