MIPS: pci-ar724x: convert into a platform driver
[linux-2.6-microblaze.git] / arch / mips / pci / pci-ar724x.c
1 /*
2  *  Atheros AR724X PCI host controller driver
3  *
4  *  Copyright (C) 2011 RenĂ© Bolldorf <xsecute@googlemail.com>
5  *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
6  *
7  *  This program is free software; you can redistribute it and/or modify it
8  *  under the terms of the GNU General Public License version 2 as published
9  *  by the Free Software Foundation.
10  */
11
12 #include <linux/irq.h>
13 #include <linux/pci.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <asm/mach-ath79/ath79.h>
17 #include <asm/mach-ath79/ar71xx_regs.h>
18 #include <asm/mach-ath79/pci.h>
19
20 #define AR724X_PCI_CFG_BASE     0x14000000
21 #define AR724X_PCI_CFG_SIZE     0x1000
22 #define AR724X_PCI_CTRL_BASE    (AR71XX_APB_BASE + 0x000f0000)
23 #define AR724X_PCI_CTRL_SIZE    0x100
24
25 #define AR724X_PCI_MEM_BASE     0x10000000
26 #define AR724X_PCI_MEM_SIZE     0x04000000
27
28 #define AR724X_PCI_REG_RESET            0x18
29 #define AR724X_PCI_REG_INT_STATUS       0x4c
30 #define AR724X_PCI_REG_INT_MASK         0x50
31
32 #define AR724X_PCI_RESET_LINK_UP        BIT(0)
33
34 #define AR724X_PCI_INT_DEV0             BIT(14)
35
36 #define AR724X_PCI_IRQ_COUNT            1
37
38 #define AR7240_BAR0_WAR_VALUE   0xffff
39
40 static DEFINE_SPINLOCK(ar724x_pci_lock);
41 static void __iomem *ar724x_pci_devcfg_base;
42 static void __iomem *ar724x_pci_ctrl_base;
43
44 static u32 ar724x_pci_bar0_value;
45 static bool ar724x_pci_bar0_is_cached;
46 static bool ar724x_pci_link_up;
47
48 static inline bool ar724x_pci_check_link(void)
49 {
50         u32 reset;
51
52         reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET);
53         return reset & AR724X_PCI_RESET_LINK_UP;
54 }
55
56 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
57                             int size, uint32_t *value)
58 {
59         unsigned long flags;
60         void __iomem *base;
61         u32 data;
62
63         if (!ar724x_pci_link_up)
64                 return PCIBIOS_DEVICE_NOT_FOUND;
65
66         if (devfn)
67                 return PCIBIOS_DEVICE_NOT_FOUND;
68
69         base = ar724x_pci_devcfg_base;
70
71         spin_lock_irqsave(&ar724x_pci_lock, flags);
72         data = __raw_readl(base + (where & ~3));
73
74         switch (size) {
75         case 1:
76                 if (where & 1)
77                         data >>= 8;
78                 if (where & 2)
79                         data >>= 16;
80                 data &= 0xff;
81                 break;
82         case 2:
83                 if (where & 2)
84                         data >>= 16;
85                 data &= 0xffff;
86                 break;
87         case 4:
88                 break;
89         default:
90                 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
91
92                 return PCIBIOS_BAD_REGISTER_NUMBER;
93         }
94
95         spin_unlock_irqrestore(&ar724x_pci_lock, flags);
96
97         if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
98             ar724x_pci_bar0_is_cached) {
99                 /* use the cached value */
100                 *value = ar724x_pci_bar0_value;
101         } else {
102                 *value = data;
103         }
104
105         return PCIBIOS_SUCCESSFUL;
106 }
107
108 static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
109                              int size, uint32_t value)
110 {
111         unsigned long flags;
112         void __iomem *base;
113         u32 data;
114         int s;
115
116         if (!ar724x_pci_link_up)
117                 return PCIBIOS_DEVICE_NOT_FOUND;
118
119         if (devfn)
120                 return PCIBIOS_DEVICE_NOT_FOUND;
121
122         if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
123                 if (value != 0xffffffff) {
124                         /*
125                          * WAR for a hw issue. If the BAR0 register of the
126                          * device is set to the proper base address, the
127                          * memory space of the device is not accessible.
128                          *
129                          * Cache the intended value so it can be read back,
130                          * and write a SoC specific constant value to the
131                          * BAR0 register in order to make the device memory
132                          * accessible.
133                          */
134                         ar724x_pci_bar0_is_cached = true;
135                         ar724x_pci_bar0_value = value;
136
137                         value = AR7240_BAR0_WAR_VALUE;
138                 } else {
139                         ar724x_pci_bar0_is_cached = false;
140                 }
141         }
142
143         base = ar724x_pci_devcfg_base;
144
145         spin_lock_irqsave(&ar724x_pci_lock, flags);
146         data = __raw_readl(base + (where & ~3));
147
148         switch (size) {
149         case 1:
150                 s = ((where & 3) * 8);
151                 data &= ~(0xff << s);
152                 data |= ((value & 0xff) << s);
153                 break;
154         case 2:
155                 s = ((where & 2) * 8);
156                 data &= ~(0xffff << s);
157                 data |= ((value & 0xffff) << s);
158                 break;
159         case 4:
160                 data = value;
161                 break;
162         default:
163                 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
164
165                 return PCIBIOS_BAD_REGISTER_NUMBER;
166         }
167
168         __raw_writel(data, base + (where & ~3));
169         /* flush write */
170         __raw_readl(base + (where & ~3));
171         spin_unlock_irqrestore(&ar724x_pci_lock, flags);
172
173         return PCIBIOS_SUCCESSFUL;
174 }
175
176 static struct pci_ops ar724x_pci_ops = {
177         .read   = ar724x_pci_read,
178         .write  = ar724x_pci_write,
179 };
180
181 static struct resource ar724x_io_resource = {
182         .name   = "PCI IO space",
183         .start  = 0,
184         .end    = 0,
185         .flags  = IORESOURCE_IO,
186 };
187
188 static struct resource ar724x_mem_resource = {
189         .name   = "PCI memory space",
190         .start  = AR724X_PCI_MEM_BASE,
191         .end    = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1,
192         .flags  = IORESOURCE_MEM,
193 };
194
195 static struct pci_controller ar724x_pci_controller = {
196         .pci_ops        = &ar724x_pci_ops,
197         .io_resource    = &ar724x_io_resource,
198         .mem_resource   = &ar724x_mem_resource,
199 };
200
201 static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
202 {
203         void __iomem *base;
204         u32 pending;
205
206         base = ar724x_pci_ctrl_base;
207
208         pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
209                   __raw_readl(base + AR724X_PCI_REG_INT_MASK);
210
211         if (pending & AR724X_PCI_INT_DEV0)
212                 generic_handle_irq(ATH79_PCI_IRQ(0));
213
214         else
215                 spurious_interrupt();
216 }
217
218 static void ar724x_pci_irq_unmask(struct irq_data *d)
219 {
220         void __iomem *base;
221         u32 t;
222
223         base = ar724x_pci_ctrl_base;
224
225         switch (d->irq) {
226         case ATH79_PCI_IRQ(0):
227                 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
228                 __raw_writel(t | AR724X_PCI_INT_DEV0,
229                              base + AR724X_PCI_REG_INT_MASK);
230                 /* flush write */
231                 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
232         }
233 }
234
235 static void ar724x_pci_irq_mask(struct irq_data *d)
236 {
237         void __iomem *base;
238         u32 t;
239
240         base = ar724x_pci_ctrl_base;
241
242         switch (d->irq) {
243         case ATH79_PCI_IRQ(0):
244                 t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
245                 __raw_writel(t & ~AR724X_PCI_INT_DEV0,
246                              base + AR724X_PCI_REG_INT_MASK);
247
248                 /* flush write */
249                 __raw_readl(base + AR724X_PCI_REG_INT_MASK);
250
251                 t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
252                 __raw_writel(t | AR724X_PCI_INT_DEV0,
253                              base + AR724X_PCI_REG_INT_STATUS);
254
255                 /* flush write */
256                 __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
257         }
258 }
259
260 static struct irq_chip ar724x_pci_irq_chip = {
261         .name           = "AR724X PCI ",
262         .irq_mask       = ar724x_pci_irq_mask,
263         .irq_unmask     = ar724x_pci_irq_unmask,
264         .irq_mask_ack   = ar724x_pci_irq_mask,
265 };
266
267 static void ar724x_pci_irq_init(int irq)
268 {
269         void __iomem *base;
270         int i;
271
272         base = ar724x_pci_ctrl_base;
273
274         __raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
275         __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
276
277         BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT);
278
279         for (i = ATH79_PCI_IRQ_BASE;
280              i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++)
281                 irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
282                                          handle_level_irq);
283
284         irq_set_chained_handler(irq, ar724x_pci_irq_handler);
285 }
286
287 int ar724x_pcibios_init(int irq)
288 {
289         int ret;
290
291         ret = -ENOMEM;
292
293         ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
294                                          AR724X_PCI_CFG_SIZE);
295         if (ar724x_pci_devcfg_base == NULL)
296                 goto err;
297
298         ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE,
299                                        AR724X_PCI_CTRL_SIZE);
300         if (ar724x_pci_ctrl_base == NULL)
301                 goto err_unmap_devcfg;
302
303         ar724x_pci_link_up = ar724x_pci_check_link();
304         if (!ar724x_pci_link_up)
305                 pr_warn("ar724x: PCIe link is down\n");
306
307         ar724x_pci_irq_init(irq);
308         register_pci_controller(&ar724x_pci_controller);
309
310         return PCIBIOS_SUCCESSFUL;
311
312 err_unmap_devcfg:
313         iounmap(ar724x_pci_devcfg_base);
314 err:
315         return ret;
316 }
317
318 static int ar724x_pci_probe(struct platform_device *pdev)
319 {
320         struct resource *res;
321         int irq;
322
323         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base");
324         if (!res)
325                 return -EINVAL;
326
327         ar724x_pci_ctrl_base = devm_request_and_ioremap(&pdev->dev, res);
328         if (ar724x_pci_ctrl_base == NULL)
329                 return -EBUSY;
330
331         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
332         if (!res)
333                 return -EINVAL;
334
335         ar724x_pci_devcfg_base = devm_request_and_ioremap(&pdev->dev, res);
336         if (!ar724x_pci_devcfg_base)
337                 return -EBUSY;
338
339         irq = platform_get_irq(pdev, 0);
340         if (irq < 0)
341                 return -EINVAL;
342
343         ar724x_pci_link_up = ar724x_pci_check_link();
344         if (!ar724x_pci_link_up)
345                 dev_warn(&pdev->dev, "PCIe link is down\n");
346
347         ar724x_pci_irq_init(irq);
348
349         register_pci_controller(&ar724x_pci_controller);
350
351         return 0;
352 }
353
354 static struct platform_driver ar724x_pci_driver = {
355         .probe = ar724x_pci_probe,
356         .driver = {
357                 .name = "ar724x-pci",
358                 .owner = THIS_MODULE,
359         },
360 };
361
362 static int __init ar724x_pci_init(void)
363 {
364         return platform_driver_register(&ar724x_pci_driver);
365 }
366
367 postcore_initcall(ar724x_pci_init);