brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · 3b43848 Raw
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