1ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens/*
2ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * Broadcom specific AMBA
3ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * System on Chip (SoC) Host
4ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens *
5ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens * Licensed under the GNU/GPL. See COPYING for details.
6ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens */
7ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
8ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include "bcma_private.h"
9ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include "scan.h"
10ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include <linux/bcma/bcma.h>
11ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#include <linux/bcma/bcma_soc.h>
12ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
13ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
14ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
15ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	return readb(core->io_addr + offset);
16ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
17ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
18ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
19ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
20ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	return readw(core->io_addr + offset);
21ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
22ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
23ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
24ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
25ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	return readl(core->io_addr + offset);
26ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
27ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
28ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
29ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens				 u8 value)
30ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
31ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	writeb(value, core->io_addr + offset);
32ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
33ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
34ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
35ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens				 u16 value)
36ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
37ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	writew(value, core->io_addr + offset);
38ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
39ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
40ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
41ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens				 u32 value)
42ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
43ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	writel(value, core->io_addr + offset);
44ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
45ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
46ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#ifdef CONFIG_BCMA_BLOCKIO
47ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
48ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens				     size_t count, u16 offset, u8 reg_width)
49ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
50ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	void __iomem *addr = core->io_addr + offset;
51ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
52ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	switch (reg_width) {
53ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	case sizeof(u8): {
54ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		u8 *buf = buffer;
55ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
56ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		while (count) {
57ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			*buf = __raw_readb(addr);
58ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			buf++;
59ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			count--;
60ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		}
61ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		break;
62ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
63ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	case sizeof(u16): {
64ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		__le16 *buf = buffer;
65ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
66ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		WARN_ON(count & 1);
67ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		while (count) {
68ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			*buf = (__force __le16)__raw_readw(addr);
69ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			buf++;
70ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			count -= 2;
71ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		}
72ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		break;
73ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
74ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	case sizeof(u32): {
75ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		__le32 *buf = buffer;
76ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
77ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		WARN_ON(count & 3);
78ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		while (count) {
79ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			*buf = (__force __le32)__raw_readl(addr);
80ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			buf++;
81ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			count -= 4;
82ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		}
83ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		break;
84ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
85ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	default:
86ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		WARN_ON(1);
87ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
88ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
89ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
90ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_block_write(struct bcma_device *core,
91ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens				      const void *buffer,
92ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens				      size_t count, u16 offset, u8 reg_width)
93ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
94ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	void __iomem *addr = core->io_addr + offset;
95ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
96ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	switch (reg_width) {
97ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	case sizeof(u8): {
98ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		const u8 *buf = buffer;
99ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
100ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		while (count) {
101ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			__raw_writeb(*buf, addr);
102ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			buf++;
103ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			count--;
104ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		}
105ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		break;
106ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
107ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	case sizeof(u16): {
108ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		const __le16 *buf = buffer;
109ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
110ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		WARN_ON(count & 1);
111ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		while (count) {
112ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			__raw_writew((__force u16)(*buf), addr);
113ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			buf++;
114ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			count -= 2;
115ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		}
116ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		break;
117ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
118ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	case sizeof(u32): {
119ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		const __le32 *buf = buffer;
120ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
121ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		WARN_ON(count & 3);
122ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		while (count) {
123ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			__raw_writel((__force u32)(*buf), addr);
124ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			buf++;
125ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens			count -= 4;
126ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		}
127ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		break;
128ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
129ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	default:
130ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		WARN_ON(1);
131ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	}
132ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
133ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#endif /* CONFIG_BCMA_BLOCKIO */
134ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
135ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
136ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
137ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	return readl(core->io_wrap + offset);
138ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
139ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
140ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensstatic void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
141ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens				  u32 value)
142ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
143ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	writel(value, core->io_wrap + offset);
144ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
145ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
146ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensconst struct bcma_host_ops bcma_host_soc_ops = {
147ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.read8		= bcma_host_soc_read8,
148ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.read16		= bcma_host_soc_read16,
149ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.read32		= bcma_host_soc_read32,
150ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.write8		= bcma_host_soc_write8,
151ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.write16	= bcma_host_soc_write16,
152ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.write32	= bcma_host_soc_write32,
153ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#ifdef CONFIG_BCMA_BLOCKIO
154ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.block_read	= bcma_host_soc_block_read,
155ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.block_write	= bcma_host_soc_block_write,
156ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens#endif
157ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.aread32	= bcma_host_soc_aread32,
158ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	.awrite32	= bcma_host_soc_awrite32,
159ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens};
160ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
161ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtensint __init bcma_host_soc_register(struct bcma_soc *soc)
162ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens{
163ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	struct bcma_bus *bus = &soc->bus;
164ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	int err;
165ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
166ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	/* iomap only first core. We have to read some register on this core
167ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	 * to scan the bus.
168ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	 */
169ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
170ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	if (!bus->mmio)
171ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		return -ENOMEM;
172ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
173ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	/* Host specific */
174ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	bus->hosttype = BCMA_HOSTTYPE_SOC;
175ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	bus->ops = &bcma_host_soc_ops;
176ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
177ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	/* Register */
178ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
179ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	if (err)
180ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens		iounmap(bus->mmio);
181ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens
182ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens	return err;
183ecd177c21640e92b059a71139f5850243a8f0942Hauke Mehrtens}
184