Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / arch / mips / pci / pci-ath724x.c
bloba4dd24a4130bd284f19c970aebc186f678cd1742
1 /*
2 * Atheros 724x PCI support
4 * Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
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 */
11 #include <linux/pci.h>
12 #include <asm/mach-ath79/pci-ath724x.h>
14 #define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys))
15 #define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val))
17 #define ATH724X_PCI_DEV_BASE 0x14000000
18 #define ATH724X_PCI_MEM_BASE 0x10000000
19 #define ATH724X_PCI_MEM_SIZE 0x08000000
21 static DEFINE_SPINLOCK(ath724x_pci_lock);
22 static struct ath724x_pci_data *pci_data;
23 static int pci_data_size;
25 static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
26 int size, uint32_t *value)
28 unsigned long flags, addr, tval, mask;
30 if (devfn)
31 return PCIBIOS_DEVICE_NOT_FOUND;
33 if (where & (size - 1))
34 return PCIBIOS_BAD_REGISTER_NUMBER;
36 spin_lock_irqsave(&ath724x_pci_lock, flags);
38 switch (size) {
39 case 1:
40 addr = where & ~3;
41 mask = 0xff000000 >> ((where % 4) * 8);
42 tval = reg_read(ATH724X_PCI_DEV_BASE + addr);
43 tval = tval & ~mask;
44 *value = (tval >> ((4 - (where % 4))*8));
45 break;
46 case 2:
47 addr = where & ~3;
48 mask = 0xffff0000 >> ((where % 4)*8);
49 tval = reg_read(ATH724X_PCI_DEV_BASE + addr);
50 tval = tval & ~mask;
51 *value = (tval >> ((4 - (where % 4))*8));
52 break;
53 case 4:
54 *value = reg_read(ATH724X_PCI_DEV_BASE + where);
55 break;
56 default:
57 spin_unlock_irqrestore(&ath724x_pci_lock, flags);
59 return PCIBIOS_BAD_REGISTER_NUMBER;
62 spin_unlock_irqrestore(&ath724x_pci_lock, flags);
64 return PCIBIOS_SUCCESSFUL;
67 static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
68 int size, uint32_t value)
70 unsigned long flags, tval, addr, mask;
72 if (devfn)
73 return PCIBIOS_DEVICE_NOT_FOUND;
75 if (where & (size - 1))
76 return PCIBIOS_BAD_REGISTER_NUMBER;
78 spin_lock_irqsave(&ath724x_pci_lock, flags);
80 switch (size) {
81 case 1:
82 addr = (ATH724X_PCI_DEV_BASE + where) & ~3;
83 mask = 0xff000000 >> ((where % 4)*8);
84 tval = reg_read(addr);
85 tval = tval & ~mask;
86 tval |= (value << ((4 - (where % 4))*8)) & mask;
87 reg_write(addr, tval);
88 break;
89 case 2:
90 addr = (ATH724X_PCI_DEV_BASE + where) & ~3;
91 mask = 0xffff0000 >> ((where % 4)*8);
92 tval = reg_read(addr);
93 tval = tval & ~mask;
94 tval |= (value << ((4 - (where % 4))*8)) & mask;
95 reg_write(addr, tval);
96 break;
97 case 4:
98 reg_write((ATH724X_PCI_DEV_BASE + where), value);
99 break;
100 default:
101 spin_unlock_irqrestore(&ath724x_pci_lock, flags);
103 return PCIBIOS_BAD_REGISTER_NUMBER;
106 spin_unlock_irqrestore(&ath724x_pci_lock, flags);
108 return PCIBIOS_SUCCESSFUL;
111 static struct pci_ops ath724x_pci_ops = {
112 .read = ath724x_pci_read,
113 .write = ath724x_pci_write,
116 static struct resource ath724x_io_resource = {
117 .name = "PCI IO space",
118 .start = 0,
119 .end = 0,
120 .flags = IORESOURCE_IO,
123 static struct resource ath724x_mem_resource = {
124 .name = "PCI memory space",
125 .start = ATH724X_PCI_MEM_BASE,
126 .end = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1,
127 .flags = IORESOURCE_MEM,
130 static struct pci_controller ath724x_pci_controller = {
131 .pci_ops = &ath724x_pci_ops,
132 .io_resource = &ath724x_io_resource,
133 .mem_resource = &ath724x_mem_resource,
136 void ath724x_pci_add_data(struct ath724x_pci_data *data, int size)
138 pci_data = data;
139 pci_data_size = size;
142 int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
144 unsigned int devfn = dev->devfn;
145 int irq = -1;
147 if (devfn > pci_data_size - 1)
148 return irq;
150 irq = pci_data[devfn].irq;
152 return irq;
155 int pcibios_plat_dev_init(struct pci_dev *dev)
157 unsigned int devfn = dev->devfn;
159 if (devfn > pci_data_size - 1)
160 return PCIBIOS_DEVICE_NOT_FOUND;
162 dev->dev.platform_data = pci_data[devfn].pdata;
164 return PCIBIOS_SUCCESSFUL;
167 static int __init ath724x_pcibios_init(void)
169 register_pci_controller(&ath724x_pci_controller);
171 return PCIBIOS_SUCCESSFUL;
174 arch_initcall(ath724x_pcibios_init);