blob: 07b7e307173528e6d62fd2b419b478b04b0c1325 [file] [log] [blame]
Rene Bolldorf4ff40d52011-11-17 14:25:09 +00001/*
2 * Atheros 724x PCI support
3 *
4 * Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
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>
Gabor Juhos6015a852012-03-14 10:36:05 +010012#include <asm/mach-ath79/ath79.h>
Gabor Juhos659243c2012-03-14 10:29:23 +010013#include <asm/mach-ath79/pci.h>
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000014
Gabor Juhosc1984412012-03-14 10:29:27 +010015#define AR724X_PCI_CFG_BASE 0x14000000
16#define AR724X_PCI_CFG_SIZE 0x1000
Gabor Juhosd624bd32012-03-14 10:29:26 +010017#define AR724X_PCI_MEM_BASE 0x10000000
18#define AR724X_PCI_MEM_SIZE 0x08000000
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000019
Gabor Juhos6015a852012-03-14 10:36:05 +010020#define AR7240_BAR0_WAR_VALUE 0xffff
21
Gabor Juhosd624bd32012-03-14 10:29:26 +010022static DEFINE_SPINLOCK(ar724x_pci_lock);
Gabor Juhosc1984412012-03-14 10:29:27 +010023static void __iomem *ar724x_pci_devcfg_base;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000024
Gabor Juhos6015a852012-03-14 10:36:05 +010025static u32 ar724x_pci_bar0_value;
26static bool ar724x_pci_bar0_is_cached;
27
Gabor Juhosd624bd32012-03-14 10:29:26 +010028static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000029 int size, uint32_t *value)
30{
Gabor Juhos64adb6b2012-03-14 10:36:04 +010031 unsigned long flags;
Gabor Juhosc1984412012-03-14 10:29:27 +010032 void __iomem *base;
Gabor Juhos64adb6b2012-03-14 10:36:04 +010033 u32 data;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000034
35 if (devfn)
36 return PCIBIOS_DEVICE_NOT_FOUND;
37
Gabor Juhosc1984412012-03-14 10:29:27 +010038 base = ar724x_pci_devcfg_base;
39
Gabor Juhosd624bd32012-03-14 10:29:26 +010040 spin_lock_irqsave(&ar724x_pci_lock, flags);
Gabor Juhos64adb6b2012-03-14 10:36:04 +010041 data = __raw_readl(base + (where & ~3));
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000042
43 switch (size) {
44 case 1:
Gabor Juhos64adb6b2012-03-14 10:36:04 +010045 if (where & 1)
46 data >>= 8;
47 if (where & 2)
48 data >>= 16;
49 data &= 0xff;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000050 break;
51 case 2:
Gabor Juhos64adb6b2012-03-14 10:36:04 +010052 if (where & 2)
53 data >>= 16;
54 data &= 0xffff;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000055 break;
56 case 4:
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000057 break;
58 default:
Gabor Juhosd624bd32012-03-14 10:29:26 +010059 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000060
61 return PCIBIOS_BAD_REGISTER_NUMBER;
62 }
63
Gabor Juhosd624bd32012-03-14 10:29:26 +010064 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Gabor Juhos6015a852012-03-14 10:36:05 +010065
66 if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
67 ar724x_pci_bar0_is_cached) {
68 /* use the cached value */
69 *value = ar724x_pci_bar0_value;
70 } else {
71 *value = data;
72 }
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000073
74 return PCIBIOS_SUCCESSFUL;
75}
76
Gabor Juhosd624bd32012-03-14 10:29:26 +010077static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000078 int size, uint32_t value)
79{
Gabor Juhos64adb6b2012-03-14 10:36:04 +010080 unsigned long flags;
Gabor Juhosc1984412012-03-14 10:29:27 +010081 void __iomem *base;
Gabor Juhos64adb6b2012-03-14 10:36:04 +010082 u32 data;
83 int s;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +000084
85 if (devfn)
86 return PCIBIOS_DEVICE_NOT_FOUND;
87
Gabor Juhos6015a852012-03-14 10:36:05 +010088 if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
89 if (value != 0xffffffff) {
90 /*
91 * WAR for a hw issue. If the BAR0 register of the
92 * device is set to the proper base address, the
93 * memory space of the device is not accessible.
94 *
95 * Cache the intended value so it can be read back,
96 * and write a SoC specific constant value to the
97 * BAR0 register in order to make the device memory
98 * accessible.
99 */
100 ar724x_pci_bar0_is_cached = true;
101 ar724x_pci_bar0_value = value;
102
103 value = AR7240_BAR0_WAR_VALUE;
104 } else {
105 ar724x_pci_bar0_is_cached = false;
106 }
107 }
108
Gabor Juhosc1984412012-03-14 10:29:27 +0100109 base = ar724x_pci_devcfg_base;
110
Gabor Juhosd624bd32012-03-14 10:29:26 +0100111 spin_lock_irqsave(&ar724x_pci_lock, flags);
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100112 data = __raw_readl(base + (where & ~3));
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000113
114 switch (size) {
115 case 1:
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100116 s = ((where & 3) * 8);
117 data &= ~(0xff << s);
118 data |= ((value & 0xff) << s);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000119 break;
120 case 2:
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100121 s = ((where & 2) * 8);
122 data &= ~(0xffff << s);
123 data |= ((value & 0xffff) << s);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000124 break;
125 case 4:
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100126 data = value;
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000127 break;
128 default:
Gabor Juhosd624bd32012-03-14 10:29:26 +0100129 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000130
131 return PCIBIOS_BAD_REGISTER_NUMBER;
132 }
133
Gabor Juhos64adb6b2012-03-14 10:36:04 +0100134 __raw_writel(data, base + (where & ~3));
135 /* flush write */
136 __raw_readl(base + (where & ~3));
Gabor Juhosd624bd32012-03-14 10:29:26 +0100137 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000138
139 return PCIBIOS_SUCCESSFUL;
140}
141
Gabor Juhosd624bd32012-03-14 10:29:26 +0100142static struct pci_ops ar724x_pci_ops = {
143 .read = ar724x_pci_read,
144 .write = ar724x_pci_write,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000145};
146
Gabor Juhosd624bd32012-03-14 10:29:26 +0100147static struct resource ar724x_io_resource = {
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000148 .name = "PCI IO space",
149 .start = 0,
150 .end = 0,
151 .flags = IORESOURCE_IO,
152};
153
Gabor Juhosd624bd32012-03-14 10:29:26 +0100154static struct resource ar724x_mem_resource = {
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000155 .name = "PCI memory space",
Gabor Juhosd624bd32012-03-14 10:29:26 +0100156 .start = AR724X_PCI_MEM_BASE,
157 .end = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000158 .flags = IORESOURCE_MEM,
159};
160
Gabor Juhosd624bd32012-03-14 10:29:26 +0100161static struct pci_controller ar724x_pci_controller = {
162 .pci_ops = &ar724x_pci_ops,
163 .io_resource = &ar724x_io_resource,
164 .mem_resource = &ar724x_mem_resource,
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000165};
166
Gabor Juhosd624bd32012-03-14 10:29:26 +0100167int __init ar724x_pcibios_init(void)
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000168{
Gabor Juhosc1984412012-03-14 10:29:27 +0100169 ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
170 AR724X_PCI_CFG_SIZE);
171 if (ar724x_pci_devcfg_base == NULL)
172 return -ENOMEM;
173
Gabor Juhosd624bd32012-03-14 10:29:26 +0100174 register_pci_controller(&ar724x_pci_controller);
Rene Bolldorf4ff40d52011-11-17 14:25:09 +0000175
176 return PCIBIOS_SUCCESSFUL;
177}