]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/ssb/host_soc.c
Merge tag 'drm-intel-next-fixes-2016-08-05' of git://anongit.freedesktop.org/drm...
[karo-tx-linux.git] / drivers / ssb / host_soc.c
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 <linux/bcm47xx_nvram.h>
12 #include <linux/ssb/ssb.h>
13
14 #include "ssb_private.h"
15
16 static 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
24 static 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
32 static 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
41 static 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                 SSB_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                 SSB_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                 SSB_WARN_ON(1);
85         }
86 }
87 #endif /* CONFIG_SSB_BLOCKIO */
88
89 static 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
97 static 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
105 static 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
114 static 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                 SSB_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                 SSB_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                 SSB_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). */
163 const 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
176 int 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 }