2 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
3 * Copyright (C) 2012 Florian Fainelli <florian@openwrt.org>
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
9 * Note that this controller is identical to the ADM5120 one
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/pci.h>
15 #include <linux/types.h>
16 #include <linux/spinlock.h>
18 #include <asm/byteorder.h>
22 static DEFINE_SPINLOCK(pci_lock
);
24 #define PCI_ENABLE 0x80000000
25 #define ADMPCI_IO_BASE 0x12600000
26 #define ADMPCI_IO_SIZE 0x1fffff
27 #define ADMPCI_MEM_BASE 0x16000000
28 #define ADMPCI_MEM_SIZE 0x7ffffff
30 static inline void write_cfgaddr(u32 addr
)
32 __raw_writel((addr
| PCI_ENABLE
),
33 (void __iomem
*)KSEG1ADDR(ADM8668_PCICFG_BASE
));
36 static inline void write_cfgdata(u32 data
)
38 __raw_writel(data
, (void __iomem
*)KSEG1ADDR(ADM8668_PCIDAT_BASE
));
41 static inline u32
read_cfgdata(void)
43 return __raw_readl((void __iomem
*)KSEG1ADDR(ADM8668_PCIDAT_BASE
));
46 static inline u32
mkaddr(struct pci_bus
*bus
, unsigned int devfn
, int where
)
48 return ((bus
->number
& 0xff) << 16) | ((devfn
& 0xff) << 8) |
52 static int pci_read_config(struct pci_bus
*bus
, unsigned int devfn
,
53 int where
, int size
, u32
*val
)
58 spin_lock_irqsave(&pci_lock
, flags
);
59 write_cfgaddr(mkaddr(bus
, devfn
, where
));
60 data
= read_cfgdata();
79 spin_unlock_irqrestore(&pci_lock
, flags
);
81 return PCIBIOS_SUCCESSFUL
;
84 static int pci_write_config(struct pci_bus
*bus
, unsigned int devfn
,
85 int where
, int size
, u32 val
)
91 spin_lock_irqsave(&pci_lock
, flags
);
93 write_cfgaddr(mkaddr(bus
, devfn
, where
));
94 data
= read_cfgdata();
98 s
= ((where
& 3) << 3);
100 data
|= ((val
& 0xff) << s
);
103 s
= ((where
& 2) << 4);
104 data
&= ~(0xffff << s
);
105 data
|= ((val
& 0xffff) << s
);
114 spin_unlock_irqrestore(&pci_lock
, flags
);
116 return PCIBIOS_SUCCESSFUL
;
119 struct pci_ops adm8668_pci_ops
= {
120 .read
= pci_read_config
,
121 .write
= pci_write_config
125 struct resource pciioport_resource
= {
126 .name
= "adm8668_pci",
127 .start
= ADMPCI_IO_BASE
,
128 .end
= ADMPCI_IO_BASE
+ ADMPCI_IO_SIZE
,
129 .flags
= IORESOURCE_IO
132 struct resource pciiomem_resource
= {
133 .name
= "adm8668_pci",
134 .start
= ADMPCI_MEM_BASE
,
135 .end
= ADMPCI_MEM_BASE
+ ADMPCI_MEM_SIZE
,
136 .flags
= IORESOURCE_MEM
139 struct pci_controller adm8668_pci_controller
= {
140 .pci_ops
= &adm8668_pci_ops
,
141 .io_resource
= &pciioport_resource
,
142 .mem_resource
= &pciiomem_resource
,
145 int pcibios_map_irq(const struct pci_dev
*dev
, u8 slot
, u8 pin
)
159 int pcibios_plat_dev_init(struct pci_dev
*dev
)
164 static void adm8668_pci_fixup(struct pci_dev
*dev
)
169 pr_info("PCI: fixing up ADM8668 controller\n");
171 /* setup COMMAND register */
172 pci_write_config_word(dev
, PCI_COMMAND
,
173 (PCI_COMMAND_IO
| PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
));
175 /* setup CACHE_LINE_SIZE register */
176 pci_write_config_byte(dev
, PCI_CACHE_LINE_SIZE
, 4);
179 pci_write_config_dword(dev
, PCI_BASE_ADDRESS_0
, 0);
180 pci_write_config_dword(dev
, PCI_BASE_ADDRESS_1
, 0);
182 DECLARE_PCI_FIXUP_HEADER(0x1317, 0x8688, adm8668_pci_fixup
);
184 static int __init
adm8668_pci_init(void)
186 void __iomem
*io_map_base
;
188 ioport_resource
.start
= ADMPCI_IO_BASE
;
189 ioport_resource
.end
= ADMPCI_IO_BASE
+ ADMPCI_IO_SIZE
;
191 io_map_base
= ioremap(ADMPCI_IO_BASE
, ADMPCI_IO_SIZE
);
193 printk("io_map_base didn't work.\n");
195 adm8668_pci_controller
.io_map_base
= (unsigned long)io_map_base
;
196 register_pci_controller(&adm8668_pci_controller
);
200 arch_initcall(adm8668_pci_init
);