1830c7df4SRafał Miłecki /* 2830c7df4SRafał Miłecki * Sonics Silicon Backplane SoC host related functions. 3830c7df4SRafał Miłecki * Subsystem core 4830c7df4SRafał Miłecki * 5830c7df4SRafał Miłecki * Copyright 2005, Broadcom Corporation 6830c7df4SRafał Miłecki * Copyright 2006, 2007, Michael Buesch <m@bues.ch> 7830c7df4SRafał Miłecki * 8830c7df4SRafał Miłecki * Licensed under the GNU/GPL. See COPYING for details. 9830c7df4SRafał Miłecki */ 10830c7df4SRafał Miłecki 11*541c9a84SRafał Miłecki #include <linux/bcm47xx_nvram.h> 12830c7df4SRafał Miłecki #include <linux/ssb/ssb.h> 13830c7df4SRafał Miłecki 14830c7df4SRafał Miłecki #include "ssb_private.h" 15830c7df4SRafał Miłecki 16830c7df4SRafał Miłecki static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset) 17830c7df4SRafał Miłecki { 18830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 19830c7df4SRafał Miłecki 20830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 21830c7df4SRafał Miłecki return readb(bus->mmio + offset); 22830c7df4SRafał Miłecki } 23830c7df4SRafał Miłecki 24830c7df4SRafał Miłecki static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset) 25830c7df4SRafał Miłecki { 26830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 27830c7df4SRafał Miłecki 28830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 29830c7df4SRafał Miłecki return readw(bus->mmio + offset); 30830c7df4SRafał Miłecki } 31830c7df4SRafał Miłecki 32830c7df4SRafał Miłecki static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset) 33830c7df4SRafał Miłecki { 34830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 35830c7df4SRafał Miłecki 36830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 37830c7df4SRafał Miłecki return readl(bus->mmio + offset); 38830c7df4SRafał Miłecki } 39830c7df4SRafał Miłecki 40830c7df4SRafał Miłecki #ifdef CONFIG_SSB_BLOCKIO 41830c7df4SRafał Miłecki static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer, 42830c7df4SRafał Miłecki size_t count, u16 offset, u8 reg_width) 43830c7df4SRafał Miłecki { 44830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 45830c7df4SRafał Miłecki void __iomem *addr; 46830c7df4SRafał Miłecki 47830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 48830c7df4SRafał Miłecki addr = bus->mmio + offset; 49830c7df4SRafał Miłecki 50830c7df4SRafał Miłecki switch (reg_width) { 51830c7df4SRafał Miłecki case sizeof(u8): { 52830c7df4SRafał Miłecki u8 *buf = buffer; 53830c7df4SRafał Miłecki 54830c7df4SRafał Miłecki while (count) { 55830c7df4SRafał Miłecki *buf = __raw_readb(addr); 56830c7df4SRafał Miłecki buf++; 57830c7df4SRafał Miłecki count--; 58830c7df4SRafał Miłecki } 59830c7df4SRafał Miłecki break; 60830c7df4SRafał Miłecki } 61830c7df4SRafał Miłecki case sizeof(u16): { 62830c7df4SRafał Miłecki __le16 *buf = buffer; 63830c7df4SRafał Miłecki 64830c7df4SRafał Miłecki SSB_WARN_ON(count & 1); 65830c7df4SRafał Miłecki while (count) { 66830c7df4SRafał Miłecki *buf = (__force __le16)__raw_readw(addr); 67830c7df4SRafał Miłecki buf++; 68830c7df4SRafał Miłecki count -= 2; 69830c7df4SRafał Miłecki } 70830c7df4SRafał Miłecki break; 71830c7df4SRafał Miłecki } 72830c7df4SRafał Miłecki case sizeof(u32): { 73830c7df4SRafał Miłecki __le32 *buf = buffer; 74830c7df4SRafał Miłecki 75830c7df4SRafał Miłecki SSB_WARN_ON(count & 3); 76830c7df4SRafał Miłecki while (count) { 77830c7df4SRafał Miłecki *buf = (__force __le32)__raw_readl(addr); 78830c7df4SRafał Miłecki buf++; 79830c7df4SRafał Miłecki count -= 4; 80830c7df4SRafał Miłecki } 81830c7df4SRafał Miłecki break; 82830c7df4SRafał Miłecki } 83830c7df4SRafał Miłecki default: 84830c7df4SRafał Miłecki SSB_WARN_ON(1); 85830c7df4SRafał Miłecki } 86830c7df4SRafał Miłecki } 87830c7df4SRafał Miłecki #endif /* CONFIG_SSB_BLOCKIO */ 88830c7df4SRafał Miłecki 89830c7df4SRafał Miłecki static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value) 90830c7df4SRafał Miłecki { 91830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 92830c7df4SRafał Miłecki 93830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 94830c7df4SRafał Miłecki writeb(value, bus->mmio + offset); 95830c7df4SRafał Miłecki } 96830c7df4SRafał Miłecki 97830c7df4SRafał Miłecki static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value) 98830c7df4SRafał Miłecki { 99830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 100830c7df4SRafał Miłecki 101830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 102830c7df4SRafał Miłecki writew(value, bus->mmio + offset); 103830c7df4SRafał Miłecki } 104830c7df4SRafał Miłecki 105830c7df4SRafał Miłecki static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value) 106830c7df4SRafał Miłecki { 107830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 108830c7df4SRafał Miłecki 109830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 110830c7df4SRafał Miłecki writel(value, bus->mmio + offset); 111830c7df4SRafał Miłecki } 112830c7df4SRafał Miłecki 113830c7df4SRafał Miłecki #ifdef CONFIG_SSB_BLOCKIO 114830c7df4SRafał Miłecki static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer, 115830c7df4SRafał Miłecki size_t count, u16 offset, u8 reg_width) 116830c7df4SRafał Miłecki { 117830c7df4SRafał Miłecki struct ssb_bus *bus = dev->bus; 118830c7df4SRafał Miłecki void __iomem *addr; 119830c7df4SRafał Miłecki 120830c7df4SRafał Miłecki offset += dev->core_index * SSB_CORE_SIZE; 121830c7df4SRafał Miłecki addr = bus->mmio + offset; 122830c7df4SRafał Miłecki 123830c7df4SRafał Miłecki switch (reg_width) { 124830c7df4SRafał Miłecki case sizeof(u8): { 125830c7df4SRafał Miłecki const u8 *buf = buffer; 126830c7df4SRafał Miłecki 127830c7df4SRafał Miłecki while (count) { 128830c7df4SRafał Miłecki __raw_writeb(*buf, addr); 129830c7df4SRafał Miłecki buf++; 130830c7df4SRafał Miłecki count--; 131830c7df4SRafał Miłecki } 132830c7df4SRafał Miłecki break; 133830c7df4SRafał Miłecki } 134830c7df4SRafał Miłecki case sizeof(u16): { 135830c7df4SRafał Miłecki const __le16 *buf = buffer; 136830c7df4SRafał Miłecki 137830c7df4SRafał Miłecki SSB_WARN_ON(count & 1); 138830c7df4SRafał Miłecki while (count) { 139830c7df4SRafał Miłecki __raw_writew((__force u16)(*buf), addr); 140830c7df4SRafał Miłecki buf++; 141830c7df4SRafał Miłecki count -= 2; 142830c7df4SRafał Miłecki } 143830c7df4SRafał Miłecki break; 144830c7df4SRafał Miłecki } 145830c7df4SRafał Miłecki case sizeof(u32): { 146830c7df4SRafał Miłecki const __le32 *buf = buffer; 147830c7df4SRafał Miłecki 148830c7df4SRafał Miłecki SSB_WARN_ON(count & 3); 149830c7df4SRafał Miłecki while (count) { 150830c7df4SRafał Miłecki __raw_writel((__force u32)(*buf), addr); 151830c7df4SRafał Miłecki buf++; 152830c7df4SRafał Miłecki count -= 4; 153830c7df4SRafał Miłecki } 154830c7df4SRafał Miłecki break; 155830c7df4SRafał Miłecki } 156830c7df4SRafał Miłecki default: 157830c7df4SRafał Miłecki SSB_WARN_ON(1); 158830c7df4SRafał Miłecki } 159830c7df4SRafał Miłecki } 160830c7df4SRafał Miłecki #endif /* CONFIG_SSB_BLOCKIO */ 161830c7df4SRafał Miłecki 162830c7df4SRafał Miłecki /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ 163830c7df4SRafał Miłecki const struct ssb_bus_ops ssb_host_soc_ops = { 164830c7df4SRafał Miłecki .read8 = ssb_host_soc_read8, 165830c7df4SRafał Miłecki .read16 = ssb_host_soc_read16, 166830c7df4SRafał Miłecki .read32 = ssb_host_soc_read32, 167830c7df4SRafał Miłecki .write8 = ssb_host_soc_write8, 168830c7df4SRafał Miłecki .write16 = ssb_host_soc_write16, 169830c7df4SRafał Miłecki .write32 = ssb_host_soc_write32, 170830c7df4SRafał Miłecki #ifdef CONFIG_SSB_BLOCKIO 171830c7df4SRafał Miłecki .block_read = ssb_host_soc_block_read, 172830c7df4SRafał Miłecki .block_write = ssb_host_soc_block_write, 173830c7df4SRafał Miłecki #endif 174830c7df4SRafał Miłecki }; 175*541c9a84SRafał Miłecki 176*541c9a84SRafał Miłecki int ssb_host_soc_get_invariants(struct ssb_bus *bus, 177*541c9a84SRafał Miłecki struct ssb_init_invariants *iv) 178*541c9a84SRafał Miłecki { 179*541c9a84SRafał Miłecki char buf[20]; 180*541c9a84SRafał Miłecki int len, err; 181*541c9a84SRafał Miłecki 182*541c9a84SRafał Miłecki /* Fill boardinfo structure */ 183*541c9a84SRafał Miłecki memset(&iv->boardinfo, 0, sizeof(struct ssb_boardinfo)); 184*541c9a84SRafał Miłecki 185*541c9a84SRafał Miłecki len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf)); 186*541c9a84SRafał Miłecki if (len > 0) { 187*541c9a84SRafał Miłecki err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor); 188*541c9a84SRafał Miłecki if (err) 189*541c9a84SRafał Miłecki pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n", 190*541c9a84SRafał Miłecki buf); 191*541c9a84SRafał Miłecki } 192*541c9a84SRafał Miłecki if (!iv->boardinfo.vendor) 193*541c9a84SRafał Miłecki iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; 194*541c9a84SRafał Miłecki 195*541c9a84SRafał Miłecki len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf)); 196*541c9a84SRafał Miłecki if (len > 0) { 197*541c9a84SRafał Miłecki err = kstrtou16(strim(buf), 0, &iv->boardinfo.type); 198*541c9a84SRafał Miłecki if (err) 199*541c9a84SRafał Miłecki pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n", 200*541c9a84SRafał Miłecki buf); 201*541c9a84SRafał Miłecki } 202*541c9a84SRafał Miłecki 203*541c9a84SRafał Miłecki memset(&iv->sprom, 0, sizeof(struct ssb_sprom)); 204*541c9a84SRafał Miłecki ssb_fill_sprom_with_fallback(bus, &iv->sprom); 205*541c9a84SRafał Miłecki 206*541c9a84SRafał Miłecki if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) 207*541c9a84SRafał Miłecki iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); 208*541c9a84SRafał Miłecki 209*541c9a84SRafał Miłecki return 0; 210*541c9a84SRafał Miłecki } 211