1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  PPC Board Support Package: PCI         File: mpc824x_pci_machdep.c
5    *
6    *  Author:  Ed Satterthwaite
7    *
8    *********************************************************************
9    *
10    *  Copyright 2004
11    *  Broadcom Corporation. All rights reserved.
12    *
13    *  This software is furnished under license and may be used and
14    *  copied only in accordance with the following terms and
15    *  conditions.  Subject to these conditions, you may download,
16    *  copy, install, use, modify and distribute modified or unmodified
17    *  copies of this software in source and/or binary form.  No title
18    *  or ownership is transferred hereby.
19    *
20    *  1) Any source code used, modified or distributed must reproduce
21    *     and retain this copyright notice and list of conditions
22    *     as they appear in the source file.
23    *
24    *  2) No right is granted to use any trade name, trademark, or
25    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
26    *     name may not be used to endorse or promote products derived
27    *     from this software without the prior written permission of
28    *     Broadcom Corporation.
29    *
30    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
31    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
32    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
33    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
34    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
35    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
36    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
40    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
42    *     THE POSSIBILITY OF SUCH DAMAGE.
43    ********************************************************************* */
44
45/*
46 * MPC824x machine-specific functions for PCI autoconfiguration.
47 */
48
49#include "lib_types.h"
50#include "lib_printf.h"
51#include "lib_string.h"
52#include "cfe_timer.h"
53
54#include "bsp_config.h"
55
56#include "endian.h"
57#include "addrspace.h"
58
59#include "ppcdefs.h"
60#include "mpc824x.h"
61
62#include "pcivar.h"
63#include "pci_internal.h"
64#include "pcireg.h"
65
66#if ((ENDIAN_BIG + ENDIAN_LITTLE) != 1)
67#error "mpc824x_pci_machdep: system endian not set"
68#endif
69
70extern int _pciverbose;
71
72const cons_t pci_optnames[] = {
73    {"verbose", PCI_FLG_VERBOSE},
74    {NULL, 0}
75};
76
77/* Templates for bus attributes. */
78
79static const struct pci_bus init_pci_bus = {
80	0,		/* minimum grant */
81	255,		/* maximum latency */
82	0,		/* devsel time = unknown */
83	0,		/* configure fast back-to-back */
84	0,		/* we don't prefetch */
85	0,		/* configure 66 MHz */
86	0,		/* we don't support 64 bits */
87	4000000,	/* bandwidth: in 0.25us cycles / sec */
88	0,		/* initially no devices on bus */
89};
90
91#define MAXBUS	10
92static struct pci_bus _pci_bus[MAXBUS];
93static int _pci_nbus = 0;
94
95#define PCI_MAKE_TAG(b,d,f) \
96    (((b) << 16) | ((d) << 11) | ((f) << 8))
97
98
99/* PCI spaces as seen by the CPU in Host mode (Table 3-1). */
100
101/* Core regions allocated for mapping to PCI address spaces. */
102#define MPC824X_PCI_MEM_SPACE       0x80000000
103#define MPC824X_PCI_MEM_SPACE_SIZE  0x7D000000
104#define MPC824X_PCI_IO_SPACE        0xFE800000
105#define MPC824X_PCI_IO_SPACE_SIZE   0x00400000
106
107/* PCI regions mapped from the core addresses. */
108#define MPC824X_PCI_MEM_BASE        0x80000000
109#define MPC824X_PCI_IO_BASE         0x00800000
110
111/* Window on configuration registers */
112#define MPC824X_CONFIG_ADDR         0xFEC00000
113#define MPC824X_CONFIG_DATA         0xFEE00000
114
115#define MPC824X_PCI_ENABLE          0x80000000
116
117
118/* The following should return the index of the last usable bus port. */
119int
120pci_maxport (void)
121{
122    return PCI_HOST_PORTS - 1;
123}
124
125
126/* The following must either fail or return the next sequential bus
127   number to make secondary/subordinate numbering work correctly. */
128int
129pci_nextbus (int port)
130{
131    int bus = _pci_nbus;
132
133    if (bus >= MAXBUS)
134	return -1;
135    _pci_nbus++;
136    return bus;
137}
138
139int
140pci_maxbus (int port)
141{
142    return _pci_nbus - 1;
143}
144
145struct pci_bus *
146pci_businfo (int port, int bus)
147{
148    return (bus < _pci_nbus ? &_pci_bus[bus] : NULL);
149}
150
151/*
152 * PCI address resources.
153 * NB: initial limits for address allocation are assumed to be aligned
154 * appropriately for PCI bridges (4K boundaries for I/O, 1M for memory).
155 */
156
157pcireg_t
158pci_minmemaddr (int port)
159{
160    return MPC824X_PCI_MEM_BASE;
161}
162
163pcireg_t
164pci_maxmemaddr (int port)
165{
166    return MPC824X_PCI_MEM_BASE + MPC824X_PCI_MEM_SPACE_SIZE;
167}
168
169pcireg_t
170pci_minioaddr (int port)
171{
172    return MPC824X_PCI_IO_BASE;
173}
174
175pcireg_t
176pci_maxioaddr (int port)
177{
178    return MPC824X_PCI_IO_BASE + MPC824X_PCI_IO_SPACE_SIZE;
179}
180
181
182/* The PCI core (a host bridge in Host mode) */
183
184#define PPC_PCI_BRIDGE     (PCI_MAKE_TAG(0,0,0))
185
186/* Called to initialise the host bridge at the beginning of time. */
187static void
188phb_init (void)
189{
190    pcireg_t csr;
191
192    /* stop the servicing of any further PCI */
193    pci_conf_write(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, 0);
194    cfe_usleep(100);
195
196    /* XXX set up PMCR2, arbiter, PICR1 */
197
198    /* enable bridge to PCI and PCI memory accesses, including
199       write-invalidate, plus error handling */
200    csr = PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE |
201          PCI_COMMAND_INVALIDATE_ENABLE |
202          PCI_COMMAND_SERR_ENABLE |  PCI_COMMAND_PARITY_ENABLE;
203    pci_conf_write(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, csr);
204
205    /* clear errors */
206    csr = pci_conf_read(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG);
207    csr |= PCI_STATUS_PARITY_ERROR | PCI_STATUS_SYSTEM_ERROR |
208           PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT |
209           PCI_STATUS_TARGET_TARGET_ABORT | PCI_STATUS_PARITY_DETECT;
210    pci_conf_write(PPC_PCI_BRIDGE, PCI_COMMAND_STATUS_REG, csr);
211
212    (void)pci_conf_read(PPC_PCI_BRIDGE, PCI_ID_REG);   /* push */
213}
214
215
216int
217pci_hwinit (int port, pci_flags_t flags)
218{
219    int i;
220
221    /* Enable the internal arbiter.  PARK_LAST apparently locks the bus
222       when there is no response. */
223    /* XXX TBD, currently done in cpu init. */
224
225    memcpy(&_pci_bus[_pci_nbus], &init_pci_bus, sizeof(struct pci_bus));
226    _pci_bus[_pci_nbus].port = port;
227    _pci_nbus++;
228    for (i = _pci_nbus; i < MAXBUS; i++)
229	memcpy(&_pci_bus[i], &init_pci_bus, sizeof(struct pci_bus));
230
231    cfe_sleep(CFE_HZ/2);                /* let devices initialize */
232
233    phb_init();
234    return 0;
235}
236
237/* Called to update the host bridge after we've scanned each PCI
238   device and know what is possible. */
239void
240pci_hwreinit (int port, pci_flags_t flags)
241{
242}
243
244
245/* The following functions provide for device-specific setup required
246   during configuration.  There is nothing host-specific about them,
247   and it would be better to do the packaging and registration in a
248   more modular way. */
249
250/* Dispatch functions for device pre- and post-configuration hooks. */
251
252/* Called for each hostbridge, to discover and scan secondary buses */
253void
254pci_businit_hostbridge (pcitag_t tag, pci_flags_t flags)
255{
256}
257
258/* Called for each function prior to assigning PCI resources.  */
259int
260pci_device_preset (pcitag_t tag)
261{
262    /* Check for a host bridge seen internally, in which case
263       we don't want to allocate any address space for its BARs. */
264
265    return (tag == PPC_PCI_BRIDGE ? 1 : 0);
266}
267
268
269/* Called for each non-bridge (Type 0) function after assigning the
270   BAR and InterruptLine resources. */
271void
272pci_device_setup (pcitag_t tag)
273{
274}
275
276/* Called for each bridge (Type 1) function after configuring the
277   secondary bus, to allow device-specific initialization. */
278void
279pci_bridge_setup (pcitag_t tag, pci_flags_t flags)
280{
281}
282
283
284/* Machine dependent access primitives and utility functions */
285
286void
287pci_flush (void)
288{
289}
290
291
292pcitag_t
293pci_make_tag (int port, int bus, int device, int function)
294{
295    return PCI_MAKE_TAG(bus, device, function);
296}
297
298void
299pci_break_tag (pcitag_t tag,
300	       int *portp, int *busp, int *devicep, int *functionp)
301{
302    if (portp) *portp = 0;
303    if (busp) *busp = (tag >> 16) & PCI_BUSMAX;
304    if (devicep) *devicep = (tag >> 11) & PCI_DEVMAX;
305    if (functionp) *functionp = (tag >> 8) & PCI_FUNCMAX;
306}
307
308
309/* Read/write access to PCI configuration registers.  Type0 addresses
310   are used for bus 0, with a unary encoding of IDSEL in which device
311   n is mapped to AD bit n except that device 10 is mapped to bit 31
312   (21 possible possible devices, 10..30).  The host bridge itself
313   is mapped internally to bus 0, device 0. */
314
315int
316pci_canscan (pcitag_t tag)
317{
318    int bus, device, function;
319
320    pci_break_tag(tag, NULL, &bus, &device, &function);
321    if (bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX)
322	return 0;
323
324    return 1;
325}
326
327int
328pci_probe_tag(pcitag_t tag)
329{
330    pcireg_t data;
331
332    if (!pci_canscan(tag))
333	return 0;
334
335    data = pci_conf_read(tag, PCI_ID_REG);  /* bus error if no response */
336
337    /* if it returned all vendor id bits set, it's not a device */
338    return (PCI_VENDOR(data) != 0xffff);
339}
340
341
342pcireg_t
343pci_conf_read(pcitag_t tag, int reg)
344{
345    pcireg_t data;
346    uint32_t cfg;
347    uint32_t addr = MPC824X_PCI_ENABLE | tag | reg;
348
349#if ENDIAN_BIG
350    __asm __volatile ("\
351	addis  %0,0,0xfec0  \t\n \
352	stwbrx %2,0,%0      \t\n \
353	sync                \t\n \
354	addis  %0,0,0xfee0  \t\n \
355	lwbrx  %1,0,%0      \t\n \
356	sync  " :
357      "=r&" (cfg), "=r" (data) : "r" (addr));
358#else
359    __asm __volatile ("\
360	addis  %0,0,0xfec0  \n\t \
361	stw    %2,0(%0)     \n\t \
362	sync                \n\t \
363	addis  %0,0,0xfee0  \n\t \
364	lw     %1,0(%0)     \n\t \
365	sync  " :
366      "=&r" (cfg), "=r" (data) : "r" (addr));
367#endif
368
369    return data;
370}
371
372void
373pci_conf_write(pcitag_t tag, int reg, pcireg_t data)
374{
375    uint32_t addr = MPC824X_PCI_ENABLE | tag | reg;
376    uint32_t cfg;
377
378#if ENDIAN_BIG
379    __asm __volatile ("\
380	addis  %0,0,0xfec0  \t\n \
381	stwbrx %2,0,%0      \t\n \
382	sync                \t\n \
383	addis  %0,0,0xfee0  \t\n \
384	stwbrx %1,0,%0      \t\n \
385	sync  " :
386      "=&r" (cfg) : "r" (data), "r" (addr));
387#else
388    __asm __volatile ("\
389	addis  %0,0,0xfec0  \n\t \
390	stw    %2,0(%0)     \n\t \
391	sync                \n\t \
392	addis  %0,0,0xfee0  \n\t \
393	stw    %1,0(%0)     \n\t \
394	sync  " :
395      "=&r" (cfg) : "r" (data), "r" (addr));
396#endif
397}
398
399int
400pci_conf_write_acked(pcitag_t tag, int reg, pcireg_t data)
401{
402    pci_conf_write(tag, reg, data);
403    (void) pci_conf_read(tag, reg);
404    return 1;
405}
406
407
408int
409pci_map_io(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap)
410{
411    pcireg_t address;
412    phys_addr_t pa;
413
414#if ENDIAN_BIG
415    if (endian == PCI_MATCH_BITS) {
416	if (_pciverbose != 0)
417	    pci_tagprintf(tag, "pci_map_io: attempt to use MATCH BITS mode\n");
418	return -1;
419    }
420#endif
421
422    if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {
423	if (_pciverbose != 0)
424	    pci_tagprintf(tag, "pci_map_io: bad request\n");
425	return -1;
426    }
427
428    address = pci_conf_read(tag, reg);
429
430    if ((address & PCI_MAPREG_TYPE_IO) == 0) {
431	if (_pciverbose != 0)
432	    pci_tagprintf(tag, "pci_map_io: attempt to i/o map a memory region\n");
433	return -1;
434    }
435
436    pa = ((address & PCI_MAPREG_IO_ADDR_MASK) - MPC824X_PCI_IO_BASE)
437         + MPC824X_PCI_IO_SPACE;
438    *pap = pa;
439    return 0;
440}
441
442int
443pci_map_mem(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap)
444{
445    pcireg_t address;
446    phys_addr_t pa;
447
448#if ENDIAN_BIG
449    if (endian == PCI_MATCH_BITS) {
450	if (_pciverbose != 0)
451	    pci_tagprintf(tag, "pci_map_mem: attempt to use MATCH BITS mode\n");
452	return -1;
453    }
454#endif
455
456    if (reg == PCI_MAPREG_ROM) {
457	/* expansion ROM */
458	address = pci_conf_read(tag, reg);
459	if ((address & PCI_MAPREG_ROM_ENABLE) == 0) {
460	    pci_tagprintf(tag, "pci_map_mem: attempt to map missing rom\n");
461	    return -1;
462	    }
463	pa = address & PCI_MAPREG_ROM_ADDR_MASK;
464	}
465    else {
466	if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {
467	    if (_pciverbose != 0)
468		pci_tagprintf(tag, "pci_map_mem: bad request\n");
469	    return -1;
470	    }
471
472	address = pci_conf_read(tag, reg);
473
474	if ((address & PCI_MAPREG_TYPE_IO) != 0) {
475	    if (_pciverbose != 0)
476		pci_tagprintf(tag, "pci_map_mem: attempt to memory map an I/O region\n");
477	    return -1;
478	    }
479
480	pa = address & PCI_MAPREG_MEM_ADDR_MASK;
481
482	switch (address & PCI_MAPREG_MEM_TYPE_MASK) {
483	    case PCI_MAPREG_MEM_TYPE_32BIT:
484	    case PCI_MAPREG_MEM_TYPE_32BIT_1M:
485		break;
486	    case PCI_MAPREG_MEM_TYPE_64BIT:
487		if (reg + 4 < PCI_MAPREG_END)
488#if 0  /* XXX check for all zeros at reg+4 */
489		    pa |= ((phys_addr_t)pci_conf_read(tag, reg+4) << 32);
490#else
491		    ;
492#endif
493		else {
494		    if (_pciverbose != 0)
495			pci_tagprintf(tag, "pci_map_mem: bad 64-bit reguest\n");
496		    return -1;
497		    }
498		break;
499	    default:
500		if (_pciverbose != 0)
501		    pci_tagprintf(tag, "pci_map_mem: reserved mapping type\n");
502		return -1;
503	    }
504	}
505
506    pa = (pa - MPC824X_PCI_MEM_BASE) + MPC824X_PCI_MEM_SPACE;
507    *pap = pa;
508    return 0;
509}
510
511
512/* ISA-style i/o access (not supported) */
513
514uint8_t
515inb (unsigned int port)
516{
517    xprintf("inb: i/o regions not supported\n");
518    return 0xFF;
519}
520
521uint16_t
522inw (unsigned int port)
523{
524    xprintf("inw: i/o regions not supported\n");
525    return 0xFFFF;
526}
527
528uint32_t
529inl (unsigned int port)
530{
531    xprintf("inl: i/o regions not supported\n");
532    return 0xFFFFFFFF;
533}
534
535void
536outb (unsigned int port, uint8_t val)
537{
538    xprintf("outb: i/o regions not supported\n");
539}
540
541void
542outw (unsigned int port, uint16_t val)
543{
544    xprintf("outw: i/o regions not supported\n");
545}
546
547void
548outl (unsigned int port, uint32_t val)
549{
550    xprintf("outl: i/o regions not supported\n");
551}
552
553
554/* Map PCI interrupts A, B, C, D into the index in the IRQ vector, or
555   0xff if none.  This makes assumptions about both the CPLD and the
556   programming of the EPIC. */
557uint8_t
558pci_int_line(uint8_t pci_int)
559{
560    return pci_int;
561}
562