Linux Audio

Check our new training course

Loading...
v5.9
  1/*
  2 * Sonics Silicon Backplane SoC host related functions.
  3 * Subsystem core
  4 *
  5 * Copyright 2005, Broadcom Corporation
  6 * 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_BLOCKIO
 41static 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_BLOCKIO
114static 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_BLOCKIO
171	.block_read	= ssb_host_soc_block_read,
172	.block_write	= ssb_host_soc_block_write,
173#endif
174};
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}
v6.8
  1/*
  2 * Sonics Silicon Backplane SoC host related functions.
  3 * Subsystem core
  4 *
  5 * Copyright 2005, Broadcom Corporation
  6 * 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_BLOCKIO
 41static 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_BLOCKIO
114static 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_BLOCKIO
171	.block_read	= ssb_host_soc_block_read,
172	.block_write	= ssb_host_soc_block_write,
173#endif
174};
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}