2bf119297225aea668b2bced8fb9ccb83a20c2a4
[openwrt/openwrt.git] / target / linux / adm8668 / files / arch / mips / adm8668 / pci.c
1 /*
2 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
3 *
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
6 * for more details.
7 */
8
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>
14 #include <asm/pci.h>
15 #include <adm8668.h>
16
17 volatile u32* pci_config_address_reg = (volatile u32*)KSEG1ADDR(PCICFG_BASE);
18 volatile u32* pci_config_data_reg = (volatile u32*)KSEG1ADDR(PCIDAT_BASE);
19
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)
29
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)
33
34
35 #define cfgaddr(bus, devfn, where) ( \
36 (bus ? ((bus->number & 0xff) << 0x10) : 0) | \
37 ((devfn & 0xff) << 0x08) | \
38 (where & 0xfc)) | PCI_ENABLE
39
40 /* assumed little endian */
41 static int adm8668_read_config(struct pci_bus *bus, unsigned int devfn,
42 int where, int size, u32 *val)
43 {
44 switch (size)
45 {
46 case 1:
47 *pci_config_address_reg = cfgaddr(bus, devfn, where);
48 *val = (le32_to_cpu(*pci_config_data_reg) >> ((where&3)<<3)) & 0xff;
49 break;
50 case 2:
51 if (where & 1)
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;
55 break;
56 case 4:
57 if (where & 3)
58 return PCIBIOS_BAD_REGISTER_NUMBER;
59 *pci_config_address_reg = cfgaddr(bus, devfn, where);
60 *val = le32_to_cpu(*pci_config_data_reg);
61 break;
62 }
63
64 return PCIBIOS_SUCCESSFUL;
65 }
66
67 static int adm8668_write_config(struct pci_bus *bus, unsigned int devfn,
68 int where, int size, u32 val)
69 {
70 switch (size)
71 {
72 case 1:
73 *pci_config_address_reg = cfgaddr(bus, devfn, where);
74 *(volatile u8 *)(((int)pci_config_data_reg) + (where & 3)) = val;
75 break;
76 case 2:
77 if (where & 1)
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;
81 break;
82 case 4:
83 if (where & 3)
84 return PCIBIOS_BAD_REGISTER_NUMBER;
85 *pci_config_address_reg = cfgaddr(bus, devfn, where);
86 *pci_config_data_reg = (val);
87 }
88
89 return PCIBIOS_SUCCESSFUL;
90 }
91
92
93 struct pci_ops adm8668_pci_ops = {
94 .read = adm8668_read_config,
95 .write = adm8668_write_config
96 };
97
98
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
104 };
105
106
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
112 };
113
114 #ifdef CONFIG_ADM8668_DISABLE_PCI
115 struct pci_controller mips_pci_channels[] = {
116 { NULL, NULL, NULL , NULL , NULL}
117 };
118 #else
119 struct pci_controller mips_pci_channels = {
120 .pci_ops = &adm8668_pci_ops,
121 .io_resource = &pciioport_resource,
122 .mem_resource = &pciiomem_resource,
123 };
124 #endif
125
126 int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
127 {
128 switch (slot)
129 {
130 case 1:
131 return 14;
132 case 2:
133 return 13;
134 case 3:
135 return 12;
136 default:
137 return dev->irq;
138 }
139 }
140
141 int pcibios_plat_dev_init(struct pci_dev *dev)
142 {
143 return 0;
144 }
145
146 static int __init adm8668_pci_init(void)
147 {
148 void __iomem *io_map_base;
149
150 printk("adm8668_pci_init()\n");
151
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;
155
156 io_map_base = ioremap(ADMPCI_IO_BASE, ADMPCI_IO_SIZE);
157 if (!io_map_base)
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);
161
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);
167
168 return 0;
169 }
170
171 arch_initcall(adm8668_pci_init);