Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / powerpc / platforms / cell / celleb_scc_epci.c
1 /*
2  * Support for SCC external PCI
3  *
4  * (C) Copyright 2004-2007 TOSHIBA CORPORATION
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #undef DEBUG
22
23 #include <linux/kernel.h>
24 #include <linux/threads.h>
25 #include <linux/pci.h>
26 #include <linux/init.h>
27 #include <linux/pci_regs.h>
28
29 #include <asm/io.h>
30 #include <asm/irq.h>
31 #include <asm/prom.h>
32 #include <asm/pci-bridge.h>
33 #include <asm/ppc-pci.h>
34
35 #include "celleb_scc.h"
36 #include "celleb_pci.h"
37
38 #define MAX_PCI_DEVICES   32
39 #define MAX_PCI_FUNCTIONS  8
40
41 #define iob()  __asm__ __volatile__("eieio; sync":::"memory")
42
43 static inline PCI_IO_ADDR celleb_epci_get_epci_base(
44                                         struct pci_controller *hose)
45 {
46         /*
47          * Note:
48          * Celleb epci uses cfg_addr as a base address for
49          * epci control registers.
50          */
51
52         return hose->cfg_addr;
53 }
54
55 static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
56                                         struct pci_controller *hose)
57 {
58         /*
59          * Note:
60          * Celleb epci uses cfg_data as a base address for
61          * configuration area for epci devices.
62          */
63
64         return hose->cfg_data;
65 }
66
67 static inline void clear_and_disable_master_abort_interrupt(
68                                         struct pci_controller *hose)
69 {
70         PCI_IO_ADDR epci_base;
71         PCI_IO_ADDR reg;
72         epci_base = celleb_epci_get_epci_base(hose);
73         reg = epci_base + PCI_COMMAND;
74         out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
75 }
76
77 static int celleb_epci_check_abort(struct pci_controller *hose,
78                                    PCI_IO_ADDR addr)
79 {
80         PCI_IO_ADDR reg;
81         PCI_IO_ADDR epci_base;
82         u32 val;
83
84         iob();
85         epci_base = celleb_epci_get_epci_base(hose);
86
87         reg = epci_base + PCI_COMMAND;
88         val = in_be32(reg);
89
90         if (val & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
91                 out_be32(reg,
92                          (val & 0xffff) | (PCI_STATUS_REC_MASTER_ABORT << 16));
93
94                 /* clear PCI Controller error, FRE, PMFE */
95                 reg = epci_base + SCC_EPCI_STATUS;
96                 out_be32(reg, SCC_EPCI_INT_PAI);
97
98                 reg = epci_base + SCC_EPCI_VCSR;
99                 val = in_be32(reg) & 0xffff;
100                 val |= SCC_EPCI_VCSR_FRE;
101                 out_be32(reg, val);
102
103                 reg = epci_base + SCC_EPCI_VISTAT;
104                 out_be32(reg, SCC_EPCI_VISTAT_PMFE);
105                 return PCIBIOS_DEVICE_NOT_FOUND;
106         }
107
108         return PCIBIOS_SUCCESSFUL;
109 }
110
111 static PCI_IO_ADDR celleb_epci_make_config_addr(struct pci_bus *bus,
112                 struct pci_controller *hose, unsigned int devfn, int where)
113 {
114         PCI_IO_ADDR addr;
115
116         if (bus != hose->bus)
117                 addr = celleb_epci_get_epci_cfg(hose) +
118                        (((bus->number & 0xff) << 16)
119                         | ((devfn & 0xff) << 8)
120                         | (where & 0xff)
121                         | 0x01000000);
122         else
123                 addr = celleb_epci_get_epci_cfg(hose) +
124                        (((devfn & 0xff) << 8) | (where & 0xff));
125
126         pr_debug("EPCI: config_addr = 0x%p\n", addr);
127
128         return addr;
129 }
130
131 static int celleb_epci_read_config(struct pci_bus *bus,
132                         unsigned int devfn, int where, int size, u32 *val)
133 {
134         PCI_IO_ADDR epci_base;
135         PCI_IO_ADDR addr;
136         struct pci_controller *hose = pci_bus_to_host(bus);
137
138         /* allignment check */
139         BUG_ON(where % size);
140
141         if (!celleb_epci_get_epci_cfg(hose))
142                 return PCIBIOS_DEVICE_NOT_FOUND;
143
144         if (bus->number == hose->first_busno && devfn == 0) {
145                 /* EPCI controller self */
146
147                 epci_base = celleb_epci_get_epci_base(hose);
148                 addr = epci_base + where;
149
150                 switch (size) {
151                 case 1:
152                         *val = in_8(addr);
153                         break;
154                 case 2:
155                         *val = in_be16(addr);
156                         break;
157                 case 4:
158                         *val = in_be32(addr);
159                         break;
160                 default:
161                         return PCIBIOS_DEVICE_NOT_FOUND;
162                 }
163
164         } else {
165
166                 clear_and_disable_master_abort_interrupt(hose);
167                 addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
168
169                 switch (size) {
170                 case 1:
171                         *val = in_8(addr);
172                         break;
173                 case 2:
174                         *val = in_le16(addr);
175                         break;
176                 case 4:
177                         *val = in_le32(addr);
178                         break;
179                 default:
180                         return PCIBIOS_DEVICE_NOT_FOUND;
181                 }
182         }
183
184         pr_debug("EPCI: "
185                  "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
186                  addr, devfn, where, size, *val);
187
188         return celleb_epci_check_abort(hose, NULL);
189 }
190
191 static int celleb_epci_write_config(struct pci_bus *bus,
192                         unsigned int devfn, int where, int size, u32 val)
193 {
194         PCI_IO_ADDR epci_base;
195         PCI_IO_ADDR addr;
196         struct pci_controller *hose = pci_bus_to_host(bus);
197
198         /* allignment check */
199         BUG_ON(where % size);
200
201         if (!celleb_epci_get_epci_cfg(hose))
202                 return PCIBIOS_DEVICE_NOT_FOUND;
203
204         if (bus->number == hose->first_busno && devfn == 0) {
205                 /* EPCI controller self */
206
207                 epci_base = celleb_epci_get_epci_base(hose);
208                 addr = epci_base + where;
209
210                 switch (size) {
211                 case 1:
212                         out_8(addr, val);
213                         break;
214                 case 2:
215                         out_be16(addr, val);
216                         break;
217                 case 4:
218                         out_be32(addr, val);
219                         break;
220                 default:
221                         return PCIBIOS_DEVICE_NOT_FOUND;
222                 }
223
224         } else {
225
226                 clear_and_disable_master_abort_interrupt(hose);
227                 addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
228
229                 switch (size) {
230                 case 1:
231                         out_8(addr, val);
232                         break;
233                 case 2:
234                         out_le16(addr, val);
235                         break;
236                 case 4:
237                         out_le32(addr, val);
238                         break;
239                 default:
240                         return PCIBIOS_DEVICE_NOT_FOUND;
241                 }
242         }
243
244         return celleb_epci_check_abort(hose, addr);
245 }
246
247 struct pci_ops celleb_epci_ops = {
248         .read = celleb_epci_read_config,
249         .write = celleb_epci_write_config,
250 };
251
252 /* to be moved in FW */
253 static int __init celleb_epci_init(struct pci_controller *hose)
254 {
255         u32 val;
256         PCI_IO_ADDR reg;
257         PCI_IO_ADDR epci_base;
258         int hwres = 0;
259
260         epci_base = celleb_epci_get_epci_base(hose);
261
262         /* PCI core reset(Internal bus and PCI clock) */
263         reg = epci_base + SCC_EPCI_CKCTRL;
264         val = in_be32(reg);
265         if (val == 0x00030101)
266                 hwres = 1;
267         else {
268                 val &= ~(SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
269                 out_be32(reg, val);
270
271                 /* set PCI core clock */
272                 val = in_be32(reg);
273                 val |= (SCC_EPCI_CKCTRL_OCLKEN | SCC_EPCI_CKCTRL_LCLKEN);
274                 out_be32(reg, val);
275
276                 /* release PCI core reset (internal bus) */
277                 val = in_be32(reg);
278                 val |= SCC_EPCI_CKCTRL_CRST0;
279                 out_be32(reg, val);
280
281                 /* set PCI clock select */
282                 reg = epci_base + SCC_EPCI_CLKRST;
283                 val = in_be32(reg);
284                 val &= ~SCC_EPCI_CLKRST_CKS_MASK;
285                 val |= SCC_EPCI_CLKRST_CKS_2;
286                 out_be32(reg, val);
287
288                 /* set arbiter */
289                 reg = epci_base + SCC_EPCI_ABTSET;
290                 out_be32(reg, 0x0f1f001f);      /* temporary value */
291
292                 /* buffer on */
293                 reg = epci_base + SCC_EPCI_CLKRST;
294                 val = in_be32(reg);
295                 val |= SCC_EPCI_CLKRST_BC;
296                 out_be32(reg, val);
297
298                 /* PCI clock enable */
299                 val = in_be32(reg);
300                 val |= SCC_EPCI_CLKRST_PCKEN;
301                 out_be32(reg, val);
302
303                 /* release PCI core reset (all) */
304                 reg = epci_base + SCC_EPCI_CKCTRL;
305                 val = in_be32(reg);
306                 val |= (SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
307                 out_be32(reg, val);
308
309                 /* set base translation registers. (already set by Beat) */
310
311                 /* set base address masks. (already set by Beat) */
312         }
313
314         /* release interrupt masks and clear all interrupts */
315         reg = epci_base + SCC_EPCI_INTSET;
316         out_be32(reg, 0x013f011f);      /* all interrupts enable */
317         reg = epci_base + SCC_EPCI_VIENAB;
318         val = SCC_EPCI_VIENAB_PMPEE | SCC_EPCI_VIENAB_PMFEE;
319         out_be32(reg, val);
320         reg = epci_base + SCC_EPCI_STATUS;
321         out_be32(reg, 0xffffffff);
322         reg = epci_base + SCC_EPCI_VISTAT;
323         out_be32(reg, 0xffffffff);
324
325         /* disable PCI->IB address translation */
326         reg = epci_base + SCC_EPCI_VCSR;
327         val = in_be32(reg);
328         val &= ~(SCC_EPCI_VCSR_DR | SCC_EPCI_VCSR_AT);
329         out_be32(reg, val);
330
331         /* set base addresses. (no need to set?) */
332
333         /* memory space, bus master enable */
334         reg = epci_base + PCI_COMMAND;
335         val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
336         out_be32(reg, val);
337
338         /* endian mode setup */
339         reg = epci_base + SCC_EPCI_ECMODE;
340         val = 0x00550155;
341         out_be32(reg, val);
342
343         /* set control option */
344         reg = epci_base + SCC_EPCI_CNTOPT;
345         val = in_be32(reg);
346         val |= SCC_EPCI_CNTOPT_O2PMB;
347         out_be32(reg, val);
348
349         /* XXX: temporay: set registers for address conversion setup */
350         reg = epci_base + SCC_EPCI_CNF10_REG;
351         out_be32(reg, 0x80000008);
352         reg = epci_base + SCC_EPCI_CNF14_REG;
353         out_be32(reg, 0x40000008);
354
355         reg = epci_base + SCC_EPCI_BAM0;
356         out_be32(reg, 0x80000000);
357         reg = epci_base + SCC_EPCI_BAM1;
358         out_be32(reg, 0xe0000000);
359
360         reg = epci_base + SCC_EPCI_PVBAT;
361         out_be32(reg, 0x80000000);
362
363         if (!hwres) {
364                 /* release external PCI reset */
365                 reg = epci_base + SCC_EPCI_CLKRST;
366                 val = in_be32(reg);
367                 val |= SCC_EPCI_CLKRST_PCIRST;
368                 out_be32(reg, val);
369         }
370
371         return 0;
372 }
373
374 static int __init celleb_setup_epci(struct device_node *node,
375                                     struct pci_controller *hose)
376 {
377         struct resource r;
378
379         pr_debug("PCI: celleb_setup_epci()\n");
380
381         /*
382          * Note:
383          * Celleb epci uses cfg_addr and cfg_data member of
384          * pci_controller structure in irregular way.
385          *
386          * cfg_addr is used to map for control registers of
387          * celleb epci.
388          *
389          * cfg_data is used for configuration area of devices
390          * on Celleb epci buses.
391          */
392
393         if (of_address_to_resource(node, 0, &r))
394                 goto error;
395         hose->cfg_addr = ioremap(r.start, resource_size(&r));
396         if (!hose->cfg_addr)
397                 goto error;
398         pr_debug("EPCI: cfg_addr map 0x%016llx->0x%016lx + 0x%016llx\n",
399                  r.start, (unsigned long)hose->cfg_addr, resource_size(&r));
400
401         if (of_address_to_resource(node, 2, &r))
402                 goto error;
403         hose->cfg_data = ioremap(r.start, resource_size(&r));
404         if (!hose->cfg_data)
405                 goto error;
406         pr_debug("EPCI: cfg_data map 0x%016llx->0x%016lx + 0x%016llx\n",
407                  r.start, (unsigned long)hose->cfg_data, resource_size(&r));
408
409         hose->ops = &celleb_epci_ops;
410         celleb_epci_init(hose);
411
412         return 0;
413
414 error:
415         if (hose->cfg_addr)
416                 iounmap(hose->cfg_addr);
417
418         if (hose->cfg_data)
419                 iounmap(hose->cfg_data);
420         return 1;
421 }
422
423 struct celleb_phb_spec celleb_epci_spec __initdata = {
424         .setup = celleb_setup_epci,
425         .ops = &spiderpci_ops,
426         .iowa_init = &spiderpci_iowa_init,
427         .iowa_data = (void *)0,
428 };