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