PageRenderTime 116ms CodeModel.GetById 22ms app.highlight 70ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/powerpc/platforms/cell/celleb_scc_pciex.c

https://bitbucket.org/cresqo/cm7-p500-kernel
C | 541 lines | 426 code | 74 blank | 41 comment | 47 complexity | a503fb477c72f1ff1e5c57a2136317d7 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  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
 43static 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)					\
 52static 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)					\
 60static 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
 67PCIEX_MMIO_READ(readb, u8)
 68PCIEX_MMIO_READ(readw, u16)
 69PCIEX_MMIO_READ(readl, u32)
 70PCIEX_MMIO_READ(readq, u64)
 71PCIEX_MMIO_READ(readw_be, u16)
 72PCIEX_MMIO_READ(readl_be, u32)
 73PCIEX_MMIO_READ(readq_be, u64)
 74PCIEX_MMIO_READ_STR(readsb)
 75PCIEX_MMIO_READ_STR(readsw)
 76PCIEX_MMIO_READ_STR(readsl)
 77
 78static 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
 89static 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
 95static 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
121static 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
145static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port)
146{
147	return (u8)scc_pciex_read_port(phb, port, 1);
148}
149
150static 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
163static 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
177static 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
183static 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
196static 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)					\
211static 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}									\
218static 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}									\
226static 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}									\
231static 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)
242PCIEX_PIO_FUNC(8, b)
243PCIEX_PIO_FUNC(16, w)
244PCIEX_PIO_FUNC(32, l)
245
246static 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
272static 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
309static 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
325static 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))
343static 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
351static 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 */
367static 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
386static 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
402static struct pci_ops scc_pciex_pci_ops = {
403	scc_pciex_read_config,
404	scc_pciex_write_config,
405};
406
407static 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
415static 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
424static 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
432static 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
472static 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
485static __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
529error:
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
537struct 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};