Root/target/linux/ar71xx/files/arch/mips/ar71xx/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-ar71xx/ar71xx.h>
15#include <asm/mach-ar71xx/pci.h>
16
17struct ath9k_fixup {
18    u16 *cal_data;
19    unsigned slot;
20};
21
22static int ath9k_num_fixups;
23static struct ath9k_fixup ath9k_fixups[2];
24
25static void ath9k_pci_fixup(struct pci_dev *dev)
26{
27    void __iomem *mem;
28    u16 *cal_data = NULL;
29    u16 cmd;
30    u32 bar0;
31    u32 val;
32    unsigned i;
33
34    for (i = 0; i < ath9k_num_fixups; i++) {
35        if (ath9k_fixups[i].cal_data == NULL)
36            continue;
37
38        if (ath9k_fixups[i].slot != PCI_SLOT(dev->devfn))
39            continue;
40
41        cal_data = ath9k_fixups[i].cal_data;
42        break;
43    }
44
45    if (cal_data == NULL)
46        return;
47
48    if (*cal_data != 0xa55a) {
49        pr_err("pci %s: invalid calibration data\n", pci_name(dev));
50        return;
51    }
52
53    pr_info("pci %s: fixup device configuration\n", pci_name(dev));
54
55    mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000);
56    if (!mem) {
57        pr_err("pci %s: ioremap error\n", pci_name(dev));
58        return;
59    }
60
61    pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
62
63    switch (ar71xx_soc) {
64    case AR71XX_SOC_AR7161:
65        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
66                       AR71XX_PCI_MEM_BASE);
67        break;
68    case AR71XX_SOC_AR7240:
69        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff);
70        break;
71
72    case AR71XX_SOC_AR7241:
73    case AR71XX_SOC_AR7242:
74        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0x1000ffff);
75        break;
76
77    default:
78        BUG();
79    }
80
81    pci_read_config_word(dev, PCI_COMMAND, &cmd);
82    cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
83    pci_write_config_word(dev, PCI_COMMAND, cmd);
84
85    /* set pointer to first reg address */
86    cal_data += 3;
87    while (*cal_data != 0xffff) {
88        u32 reg;
89        reg = *cal_data++;
90        val = *cal_data++;
91        val |= (*cal_data++) << 16;
92
93        __raw_writel(val, mem + reg);
94        udelay(100);
95    }
96
97    pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
98    dev->vendor = val & 0xffff;
99    dev->device = (val >> 16) & 0xffff;
100
101    pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
102    dev->revision = val & 0xff;
103    dev->class = val >> 8; /* upper 3 bytes */
104
105    pci_read_config_word(dev, PCI_COMMAND, &cmd);
106    cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
107    pci_write_config_word(dev, PCI_COMMAND, cmd);
108
109    pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
110
111    iounmap(mem);
112}
113DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
114
115void __init pci_enable_ath9k_fixup(unsigned slot, u16 *cal_data)
116{
117    if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
118        return;
119
120    ath9k_fixups[ath9k_num_fixups].slot = slot;
121    ath9k_fixups[ath9k_num_fixups].cal_data = cal_data;
122    ath9k_num_fixups++;
123}
124

Archive Download this file



interactive