bb4f2162d4e4b3464c2c0c2856725e30356c0f57
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / mips / pci / pci-ar724x.c
1 /*
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>
12 #include <asm/mach-ath79/pci.h>
13
14 #define AR724X_PCI_CFG_BASE     0x14000000
15 #define AR724X_PCI_CFG_SIZE     0x1000
16 #define AR724X_PCI_MEM_BASE     0x10000000
17 #define AR724X_PCI_MEM_SIZE     0x08000000
18
19 static DEFINE_SPINLOCK(ar724x_pci_lock);
20 static void __iomem *ar724x_pci_devcfg_base;
21
22 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
23                             int size, uint32_t *value)
24 {
25         unsigned long flags;
26         void __iomem *base;
27         u32 data;
28
29         if (devfn)
30                 return PCIBIOS_DEVICE_NOT_FOUND;
31
32         base = ar724x_pci_devcfg_base;
33
34         spin_lock_irqsave(&ar724x_pci_lock, flags);
35         data = __raw_readl(base + (where & ~3));
36
37         switch (size) {
38         case 1:
39                 if (where & 1)
40                         data >>= 8;
41                 if (where & 2)
42                         data >>= 16;
43                 data &= 0xff;
44                 break;
45         case 2:
46                 if (where & 2)
47                         data >>= 16;
48                 data &= 0xffff;
49                 break;
50         case 4:
51                 break;
52         default:
53                 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
54
55                 return PCIBIOS_BAD_REGISTER_NUMBER;
56         }
57
58         spin_unlock_irqrestore(&ar724x_pci_lock, flags);
59         *value = data;
60
61         return PCIBIOS_SUCCESSFUL;
62 }
63
64 static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
65                              int size, uint32_t value)
66 {
67         unsigned long flags;
68         void __iomem *base;
69         u32 data;
70         int s;
71
72         if (devfn)
73                 return PCIBIOS_DEVICE_NOT_FOUND;
74
75         base = ar724x_pci_devcfg_base;
76
77         spin_lock_irqsave(&ar724x_pci_lock, flags);
78         data = __raw_readl(base + (where & ~3));
79
80         switch (size) {
81         case 1:
82                 s = ((where & 3) * 8);
83                 data &= ~(0xff << s);
84                 data |= ((value & 0xff) << s);
85                 break;
86         case 2:
87                 s = ((where & 2) * 8);
88                 data &= ~(0xffff << s);
89                 data |= ((value & 0xffff) << s);
90                 break;
91         case 4:
92                 data = value;
93                 break;
94         default:
95                 spin_unlock_irqrestore(&ar724x_pci_lock, flags);
96
97                 return PCIBIOS_BAD_REGISTER_NUMBER;
98         }
99
100         __raw_writel(data, base + (where & ~3));
101         /* flush write */
102         __raw_readl(base + (where & ~3));
103         spin_unlock_irqrestore(&ar724x_pci_lock, flags);
104
105         return PCIBIOS_SUCCESSFUL;
106 }
107
108 static struct pci_ops ar724x_pci_ops = {
109         .read   = ar724x_pci_read,
110         .write  = ar724x_pci_write,
111 };
112
113 static struct resource ar724x_io_resource = {
114         .name   = "PCI IO space",
115         .start  = 0,
116         .end    = 0,
117         .flags  = IORESOURCE_IO,
118 };
119
120 static struct resource ar724x_mem_resource = {
121         .name   = "PCI memory space",
122         .start  = AR724X_PCI_MEM_BASE,
123         .end    = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1,
124         .flags  = IORESOURCE_MEM,
125 };
126
127 static struct pci_controller ar724x_pci_controller = {
128         .pci_ops        = &ar724x_pci_ops,
129         .io_resource    = &ar724x_io_resource,
130         .mem_resource   = &ar724x_mem_resource,
131 };
132
133 int __init ar724x_pcibios_init(void)
134 {
135         ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE,
136                                          AR724X_PCI_CFG_SIZE);
137         if (ar724x_pci_devcfg_base == NULL)
138                 return -ENOMEM;
139
140         register_pci_controller(&ar724x_pci_controller);
141
142         return PCIBIOS_SUCCESSFUL;
143 }