1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  HT7520 (Golem) Bridge Support			File: dev_ht7520.c
5    *
6    *********************************************************************
7    *
8    *  Copyright 2002,2003
9    *  Broadcom Corporation. All rights reserved.
10    *
11    *  This software is furnished under license and may be used and
12    *  copied only in accordance with the following terms and
13    *  conditions.  Subject to these conditions, you may download,
14    *  copy, install, use, modify and distribute modified or unmodified
15    *  copies of this software in source and/or binary form.  No title
16    *  or ownership is transferred hereby.
17    *
18    *  1) Any source code used, modified or distributed must reproduce
19    *     and retain this copyright notice and list of conditions
20    *     as they appear in the source file.
21    *
22    *  2) No right is granted to use any trade name, trademark, or
23    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
24    *     name may not be used to endorse or promote products derived
25    *     from this software without the prior written permission of
26    *     Broadcom Corporation.
27    *
28    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
29    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
30    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
31    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
32    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
33    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
34    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
37    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
38    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
40    *     THE POSSIBILITY OF SUCH DAMAGE.
41    ********************************************************************* */
42
43#include "lib_types.h"
44#include "lib_physio.h"
45
46#include "pcireg.h"
47#include "pcivar.h"
48#include "pci_internal.h"
49
50extern int eoi_implemented;
51
52void ht7520apic_preset (pcitag_t tag);
53void ht7520apic_setup (pcitag_t tag);
54
55
56/* PLX HT7520 (LDT to PCI-X bridge + APIC) specific definitions */
57
58#define	PCI_VENDOR_AMD			0x1022
59#define PCI_PRODUCT_PLX_HT7520		0x7450
60#define PCI_PRODUCT_PLX_HT7520_APIC	0x7451
61
62/* HT7520 specific registers */
63
64/* APIC configuration registers */
65
66#define APIC_CONTROL_REG                0x0044
67
68#define APIC_CONTROL_OSVISBAR           (1 << 0)
69#define APIC_CONTROL_IOAEN              (1 << 1)
70
71#define APIC_BASE_ADDR_REG              0x0048
72
73/* APIC registers in BAR0 memory space */
74
75#define HT7520_APIC_INDEX_REG           0x0000
76#define HT7520_APIC_DATA_REG            0x0010
77
78#define APIC_ID_INDEX                   0x00
79#define APIC_VERSION_INDEX              0x01
80#define APIC_ARBID_INDEX                0x02
81#define APIC_RDR_BASE_INDEX             0x10
82#define APIC_RDR_LO_INDEX(n)            (APIC_RDR_BASE_INDEX + 2*(n))
83#define APIC_RDR_HI_INDEX(n)            (APIC_RDR_BASE_INDEX + 2*(n) + 1)
84
85#define RDR_HI_DEST_SHIFT               (56-32)
86#define RDR_HI_DEST_MASK                (0xff << RDR_HI_DEST_SHIFT)
87#define RDR_LO_IM                       (1 << 16)
88#define RDR_LO_TM                       (1 << 15)
89#define RDR_LO_IRR                      (1 << 14)
90#define RDR_LO_POL                      (1 << 13)
91#define RDR_LO_DS                       (1 << 12)
92#define RDR_LO_DM                       (1 << 11)
93#define RDR_LO_MT_SHIFT                 8
94#define RDR_LO_MT_MASK                  (3 << RDR_LO_MT_SHIFT)
95#define RDR_LO_IV_SHIFT                 0
96#define RDR_LO_IV_MASK                  (0xff << RDR_LO_IV_SHIFT)
97
98void
99ht7520apic_preset (pcitag_t tag)
100{
101    pcireg_t ctrl;
102
103    /* For some reason, BAR0 (necessary for setting the interrupt
104       mapping) is hidden by default; the following makes it
105       visible. */
106    ctrl = pci_conf_read(tag, APIC_CONTROL_REG);
107    ctrl |= APIC_CONTROL_IOAEN | APIC_CONTROL_OSVISBAR;
108    pci_conf_write(tag, APIC_CONTROL_REG, ctrl);
109    ctrl = pci_conf_read(tag, APIC_CONTROL_REG);   /* push */
110}
111
112void
113ht7520apic_setup (pcitag_t tag)
114{
115    int port, bus, device, function;
116    pcitag_t br_tag;
117    int secondary;
118    struct pci_bus *pb;
119    unsigned offset;
120    phys_addr_t apic_addr;
121    unsigned int iv;
122    uint32_t rdrh, rdrl;
123    int i;
124
125    /* The HT7520 splits the bridge and APIC functionality between two
126       functions.  The following code depends upon a known
127       relationship between the bridge and APIC tags, with a temporary
128       fudge for the simulator.  NB: We assume that the bridge
129       function has already been initialized. */
130
131    pci_break_tag(tag, &port, &bus, &device, &function);
132
133#ifdef _FUNCSIM_
134    br_tag = pci_make_tag(port, bus, device-2, 0);
135#else
136    br_tag = pci_make_tag(port, bus, device, function-1);
137#endif
138    secondary = (pci_conf_read(br_tag, PPB_BUSINFO_REG) >> 8) & 0xff;
139    pb = pci_businfo(port, secondary);
140
141    /* Set up interrupt mappings. */
142    pci_map_mem(tag, PCI_MAPREG(0), PCI_MATCH_BITS, &apic_addr);
143
144    offset = pb->inta_shift % 4;
145    for (i = 0; i < 4; i++) {
146	iv = pci_int_line(offset+1);   /* PCI_INTA = 1, etc. */
147	phys_write32(apic_addr + HT7520_APIC_INDEX_REG, APIC_RDR_HI_INDEX(i));
148	rdrh = 0x01 << RDR_HI_DEST_SHIFT;        /* CPU 0 */
149	phys_write32(apic_addr + HT7520_APIC_DATA_REG, rdrh);
150	rdrh = phys_read32(apic_addr + HT7520_APIC_DATA_REG);  /* push */
151
152	phys_write32(apic_addr + HT7520_APIC_INDEX_REG, APIC_RDR_LO_INDEX(i));
153	if (eoi_implemented) {
154	    /* Passes >=2 have working EOI. Trigger=Level */
155	    rdrl = (RDR_LO_TM |                      /* Level */
156		    RDR_LO_POL |                     /* Active Low */
157		    RDR_LO_DM |                      /* Logical */
158		    0x0 << RDR_LO_MT_SHIFT |         /* Fixed */
159		    iv << RDR_LO_IV_SHIFT);          /* Vector */
160	} else {
161	    /* Pass 1 lacks working EOI. Trigger=Edge.  Note that
162	       LO_POL appears mis-documented for edges.  */
163	    rdrl = (RDR_LO_DM |                      /* Logical */
164		    0x0 << RDR_LO_MT_SHIFT |         /* Fixed */
165		    iv << RDR_LO_IV_SHIFT);          /* Vector */
166	}
167	phys_write32(apic_addr + HT7520_APIC_DATA_REG, rdrl);
168	offset = (offset + 1) % 4;
169    }
170}
171