211 lines · c
1/*2 * Sonics Silicon Backplane SoC host related functions.3 * Subsystem core4 *5 * Copyright 2005, Broadcom Corporation6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>7 *8 * Licensed under the GNU/GPL. See COPYING for details.9 */10 11#include "ssb_private.h"12 13#include <linux/bcm47xx_nvram.h>14#include <linux/ssb/ssb.h>15 16static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)17{18 struct ssb_bus *bus = dev->bus;19 20 offset += dev->core_index * SSB_CORE_SIZE;21 return readb(bus->mmio + offset);22}23 24static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)25{26 struct ssb_bus *bus = dev->bus;27 28 offset += dev->core_index * SSB_CORE_SIZE;29 return readw(bus->mmio + offset);30}31 32static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)33{34 struct ssb_bus *bus = dev->bus;35 36 offset += dev->core_index * SSB_CORE_SIZE;37 return readl(bus->mmio + offset);38}39 40#ifdef CONFIG_SSB_BLOCKIO41static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,42 size_t count, u16 offset, u8 reg_width)43{44 struct ssb_bus *bus = dev->bus;45 void __iomem *addr;46 47 offset += dev->core_index * SSB_CORE_SIZE;48 addr = bus->mmio + offset;49 50 switch (reg_width) {51 case sizeof(u8): {52 u8 *buf = buffer;53 54 while (count) {55 *buf = __raw_readb(addr);56 buf++;57 count--;58 }59 break;60 }61 case sizeof(u16): {62 __le16 *buf = buffer;63 64 WARN_ON(count & 1);65 while (count) {66 *buf = (__force __le16)__raw_readw(addr);67 buf++;68 count -= 2;69 }70 break;71 }72 case sizeof(u32): {73 __le32 *buf = buffer;74 75 WARN_ON(count & 3);76 while (count) {77 *buf = (__force __le32)__raw_readl(addr);78 buf++;79 count -= 4;80 }81 break;82 }83 default:84 WARN_ON(1);85 }86}87#endif /* CONFIG_SSB_BLOCKIO */88 89static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)90{91 struct ssb_bus *bus = dev->bus;92 93 offset += dev->core_index * SSB_CORE_SIZE;94 writeb(value, bus->mmio + offset);95}96 97static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)98{99 struct ssb_bus *bus = dev->bus;100 101 offset += dev->core_index * SSB_CORE_SIZE;102 writew(value, bus->mmio + offset);103}104 105static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)106{107 struct ssb_bus *bus = dev->bus;108 109 offset += dev->core_index * SSB_CORE_SIZE;110 writel(value, bus->mmio + offset);111}112 113#ifdef CONFIG_SSB_BLOCKIO114static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,115 size_t count, u16 offset, u8 reg_width)116{117 struct ssb_bus *bus = dev->bus;118 void __iomem *addr;119 120 offset += dev->core_index * SSB_CORE_SIZE;121 addr = bus->mmio + offset;122 123 switch (reg_width) {124 case sizeof(u8): {125 const u8 *buf = buffer;126 127 while (count) {128 __raw_writeb(*buf, addr);129 buf++;130 count--;131 }132 break;133 }134 case sizeof(u16): {135 const __le16 *buf = buffer;136 137 WARN_ON(count & 1);138 while (count) {139 __raw_writew((__force u16)(*buf), addr);140 buf++;141 count -= 2;142 }143 break;144 }145 case sizeof(u32): {146 const __le32 *buf = buffer;147 148 WARN_ON(count & 3);149 while (count) {150 __raw_writel((__force u32)(*buf), addr);151 buf++;152 count -= 4;153 }154 break;155 }156 default:157 WARN_ON(1);158 }159}160#endif /* CONFIG_SSB_BLOCKIO */161 162/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */163const struct ssb_bus_ops ssb_host_soc_ops = {164 .read8 = ssb_host_soc_read8,165 .read16 = ssb_host_soc_read16,166 .read32 = ssb_host_soc_read32,167 .write8 = ssb_host_soc_write8,168 .write16 = ssb_host_soc_write16,169 .write32 = ssb_host_soc_write32,170#ifdef CONFIG_SSB_BLOCKIO171 .block_read = ssb_host_soc_block_read,172 .block_write = ssb_host_soc_block_write,173#endif174};175 176int ssb_host_soc_get_invariants(struct ssb_bus *bus,177 struct ssb_init_invariants *iv)178{179 char buf[20];180 int len, err;181 182 /* Fill boardinfo structure */183 memset(&iv->boardinfo, 0, sizeof(struct ssb_boardinfo));184 185 len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));186 if (len > 0) {187 err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);188 if (err)189 pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",190 buf);191 }192 if (!iv->boardinfo.vendor)193 iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;194 195 len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));196 if (len > 0) {197 err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);198 if (err)199 pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",200 buf);201 }202 203 memset(&iv->sprom, 0, sizeof(struct ssb_sprom));204 ssb_fill_sprom_with_fallback(bus, &iv->sprom);205 206 if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)207 iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);208 209 return 0;210}211