123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- * Sonics Silicon Backplane SoC host related functions.
- * Subsystem core
- *
- * Copyright 2005, Broadcom Corporation
- * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
- */
- #include "ssb_private.h"
- #include <linux/bcm47xx_nvram.h>
- #include <linux/ssb/ssb.h>
- static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
- {
- struct ssb_bus *bus = dev->bus;
- offset += dev->core_index * SSB_CORE_SIZE;
- return readb(bus->mmio + offset);
- }
- static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
- {
- struct ssb_bus *bus = dev->bus;
- offset += dev->core_index * SSB_CORE_SIZE;
- return readw(bus->mmio + offset);
- }
- static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
- {
- struct ssb_bus *bus = dev->bus;
- offset += dev->core_index * SSB_CORE_SIZE;
- return readl(bus->mmio + offset);
- }
- #ifdef CONFIG_SSB_BLOCKIO
- static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
- size_t count, u16 offset, u8 reg_width)
- {
- struct ssb_bus *bus = dev->bus;
- void __iomem *addr;
- offset += dev->core_index * SSB_CORE_SIZE;
- addr = bus->mmio + offset;
- switch (reg_width) {
- case sizeof(u8): {
- u8 *buf = buffer;
- while (count) {
- *buf = __raw_readb(addr);
- buf++;
- count--;
- }
- break;
- }
- case sizeof(u16): {
- __le16 *buf = buffer;
- WARN_ON(count & 1);
- while (count) {
- *buf = (__force __le16)__raw_readw(addr);
- buf++;
- count -= 2;
- }
- break;
- }
- case sizeof(u32): {
- __le32 *buf = buffer;
- WARN_ON(count & 3);
- while (count) {
- *buf = (__force __le32)__raw_readl(addr);
- buf++;
- count -= 4;
- }
- break;
- }
- default:
- WARN_ON(1);
- }
- }
- #endif /* CONFIG_SSB_BLOCKIO */
- static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
- {
- struct ssb_bus *bus = dev->bus;
- offset += dev->core_index * SSB_CORE_SIZE;
- writeb(value, bus->mmio + offset);
- }
- static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
- {
- struct ssb_bus *bus = dev->bus;
- offset += dev->core_index * SSB_CORE_SIZE;
- writew(value, bus->mmio + offset);
- }
- static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
- {
- struct ssb_bus *bus = dev->bus;
- offset += dev->core_index * SSB_CORE_SIZE;
- writel(value, bus->mmio + offset);
- }
- #ifdef CONFIG_SSB_BLOCKIO
- static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
- size_t count, u16 offset, u8 reg_width)
- {
- struct ssb_bus *bus = dev->bus;
- void __iomem *addr;
- offset += dev->core_index * SSB_CORE_SIZE;
- addr = bus->mmio + offset;
- switch (reg_width) {
- case sizeof(u8): {
- const u8 *buf = buffer;
- while (count) {
- __raw_writeb(*buf, addr);
- buf++;
- count--;
- }
- break;
- }
- case sizeof(u16): {
- const __le16 *buf = buffer;
- WARN_ON(count & 1);
- while (count) {
- __raw_writew((__force u16)(*buf), addr);
- buf++;
- count -= 2;
- }
- break;
- }
- case sizeof(u32): {
- const __le32 *buf = buffer;
- WARN_ON(count & 3);
- while (count) {
- __raw_writel((__force u32)(*buf), addr);
- buf++;
- count -= 4;
- }
- break;
- }
- default:
- WARN_ON(1);
- }
- }
- #endif /* CONFIG_SSB_BLOCKIO */
- /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
- const struct ssb_bus_ops ssb_host_soc_ops = {
- .read8 = ssb_host_soc_read8,
- .read16 = ssb_host_soc_read16,
- .read32 = ssb_host_soc_read32,
- .write8 = ssb_host_soc_write8,
- .write16 = ssb_host_soc_write16,
- .write32 = ssb_host_soc_write32,
- #ifdef CONFIG_SSB_BLOCKIO
- .block_read = ssb_host_soc_block_read,
- .block_write = ssb_host_soc_block_write,
- #endif
- };
- int ssb_host_soc_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv)
- {
- char buf[20];
- int len, err;
- /* Fill boardinfo structure */
- memset(&iv->boardinfo, 0, sizeof(struct ssb_boardinfo));
- len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
- if (len > 0) {
- err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
- if (err)
- pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
- buf);
- }
- if (!iv->boardinfo.vendor)
- iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
- len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
- if (len > 0) {
- err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
- if (err)
- pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
- buf);
- }
- memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
- ssb_fill_sprom_with_fallback(bus, &iv->sprom);
- if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
- iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
- return 0;
- }
|