Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-pxa/cm-x2xx-pci.c
10817 views
1
/*
2
* linux/arch/arm/mach-pxa/cm-x2xx-pci.c
3
*
4
* PCI bios-type initialisation for PCI machines
5
*
6
* Bits taken from various places.
7
*
8
* Copyright (C) 2007, 2008 Compulab, Ltd.
9
* Mike Rapoport <[email protected]>
10
*
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License version 2 as
13
* published by the Free Software Foundation.
14
*/
15
16
#include <linux/kernel.h>
17
#include <linux/pci.h>
18
#include <linux/init.h>
19
#include <linux/device.h>
20
#include <linux/platform_device.h>
21
#include <linux/irq.h>
22
#include <linux/gpio.h>
23
24
#include <asm/mach/pci.h>
25
#include <asm/mach-types.h>
26
27
#include <asm/hardware/it8152.h>
28
29
unsigned long it8152_base_address;
30
static int cmx2xx_it8152_irq_gpio;
31
32
static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
33
{
34
/* clear our parent irq */
35
desc->irq_data.chip->irq_ack(&desc->irq_data);
36
37
it8152_irq_demux(irq, desc);
38
}
39
40
void __cmx2xx_pci_init_irq(int irq_gpio)
41
{
42
it8152_init_irq();
43
44
cmx2xx_it8152_irq_gpio = irq_gpio;
45
46
irq_set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING);
47
48
irq_set_chained_handler(gpio_to_irq(irq_gpio),
49
cmx2xx_it8152_irq_demux);
50
}
51
52
#ifdef CONFIG_PM
53
static unsigned long sleep_save_ite[10];
54
55
void __cmx2xx_pci_suspend(void)
56
{
57
/* save ITE state */
58
sleep_save_ite[0] = __raw_readl(IT8152_INTC_PDCNIMR);
59
sleep_save_ite[1] = __raw_readl(IT8152_INTC_LPCNIMR);
60
sleep_save_ite[2] = __raw_readl(IT8152_INTC_LPNIAR);
61
62
/* Clear ITE IRQ's */
63
__raw_writel((0), IT8152_INTC_PDCNIRR);
64
__raw_writel((0), IT8152_INTC_LPCNIRR);
65
}
66
67
void __cmx2xx_pci_resume(void)
68
{
69
/* restore IT8152 state */
70
__raw_writel((sleep_save_ite[0]), IT8152_INTC_PDCNIMR);
71
__raw_writel((sleep_save_ite[1]), IT8152_INTC_LPCNIMR);
72
__raw_writel((sleep_save_ite[2]), IT8152_INTC_LPNIAR);
73
}
74
#else
75
void cmx2xx_pci_suspend(void) {}
76
void cmx2xx_pci_resume(void) {}
77
#endif
78
79
/* PCI IRQ mapping*/
80
static int __init cmx2xx_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
81
{
82
int irq;
83
84
dev_dbg(&dev->dev, "%s: slot=%x, pin=%x\n", __func__, slot, pin);
85
86
irq = it8152_pci_map_irq(dev, slot, pin);
87
if (irq)
88
return irq;
89
90
/*
91
Here comes the ugly part. The routing is baseboard specific,
92
but defining a platform for each possible base of CM-X2XX is
93
unrealistic. Here we keep mapping for ATXBase and SB-X2XX.
94
*/
95
/* ATXBASE PCI slot */
96
if (slot == 7)
97
return IT8152_PCI_INTA;
98
99
/* ATXBase/SB-X2XX CardBus */
100
if (slot == 8 || slot == 0)
101
return IT8152_PCI_INTB;
102
103
/* ATXBase Ethernet */
104
if (slot == 9)
105
return IT8152_PCI_INTA;
106
107
/* CM-x255 Onboard Ethernet */
108
if (slot == 15)
109
return IT8152_PCI_INTC;
110
111
/* SB-x2xx Ethernet */
112
if (slot == 16)
113
return IT8152_PCI_INTA;
114
115
/* PC104+ interrupt routing */
116
if ((slot == 17) || (slot == 19))
117
return IT8152_PCI_INTA;
118
if ((slot == 18) || (slot == 20))
119
return IT8152_PCI_INTB;
120
121
return(0);
122
}
123
124
static void cmx2xx_pci_preinit(void)
125
{
126
pr_info("Initializing CM-X2XX PCI subsystem\n");
127
128
__raw_writel(0x800, IT8152_PCI_CFG_ADDR);
129
if (__raw_readl(IT8152_PCI_CFG_DATA) == 0x81521283) {
130
pr_info("PCI Bridge found.\n");
131
132
/* set PCI I/O base at 0 */
133
writel(0x848, IT8152_PCI_CFG_ADDR);
134
writel(0, IT8152_PCI_CFG_DATA);
135
136
/* set PCI memory base at 0 */
137
writel(0x840, IT8152_PCI_CFG_ADDR);
138
writel(0, IT8152_PCI_CFG_DATA);
139
140
writel(0x20, IT8152_GPIO_GPDR);
141
142
/* CardBus Controller on ATXbase baseboard */
143
writel(0x4000, IT8152_PCI_CFG_ADDR);
144
if (readl(IT8152_PCI_CFG_DATA) == 0xAC51104C) {
145
pr_info("CardBus Bridge found.\n");
146
147
/* Configure socket 0 */
148
writel(0x408C, IT8152_PCI_CFG_ADDR);
149
writel(0x1022, IT8152_PCI_CFG_DATA);
150
151
writel(0x4080, IT8152_PCI_CFG_ADDR);
152
writel(0x3844d060, IT8152_PCI_CFG_DATA);
153
154
writel(0x4090, IT8152_PCI_CFG_ADDR);
155
writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) |
156
0x60440000),
157
IT8152_PCI_CFG_DATA);
158
159
writel(0x4018, IT8152_PCI_CFG_ADDR);
160
writel(0xb0000000, IT8152_PCI_CFG_DATA);
161
162
/* Configure socket 1 */
163
writel(0x418C, IT8152_PCI_CFG_ADDR);
164
writel(0x1022, IT8152_PCI_CFG_DATA);
165
166
writel(0x4180, IT8152_PCI_CFG_ADDR);
167
writel(0x3844d060, IT8152_PCI_CFG_DATA);
168
169
writel(0x4190, IT8152_PCI_CFG_ADDR);
170
writel(((readl(IT8152_PCI_CFG_DATA) & 0xffff) |
171
0x60440000),
172
IT8152_PCI_CFG_DATA);
173
174
writel(0x4118, IT8152_PCI_CFG_ADDR);
175
writel(0xb0000000, IT8152_PCI_CFG_DATA);
176
}
177
}
178
}
179
180
static struct hw_pci cmx2xx_pci __initdata = {
181
.swizzle = pci_std_swizzle,
182
.map_irq = cmx2xx_pci_map_irq,
183
.nr_controllers = 1,
184
.setup = it8152_pci_setup,
185
.scan = it8152_pci_scan_bus,
186
.preinit = cmx2xx_pci_preinit,
187
};
188
189
static int __init cmx2xx_init_pci(void)
190
{
191
if (machine_is_armcore())
192
pci_common_init(&cmx2xx_pci);
193
194
return 0;
195
}
196
197
subsys_initcall(cmx2xx_init_pci);
198
199