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.
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
;
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
);
41 mask
= 0xff000000 >> ((where
% 4) * 8);
42 tval
= reg_read(ATH724X_PCI_DEV_BASE
+ addr
);
44 *value
= (tval
>> ((4 - (where
% 4))*8));
48 mask
= 0xffff0000 >> ((where
% 4)*8);
49 tval
= reg_read(ATH724X_PCI_DEV_BASE
+ addr
);
51 *value
= (tval
>> ((4 - (where
% 4))*8));
54 *value
= reg_read(ATH724X_PCI_DEV_BASE
+ where
);
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
;
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
);
82 addr
= (ATH724X_PCI_DEV_BASE
+ where
) & ~3;
83 mask
= 0xff000000 >> ((where
% 4)*8);
84 tval
= reg_read(addr
);
86 tval
|= (value
<< ((4 - (where
% 4))*8)) & mask
;
87 reg_write(addr
, tval
);
90 addr
= (ATH724X_PCI_DEV_BASE
+ where
) & ~3;
91 mask
= 0xffff0000 >> ((where
% 4)*8);
92 tval
= reg_read(addr
);
94 tval
|= (value
<< ((4 - (where
% 4))*8)) & mask
;
95 reg_write(addr
, tval
);
98 reg_write((ATH724X_PCI_DEV_BASE
+ where
), value
);
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",
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
)
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
;
147 if (devfn
> pci_data_size
- 1)
150 irq
= pci_data
[devfn
].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
);