2 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/pci.h>
12 #include <linux/types.h>
13 #include <asm/byteorder.h>
17 volatile u32
* pci_config_address_reg
= (volatile u32
*)KSEG1ADDR(PCICFG_BASE
);
18 volatile u32
* pci_config_data_reg
= (volatile u32
*)KSEG1ADDR(PCIDAT_BASE
);
20 #define PCI_ENABLE 0x80000000
21 #define ADMPCI_IO_BASE 0x12600000
22 #define ADMPCI_IO_SIZE 0x1fffff
23 #define ADMPCI_MEM_BASE 0x16000000
24 #define ADMPCI_MEM_SIZE 0x7ffffff
25 #define PCI_CMM_IOACC_EN 0x1
26 #define PCI_CMM_MEMACC_EN 0x2
27 #define PCI_CMM_MASTER_EN 0x4
28 #define PCI_CMM_DEF (PCI_CMM_IOACC_EN | PCI_CMM_MEMACC_EN | PCI_CMM_MASTER_EN)
30 #define PCI_DEF_CACHE_LINE_SZ 0
31 #define PCI_DEF_LATENCY_TIMER 0x20
32 #define PCI_DEF_CACHE_LATENCY ((PCI_DEF_LATENCY_TIMER << 8) | PCI_DEF_CACHE_LINE_SZ)
35 #define cfgaddr(bus, devfn, where) ( \
36 (bus ? ((bus->number & 0xff) << 0x10) : 0) | \
37 ((devfn & 0xff) << 0x08) | \
38 (where & 0xfc)) | PCI_ENABLE
40 /* assumed little endian */
41 static int adm8668_read_config(struct pci_bus
*bus
, unsigned int devfn
,
42 int where
, int size
, u32
*val
)
47 *pci_config_address_reg
= cfgaddr(bus
, devfn
, where
);
48 *val
= (le32_to_cpu(*pci_config_data_reg
) >> ((where
&3)<<3)) & 0xff;
52 return PCIBIOS_BAD_REGISTER_NUMBER
;
53 *pci_config_address_reg
= cfgaddr(bus
, devfn
, where
);
54 *val
= (le32_to_cpu(*pci_config_data_reg
) >> ((where
&3)<<3)) & 0xffff;
58 return PCIBIOS_BAD_REGISTER_NUMBER
;
59 *pci_config_address_reg
= cfgaddr(bus
, devfn
, where
);
60 *val
= le32_to_cpu(*pci_config_data_reg
);
64 return PCIBIOS_SUCCESSFUL
;
67 static int adm8668_write_config(struct pci_bus
*bus
, unsigned int devfn
,
68 int where
, int size
, u32 val
)
73 *pci_config_address_reg
= cfgaddr(bus
, devfn
, where
);
74 *(volatile u8
*)(((int)pci_config_data_reg
) + (where
& 3)) = val
;
78 return PCIBIOS_BAD_REGISTER_NUMBER
;
79 *pci_config_address_reg
= cfgaddr(bus
, devfn
, where
);
80 *(volatile u16
*)(((int)pci_config_data_reg
) + (where
& 2)) = val
;
84 return PCIBIOS_BAD_REGISTER_NUMBER
;
85 *pci_config_address_reg
= cfgaddr(bus
, devfn
, where
);
86 *pci_config_data_reg
= (val
);
89 return PCIBIOS_SUCCESSFUL
;
93 struct pci_ops adm8668_pci_ops
= {
94 .read
= adm8668_read_config
,
95 .write
= adm8668_write_config
99 struct resource pciioport_resource
= {
100 .name
= "adm8668_pci",
101 .start
= ADMPCI_IO_BASE
,
102 .end
= ADMPCI_IO_BASE
+ ADMPCI_IO_SIZE
,
103 .flags
= IORESOURCE_IO
107 struct resource pciiomem_resource
= {
108 .name
= "adm8668_pci",
109 .start
= ADMPCI_MEM_BASE
,
110 .end
= ADMPCI_MEM_BASE
+ ADMPCI_MEM_SIZE
,
111 .flags
= IORESOURCE_MEM
114 #ifdef CONFIG_ADM8668_DISABLE_PCI
115 struct pci_controller mips_pci_channels
[] = {
116 { NULL
, NULL
, NULL
, NULL
, NULL
}
119 struct pci_controller mips_pci_channels
= {
120 .pci_ops
= &adm8668_pci_ops
,
121 .io_resource
= &pciioport_resource
,
122 .mem_resource
= &pciiomem_resource
,
126 int pcibios_map_irq(const struct pci_dev
*dev
, u8 slot
, u8 pin
)
141 int pcibios_plat_dev_init(struct pci_dev
*dev
)
146 static int __init
adm8668_pci_init(void)
148 void __iomem
*io_map_base
;
150 printk("adm8668_pci_init()\n");
152 /* what's an io port? this is MIPS... *shrug* */
153 ioport_resource
.start
= ADMPCI_IO_BASE
;
154 ioport_resource
.end
= ADMPCI_IO_BASE
+ ADMPCI_IO_SIZE
;
156 io_map_base
= ioremap(ADMPCI_IO_BASE
, ADMPCI_IO_SIZE
);
158 printk("io_map_base didn't work.\n");
159 mips_pci_channels
.io_map_base
= (unsigned long)io_map_base
;
160 register_pci_controller(&mips_pci_channels
);
162 /* this needed? linksys' gpl 2.4 did it... */
163 adm8668_write_config(NULL
, 0, PCI_CACHE_LINE_SIZE
, 2, 0);
164 adm8668_write_config(NULL
, 0, PCI_BASE_ADDRESS_0
, 4, 0);
165 adm8668_write_config(NULL
, 0, PCI_BASE_ADDRESS_1
, 4, 0);
166 adm8668_write_config(NULL
, 0, PCI_COMMAND
, 4, PCI_CMM_DEF
);
171 arch_initcall(adm8668_pci_init
);