source: src/linux/pb42/linux-2.6.34.6/arch/mips/pci/pci-ar7100.c @ 15773

Last change on this file since 15773 was 15773, checked in by BrainSlayer, 3 years ago

AR7242 support with RGMII phy

File size: 8.3 KB
Line 
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/types.h>
4#include <linux/irq.h>
5#include <linux/interrupt.h>
6#include <linux/pci.h>
7#include <linux/cpumask.h>
8#include <linux/delay.h>
9#include <linux/ath9k_platform.h>
10
11#include <asm/delay.h>
12
13#define ag7100_delay1s()    mdelay(1000);
14
15#include "ar7100.h"
16
17
18static int ar71xx_pci_fixup_enable;
19
20/*
21 * Support for Ar7100 pci interrupt and core pci initialization
22 */
23/*
24 * PCI interrupts.
25 * roughly the interrupts flow is:
26 *
27 * - save flags
28 * - CLI (disable all)
29 * - IC->ack (mask out the source)
30 * - EI (enable all, except the source that was masked of course)
31 * - action (ISR)
32 * - IC->enable (unmask the source)
33 *
34 * The reason we have a separate PCI IC is beacause of the following:
35 * If we dont, then Throughout the "action" of a PCI slot, the
36 * entire PCI "IP" on the cpu will remain disabled. Which means that we cant
37 * prioritize between PCI interrupts. Normally this should be ok, if all PCI
38 * interrupts are considered equal. However, creating a PCI IC gives
39 * the flexibility to prioritize.
40 */
41
42static void
43ar7100_pci_irq_enable(unsigned int irq)
44{
45    ar7100_reg_rmw_set(AR7100_PCI_INT_MASK,
46                       (1 << (irq - AR7100_PCI_IRQ_BASE)));
47}
48
49static void
50ar7100_pci_irq_disable(unsigned int irq)
51{
52    ar7100_reg_rmw_clear(AR7100_PCI_INT_MASK,
53                       (1 << (irq - AR7100_PCI_IRQ_BASE)));
54}
55
56static unsigned int
57ar7100_pci_irq_startup(unsigned int irq)
58{
59        ar7100_pci_irq_enable(irq);
60        return 0;
61}
62
63static void
64ar7100_pci_irq_shutdown(unsigned int irq)
65{
66        ar7100_pci_irq_disable(irq);
67}
68
69static void
70ar7100_pci_irq_ack(unsigned int irq)
71{
72        ar7100_pci_irq_disable(irq);
73}
74
75static void
76ar7100_pci_irq_end(unsigned int irq)
77{
78        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
79                ar7100_pci_irq_enable(irq);
80}
81
82static int
83ar7100_pci_irq_set_affinity(unsigned int irq, const struct cpumask *mask)
84{
85        /*
86     * Only 1 CPU; ignore affinity request
87     */
88     return 0;
89}
90
91static struct irq_chip ar7100_pci_irq_chip = {
92        .name           = "AR7100 PCI ",
93        .mask           = ar7100_pci_irq_disable,
94        .unmask         = ar7100_pci_irq_enable,
95        .mask_ack       = ar7100_pci_irq_disable,
96};
97
98
99void
100ar7100_pci_irq_init(int irq_base)
101{
102        int i;
103
104        for (i = irq_base; i < irq_base + AR7100_PCI_IRQ_COUNT; i++) {
105                irq_desc[i].status = IRQ_DISABLED;
106                set_irq_chip_and_handler(i, &ar7100_pci_irq_chip,
107                                         handle_level_irq);
108        }
109}
110
111/*
112 * init the pci controller
113 */
114
115static struct resource ar7100_io_resource = {
116        .name           = "PCI IO space",
117        .start          = 0x0000,
118        .end            = 0,
119        .flags          = IORESOURCE_IO,
120};
121
122static struct resource ar7100_mem_resource = {
123        .name           = "PCI memory space",
124        .start          = AR7100_PCI_MEM_BASE,
125        .end            = AR7100_PCI_MEM_BASE + AR7100_PCI_WINDOW - 1,
126        .flags          = IORESOURCE_MEM
127};
128
129extern struct pci_ops ar7100_pci_ops;
130
131static struct pci_controller ar7100_pci_controller = {
132        .pci_ops            = &ar7100_pci_ops,
133        .mem_resource   = &ar7100_mem_resource,
134        .io_resource    = &ar7100_io_resource,
135};
136
137
138irqreturn_t
139ar7100_pci_core_intr(int cpl, void *dev_id)
140{
141        printk("PCI error intr\n");
142        ar7100_check_error(1);
143
144        return IRQ_HANDLED;
145}
146
147/*
148 * We want a 1:1 mapping between PCI and DDR for inbound and outbound.
149 * The PCI<---AHB decoding works as follows:
150 *
151 * 8 registers in the DDR unit provide software configurable 32 bit offsets
152 * for each of the eight 16MB PCI windows in the 128MB. The offsets will be
153 * added to any address in the 16MB segment before being sent to the PCI unit.
154 *
155 * Essentially  for any AHB address generated by the CPU,
156 * 1. the MSB  four bits are stripped off, [31:28],
157 * 2. Bit 27 is used to decide between the lower 128Mb (PCI) or the rest of
158 *    the AHB space
159 * 3. Bits 26:24 are used to access one of the 8 window registers and are
160 *    masked off.
161 * 4. If it is a PCI address, then the WINDOW offset in the WINDOW register
162 *    corresponding to the next 3 bits (bit 26:24) is ADDED to the address,
163 *    to generate the address to PCI unit.
164 *
165 *     eg. CPU address = 0x100000ff
166 *         window 0 offset = 0x10000000
167 *         This points to lowermost 16MB window in PCI space.
168 *         So the resulting address would be 0x000000ff+0x10000000
169 *         = 0x100000ff
170 *
171 *         eg2. CPU address = 0x120000ff
172 *         WINDOW 2 offset = 0x12000000
173 *         resulting address would be 0x000000ff+0x12000000
174 *                         = 0x120000ff
175 *
176 * There is no translation for inbound access (PCI device as a master)
177 */
178static void ar71xx_pci_fixup(struct pci_dev *dev)
179{
180        u32 t;
181
182        if (!ar71xx_pci_fixup_enable)
183                return;
184               
185
186        if (dev->bus->number != 0 || dev->devfn != 0)
187                return;
188
189
190        /* setup COMMAND register */
191        t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
192          | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK;
193
194        pci_write_config_word(dev, PCI_COMMAND, t);
195}
196DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ar71xx_pci_fixup);
197 
198static void *getCalData(int slot)
199{
200u8 *base;
201for (base=(u8 *) KSEG1ADDR(0x1f000000);base<KSEG1ADDR (0x1fff0000);base+=0x1000) {
202    u32 *cal = (u32 *)base;
203    if (*cal==0xa55a0000 || *cal==0x5aa50000) { //protection bit is always zero on inflash devices, so we can use for match it
204        if (slot) {
205            base+=0x4000;
206            }
207        printk(KERN_INFO "found calibration data for slot %d on 0x%08X\n",slot,base);
208        return base;
209        }
210    }
211return NULL;
212}
213static struct ath9k_platform_data wmac_data[2];
214
215static void ath_pci_fixup(struct pci_dev *dev)
216{
217        void __iomem *mem;
218        u16 *cal_data = NULL;
219        u16 cmd;
220        u32 bar0;
221        u32 val;
222
223        if (!ar71xx_pci_fixup_enable)
224                return;
225
226        switch (PCI_SLOT(dev->devfn)) {
227        case 0:
228                cal_data = (u16 *)getCalData(0);
229                if (cal_data) {
230                memcpy(wmac_data[0].eeprom_data,cal_data,sizeof(wmac_data[0].eeprom_data));
231                dev->dev.platform_data = &wmac_data[0];
232                }
233                break;
234        case 1:
235                cal_data = (u16 *)getCalData(1);
236                if (cal_data) {
237                memcpy(wmac_data[1].eeprom_data,cal_data,sizeof(wmac_data[1].eeprom_data));
238                dev->dev.platform_data = &wmac_data[1];
239                }
240                break;
241        default:
242                return;
243        }
244        if (!cal_data) {
245                printk(KERN_INFO "no in flash calibration fata found, no fix required\n");
246                return;
247        }
248       
249        mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000);
250        if (!mem) {
251                printk(KERN_ERR "PCI: ioremap error for device %s\n",
252                       pci_name(dev));
253                return;
254        }
255
256        printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev));
257
258        pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
259
260        /* Setup the PCI device to allow access to the internal registers */
261        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, AR71XX_PCI_MEM_BASE);
262        pci_read_config_word(dev, PCI_COMMAND, &cmd);
263        cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
264        pci_write_config_word(dev, PCI_COMMAND, cmd);
265
266        /* set pointer to first reg address */
267        cal_data += 3;
268        while (*cal_data != 0xffff) {
269                u32 reg;
270                reg = *cal_data++;
271                val = *cal_data++;
272                val |= (*cal_data++) << 16;
273
274                __raw_writel(val, mem + reg);
275                udelay(100);
276        }
277
278        pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
279        dev->vendor = val & 0xffff;
280        dev->device = (val >> 16) & 0xffff;
281
282        pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
283        dev->revision = val & 0xff;
284        dev->class = val >> 8; /* upper 3 bytes */
285
286        pci_read_config_word(dev, PCI_COMMAND, &cmd);
287        cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
288        pci_write_config_word(dev, PCI_COMMAND, cmd);
289
290        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
291
292        iounmap(mem);
293        return;
294}
295DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath_pci_fixup);
296 
297static int __init ar7100_pcibios_init(void)
298{
299        uint32_t cmd;
300
301        ar7100_reg_rmw_set(AR7100_RESET,
302                        (AR7100_RESET_PCI_BUS|AR7100_RESET_PCI_CORE));
303        ag7100_delay1s();
304
305        ar7100_reg_rmw_clear(AR7100_RESET,
306                        (AR7100_RESET_PCI_BUS|AR7100_RESET_PCI_CORE));
307        ag7100_delay1s();
308
309        ar7100_write_pci_window(0);
310        ar7100_write_pci_window(1);
311        ar7100_write_pci_window(2);
312        ar7100_write_pci_window(3);
313        ar7100_write_pci_window(4);
314        ar7100_write_pci_window(5);
315        ar7100_write_pci_window(6);
316        ar7100_write_pci_window(7);
317
318        ag7100_delay1s();
319
320
321        cmd = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE |
322                PCI_COMMAND_PARITY|PCI_COMMAND_SERR|PCI_COMMAND_FAST_BACK;
323
324        ar7100_local_write_config(PCI_COMMAND, 4, cmd);
325
326        /*
327         * clear any lingering errors and register core error IRQ
328         */
329        ar7100_check_error(0);
330
331        ar71xx_pci_fixup_enable = 1;
332        register_pci_controller(&ar7100_pci_controller);
333        request_irq(AR7100_PCI_IRQ_CORE, ar7100_pci_core_intr, IRQ_DISABLED,"ar7100 pci core", NULL);
334
335        return 0;
336}
337
338arch_initcall(ar7100_pcibios_init);
Note: See TracBrowser for help on using the repository browser.