Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
host_soc.c
Go to the documentation of this file.
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 
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  */
170  if (!bus->mmio)
171  return -ENOMEM;
172 
173  /* Host specific */
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 }