Root/target/linux/ar71xx/files/arch/mips/ath79/pci-ath9k-fixup.c

1/*
2 * Atheros AP94 reference board PCI initialization
3 *
4 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 */
10
11#include <linux/pci.h>
12#include <linux/delay.h>
13
14#include <asm/mach-ath79/ar71xx_regs.h>
15#include <asm/mach-ath79/ath79.h>
16#include <asm/mach-ath79/pci.h>
17
18struct ath9k_fixup {
19    u16 *cal_data;
20    unsigned slot;
21};
22
23static int ath9k_num_fixups;
24static struct ath9k_fixup ath9k_fixups[2];
25
26static void ath9k_pci_fixup(struct pci_dev *dev)
27{
28    void __iomem *mem;
29    u16 *cal_data = NULL;
30    u16 cmd;
31    u32 bar0;
32    u32 val;
33    unsigned i;
34
35    for (i = 0; i < ath9k_num_fixups; i++) {
36        if (ath9k_fixups[i].cal_data == NULL)
37            continue;
38
39        if (ath9k_fixups[i].slot != PCI_SLOT(dev->devfn))
40            continue;
41
42        cal_data = ath9k_fixups[i].cal_data;
43        break;
44    }
45
46    if (cal_data == NULL)
47        return;
48
49    if (*cal_data != 0xa55a) {
50        pr_err("pci %s: invalid calibration data\n", pci_name(dev));
51        return;
52    }
53
54    pr_info("pci %s: fixup device configuration\n", pci_name(dev));
55
56    mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000);
57    if (!mem) {
58        pr_err("pci %s: ioremap error\n", pci_name(dev));
59        return;
60    }
61
62    pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
63
64    switch (ath79_soc) {
65    case ATH79_SOC_AR7161:
66        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
67                       AR71XX_PCI_MEM_BASE);
68        break;
69    case ATH79_SOC_AR7240:
70        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff);
71        break;
72
73    case ATH79_SOC_AR7241:
74    case ATH79_SOC_AR7242:
75        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x1000ffff);
76        break;
77
78    default:
79        BUG();
80    }
81
82    pci_read_config_word(dev, PCI_COMMAND, &cmd);
83    cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
84    pci_write_config_word(dev, PCI_COMMAND, cmd);
85
86    /* set pointer to first reg address */
87    cal_data += 3;
88    while (*cal_data != 0xffff) {
89        u32 reg;
90        reg = *cal_data++;
91        val = *cal_data++;
92        val |= (*cal_data++) << 16;
93
94        __raw_writel(val, mem + reg);
95        udelay(100);
96    }
97
98    pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
99    dev->vendor = val & 0xffff;
100    dev->device = (val >> 16) & 0xffff;
101
102    pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
103    dev->revision = val & 0xff;
104    dev->class = val >> 8; /* upper 3 bytes */
105
106    pci_read_config_word(dev, PCI_COMMAND, &cmd);
107    cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
108    pci_write_config_word(dev, PCI_COMMAND, cmd);
109
110    pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
111
112    iounmap(mem);
113}
114DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
115
116void __init pci_enable_ath9k_fixup(unsigned slot, u16 *cal_data)
117{
118    if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
119        return;
120
121    ath9k_fixups[ath9k_num_fixups].slot = slot;
122    ath9k_fixups[ath9k_num_fixups].cal_data = cal_data;
123    ath9k_num_fixups++;
124}
125

Archive Download this file



interactive