Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/cell/celleb_scc_pciex.c
10818 views
1
/*
2
* Support for Celleb PCI-Express.
3
*
4
* (C) Copyright 2007-2008 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/pci.h>
25
#include <linux/string.h>
26
#include <linux/slab.h>
27
#include <linux/init.h>
28
#include <linux/bootmem.h>
29
#include <linux/delay.h>
30
#include <linux/interrupt.h>
31
32
#include <asm/io.h>
33
#include <asm/irq.h>
34
#include <asm/iommu.h>
35
#include <asm/byteorder.h>
36
37
#include "celleb_scc.h"
38
#include "celleb_pci.h"
39
40
#define PEX_IN(base, off) in_be32((void __iomem *)(base) + (off))
41
#define PEX_OUT(base, off, data) out_be32((void __iomem *)(base) + (off), (data))
42
43
static void scc_pciex_io_flush(struct iowa_bus *bus)
44
{
45
(void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0);
46
}
47
48
/*
49
* Memory space access to device on PCIEX
50
*/
51
#define PCIEX_MMIO_READ(name, ret) \
52
static ret scc_pciex_##name(const PCI_IO_ADDR addr) \
53
{ \
54
ret val = __do_##name(addr); \
55
scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
56
return val; \
57
}
58
59
#define PCIEX_MMIO_READ_STR(name) \
60
static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf, \
61
unsigned long count) \
62
{ \
63
__do_##name(addr, buf, count); \
64
scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
65
}
66
67
PCIEX_MMIO_READ(readb, u8)
68
PCIEX_MMIO_READ(readw, u16)
69
PCIEX_MMIO_READ(readl, u32)
70
PCIEX_MMIO_READ(readq, u64)
71
PCIEX_MMIO_READ(readw_be, u16)
72
PCIEX_MMIO_READ(readl_be, u32)
73
PCIEX_MMIO_READ(readq_be, u64)
74
PCIEX_MMIO_READ_STR(readsb)
75
PCIEX_MMIO_READ_STR(readsw)
76
PCIEX_MMIO_READ_STR(readsl)
77
78
static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
79
unsigned long n)
80
{
81
__do_memcpy_fromio(dest, src, n);
82
scc_pciex_io_flush(iowa_mem_find_bus(src));
83
}
84
85
/*
86
* I/O port access to devices on PCIEX.
87
*/
88
89
static inline unsigned long get_bus_address(struct pci_controller *phb,
90
unsigned long port)
91
{
92
return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE);
93
}
94
95
static u32 scc_pciex_read_port(struct pci_controller *phb,
96
unsigned long port, int size)
97
{
98
unsigned int byte_enable;
99
unsigned int cmd, shift;
100
unsigned long addr;
101
u32 data, ret;
102
103
BUG_ON(((port & 0x3ul) + size) > 4);
104
105
addr = get_bus_address(phb, port);
106
shift = addr & 0x3ul;
107
byte_enable = ((1 << size) - 1) << shift;
108
cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
109
PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
110
PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
111
data = PEX_IN(phb->cfg_addr, PEXDRDATA);
112
ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8));
113
114
pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x,"
115
" cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable,
116
cmd, data, ret);
117
118
return ret;
119
}
120
121
static void scc_pciex_write_port(struct pci_controller *phb,
122
unsigned long port, int size, u32 val)
123
{
124
unsigned int byte_enable;
125
unsigned int cmd, shift;
126
unsigned long addr;
127
u32 data;
128
129
BUG_ON(((port & 0x3ul) + size) > 4);
130
131
addr = get_bus_address(phb, port);
132
shift = addr & 0x3ul;
133
byte_enable = ((1 << size) - 1) << shift;
134
cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
135
data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8);
136
PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
137
PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
138
PEX_OUT(phb->cfg_addr, PEXDWDATA, data);
139
140
pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x,"
141
" be=%x, cmd=%x, data=%x\n", port, addr, size, val,
142
byte_enable, cmd, data);
143
}
144
145
static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port)
146
{
147
return (u8)scc_pciex_read_port(phb, port, 1);
148
}
149
150
static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port)
151
{
152
u32 data;
153
if ((port & 0x3ul) < 3)
154
data = scc_pciex_read_port(phb, port, 2);
155
else {
156
u32 d1 = scc_pciex_read_port(phb, port, 1);
157
u32 d2 = scc_pciex_read_port(phb, port + 1, 1);
158
data = d1 | (d2 << 8);
159
}
160
return (u16)data;
161
}
162
163
static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port)
164
{
165
unsigned int mod = port & 0x3ul;
166
u32 data;
167
if (mod == 0)
168
data = scc_pciex_read_port(phb, port, 4);
169
else {
170
u32 d1 = scc_pciex_read_port(phb, port, 4 - mod);
171
u32 d2 = scc_pciex_read_port(phb, port + 1, mod);
172
data = d1 | (d2 << (mod * 8));
173
}
174
return data;
175
}
176
177
static void __scc_pciex_outb(struct pci_controller *phb,
178
u8 val, unsigned long port)
179
{
180
scc_pciex_write_port(phb, port, 1, (u32)val);
181
}
182
183
static void __scc_pciex_outw(struct pci_controller *phb,
184
u16 val, unsigned long port)
185
{
186
if ((port & 0x3ul) < 3)
187
scc_pciex_write_port(phb, port, 2, (u32)val);
188
else {
189
u32 d1 = val & 0x000000FF;
190
u32 d2 = (val & 0x0000FF00) >> 8;
191
scc_pciex_write_port(phb, port, 1, d1);
192
scc_pciex_write_port(phb, port + 1, 1, d2);
193
}
194
}
195
196
static void __scc_pciex_outl(struct pci_controller *phb,
197
u32 val, unsigned long port)
198
{
199
unsigned int mod = port & 0x3ul;
200
if (mod == 0)
201
scc_pciex_write_port(phb, port, 4, val);
202
else {
203
u32 d1 = val & (0xFFFFFFFFul >> (mod * 8));
204
u32 d2 = val >> ((4 - mod) * 8);
205
scc_pciex_write_port(phb, port, 4 - mod, d1);
206
scc_pciex_write_port(phb, port + 1, mod, d2);
207
}
208
}
209
210
#define PCIEX_PIO_FUNC(size, name) \
211
static u##size scc_pciex_in##name(unsigned long port) \
212
{ \
213
struct iowa_bus *bus = iowa_pio_find_bus(port); \
214
u##size data = __scc_pciex_in##name(bus->phb, port); \
215
scc_pciex_io_flush(bus); \
216
return data; \
217
} \
218
static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \
219
{ \
220
struct iowa_bus *bus = iowa_pio_find_bus(p); \
221
__le##size *dst = b; \
222
for (; c != 0; c--, dst++) \
223
*dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \
224
scc_pciex_io_flush(bus); \
225
} \
226
static void scc_pciex_out##name(u##size val, unsigned long port) \
227
{ \
228
struct iowa_bus *bus = iowa_pio_find_bus(port); \
229
__scc_pciex_out##name(bus->phb, val, port); \
230
} \
231
static void scc_pciex_outs##name(unsigned long p, const void *b, \
232
unsigned long c) \
233
{ \
234
struct iowa_bus *bus = iowa_pio_find_bus(p); \
235
const __le##size *src = b; \
236
for (; c != 0; c--, src++) \
237
__scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \
238
}
239
#define __le8 u8
240
#define cpu_to_le8(x) (x)
241
#define le8_to_cpu(x) (x)
242
PCIEX_PIO_FUNC(8, b)
243
PCIEX_PIO_FUNC(16, w)
244
PCIEX_PIO_FUNC(32, l)
245
246
static struct ppc_pci_io scc_pciex_ops = {
247
.readb = scc_pciex_readb,
248
.readw = scc_pciex_readw,
249
.readl = scc_pciex_readl,
250
.readq = scc_pciex_readq,
251
.readw_be = scc_pciex_readw_be,
252
.readl_be = scc_pciex_readl_be,
253
.readq_be = scc_pciex_readq_be,
254
.readsb = scc_pciex_readsb,
255
.readsw = scc_pciex_readsw,
256
.readsl = scc_pciex_readsl,
257
.memcpy_fromio = scc_pciex_memcpy_fromio,
258
.inb = scc_pciex_inb,
259
.inw = scc_pciex_inw,
260
.inl = scc_pciex_inl,
261
.outb = scc_pciex_outb,
262
.outw = scc_pciex_outw,
263
.outl = scc_pciex_outl,
264
.insb = scc_pciex_insb,
265
.insw = scc_pciex_insw,
266
.insl = scc_pciex_insl,
267
.outsb = scc_pciex_outsb,
268
.outsw = scc_pciex_outsw,
269
.outsl = scc_pciex_outsl,
270
};
271
272
static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data)
273
{
274
dma_addr_t dummy_page_da;
275
void *dummy_page_va;
276
277
dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
278
if (!dummy_page_va) {
279
pr_err("PCIEX:Alloc dummy_page_va failed\n");
280
return -1;
281
}
282
283
dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
284
PAGE_SIZE, DMA_FROM_DEVICE);
285
if (dma_mapping_error(bus->phb->parent, dummy_page_da)) {
286
pr_err("PCIEX:Map dummy page failed.\n");
287
kfree(dummy_page_va);
288
return -1;
289
}
290
291
PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da);
292
293
return 0;
294
}
295
296
/*
297
* config space access
298
*/
299
#define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \
300
((uint32_t)(((addr) & ~0x3UL) | \
301
((bus_no) << PEXDADRS_BUSNO_SHIFT) | \
302
((dev_no) << PEXDADRS_DEVNO_SHIFT) | \
303
((func_no) << PEXDADRS_FUNCNO_SHIFT)))
304
305
#define MK_PEXDCMND_BYTE_EN(addr, size) \
306
((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT)
307
#define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size))
308
309
static uint32_t config_read_pciex_dev(unsigned int __iomem *base,
310
uint64_t bus_no, uint64_t dev_no, uint64_t func_no,
311
uint64_t off, uint64_t size)
312
{
313
uint32_t ret;
314
uint32_t addr, cmd;
315
316
addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
317
cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size);
318
PEX_OUT(base, PEXDADRS, addr);
319
PEX_OUT(base, PEXDCMND, cmd);
320
ret = (PEX_IN(base, PEXDRDATA)
321
>> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1);
322
return ret;
323
}
324
325
static void config_write_pciex_dev(unsigned int __iomem *base, uint64_t bus_no,
326
uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size,
327
uint32_t data)
328
{
329
uint32_t addr, cmd;
330
331
addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
332
cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size);
333
PEX_OUT(base, PEXDADRS, addr);
334
PEX_OUT(base, PEXDCMND, cmd);
335
PEX_OUT(base, PEXDWDATA,
336
(data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8));
337
}
338
339
#define MK_PEXCADRS_BYTE_EN(off, len) \
340
((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT)
341
#define MK_PEXCADRS(cmd, addr, size) \
342
((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3))
343
static uint32_t config_read_pciex_rc(unsigned int __iomem *base,
344
uint32_t where, uint32_t size)
345
{
346
PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size));
347
return (PEX_IN(base, PEXCRDATA)
348
>> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1);
349
}
350
351
static void config_write_pciex_rc(unsigned int __iomem *base, uint32_t where,
352
uint32_t size, uint32_t val)
353
{
354
uint32_t data;
355
356
data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8);
357
PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size));
358
PEX_OUT(base, PEXCWDATA, data);
359
}
360
361
/* Interfaces */
362
/* Note: Work-around
363
* On SCC PCIEXC, one device is seen on all 32 dev_no.
364
* As SCC PCIEXC can have only one device on the bus, we look only one dev_no.
365
* (dev_no = 1)
366
*/
367
static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
368
int where, int size, unsigned int *val)
369
{
370
struct pci_controller *phb = pci_bus_to_host(bus);
371
372
if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) {
373
*val = ~0;
374
return PCIBIOS_DEVICE_NOT_FOUND;
375
}
376
377
if (bus->number == 0 && PCI_SLOT(devfn) == 0)
378
*val = config_read_pciex_rc(phb->cfg_addr, where, size);
379
else
380
*val = config_read_pciex_dev(phb->cfg_addr, bus->number,
381
PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
382
383
return PCIBIOS_SUCCESSFUL;
384
}
385
386
static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
387
int where, int size, unsigned int val)
388
{
389
struct pci_controller *phb = pci_bus_to_host(bus);
390
391
if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1)
392
return PCIBIOS_DEVICE_NOT_FOUND;
393
394
if (bus->number == 0 && PCI_SLOT(devfn) == 0)
395
config_write_pciex_rc(phb->cfg_addr, where, size, val);
396
else
397
config_write_pciex_dev(phb->cfg_addr, bus->number,
398
PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
399
return PCIBIOS_SUCCESSFUL;
400
}
401
402
static struct pci_ops scc_pciex_pci_ops = {
403
scc_pciex_read_config,
404
scc_pciex_write_config,
405
};
406
407
static void pciex_clear_intr_all(unsigned int __iomem *base)
408
{
409
PEX_OUT(base, PEXAERRSTS, 0xffffffff);
410
PEX_OUT(base, PEXPRERRSTS, 0xffffffff);
411
PEX_OUT(base, PEXINTSTS, 0xffffffff);
412
}
413
414
#if 0
415
static void pciex_disable_intr_all(unsigned int *base)
416
{
417
PEX_OUT(base, PEXINTMASK, 0x0);
418
PEX_OUT(base, PEXAERRMASK, 0x0);
419
PEX_OUT(base, PEXPRERRMASK, 0x0);
420
PEX_OUT(base, PEXVDMASK, 0x0);
421
}
422
#endif
423
424
static void pciex_enable_intr_all(unsigned int __iomem *base)
425
{
426
PEX_OUT(base, PEXINTMASK, 0x0000e7f1);
427
PEX_OUT(base, PEXAERRMASK, 0x03ff01ff);
428
PEX_OUT(base, PEXPRERRMASK, 0x0001010f);
429
PEX_OUT(base, PEXVDMASK, 0x00000001);
430
}
431
432
static void pciex_check_status(unsigned int __iomem *base)
433
{
434
uint32_t err = 0;
435
uint32_t intsts, aerr, prerr, rcvcp, lenerr;
436
uint32_t maea, maec;
437
438
intsts = PEX_IN(base, PEXINTSTS);
439
aerr = PEX_IN(base, PEXAERRSTS);
440
prerr = PEX_IN(base, PEXPRERRSTS);
441
rcvcp = PEX_IN(base, PEXRCVCPLIDA);
442
lenerr = PEX_IN(base, PEXLENERRIDA);
443
444
if (intsts || aerr || prerr || rcvcp || lenerr)
445
err = 1;
446
447
pr_info("PCEXC interrupt!!\n");
448
pr_info("PEXINTSTS :0x%08x\n", intsts);
449
pr_info("PEXAERRSTS :0x%08x\n", aerr);
450
pr_info("PEXPRERRSTS :0x%08x\n", prerr);
451
pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp);
452
pr_info("PEXLENERRIDA :0x%08x\n", lenerr);
453
454
/* print detail of Protection Error */
455
if (intsts & 0x00004000) {
456
uint32_t i, n;
457
for (i = 0; i < 4; i++) {
458
n = 1 << i;
459
if (prerr & n) {
460
maea = PEX_IN(base, PEXMAEA(i));
461
maec = PEX_IN(base, PEXMAEC(i));
462
pr_info("PEXMAEC%d :0x%08x\n", i, maec);
463
pr_info("PEXMAEA%d :0x%08x\n", i, maea);
464
}
465
}
466
}
467
468
if (err)
469
pciex_clear_intr_all(base);
470
}
471
472
static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id)
473
{
474
struct pci_controller *phb = dev_id;
475
476
pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq);
477
478
BUG_ON(phb->cfg_addr == NULL);
479
480
pciex_check_status(phb->cfg_addr);
481
482
return IRQ_HANDLED;
483
}
484
485
static __init int celleb_setup_pciex(struct device_node *node,
486
struct pci_controller *phb)
487
{
488
struct resource r;
489
struct of_irq oirq;
490
int virq;
491
492
/* SMMIO registers; used inside this file */
493
if (of_address_to_resource(node, 0, &r)) {
494
pr_err("PCIEXC:Failed to get config resource.\n");
495
return 1;
496
}
497
phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
498
if (!phb->cfg_addr) {
499
pr_err("PCIEXC:Failed to remap SMMIO region.\n");
500
return 1;
501
}
502
503
/* Not use cfg_data, cmd and data regs are near address reg */
504
phb->cfg_data = NULL;
505
506
/* set pci_ops */
507
phb->ops = &scc_pciex_pci_ops;
508
509
/* internal interrupt handler */
510
if (of_irq_map_one(node, 1, &oirq)) {
511
pr_err("PCIEXC:Failed to map irq\n");
512
goto error;
513
}
514
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
515
oirq.size);
516
if (request_irq(virq, pciex_handle_internal_irq,
517
IRQF_DISABLED, "pciex", (void *)phb)) {
518
pr_err("PCIEXC:Failed to request irq\n");
519
goto error;
520
}
521
522
/* enable all interrupts */
523
pciex_clear_intr_all(phb->cfg_addr);
524
pciex_enable_intr_all(phb->cfg_addr);
525
/* MSI: TBD */
526
527
return 0;
528
529
error:
530
phb->cfg_data = NULL;
531
if (phb->cfg_addr)
532
iounmap(phb->cfg_addr);
533
phb->cfg_addr = NULL;
534
return 1;
535
}
536
537
struct celleb_phb_spec celleb_pciex_spec __initdata = {
538
.setup = celleb_setup_pciex,
539
.ops = &scc_pciex_ops,
540
.iowa_init = &scc_pciex_iowa_init,
541
};
542
543