MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / arch / arm / mach-ks8695 / pci.c
blob4f76a7ed6ba2d42c4d6551040938466eef2c10c7
1 /*
2 * Copyright (c) 2003, Micrel Semiconductors
3 * Copyright (C) 2006, Greg Ungerer <gerg@snapgear.com>
5 * Written 2003 by LIQUN RUAN
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/kernel.h>
23 #include <linux/pci.h>
24 #include <linux/mm.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <asm/io.h>
28 #include <asm/mach/pci.h>
29 #include <asm/hardware.h>
30 #include <asm/arch/ks8695-regs.h>
33 static u32 pcicmd(unsigned int bus, unsigned int devfn, int where)
35 where &= 0xfffffffc;
36 return (0x80000000 | (bus << 16) | (devfn << 8) | where);
39 static void local_write_config(unsigned int bus, unsigned int devfn, int where, u32 value)
41 __raw_writel(pcicmd(bus, devfn, where), KS8695_REG(KS8695_PBCA));
42 __raw_writel(value, KS8695_REG(KS8695_PBCD));
46 static int ks8695_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
48 u32 v;
51 __raw_writel(pcicmd(bus->number, devfn, where), KS8695_REG(KS8695_PBCA));
52 v = __raw_readl(KS8695_REG(KS8695_PBCD));
54 if (size == 1)
55 *value = (u8) (v >> ((where & 0x3) * 8));
56 else if (size == 2)
57 *value = (u16) (v >> ((where & 0x2) * 8));
58 else
59 *value = v;
61 return PCIBIOS_SUCCESSFUL;
64 static u32 bytemasks[] = {
65 0xffffff00, 0xffff00ff, 0xff0ffff, 0x00ffffff,
67 static u32 wordmasks[] = {
68 0xffff0000, 0x00000000, 0x0000ffff,
71 static int ks8695_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
73 u32 cmd, v;
74 int nr;
76 v = value;
77 cmd = pcicmd(bus->number, devfn, where);
78 __raw_writel(cmd, KS8695_REG(KS8695_PBCA));
80 if (size == 1) {
81 nr = where & 0x3;
82 v = __raw_readl(KS8695_REG(KS8695_PBCD));
83 v = (v & bytemasks[nr]) | ((value & 0xff) << (nr * 8));
84 } else if (size == 2) {
85 nr = where & 0x2;
86 v = __raw_readl(KS8695_REG(KS8695_PBCD));
87 v = (v & wordmasks[nr]) | ((value & 0xffff) << (nr * 8));
90 __raw_writel(v, KS8695_REG(KS8695_PBCD));
92 return PCIBIOS_SUCCESSFUL;
95 struct pci_ops ks8695_pci_ops = {
96 .read = ks8695_pci_read_config,
97 .write = ks8695_pci_write_config,
100 static struct pci_bus *ks8695_pci_scan_bus(int nr, struct pci_sys_data *sys)
102 return pci_scan_bus(sys->busnr, &ks8695_pci_ops, sys);
105 static struct resource pci_mem = {
106 .name = "PCI memory space",
107 .start = KS8695P_PCI_MEM_BASE + 0x04000000,
108 .end = KS8695P_PCI_MEM_BASE + KS8695P_PCI_MEM_SIZE - 1,
109 .flags = IORESOURCE_MEM,
112 static struct resource pci_io = {
113 .name = "PCI IO space",
114 .start = KS8695P_PCI_IO_BASE,
115 .end = KS8695P_PCI_IO_BASE + KS8695P_PCI_IO_SIZE - 1,
116 .flags = IORESOURCE_IO,
119 static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys)
121 if (nr > 0)
122 return 0;
124 /* Assign and enable processor bridge */
125 local_write_config(0, 0, PCI_BASE_ADDRESS_0, KS8695P_PCI_MEM_BASE);
126 local_write_config(0, 0, PCI_COMMAND,
127 PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
129 request_resource(&iomem_resource, &pci_mem);
130 request_resource(&ioport_resource, &pci_io);
132 sys->resource[0] = &pci_io;
133 sys->resource[1] = &pci_mem;
134 sys->resource[2] = NULL;
136 return 1;
140 * EXT0 is used as PCI bus interrupt source.
141 * level detection (active low)
143 static void __init ks8695_pci_configure_interrupt(void)
145 u32 v;
147 v = __raw_readl(KS8695_REG(KS8695_GPIO_MODE));
148 v |= 0x00000001;
149 __raw_writel(v, KS8695_REG(KS8695_GPIO_MODE));
151 v = __raw_readl(KS8695_REG(KS8695_GPIO_CTRL));
152 v &= 0xfffffff8;
153 v |= 0x8;
154 __raw_writel(v, KS8695_REG(KS8695_GPIO_CTRL));
156 v = __raw_readl(KS8695_REG(KS8695_GPIO_MODE));
157 v &= ~0x00000001;
158 __raw_writel(v, KS8695_REG(KS8695_GPIO_MODE));
161 static void __init ks8695_pci_preinit(void)
163 #if defined(CONFIG_MACH_CM4008) || defined(CONFIG_MACH_CM41xx)
164 /* Reset the PCI bus - (GPIO line is hooked up to bus reset) */
165 u32 msk;
166 msk = __raw_readl(KS8695_REG(KS8695_GPIO_MODE));
167 __raw_writel(msk | 0x2, KS8695_REG(KS8695_GPIO_MODE));
169 msk = __raw_readl(KS8695_REG(KS8695_GPIO_DATA));
170 __raw_writel(msk & ~0x2, KS8695_REG(KS8695_GPIO_DATA));
171 udelay(1000);
172 __raw_writel(msk | 0x2, KS8695_REG(KS8695_GPIO_DATA));
173 udelay(1000);
174 #endif
176 /* stage 1 initialization, subid, subdevice = 0x0001 */
177 __raw_writel(0x00010001, KS8695_REG(KS8695_CRCSID));
179 /* stage 2 initialization */
180 /* prefetch limits with 16 words, retru enable */
181 __raw_writel(0x40000000, KS8695_REG(KS8695_PBCS));
183 /* configure memory mapping */
184 __raw_writel(KS8695P_PCIBG_MEM_BASE, KS8695_REG(KS8695_PMBA));
185 __raw_writel(KS8695P_PCI_MEM_MASK, KS8695_REG(KS8695_PMBAM));
186 __raw_writel(KS8695P_PCI_MEM_BASE, KS8695_REG(KS8695_PMBAT));
188 /* configure IO mapping */
189 __raw_writel(KS8695P_PCIBG_IO_BASE, KS8695_REG(KS8695_PIOBA));
190 __raw_writel(KS8695P_PCI_IO_MASK, KS8695_REG(KS8695_PIOBAM));
191 __raw_writel(KS8695P_PCI_IO_BASE, KS8695_REG(KS8695_PIOBAT));
193 ks8695_pci_configure_interrupt();
196 static int __init ks8695_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
198 return 2;
201 struct hw_pci ks8695_pci __initdata = {
202 .nr_controllers = 1,
203 .preinit = ks8695_pci_preinit,
204 .swizzle = pci_std_swizzle,
205 .setup = ks8695_pci_setup,
206 .scan = ks8695_pci_scan_bus,
207 .map_irq = ks8695_pci_map_irq,
210 static int __init ks8695_pci_init(void)
212 pci_common_init(&ks8695_pci);
213 return 0;
216 subsys_initcall(ks8695_pci_init);