0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "ssb_private.h"
0012
0013 #include <linux/bcm47xx_nvram.h>
0014 #include <linux/ssb/ssb.h>
0015
0016 static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
0017 {
0018 struct ssb_bus *bus = dev->bus;
0019
0020 offset += dev->core_index * SSB_CORE_SIZE;
0021 return readb(bus->mmio + offset);
0022 }
0023
0024 static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
0025 {
0026 struct ssb_bus *bus = dev->bus;
0027
0028 offset += dev->core_index * SSB_CORE_SIZE;
0029 return readw(bus->mmio + offset);
0030 }
0031
0032 static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
0033 {
0034 struct ssb_bus *bus = dev->bus;
0035
0036 offset += dev->core_index * SSB_CORE_SIZE;
0037 return readl(bus->mmio + offset);
0038 }
0039
0040 #ifdef CONFIG_SSB_BLOCKIO
0041 static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
0042 size_t count, u16 offset, u8 reg_width)
0043 {
0044 struct ssb_bus *bus = dev->bus;
0045 void __iomem *addr;
0046
0047 offset += dev->core_index * SSB_CORE_SIZE;
0048 addr = bus->mmio + offset;
0049
0050 switch (reg_width) {
0051 case sizeof(u8): {
0052 u8 *buf = buffer;
0053
0054 while (count) {
0055 *buf = __raw_readb(addr);
0056 buf++;
0057 count--;
0058 }
0059 break;
0060 }
0061 case sizeof(u16): {
0062 __le16 *buf = buffer;
0063
0064 WARN_ON(count & 1);
0065 while (count) {
0066 *buf = (__force __le16)__raw_readw(addr);
0067 buf++;
0068 count -= 2;
0069 }
0070 break;
0071 }
0072 case sizeof(u32): {
0073 __le32 *buf = buffer;
0074
0075 WARN_ON(count & 3);
0076 while (count) {
0077 *buf = (__force __le32)__raw_readl(addr);
0078 buf++;
0079 count -= 4;
0080 }
0081 break;
0082 }
0083 default:
0084 WARN_ON(1);
0085 }
0086 }
0087 #endif
0088
0089 static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
0090 {
0091 struct ssb_bus *bus = dev->bus;
0092
0093 offset += dev->core_index * SSB_CORE_SIZE;
0094 writeb(value, bus->mmio + offset);
0095 }
0096
0097 static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
0098 {
0099 struct ssb_bus *bus = dev->bus;
0100
0101 offset += dev->core_index * SSB_CORE_SIZE;
0102 writew(value, bus->mmio + offset);
0103 }
0104
0105 static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
0106 {
0107 struct ssb_bus *bus = dev->bus;
0108
0109 offset += dev->core_index * SSB_CORE_SIZE;
0110 writel(value, bus->mmio + offset);
0111 }
0112
0113 #ifdef CONFIG_SSB_BLOCKIO
0114 static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
0115 size_t count, u16 offset, u8 reg_width)
0116 {
0117 struct ssb_bus *bus = dev->bus;
0118 void __iomem *addr;
0119
0120 offset += dev->core_index * SSB_CORE_SIZE;
0121 addr = bus->mmio + offset;
0122
0123 switch (reg_width) {
0124 case sizeof(u8): {
0125 const u8 *buf = buffer;
0126
0127 while (count) {
0128 __raw_writeb(*buf, addr);
0129 buf++;
0130 count--;
0131 }
0132 break;
0133 }
0134 case sizeof(u16): {
0135 const __le16 *buf = buffer;
0136
0137 WARN_ON(count & 1);
0138 while (count) {
0139 __raw_writew((__force u16)(*buf), addr);
0140 buf++;
0141 count -= 2;
0142 }
0143 break;
0144 }
0145 case sizeof(u32): {
0146 const __le32 *buf = buffer;
0147
0148 WARN_ON(count & 3);
0149 while (count) {
0150 __raw_writel((__force u32)(*buf), addr);
0151 buf++;
0152 count -= 4;
0153 }
0154 break;
0155 }
0156 default:
0157 WARN_ON(1);
0158 }
0159 }
0160 #endif
0161
0162
0163 const struct ssb_bus_ops ssb_host_soc_ops = {
0164 .read8 = ssb_host_soc_read8,
0165 .read16 = ssb_host_soc_read16,
0166 .read32 = ssb_host_soc_read32,
0167 .write8 = ssb_host_soc_write8,
0168 .write16 = ssb_host_soc_write16,
0169 .write32 = ssb_host_soc_write32,
0170 #ifdef CONFIG_SSB_BLOCKIO
0171 .block_read = ssb_host_soc_block_read,
0172 .block_write = ssb_host_soc_block_write,
0173 #endif
0174 };
0175
0176 int ssb_host_soc_get_invariants(struct ssb_bus *bus,
0177 struct ssb_init_invariants *iv)
0178 {
0179 char buf[20];
0180 int len, err;
0181
0182
0183 memset(&iv->boardinfo, 0, sizeof(struct ssb_boardinfo));
0184
0185 len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
0186 if (len > 0) {
0187 err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
0188 if (err)
0189 pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
0190 buf);
0191 }
0192 if (!iv->boardinfo.vendor)
0193 iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
0194
0195 len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
0196 if (len > 0) {
0197 err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
0198 if (err)
0199 pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
0200 buf);
0201 }
0202
0203 memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
0204 ssb_fill_sprom_with_fallback(bus, &iv->sprom);
0205
0206 if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
0207 iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
0208
0209 return 0;
0210 }