aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/au1000
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/au1000
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/mips/au1000')
-rw-r--r--arch/mips/au1000/common/Makefile15
-rw-r--r--arch/mips/au1000/common/au1xxx_irqmap.c224
-rw-r--r--arch/mips/au1000/common/clocks.c96
-rw-r--r--arch/mips/au1000/common/cputable.c55
-rw-r--r--arch/mips/au1000/common/dbdma.c836
-rw-r--r--arch/mips/au1000/common/dbg_io.c122
-rw-r--r--arch/mips/au1000/common/dma.c243
-rw-r--r--arch/mips/au1000/common/int-handler.S68
-rw-r--r--arch/mips/au1000/common/irq.c654
-rw-r--r--arch/mips/au1000/common/pci.c97
-rw-r--r--arch/mips/au1000/common/platform.c53
-rw-r--r--arch/mips/au1000/common/power.c493
-rw-r--r--arch/mips/au1000/common/prom.c162
-rw-r--r--arch/mips/au1000/common/puts.c145
-rw-r--r--arch/mips/au1000/common/reset.c195
-rw-r--r--arch/mips/au1000/common/setup.c195
-rw-r--r--arch/mips/au1000/common/sleeper.S149
-rw-r--r--arch/mips/au1000/common/time.c469
-rw-r--r--arch/mips/au1000/common/usbdev.c1557
-rw-r--r--arch/mips/au1000/csb250/Makefile8
-rw-r--r--arch/mips/au1000/csb250/board_setup.c239
-rw-r--r--arch/mips/au1000/csb250/init.c95
-rw-r--r--arch/mips/au1000/csb250/irqmap.c60
-rw-r--r--arch/mips/au1000/db1x00/Makefile9
-rw-r--r--arch/mips/au1000/db1x00/board_setup.c127
-rw-r--r--arch/mips/au1000/db1x00/init.c74
-rw-r--r--arch/mips/au1000/db1x00/irqmap.c72
-rw-r--r--arch/mips/au1000/db1x00/mirage_ts.c261
-rw-r--r--arch/mips/au1000/hydrogen3/Makefile9
-rw-r--r--arch/mips/au1000/hydrogen3/board_setup.c70
-rw-r--r--arch/mips/au1000/hydrogen3/init.c77
-rw-r--r--arch/mips/au1000/hydrogen3/irqmap.c56
-rw-r--r--arch/mips/au1000/mtx-1/Makefile10
-rw-r--r--arch/mips/au1000/mtx-1/board_setup.c89
-rw-r--r--arch/mips/au1000/mtx-1/init.c71
-rw-r--r--arch/mips/au1000/mtx-1/irqmap.c58
-rw-r--r--arch/mips/au1000/pb1000/Makefile8
-rw-r--r--arch/mips/au1000/pb1000/board_setup.c182
-rw-r--r--arch/mips/au1000/pb1000/init.c69
-rw-r--r--arch/mips/au1000/pb1000/irqmap.c54
-rw-r--r--arch/mips/au1000/pb1100/Makefile8
-rw-r--r--arch/mips/au1000/pb1100/board_setup.c116
-rw-r--r--arch/mips/au1000/pb1100/init.c70
-rw-r--r--arch/mips/au1000/pb1100/irqmap.c57
-rw-r--r--arch/mips/au1000/pb1500/Makefile8
-rw-r--r--arch/mips/au1000/pb1500/board_setup.c138
-rw-r--r--arch/mips/au1000/pb1500/init.c69
-rw-r--r--arch/mips/au1000/pb1500/irqmap.c58
-rw-r--r--arch/mips/au1000/pb1550/Makefile9
-rw-r--r--arch/mips/au1000/pb1550/board_setup.c69
-rw-r--r--arch/mips/au1000/pb1550/init.c69
-rw-r--r--arch/mips/au1000/pb1550/irqmap.c55
-rw-r--r--arch/mips/au1000/xxs1500/Makefile9
-rw-r--r--arch/mips/au1000/xxs1500/board_setup.c91
-rw-r--r--arch/mips/au1000/xxs1500/init.c68
-rw-r--r--arch/mips/au1000/xxs1500/irqmap.c66
56 files changed, 8486 insertions, 0 deletions
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
new file mode 100644
index 000000000000..594b75e5e080
--- /dev/null
+++ b/arch/mips/au1000/common/Makefile
@@ -0,0 +1,15 @@
1#
2# Copyright 2000 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for the Alchemy Au1000 CPU, generic files.
7#
8
9obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
10 au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
11 sleeper.o cputable.o dma.o dbdma.o
12
13obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o
14obj-$(CONFIG_KGDB) += dbg_io.o
15obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c
new file mode 100644
index 000000000000..8a0f39f67c59
--- /dev/null
+++ b/arch/mips/au1000/common/au1xxx_irqmap.c
@@ -0,0 +1,224 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx processor specific IRQ tables
4 *
5 * Copyright 2004 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/config.h>
29#include <linux/errno.h>
30#include <linux/init.h>
31#include <linux/irq.h>
32#include <linux/kernel_stat.h>
33#include <linux/module.h>
34#include <linux/signal.h>
35#include <linux/sched.h>
36#include <linux/types.h>
37#include <linux/interrupt.h>
38#include <linux/ioport.h>
39#include <linux/timex.h>
40#include <linux/slab.h>
41#include <linux/random.h>
42#include <linux/delay.h>
43#include <linux/bitops.h>
44
45#include <asm/bootinfo.h>
46#include <asm/io.h>
47#include <asm/mipsregs.h>
48#include <asm/system.h>
49#include <asm/mach-au1x00/au1000.h>
50
51/* The IC0 interrupt table. This is processor, rather than
52 * board dependent, so no reason to keep this info in the board
53 * dependent files.
54 *
55 * Careful if you change match 2 request!
56 * The interrupt handler is called directly from the low level dispatch code.
57 */
58au1xxx_irq_map_t au1xxx_ic0_map[] = {
59
60#if defined(CONFIG_SOC_AU1000)
61 { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
62 { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
63 { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0},
64 { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
65 { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0},
66 { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0},
67 { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
68 { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
69 { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
70 { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
71 { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
72 { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
73 { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
74 { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
75 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
76 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
77 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
78 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
79 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
80 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
81 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
82 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
83 { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
84 { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
85 { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
86 { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
87 { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
88 { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
89 { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
90 { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
91 { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
92
93#elif defined(CONFIG_SOC_AU1500)
94
95 { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
96 { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
97 { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
98 { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
99 { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
100 { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
101 { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
102 { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
103 { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
104 { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
105 { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
106 { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
107 { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
108 { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
109 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
110 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
111 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
112 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
113 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
114 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
115 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
116 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
117 { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
118 { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
119 { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
120 { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
121 { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
122 { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
123 { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
124
125#elif defined(CONFIG_SOC_AU1100)
126
127 { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
128 { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
129 { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0},
130 { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
131 { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0},
132 { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0},
133 { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
134 { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
135 { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
136 { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
137 { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
138 { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
139 { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
140 { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
141 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
142 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
143 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
144 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
145 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
146 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
147 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
148 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
149 { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
150 { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
151 { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
152 { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
153 { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
154 { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
155 { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
156 /*{ AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0},*/
157 { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
158 { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
159
160#elif defined(CONFIG_SOC_AU1550)
161
162 { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
163 { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
164 { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
165 { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0},
166 { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0},
167 { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
168 { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
169 { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 },
170 { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
171 { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
172 { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0},
173 { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
174 { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0},
175 { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0},
176 { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 },
177 { AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
178 { AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
179 { AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
180 { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 },
181 { AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
182 { AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
183 { AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
184 { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0},
185 { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
186 { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
187 { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
188 { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
189 { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
190
191#elif defined(CONFIG_SOC_AU1200)
192
193 { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
194 { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 },
195 { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0},
196 { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0},
197 { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 },
198 { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
199 { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 },
200 { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0},
201 { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
202 { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0},
203 { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0},
204 { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 },
205 { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
206 { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
207 { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
208 { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 },
209 { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
210 { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
211 { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
212 { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0},
213 { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
214 { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
215 { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0},
216
217#else
218#error "Error: Unknown Alchemy SOC"
219#endif
220
221};
222
223int au1xxx_ic0_nr_irqs = sizeof(au1xxx_ic0_map)/sizeof(au1xxx_irq_map_t);
224
diff --git a/arch/mips/au1000/common/clocks.c b/arch/mips/au1000/common/clocks.c
new file mode 100644
index 000000000000..3ce6cace0eb0
--- /dev/null
+++ b/arch/mips/au1000/common/clocks.c
@@ -0,0 +1,96 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Simple Au1000 clocks routines.
4 *
5 * Copyright 2001 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29
30#include <linux/module.h>
31#include <asm/mach-au1x00/au1000.h>
32
33static unsigned int au1x00_clock; // Hz
34static unsigned int lcd_clock; // KHz
35static unsigned long uart_baud_base;
36
37/*
38 * Set the au1000_clock
39 */
40void set_au1x00_speed(unsigned int new_freq)
41{
42 au1x00_clock = new_freq;
43}
44
45unsigned int get_au1x00_speed(void)
46{
47 return au1x00_clock;
48}
49
50
51
52/*
53 * The UART baud base is not known at compile time ... if
54 * we want to be able to use the same code on different
55 * speed CPUs.
56 */
57unsigned long get_au1x00_uart_baud_base(void)
58{
59 return uart_baud_base;
60}
61
62void set_au1x00_uart_baud_base(unsigned long new_baud_base)
63{
64 uart_baud_base = new_baud_base;
65}
66
67/*
68 * Calculate the Au1x00's LCD clock based on the current
69 * cpu clock and the system bus clock, and try to keep it
70 * below 40 MHz (the Pb1000 board can lock-up if the LCD
71 * clock is over 40 MHz).
72 */
73void set_au1x00_lcd_clock(void)
74{
75 unsigned int static_cfg0;
76 unsigned int sys_busclk =
77 (get_au1x00_speed()/1000) /
78 ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2);
79
80 static_cfg0 = au_readl(MEM_STCFG0);
81
82 if (static_cfg0 & (1<<11))
83 lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
84 else
85 lcd_clock = sys_busclk / 4;
86
87 if (lcd_clock > 50000) /* Epson MAX */
88 printk("warning: LCD clock too high (%d KHz)\n", lcd_clock);
89}
90
91unsigned int get_au1x00_lcd_clock(void)
92{
93 return lcd_clock;
94}
95
96EXPORT_SYMBOL(get_au1x00_lcd_clock);
diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c
new file mode 100644
index 000000000000..f5521dfccfd6
--- /dev/null
+++ b/arch/mips/au1000/common/cputable.c
@@ -0,0 +1,55 @@
1/*
2 * arch/mips/au1000/common/cputable.c
3 *
4 * Copyright (C) 2004 Dan Malek (dan@embeddededge.com)
5 * Copied from PowerPC and updated for Alchemy Au1xxx processors.
6 *
7 * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14#include <linux/string.h>
15#include <linux/sched.h>
16#include <linux/threads.h>
17#include <linux/init.h>
18#include <asm/mach-au1x00/au1000.h>
19
20struct cpu_spec* cur_cpu_spec[NR_CPUS];
21
22/* With some thought, we can probably use the mask to reduce the
23 * size of the table.
24 */
25struct cpu_spec cpu_specs[] = {
26 { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0 },
27 { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0 },
28 { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0 },
29 { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1 },
30 { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1 },
31 { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1 },
32 { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1 },
33 { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1 },
34 { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1 },
35 { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1 },
36 { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1 },
37 { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 },
38 { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 },
39 { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 },
40 { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 },
41 { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 },
42};
43
44void
45set_cpuspec(void)
46{
47 struct cpu_spec *sp;
48 u32 prid;
49
50 prid = read_c0_prid();
51 sp = cpu_specs;
52 while ((prid & sp->prid_mask) != sp->prid_value)
53 sp++;
54 cur_cpu_spec[0] = sp;
55}
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
new file mode 100644
index 000000000000..adfc3172aace
--- /dev/null
+++ b/arch/mips/au1000/common/dbdma.c
@@ -0,0 +1,836 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * The Descriptor Based DMA channel manager that first appeared
5 * on the Au1550. I started with dma.c, but I think all that is
6 * left is this initial comment :-)
7 *
8 * Copyright 2004 Embedded Edge, LLC
9 * dan@embeddededge.com
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 *
31 */
32#include <linux/config.h>
33#include <linux/kernel.h>
34#include <linux/errno.h>
35#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/spinlock.h>
38#include <linux/string.h>
39#include <linux/delay.h>
40#include <linux/interrupt.h>
41#include <asm/mach-au1x00/au1000.h>
42#include <asm/mach-au1x00/au1xxx_dbdma.h>
43#include <asm/system.h>
44
45#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
46
47/*
48 * The Descriptor Based DMA supports up to 16 channels.
49 *
50 * There are 32 devices defined. We keep an internal structure
51 * of devices using these channels, along with additional
52 * information.
53 *
54 * We allocate the descriptors and allow access to them through various
55 * functions. The drivers allocate the data buffers and assign them
56 * to the descriptors.
57 */
58static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock);
59
60/* I couldn't find a macro that did this......
61*/
62#define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1))
63
64static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
65static int dbdma_initialized;
66static void au1xxx_dbdma_init(void);
67
68typedef struct dbdma_device_table {
69 u32 dev_id;
70 u32 dev_flags;
71 u32 dev_tsize;
72 u32 dev_devwidth;
73 u32 dev_physaddr; /* If FIFO */
74 u32 dev_intlevel;
75 u32 dev_intpolarity;
76} dbdev_tab_t;
77
78typedef struct dbdma_chan_config {
79 u32 chan_flags;
80 u32 chan_index;
81 dbdev_tab_t *chan_src;
82 dbdev_tab_t *chan_dest;
83 au1x_dma_chan_t *chan_ptr;
84 au1x_ddma_desc_t *chan_desc_base;
85 au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr;
86 void *chan_callparam;
87 void (*chan_callback)(int, void *, struct pt_regs *);
88} chan_tab_t;
89
90#define DEV_FLAGS_INUSE (1 << 0)
91#define DEV_FLAGS_ANYUSE (1 << 1)
92#define DEV_FLAGS_OUT (1 << 2)
93#define DEV_FLAGS_IN (1 << 3)
94
95static dbdev_tab_t dbdev_tab[] = {
96#ifdef CONFIG_SOC_AU1550
97 /* UARTS */
98 { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
99 { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
100 { DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
101 { DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 },
102
103 /* EXT DMA */
104 { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
105 { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
106 { DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 },
107 { DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 },
108
109 /* USB DEV */
110 { DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 },
111 { DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
112 { DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
113 { DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
114 { DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 },
115 { DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 },
116
117 /* PSC 0 */
118 { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
119 { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
120
121 /* PSC 1 */
122 { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
123 { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
124
125 /* PSC 2 */
126 { DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
127 { DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 },
128
129 /* PSC 3 */
130 { DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
131 { DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 },
132
133 { DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */
134 { DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */
135
136 /* MAC 0 */
137 { DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
138 { DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
139
140 /* MAC 1 */
141 { DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
142 { DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
143
144#endif /* CONFIG_SOC_AU1550 */
145
146#ifdef CONFIG_SOC_AU1200
147 { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
148 { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
149 { DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 },
150 { DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 },
151
152 { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
153 { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
154
155 { DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
156 { DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
157 { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
158 { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
159
160 { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
161 { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
162 { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
163 { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
164
165 { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
166 { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
167
168 { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
169 { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
170 { DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
171
172 { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
173 { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
174 { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
175
176 { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
177 { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
178 { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
179 { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
180
181 { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
182
183#endif // CONFIG_SOC_AU1200
184
185 { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
186 { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
187};
188
189#define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t))
190
191static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
192
193static dbdev_tab_t *
194find_dbdev_id (u32 id)
195{
196 int i;
197 dbdev_tab_t *p;
198 for (i = 0; i < DBDEV_TAB_SIZE; ++i) {
199 p = &dbdev_tab[i];
200 if (p->dev_id == id)
201 return p;
202 }
203 return NULL;
204}
205
206/* Allocate a channel and return a non-zero descriptor if successful.
207*/
208u32
209au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
210 void (*callback)(int, void *, struct pt_regs *), void *callparam)
211{
212 unsigned long flags;
213 u32 used, chan, rv;
214 u32 dcp;
215 int i;
216 dbdev_tab_t *stp, *dtp;
217 chan_tab_t *ctp;
218 volatile au1x_dma_chan_t *cp;
219
220 /* We do the intialization on the first channel allocation.
221 * We have to wait because of the interrupt handler initialization
222 * which can't be done successfully during board set up.
223 */
224 if (!dbdma_initialized)
225 au1xxx_dbdma_init();
226 dbdma_initialized = 1;
227
228 if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS))
229 return 0;
230
231 if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
232 if ((dtp = find_dbdev_id(destid)) == NULL) return 0;
233
234 used = 0;
235 rv = 0;
236
237 /* Check to see if we can get both channels.
238 */
239 spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
240 if (!(stp->dev_flags & DEV_FLAGS_INUSE) ||
241 (stp->dev_flags & DEV_FLAGS_ANYUSE)) {
242 /* Got source */
243 stp->dev_flags |= DEV_FLAGS_INUSE;
244 if (!(dtp->dev_flags & DEV_FLAGS_INUSE) ||
245 (dtp->dev_flags & DEV_FLAGS_ANYUSE)) {
246 /* Got destination */
247 dtp->dev_flags |= DEV_FLAGS_INUSE;
248 }
249 else {
250 /* Can't get dest. Release src.
251 */
252 stp->dev_flags &= ~DEV_FLAGS_INUSE;
253 used++;
254 }
255 }
256 else {
257 used++;
258 }
259 spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);
260
261 if (!used) {
262 /* Let's see if we can allocate a channel for it.
263 */
264 ctp = NULL;
265 chan = 0;
266 spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
267 for (i=0; i<NUM_DBDMA_CHANS; i++) {
268 if (chan_tab_ptr[i] == NULL) {
269 /* If kmalloc fails, it is caught below same
270 * as a channel not available.
271 */
272 ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
273 chan_tab_ptr[i] = ctp;
274 ctp->chan_index = chan = i;
275 break;
276 }
277 }
278 spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);
279
280 if (ctp != NULL) {
281 memset(ctp, 0, sizeof(chan_tab_t));
282 dcp = DDMA_CHANNEL_BASE;
283 dcp += (0x0100 * chan);
284 ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
285 cp = (volatile au1x_dma_chan_t *)dcp;
286 ctp->chan_src = stp;
287 ctp->chan_dest = dtp;
288 ctp->chan_callback = callback;
289 ctp->chan_callparam = callparam;
290
291 /* Initialize channel configuration.
292 */
293 i = 0;
294 if (stp->dev_intlevel)
295 i |= DDMA_CFG_SED;
296 if (stp->dev_intpolarity)
297 i |= DDMA_CFG_SP;
298 if (dtp->dev_intlevel)
299 i |= DDMA_CFG_DED;
300 if (dtp->dev_intpolarity)
301 i |= DDMA_CFG_DP;
302 cp->ddma_cfg = i;
303 au_sync();
304
305 /* Return a non-zero value that can be used to
306 * find the channel information in subsequent
307 * operations.
308 */
309 rv = (u32)(&chan_tab_ptr[chan]);
310 }
311 else {
312 /* Release devices.
313 */
314 stp->dev_flags &= ~DEV_FLAGS_INUSE;
315 dtp->dev_flags &= ~DEV_FLAGS_INUSE;
316 }
317 }
318 return rv;
319}
320
321/* Set the device width if source or destination is a FIFO.
322 * Should be 8, 16, or 32 bits.
323 */
324u32
325au1xxx_dbdma_set_devwidth(u32 chanid, int bits)
326{
327 u32 rv;
328 chan_tab_t *ctp;
329 dbdev_tab_t *stp, *dtp;
330
331 ctp = *((chan_tab_t **)chanid);
332 stp = ctp->chan_src;
333 dtp = ctp->chan_dest;
334 rv = 0;
335
336 if (stp->dev_flags & DEV_FLAGS_IN) { /* Source in fifo */
337 rv = stp->dev_devwidth;
338 stp->dev_devwidth = bits;
339 }
340 if (dtp->dev_flags & DEV_FLAGS_OUT) { /* Destination out fifo */
341 rv = dtp->dev_devwidth;
342 dtp->dev_devwidth = bits;
343 }
344
345 return rv;
346}
347
348/* Allocate a descriptor ring, initializing as much as possible.
349*/
350u32
351au1xxx_dbdma_ring_alloc(u32 chanid, int entries)
352{
353 int i;
354 u32 desc_base, srcid, destid;
355 u32 cmd0, cmd1, src1, dest1;
356 u32 src0, dest0;
357 chan_tab_t *ctp;
358 dbdev_tab_t *stp, *dtp;
359 au1x_ddma_desc_t *dp;
360
361 /* I guess we could check this to be within the
362 * range of the table......
363 */
364 ctp = *((chan_tab_t **)chanid);
365 stp = ctp->chan_src;
366 dtp = ctp->chan_dest;
367
368 /* The descriptors must be 32-byte aligned. There is a
369 * possibility the allocation will give us such an address,
370 * and if we try that first we are likely to not waste larger
371 * slabs of memory.
372 */
373 desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL);
374 if (desc_base == 0)
375 return 0;
376
377 if (desc_base & 0x1f) {
378 /* Lost....do it again, allocate extra, and round
379 * the address base.
380 */
381 kfree((const void *)desc_base);
382 i = entries * sizeof(au1x_ddma_desc_t);
383 i += (sizeof(au1x_ddma_desc_t) - 1);
384 if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0)
385 return 0;
386
387 desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t));
388 }
389 dp = (au1x_ddma_desc_t *)desc_base;
390
391 /* Keep track of the base descriptor.
392 */
393 ctp->chan_desc_base = dp;
394
395 /* Initialize the rings with as much information as we know.
396 */
397 srcid = stp->dev_id;
398 destid = dtp->dev_id;
399
400 cmd0 = cmd1 = src1 = dest1 = 0;
401 src0 = dest0 = 0;
402
403 cmd0 |= DSCR_CMD0_SID(srcid);
404 cmd0 |= DSCR_CMD0_DID(destid);
405 cmd0 |= DSCR_CMD0_IE | DSCR_CMD0_CV;
406 cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_CURRENT);
407
408 switch (stp->dev_devwidth) {
409 case 8:
410 cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_BYTE);
411 break;
412 case 16:
413 cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_HALFWORD);
414 break;
415 case 32:
416 default:
417 cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_WORD);
418 break;
419 }
420
421 switch (dtp->dev_devwidth) {
422 case 8:
423 cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_BYTE);
424 break;
425 case 16:
426 cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_HALFWORD);
427 break;
428 case 32:
429 default:
430 cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_WORD);
431 break;
432 }
433
434 /* If the device is marked as an in/out FIFO, ensure it is
435 * set non-coherent.
436 */
437 if (stp->dev_flags & DEV_FLAGS_IN)
438 cmd0 |= DSCR_CMD0_SN; /* Source in fifo */
439 if (dtp->dev_flags & DEV_FLAGS_OUT)
440 cmd0 |= DSCR_CMD0_DN; /* Destination out fifo */
441
442 /* Set up source1. For now, assume no stride and increment.
443 * A channel attribute update can change this later.
444 */
445 switch (stp->dev_tsize) {
446 case 1:
447 src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE1);
448 break;
449 case 2:
450 src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE2);
451 break;
452 case 4:
453 src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE4);
454 break;
455 case 8:
456 default:
457 src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE8);
458 break;
459 }
460
461 /* If source input is fifo, set static address.
462 */
463 if (stp->dev_flags & DEV_FLAGS_IN) {
464 src0 = stp->dev_physaddr;
465 src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC);
466 }
467
468 /* Set up dest1. For now, assume no stride and increment.
469 * A channel attribute update can change this later.
470 */
471 switch (dtp->dev_tsize) {
472 case 1:
473 dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE1);
474 break;
475 case 2:
476 dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE2);
477 break;
478 case 4:
479 dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE4);
480 break;
481 case 8:
482 default:
483 dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE8);
484 break;
485 }
486
487 /* If destination output is fifo, set static address.
488 */
489 if (dtp->dev_flags & DEV_FLAGS_OUT) {
490 dest0 = dtp->dev_physaddr;
491 dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC);
492 }
493
494 for (i=0; i<entries; i++) {
495 dp->dscr_cmd0 = cmd0;
496 dp->dscr_cmd1 = cmd1;
497 dp->dscr_source0 = src0;
498 dp->dscr_source1 = src1;
499 dp->dscr_dest0 = dest0;
500 dp->dscr_dest1 = dest1;
501 dp->dscr_stat = 0;
502 dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1));
503 dp++;
504 }
505
506 /* Make last descrptor point to the first.
507 */
508 dp--;
509 dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(ctp->chan_desc_base));
510 ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base;
511
512 return (u32)(ctp->chan_desc_base);
513}
514
515/* Put a source buffer into the DMA ring.
516 * This updates the source pointer and byte count. Normally used
517 * for memory to fifo transfers.
518 */
519u32
520au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes)
521{
522 chan_tab_t *ctp;
523 au1x_ddma_desc_t *dp;
524
525 /* I guess we could check this to be within the
526 * range of the table......
527 */
528 ctp = *((chan_tab_t **)chanid);
529
530 /* We should have multiple callers for a particular channel,
531 * an interrupt doesn't affect this pointer nor the descriptor,
532 * so no locking should be needed.
533 */
534 dp = ctp->put_ptr;
535
536 /* If the descriptor is valid, we are way ahead of the DMA
537 * engine, so just return an error condition.
538 */
539 if (dp->dscr_cmd0 & DSCR_CMD0_V) {
540 return 0;
541 }
542
543 /* Load up buffer address and byte count.
544 */
545 dp->dscr_source0 = virt_to_phys(buf);
546 dp->dscr_cmd1 = nbytes;
547 dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
548 ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */
549
550 /* Get next descriptor pointer.
551 */
552 ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
553
554 /* return something not zero.
555 */
556 return nbytes;
557}
558
559/* Put a destination buffer into the DMA ring.
560 * This updates the destination pointer and byte count. Normally used
561 * to place an empty buffer into the ring for fifo to memory transfers.
562 */
563u32
564au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes)
565{
566 chan_tab_t *ctp;
567 au1x_ddma_desc_t *dp;
568
569 /* I guess we could check this to be within the
570 * range of the table......
571 */
572 ctp = *((chan_tab_t **)chanid);
573
574 /* We should have multiple callers for a particular channel,
575 * an interrupt doesn't affect this pointer nor the descriptor,
576 * so no locking should be needed.
577 */
578 dp = ctp->put_ptr;
579
580 /* If the descriptor is valid, we are way ahead of the DMA
581 * engine, so just return an error condition.
582 */
583 if (dp->dscr_cmd0 & DSCR_CMD0_V)
584 return 0;
585
586 /* Load up buffer address and byte count.
587 */
588 dp->dscr_dest0 = virt_to_phys(buf);
589 dp->dscr_cmd1 = nbytes;
590 dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
591
592 /* Get next descriptor pointer.
593 */
594 ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
595
596 /* return something not zero.
597 */
598 return nbytes;
599}
600
601/* Get a destination buffer into the DMA ring.
602 * Normally used to get a full buffer from the ring during fifo
603 * to memory transfers. This does not set the valid bit, you will
604 * have to put another destination buffer to keep the DMA going.
605 */
606u32
607au1xxx_dbdma_get_dest(u32 chanid, void **buf, int *nbytes)
608{
609 chan_tab_t *ctp;
610 au1x_ddma_desc_t *dp;
611 u32 rv;
612
613 /* I guess we could check this to be within the
614 * range of the table......
615 */
616 ctp = *((chan_tab_t **)chanid);
617
618 /* We should have multiple callers for a particular channel,
619 * an interrupt doesn't affect this pointer nor the descriptor,
620 * so no locking should be needed.
621 */
622 dp = ctp->get_ptr;
623
624 /* If the descriptor is valid, we are way ahead of the DMA
625 * engine, so just return an error condition.
626 */
627 if (dp->dscr_cmd0 & DSCR_CMD0_V)
628 return 0;
629
630 /* Return buffer address and byte count.
631 */
632 *buf = (void *)(phys_to_virt(dp->dscr_dest0));
633 *nbytes = dp->dscr_cmd1;
634 rv = dp->dscr_stat;
635
636 /* Get next descriptor pointer.
637 */
638 ctp->get_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
639
640 /* return something not zero.
641 */
642 return rv;
643}
644
645void
646au1xxx_dbdma_stop(u32 chanid)
647{
648 chan_tab_t *ctp;
649 volatile au1x_dma_chan_t *cp;
650 int halt_timeout = 0;
651
652 ctp = *((chan_tab_t **)chanid);
653
654 cp = ctp->chan_ptr;
655 cp->ddma_cfg &= ~DDMA_CFG_EN; /* Disable channel */
656 au_sync();
657 while (!(cp->ddma_stat & DDMA_STAT_H)) {
658 udelay(1);
659 halt_timeout++;
660 if (halt_timeout > 100) {
661 printk("warning: DMA channel won't halt\n");
662 break;
663 }
664 }
665 /* clear current desc valid and doorbell */
666 cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
667 au_sync();
668}
669
670/* Start using the current descriptor pointer. If the dbdma encounters
671 * a not valid descriptor, it will stop. In this case, we can just
672 * continue by adding a buffer to the list and starting again.
673 */
674void
675au1xxx_dbdma_start(u32 chanid)
676{
677 chan_tab_t *ctp;
678 volatile au1x_dma_chan_t *cp;
679
680 ctp = *((chan_tab_t **)chanid);
681
682 cp = ctp->chan_ptr;
683 cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
684 cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */
685 au_sync();
686 cp->ddma_dbell = 0xffffffff; /* Make it go */
687 au_sync();
688}
689
690void
691au1xxx_dbdma_reset(u32 chanid)
692{
693 chan_tab_t *ctp;
694 au1x_ddma_desc_t *dp;
695
696 au1xxx_dbdma_stop(chanid);
697
698 ctp = *((chan_tab_t **)chanid);
699 ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base;
700
701 /* Run through the descriptors and reset the valid indicator.
702 */
703 dp = ctp->chan_desc_base;
704
705 do {
706 dp->dscr_cmd0 &= ~DSCR_CMD0_V;
707 dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
708 } while (dp != ctp->chan_desc_base);
709}
710
711u32
712au1xxx_get_dma_residue(u32 chanid)
713{
714 chan_tab_t *ctp;
715 volatile au1x_dma_chan_t *cp;
716 u32 rv;
717
718 ctp = *((chan_tab_t **)chanid);
719 cp = ctp->chan_ptr;
720
721 /* This is only valid if the channel is stopped.
722 */
723 rv = cp->ddma_bytecnt;
724 au_sync();
725
726 return rv;
727}
728
729void
730au1xxx_dbdma_chan_free(u32 chanid)
731{
732 chan_tab_t *ctp;
733 dbdev_tab_t *stp, *dtp;
734
735 ctp = *((chan_tab_t **)chanid);
736 stp = ctp->chan_src;
737 dtp = ctp->chan_dest;
738
739 au1xxx_dbdma_stop(chanid);
740
741 if (ctp->chan_desc_base != NULL)
742 kfree(ctp->chan_desc_base);
743
744 stp->dev_flags &= ~DEV_FLAGS_INUSE;
745 dtp->dev_flags &= ~DEV_FLAGS_INUSE;
746 chan_tab_ptr[ctp->chan_index] = NULL;
747
748 kfree(ctp);
749}
750
751static irqreturn_t
752dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
753{
754 u32 intstat;
755 u32 chan_index;
756 chan_tab_t *ctp;
757 au1x_ddma_desc_t *dp;
758 volatile au1x_dma_chan_t *cp;
759
760 intstat = dbdma_gptr->ddma_intstat;
761 au_sync();
762 chan_index = au_ffs(intstat) - 1;
763
764 ctp = chan_tab_ptr[chan_index];
765 cp = ctp->chan_ptr;
766 dp = ctp->cur_ptr;
767
768 /* Reset interrupt.
769 */
770 cp->ddma_irq = 0;
771 au_sync();
772
773 if (ctp->chan_callback)
774 (ctp->chan_callback)(irq, ctp->chan_callparam, regs);
775
776 ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
777
778 return IRQ_HANDLED;
779}
780
781static void
782au1xxx_dbdma_init(void)
783{
784 dbdma_gptr->ddma_config = 0;
785 dbdma_gptr->ddma_throttle = 0;
786 dbdma_gptr->ddma_inten = 0xffff;
787 au_sync();
788
789 if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT,
790 "Au1xxx dbdma", (void *)dbdma_gptr))
791 printk("Can't get 1550 dbdma irq");
792}
793
794void
795au1xxx_dbdma_dump(u32 chanid)
796{
797 chan_tab_t *ctp;
798 au1x_ddma_desc_t *dp;
799 dbdev_tab_t *stp, *dtp;
800 volatile au1x_dma_chan_t *cp;
801
802 ctp = *((chan_tab_t **)chanid);
803 stp = ctp->chan_src;
804 dtp = ctp->chan_dest;
805 cp = ctp->chan_ptr;
806
807 printk("Chan %x, stp %x (dev %d) dtp %x (dev %d) \n",
808 (u32)ctp, (u32)stp, stp - dbdev_tab, (u32)dtp, dtp - dbdev_tab);
809 printk("desc base %x, get %x, put %x, cur %x\n",
810 (u32)(ctp->chan_desc_base), (u32)(ctp->get_ptr),
811 (u32)(ctp->put_ptr), (u32)(ctp->cur_ptr));
812
813 printk("dbdma chan %x\n", (u32)cp);
814 printk("cfg %08x, desptr %08x, statptr %08x\n",
815 cp->ddma_cfg, cp->ddma_desptr, cp->ddma_statptr);
816 printk("dbell %08x, irq %08x, stat %08x, bytecnt %08x\n",
817 cp->ddma_dbell, cp->ddma_irq, cp->ddma_stat, cp->ddma_bytecnt);
818
819
820 /* Run through the descriptors
821 */
822 dp = ctp->chan_desc_base;
823
824 do {
825 printk("dp %08x, cmd0 %08x, cmd1 %08x\n",
826 (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
827 printk("src0 %08x, src1 %08x, dest0 %08x\n",
828 dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0);
829 printk("dest1 %08x, stat %08x, nxtptr %08x\n",
830 dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr);
831 dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
832 } while (dp != ctp->chan_desc_base);
833}
834
835#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
836
diff --git a/arch/mips/au1000/common/dbg_io.c b/arch/mips/au1000/common/dbg_io.c
new file mode 100644
index 000000000000..7bc768e558db
--- /dev/null
+++ b/arch/mips/au1000/common/dbg_io.c
@@ -0,0 +1,122 @@
1
2#include <linux/config.h>
3#include <asm/io.h>
4#include <asm/mach-au1x00/au1000.h>
5
6#ifdef CONFIG_KGDB
7
8/*
9 * FIXME the user should be able to select the
10 * uart to be used for debugging.
11 */
12#define DEBUG_BASE UART_DEBUG_BASE
13/**/
14
15/* we need uint32 uint8 */
16/* #include "types.h" */
17typedef unsigned char uint8;
18typedef unsigned int uint32;
19
20#define UART16550_BAUD_2400 2400
21#define UART16550_BAUD_4800 4800
22#define UART16550_BAUD_9600 9600
23#define UART16550_BAUD_19200 19200
24#define UART16550_BAUD_38400 38400
25#define UART16550_BAUD_57600 57600
26#define UART16550_BAUD_115200 115200
27
28#define UART16550_PARITY_NONE 0
29#define UART16550_PARITY_ODD 0x08
30#define UART16550_PARITY_EVEN 0x18
31#define UART16550_PARITY_MARK 0x28
32#define UART16550_PARITY_SPACE 0x38
33
34#define UART16550_DATA_5BIT 0x0
35#define UART16550_DATA_6BIT 0x1
36#define UART16550_DATA_7BIT 0x2
37#define UART16550_DATA_8BIT 0x3
38
39#define UART16550_STOP_1BIT 0x0
40#define UART16550_STOP_2BIT 0x4
41
42
43#define UART_RX 0 /* Receive buffer */
44#define UART_TX 4 /* Transmit buffer */
45#define UART_IER 8 /* Interrupt Enable Register */
46#define UART_IIR 0xC /* Interrupt ID Register */
47#define UART_FCR 0x10 /* FIFO Control Register */
48#define UART_LCR 0x14 /* Line Control Register */
49#define UART_MCR 0x18 /* Modem Control Register */
50#define UART_LSR 0x1C /* Line Status Register */
51#define UART_MSR 0x20 /* Modem Status Register */
52#define UART_CLK 0x28 /* Baud Rat4e Clock Divider */
53#define UART_MOD_CNTRL 0x100 /* Module Control */
54
55/* memory-mapped read/write of the port */
56#define UART16550_READ(y) (au_readl(DEBUG_BASE + y) & 0xff)
57#define UART16550_WRITE(y,z) (au_writel(z&0xff, DEBUG_BASE + y))
58
59extern unsigned long get_au1x00_uart_baud_base(void);
60extern unsigned long cal_r4koff(void);
61
62void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
63{
64
65 if (UART16550_READ(UART_MOD_CNTRL) != 0x3) {
66 UART16550_WRITE(UART_MOD_CNTRL, 3);
67 }
68 cal_r4koff();
69
70 /* disable interrupts */
71 UART16550_WRITE(UART_IER, 0);
72
73 /* set up baud rate */
74 {
75 uint32 divisor;
76
77 /* set divisor */
78 divisor = get_au1x00_uart_baud_base() / baud;
79 UART16550_WRITE(UART_CLK, divisor & 0xffff);
80 }
81
82 /* set data format */
83 UART16550_WRITE(UART_LCR, (data | parity | stop));
84}
85
86static int remoteDebugInitialized = 0;
87
88uint8 getDebugChar(void)
89{
90 if (!remoteDebugInitialized) {
91 remoteDebugInitialized = 1;
92 debugInit(UART16550_BAUD_115200,
93 UART16550_DATA_8BIT,
94 UART16550_PARITY_NONE,
95 UART16550_STOP_1BIT);
96 }
97
98 while((UART16550_READ(UART_LSR) & 0x1) == 0);
99 return UART16550_READ(UART_RX);
100}
101
102
103int putDebugChar(uint8 byte)
104{
105// int i;
106
107 if (!remoteDebugInitialized) {
108 remoteDebugInitialized = 1;
109 debugInit(UART16550_BAUD_115200,
110 UART16550_DATA_8BIT,
111 UART16550_PARITY_NONE,
112 UART16550_STOP_1BIT);
113 }
114
115 while ((UART16550_READ(UART_LSR)&0x40) == 0);
116 UART16550_WRITE(UART_TX, byte);
117 //for (i=0;i<0xfff;i++);
118
119 return 1;
120}
121
122#endif
diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c
new file mode 100644
index 000000000000..372c33f1353d
--- /dev/null
+++ b/arch/mips/au1000/common/dma.c
@@ -0,0 +1,243 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * A DMA channel allocator for Au1000. API is modeled loosely off of
5 * linux/kernel/dma.c.
6 *
7 * Copyright 2000 MontaVista Software Inc.
8 * Author: MontaVista Software, Inc.
9 * stevel@mvista.com or source@mvista.com
10 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 */
33#include <linux/config.h>
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/errno.h>
37#include <linux/sched.h>
38#include <linux/spinlock.h>
39#include <linux/string.h>
40#include <linux/delay.h>
41#include <linux/interrupt.h>
42#include <linux/module.h>
43#include <asm/system.h>
44#include <asm/mach-au1x00/au1000.h>
45#include <asm/mach-au1x00/au1000_dma.h>
46
47#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1100)
48/*
49 * A note on resource allocation:
50 *
51 * All drivers needing DMA channels, should allocate and release them
52 * through the public routines `request_dma()' and `free_dma()'.
53 *
54 * In order to avoid problems, all processes should allocate resources in
55 * the same sequence and release them in the reverse order.
56 *
57 * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
58 * When releasing them, first release the IRQ, then release the DMA. The
59 * main reason for this order is that, if you are requesting the DMA buffer
60 * done interrupt, you won't know the irq number until the DMA channel is
61 * returned from request_dma.
62 */
63
64
65DEFINE_SPINLOCK(au1000_dma_spin_lock);
66
67struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = {
68 {.dev_id = -1,},
69 {.dev_id = -1,},
70 {.dev_id = -1,},
71 {.dev_id = -1,},
72 {.dev_id = -1,},
73 {.dev_id = -1,},
74 {.dev_id = -1,},
75 {.dev_id = -1,}
76};
77EXPORT_SYMBOL(au1000_dma_table);
78
79// Device FIFO addresses and default DMA modes
80static const struct dma_dev {
81 unsigned int fifo_addr;
82 unsigned int dma_mode;
83} dma_dev_table[DMA_NUM_DEV] = {
84 {UART0_ADDR + UART_TX, 0},
85 {UART0_ADDR + UART_RX, 0},
86 {0, 0},
87 {0, 0},
88 {AC97C_DATA, DMA_DW16 }, // coherent
89 {AC97C_DATA, DMA_DR | DMA_DW16 }, // coherent
90 {UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC},
91 {UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC},
92 {USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC},
93 {USBD_EP0WR, DMA_DW8 | DMA_NC},
94 {USBD_EP2WR, DMA_DW8 | DMA_NC},
95 {USBD_EP3WR, DMA_DW8 | DMA_NC},
96 {USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC},
97 {USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC},
98 {I2S_DATA, DMA_DW32 | DMA_NC},
99 {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC}
100};
101
102int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
103 int length, int *eof, void *data)
104{
105 int i, len = 0;
106 struct dma_chan *chan;
107
108 for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) {
109 if ((chan = get_dma_chan(i)) != NULL) {
110 len += sprintf(buf + len, "%2d: %s\n",
111 i, chan->dev_str);
112 }
113 }
114
115 if (fpos >= len) {
116 *start = buf;
117 *eof = 1;
118 return 0;
119 }
120 *start = buf + fpos;
121 if ((len -= fpos) > length)
122 return length;
123 *eof = 1;
124 return len;
125}
126
127// Device FIFO addresses and default DMA modes - 2nd bank
128static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = {
129 {SD0_XMIT_FIFO, DMA_DS | DMA_DW8}, // coherent
130 {SD0_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8}, // coherent
131 {SD1_XMIT_FIFO, DMA_DS | DMA_DW8}, // coherent
132 {SD1_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8} // coherent
133};
134
135void dump_au1000_dma_channel(unsigned int dmanr)
136{
137 struct dma_chan *chan;
138
139 if (dmanr >= NUM_AU1000_DMA_CHANNELS)
140 return;
141 chan = &au1000_dma_table[dmanr];
142
143 printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr);
144 printk(KERN_INFO " mode = 0x%08x\n",
145 au_readl(chan->io + DMA_MODE_SET));
146 printk(KERN_INFO " addr = 0x%08x\n",
147 au_readl(chan->io + DMA_PERIPHERAL_ADDR));
148 printk(KERN_INFO " start0 = 0x%08x\n",
149 au_readl(chan->io + DMA_BUFFER0_START));
150 printk(KERN_INFO " start1 = 0x%08x\n",
151 au_readl(chan->io + DMA_BUFFER1_START));
152 printk(KERN_INFO " count0 = 0x%08x\n",
153 au_readl(chan->io + DMA_BUFFER0_COUNT));
154 printk(KERN_INFO " count1 = 0x%08x\n",
155 au_readl(chan->io + DMA_BUFFER1_COUNT));
156}
157
158
159/*
160 * Finds a free channel, and binds the requested device to it.
161 * Returns the allocated channel number, or negative on error.
162 * Requests the DMA done IRQ if irqhandler != NULL.
163 */
164int request_au1000_dma(int dev_id, const char *dev_str,
165 irqreturn_t (*irqhandler)(int, void *, struct pt_regs *),
166 unsigned long irqflags,
167 void *irq_dev_id)
168{
169 struct dma_chan *chan;
170 const struct dma_dev *dev;
171 int i, ret;
172
173#if defined(CONFIG_SOC_AU1100)
174 if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2))
175 return -EINVAL;
176#else
177 if (dev_id < 0 || dev_id >= DMA_NUM_DEV)
178 return -EINVAL;
179#endif
180
181 for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) {
182 if (au1000_dma_table[i].dev_id < 0)
183 break;
184 }
185 if (i == NUM_AU1000_DMA_CHANNELS)
186 return -ENODEV;
187
188 chan = &au1000_dma_table[i];
189
190 if (dev_id >= DMA_NUM_DEV) {
191 dev_id -= DMA_NUM_DEV;
192 dev = &dma_dev_table_bank2[dev_id];
193 } else {
194 dev = &dma_dev_table[dev_id];
195 }
196
197 if (irqhandler) {
198 chan->irq = AU1000_DMA_INT_BASE + i;
199 chan->irq_dev = irq_dev_id;
200 if ((ret = request_irq(chan->irq, irqhandler, irqflags,
201 dev_str, chan->irq_dev))) {
202 chan->irq = 0;
203 chan->irq_dev = NULL;
204 return ret;
205 }
206 } else {
207 chan->irq = 0;
208 chan->irq_dev = NULL;
209 }
210
211 // fill it in
212 chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN;
213 chan->dev_id = dev_id;
214 chan->dev_str = dev_str;
215 chan->fifo_addr = dev->fifo_addr;
216 chan->mode = dev->dma_mode;
217
218 /* initialize the channel before returning */
219 init_dma(i);
220
221 return i;
222}
223EXPORT_SYMBOL(request_au1000_dma);
224
225void free_au1000_dma(unsigned int dmanr)
226{
227 struct dma_chan *chan = get_dma_chan(dmanr);
228 if (!chan) {
229 printk("Trying to free DMA%d\n", dmanr);
230 return;
231 }
232
233 disable_dma(dmanr);
234 if (chan->irq)
235 free_irq(chan->irq, chan->irq_dev);
236
237 chan->irq = 0;
238 chan->irq_dev = NULL;
239 chan->dev_id = -1;
240}
241EXPORT_SYMBOL(free_au1000_dma);
242
243#endif // AU1000 AU1500 AU1100
diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S
new file mode 100644
index 000000000000..1c4ca883321e
--- /dev/null
+++ b/arch/mips/au1000/common/int-handler.S
@@ -0,0 +1,68 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: ppopov@mvista.com
4 *
5 * Interrupt dispatcher for Au1000 boards.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12#include <asm/asm.h>
13#include <asm/mipsregs.h>
14#include <asm/addrspace.h>
15#include <asm/regdef.h>
16#include <asm/stackframe.h>
17
18 .text
19 .set macro
20 .set noat
21 .align 5
22
23NESTED(au1000_IRQ, PT_SIZE, sp)
24 SAVE_ALL
25 CLI # Important: mark KERNEL mode !
26
27 mfc0 t0,CP0_CAUSE # get pending interrupts
28 mfc0 t1,CP0_STATUS # get enabled interrupts
29 and t0,t1 # isolate allowed ones
30
31 andi t0,0xff00 # isolate pending bits
32 beqz t0, 3f # spurious interrupt
33
34 andi a0, t0, CAUSEF_IP7
35 beq a0, zero, 1f
36 move a0, sp
37 jal mips_timer_interrupt
38 j ret_from_irq
39
401:
41 andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0
42 beq a0, zero, 2f
43 move a0,sp
44 jal intc0_req0_irqdispatch
45 j ret_from_irq
462:
47 andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1
48 beq a0, zero, 3f
49 move a0,sp
50 jal intc0_req1_irqdispatch
51 j ret_from_irq
523:
53 andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0
54 beq a0, zero, 4f
55 move a0,sp
56 jal intc1_req0_irqdispatch
57 j ret_from_irq
584:
59 andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1
60 beq a0, zero, 5f
61 move a0, sp
62 jal intc1_req1_irqdispatch
63 j ret_from_irq
64
655:
66 move a0, sp
67 j spurious_interrupt
68END(au1000_IRQ)
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
new file mode 100644
index 000000000000..d1eb5a4a9a19
--- /dev/null
+++ b/arch/mips/au1000/common/irq.c
@@ -0,0 +1,654 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1000 interrupt routines.
4 *
5 * Copyright 2001 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29#include <linux/config.h>
30#include <linux/errno.h>
31#include <linux/init.h>
32#include <linux/irq.h>
33#include <linux/kernel_stat.h>
34#include <linux/module.h>
35#include <linux/signal.h>
36#include <linux/sched.h>
37#include <linux/types.h>
38#include <linux/interrupt.h>
39#include <linux/ioport.h>
40#include <linux/timex.h>
41#include <linux/slab.h>
42#include <linux/random.h>
43#include <linux/delay.h>
44#include <linux/bitops.h>
45
46#include <asm/bootinfo.h>
47#include <asm/io.h>
48#include <asm/mipsregs.h>
49#include <asm/system.h>
50#include <asm/mach-au1x00/au1000.h>
51#ifdef CONFIG_MIPS_PB1000
52#include <asm/mach-pb1x00/pb1000.h>
53#endif
54
55#undef DEBUG_IRQ
56#ifdef DEBUG_IRQ
57/* note: prints function name for you */
58#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
59#else
60#define DPRINTK(fmt, args...)
61#endif
62
63#define EXT_INTC0_REQ0 2 /* IP 2 */
64#define EXT_INTC0_REQ1 3 /* IP 3 */
65#define EXT_INTC1_REQ0 4 /* IP 4 */
66#define EXT_INTC1_REQ1 5 /* IP 5 */
67#define MIPS_TIMER_IP 7 /* IP 7 */
68
69extern asmlinkage void au1000_IRQ(void);
70extern void set_debug_traps(void);
71extern irq_cpustat_t irq_stat [NR_CPUS];
72
73static void setup_local_irq(unsigned int irq, int type, int int_req);
74static unsigned int startup_irq(unsigned int irq);
75static void end_irq(unsigned int irq_nr);
76static inline void mask_and_ack_level_irq(unsigned int irq_nr);
77static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr);
78static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr);
79static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr);
80inline void local_enable_irq(unsigned int irq_nr);
81inline void local_disable_irq(unsigned int irq_nr);
82
83void (*board_init_irq)(void);
84
85#ifdef CONFIG_PM
86extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
87#endif
88
89static DEFINE_SPINLOCK(irq_lock);
90
91
92static unsigned int startup_irq(unsigned int irq_nr)
93{
94 local_enable_irq(irq_nr);
95 return 0;
96}
97
98
99static void shutdown_irq(unsigned int irq_nr)
100{
101 local_disable_irq(irq_nr);
102 return;
103}
104
105
106inline void local_enable_irq(unsigned int irq_nr)
107{
108 if (irq_nr > AU1000_LAST_INTC0_INT) {
109 au_writel(1<<(irq_nr-32), IC1_MASKSET);
110 au_writel(1<<(irq_nr-32), IC1_WAKESET);
111 }
112 else {
113 au_writel(1<<irq_nr, IC0_MASKSET);
114 au_writel(1<<irq_nr, IC0_WAKESET);
115 }
116 au_sync();
117}
118
119
120inline void local_disable_irq(unsigned int irq_nr)
121{
122 if (irq_nr > AU1000_LAST_INTC0_INT) {
123 au_writel(1<<(irq_nr-32), IC1_MASKCLR);
124 au_writel(1<<(irq_nr-32), IC1_WAKECLR);
125 }
126 else {
127 au_writel(1<<irq_nr, IC0_MASKCLR);
128 au_writel(1<<irq_nr, IC0_WAKECLR);
129 }
130 au_sync();
131}
132
133
134static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
135{
136 if (irq_nr > AU1000_LAST_INTC0_INT) {
137 au_writel(1<<(irq_nr-32), IC1_RISINGCLR);
138 au_writel(1<<(irq_nr-32), IC1_MASKCLR);
139 }
140 else {
141 au_writel(1<<irq_nr, IC0_RISINGCLR);
142 au_writel(1<<irq_nr, IC0_MASKCLR);
143 }
144 au_sync();
145}
146
147
148static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
149{
150 if (irq_nr > AU1000_LAST_INTC0_INT) {
151 au_writel(1<<(irq_nr-32), IC1_FALLINGCLR);
152 au_writel(1<<(irq_nr-32), IC1_MASKCLR);
153 }
154 else {
155 au_writel(1<<irq_nr, IC0_FALLINGCLR);
156 au_writel(1<<irq_nr, IC0_MASKCLR);
157 }
158 au_sync();
159}
160
161
162static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
163{
164 /* This may assume that we don't get interrupts from
165 * both edges at once, or if we do, that we don't care.
166 */
167 if (irq_nr > AU1000_LAST_INTC0_INT) {
168 au_writel(1<<(irq_nr-32), IC1_FALLINGCLR);
169 au_writel(1<<(irq_nr-32), IC1_RISINGCLR);
170 au_writel(1<<(irq_nr-32), IC1_MASKCLR);
171 }
172 else {
173 au_writel(1<<irq_nr, IC0_FALLINGCLR);
174 au_writel(1<<irq_nr, IC0_RISINGCLR);
175 au_writel(1<<irq_nr, IC0_MASKCLR);
176 }
177 au_sync();
178}
179
180
181static inline void mask_and_ack_level_irq(unsigned int irq_nr)
182{
183
184 local_disable_irq(irq_nr);
185 au_sync();
186#if defined(CONFIG_MIPS_PB1000)
187 if (irq_nr == AU1000_GPIO_15) {
188 au_writel(0x8000, PB1000_MDR); /* ack int */
189 au_sync();
190 }
191#endif
192 return;
193}
194
195
196static void end_irq(unsigned int irq_nr)
197{
198 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
199 local_enable_irq(irq_nr);
200 }
201#if defined(CONFIG_MIPS_PB1000)
202 if (irq_nr == AU1000_GPIO_15) {
203 au_writel(0x4000, PB1000_MDR); /* enable int */
204 au_sync();
205 }
206#endif
207}
208
209unsigned long save_local_and_disable(int controller)
210{
211 int i;
212 unsigned long flags, mask;
213
214 spin_lock_irqsave(&irq_lock, flags);
215 if (controller) {
216 mask = au_readl(IC1_MASKSET);
217 for (i=32; i<64; i++) {
218 local_disable_irq(i);
219 }
220 }
221 else {
222 mask = au_readl(IC0_MASKSET);
223 for (i=0; i<32; i++) {
224 local_disable_irq(i);
225 }
226 }
227 spin_unlock_irqrestore(&irq_lock, flags);
228
229 return mask;
230}
231
232void restore_local_and_enable(int controller, unsigned long mask)
233{
234 int i;
235 unsigned long flags, new_mask;
236
237 spin_lock_irqsave(&irq_lock, flags);
238 for (i=0; i<32; i++) {
239 if (mask & (1<<i)) {
240 if (controller)
241 local_enable_irq(i+32);
242 else
243 local_enable_irq(i);
244 }
245 }
246 if (controller)
247 new_mask = au_readl(IC1_MASKSET);
248 else
249 new_mask = au_readl(IC0_MASKSET);
250
251 spin_unlock_irqrestore(&irq_lock, flags);
252}
253
254
255static struct hw_interrupt_type rise_edge_irq_type = {
256 "Au1000 Rise Edge",
257 startup_irq,
258 shutdown_irq,
259 local_enable_irq,
260 local_disable_irq,
261 mask_and_ack_rise_edge_irq,
262 end_irq,
263 NULL
264};
265
266static struct hw_interrupt_type fall_edge_irq_type = {
267 "Au1000 Fall Edge",
268 startup_irq,
269 shutdown_irq,
270 local_enable_irq,
271 local_disable_irq,
272 mask_and_ack_fall_edge_irq,
273 end_irq,
274 NULL
275};
276
277static struct hw_interrupt_type either_edge_irq_type = {
278 "Au1000 Rise or Fall Edge",
279 startup_irq,
280 shutdown_irq,
281 local_enable_irq,
282 local_disable_irq,
283 mask_and_ack_either_edge_irq,
284 end_irq,
285 NULL
286};
287
288static struct hw_interrupt_type level_irq_type = {
289 "Au1000 Level",
290 startup_irq,
291 shutdown_irq,
292 local_enable_irq,
293 local_disable_irq,
294 mask_and_ack_level_irq,
295 end_irq,
296 NULL
297};
298
299#ifdef CONFIG_PM
300void startup_match20_interrupt(void)
301{
302 local_enable_irq(AU1000_TOY_MATCH2_INT);
303}
304#endif
305
306static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
307{
308 if (irq_nr > AU1000_MAX_INTR) return;
309 /* Config2[n], Config1[n], Config0[n] */
310 if (irq_nr > AU1000_LAST_INTC0_INT) {
311 switch (type) {
312 case INTC_INT_RISE_EDGE: /* 0:0:1 */
313 au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
314 au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
315 au_writel(1<<(irq_nr-32), IC1_CFG0SET);
316 irq_desc[irq_nr].handler = &rise_edge_irq_type;
317 break;
318 case INTC_INT_FALL_EDGE: /* 0:1:0 */
319 au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
320 au_writel(1<<(irq_nr-32), IC1_CFG1SET);
321 au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
322 irq_desc[irq_nr].handler = &fall_edge_irq_type;
323 break;
324 case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
325 au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
326 au_writel(1<<(irq_nr-32), IC1_CFG1SET);
327 au_writel(1<<(irq_nr-32), IC1_CFG0SET);
328 irq_desc[irq_nr].handler = &either_edge_irq_type;
329 break;
330 case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
331 au_writel(1<<(irq_nr-32), IC1_CFG2SET);
332 au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
333 au_writel(1<<(irq_nr-32), IC1_CFG0SET);
334 irq_desc[irq_nr].handler = &level_irq_type;
335 break;
336 case INTC_INT_LOW_LEVEL: /* 1:1:0 */
337 au_writel(1<<(irq_nr-32), IC1_CFG2SET);
338 au_writel(1<<(irq_nr-32), IC1_CFG1SET);
339 au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
340 irq_desc[irq_nr].handler = &level_irq_type;
341 break;
342 case INTC_INT_DISABLED: /* 0:0:0 */
343 au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
344 au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
345 au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
346 break;
347 default: /* disable the interrupt */
348 printk("unexpected int type %d (irq %d)\n", type, irq_nr);
349 au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
350 au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
351 au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
352 return;
353 }
354 if (int_req) /* assign to interrupt request 1 */
355 au_writel(1<<(irq_nr-32), IC1_ASSIGNCLR);
356 else /* assign to interrupt request 0 */
357 au_writel(1<<(irq_nr-32), IC1_ASSIGNSET);
358 au_writel(1<<(irq_nr-32), IC1_SRCSET);
359 au_writel(1<<(irq_nr-32), IC1_MASKCLR);
360 au_writel(1<<(irq_nr-32), IC1_WAKECLR);
361 }
362 else {
363 switch (type) {
364 case INTC_INT_RISE_EDGE: /* 0:0:1 */
365 au_writel(1<<irq_nr, IC0_CFG2CLR);
366 au_writel(1<<irq_nr, IC0_CFG1CLR);
367 au_writel(1<<irq_nr, IC0_CFG0SET);
368 irq_desc[irq_nr].handler = &rise_edge_irq_type;
369 break;
370 case INTC_INT_FALL_EDGE: /* 0:1:0 */
371 au_writel(1<<irq_nr, IC0_CFG2CLR);
372 au_writel(1<<irq_nr, IC0_CFG1SET);
373 au_writel(1<<irq_nr, IC0_CFG0CLR);
374 irq_desc[irq_nr].handler = &fall_edge_irq_type;
375 break;
376 case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
377 au_writel(1<<irq_nr, IC0_CFG2CLR);
378 au_writel(1<<irq_nr, IC0_CFG1SET);
379 au_writel(1<<irq_nr, IC0_CFG0SET);
380 irq_desc[irq_nr].handler = &either_edge_irq_type;
381 break;
382 case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
383 au_writel(1<<irq_nr, IC0_CFG2SET);
384 au_writel(1<<irq_nr, IC0_CFG1CLR);
385 au_writel(1<<irq_nr, IC0_CFG0SET);
386 irq_desc[irq_nr].handler = &level_irq_type;
387 break;
388 case INTC_INT_LOW_LEVEL: /* 1:1:0 */
389 au_writel(1<<irq_nr, IC0_CFG2SET);
390 au_writel(1<<irq_nr, IC0_CFG1SET);
391 au_writel(1<<irq_nr, IC0_CFG0CLR);
392 irq_desc[irq_nr].handler = &level_irq_type;
393 break;
394 case INTC_INT_DISABLED: /* 0:0:0 */
395 au_writel(1<<irq_nr, IC0_CFG0CLR);
396 au_writel(1<<irq_nr, IC0_CFG1CLR);
397 au_writel(1<<irq_nr, IC0_CFG2CLR);
398 break;
399 default: /* disable the interrupt */
400 printk("unexpected int type %d (irq %d)\n", type, irq_nr);
401 au_writel(1<<irq_nr, IC0_CFG0CLR);
402 au_writel(1<<irq_nr, IC0_CFG1CLR);
403 au_writel(1<<irq_nr, IC0_CFG2CLR);
404 return;
405 }
406 if (int_req) /* assign to interrupt request 1 */
407 au_writel(1<<irq_nr, IC0_ASSIGNCLR);
408 else /* assign to interrupt request 0 */
409 au_writel(1<<irq_nr, IC0_ASSIGNSET);
410 au_writel(1<<irq_nr, IC0_SRCSET);
411 au_writel(1<<irq_nr, IC0_MASKCLR);
412 au_writel(1<<irq_nr, IC0_WAKECLR);
413 }
414 au_sync();
415}
416
417
418void __init arch_init_irq(void)
419{
420 int i;
421 unsigned long cp0_status;
422 au1xxx_irq_map_t *imp;
423 extern au1xxx_irq_map_t au1xxx_irq_map[];
424 extern au1xxx_irq_map_t au1xxx_ic0_map[];
425 extern int au1xxx_nr_irqs;
426 extern int au1xxx_ic0_nr_irqs;
427
428 cp0_status = read_c0_status();
429 memset(irq_desc, 0, sizeof(irq_desc));
430 set_except_vector(0, au1000_IRQ);
431
432 /* Initialize interrupt controllers to a safe state.
433 */
434 au_writel(0xffffffff, IC0_CFG0CLR);
435 au_writel(0xffffffff, IC0_CFG1CLR);
436 au_writel(0xffffffff, IC0_CFG2CLR);
437 au_writel(0xffffffff, IC0_MASKCLR);
438 au_writel(0xffffffff, IC0_ASSIGNSET);
439 au_writel(0xffffffff, IC0_WAKECLR);
440 au_writel(0xffffffff, IC0_SRCSET);
441 au_writel(0xffffffff, IC0_FALLINGCLR);
442 au_writel(0xffffffff, IC0_RISINGCLR);
443 au_writel(0x00000000, IC0_TESTBIT);
444
445 au_writel(0xffffffff, IC1_CFG0CLR);
446 au_writel(0xffffffff, IC1_CFG1CLR);
447 au_writel(0xffffffff, IC1_CFG2CLR);
448 au_writel(0xffffffff, IC1_MASKCLR);
449 au_writel(0xffffffff, IC1_ASSIGNSET);
450 au_writel(0xffffffff, IC1_WAKECLR);
451 au_writel(0xffffffff, IC1_SRCSET);
452 au_writel(0xffffffff, IC1_FALLINGCLR);
453 au_writel(0xffffffff, IC1_RISINGCLR);
454 au_writel(0x00000000, IC1_TESTBIT);
455
456 /* Initialize IC0, which is fixed per processor.
457 */
458 imp = au1xxx_ic0_map;
459 for (i=0; i<au1xxx_ic0_nr_irqs; i++) {
460 setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
461 imp++;
462 }
463
464 /* Now set up the irq mapping for the board.
465 */
466 imp = au1xxx_irq_map;
467 for (i=0; i<au1xxx_nr_irqs; i++) {
468 setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
469 imp++;
470 }
471
472 set_c0_status(ALLINTS);
473
474 /* Board specific IRQ initialization.
475 */
476 if (board_init_irq)
477 (*board_init_irq)();
478}
479
480
481/*
482 * Interrupts are nested. Even if an interrupt handler is registered
483 * as "fast", we might get another interrupt before we return from
484 * intcX_reqX_irqdispatch().
485 */
486
487void intc0_req0_irqdispatch(struct pt_regs *regs)
488{
489 int irq = 0;
490 static unsigned long intc0_req0 = 0;
491
492 intc0_req0 |= au_readl(IC0_REQ0INT);
493
494 if (!intc0_req0) return;
495
496 /*
497 * Because of the tight timing of SETUP token to reply
498 * transactions, the USB devices-side packet complete
499 * interrupt needs the highest priority.
500 */
501 if ((intc0_req0 & (1<<AU1000_USB_DEV_REQ_INT))) {
502 intc0_req0 &= ~(1<<AU1000_USB_DEV_REQ_INT);
503 do_IRQ(AU1000_USB_DEV_REQ_INT, regs);
504 return;
505 }
506
507 irq = au_ffs(intc0_req0) - 1;
508 intc0_req0 &= ~(1<<irq);
509 do_IRQ(irq, regs);
510}
511
512
513void intc0_req1_irqdispatch(struct pt_regs *regs)
514{
515 int irq = 0;
516 static unsigned long intc0_req1 = 0;
517
518 intc0_req1 |= au_readl(IC0_REQ1INT);
519
520 if (!intc0_req1) return;
521
522 irq = au_ffs(intc0_req1) - 1;
523 intc0_req1 &= ~(1<<irq);
524#ifdef CONFIG_PM
525 if (irq == AU1000_TOY_MATCH2_INT) {
526 mask_and_ack_rise_edge_irq(irq);
527 counter0_irq(irq, NULL, regs);
528 local_enable_irq(irq);
529 }
530 else
531#endif
532 {
533 do_IRQ(irq, regs);
534 }
535}
536
537
538/*
539 * Interrupt Controller 1:
540 * interrupts 32 - 63
541 */
542void intc1_req0_irqdispatch(struct pt_regs *regs)
543{
544 int irq = 0;
545 static unsigned long intc1_req0 = 0;
546
547 intc1_req0 |= au_readl(IC1_REQ0INT);
548
549 if (!intc1_req0) return;
550
551 irq = au_ffs(intc1_req0) - 1;
552 intc1_req0 &= ~(1<<irq);
553 irq += 32;
554 do_IRQ(irq, regs);
555}
556
557
558void intc1_req1_irqdispatch(struct pt_regs *regs)
559{
560 int irq = 0;
561 static unsigned long intc1_req1 = 0;
562
563 intc1_req1 |= au_readl(IC1_REQ1INT);
564
565 if (!intc1_req1) return;
566
567 irq = au_ffs(intc1_req1) - 1;
568 intc1_req1 &= ~(1<<irq);
569 irq += 32;
570 do_IRQ(irq, regs);
571}
572
573#ifdef CONFIG_PM
574
575/* Save/restore the interrupt controller state.
576 * Called from the save/restore core registers as part of the
577 * au_sleep function in power.c.....maybe I should just pm_register()
578 * them instead?
579 */
580static uint sleep_intctl_config0[2];
581static uint sleep_intctl_config1[2];
582static uint sleep_intctl_config2[2];
583static uint sleep_intctl_src[2];
584static uint sleep_intctl_assign[2];
585static uint sleep_intctl_wake[2];
586static uint sleep_intctl_mask[2];
587
588void
589save_au1xxx_intctl(void)
590{
591 sleep_intctl_config0[0] = au_readl(IC0_CFG0RD);
592 sleep_intctl_config1[0] = au_readl(IC0_CFG1RD);
593 sleep_intctl_config2[0] = au_readl(IC0_CFG2RD);
594 sleep_intctl_src[0] = au_readl(IC0_SRCRD);
595 sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD);
596 sleep_intctl_wake[0] = au_readl(IC0_WAKERD);
597 sleep_intctl_mask[0] = au_readl(IC0_MASKRD);
598
599 sleep_intctl_config0[1] = au_readl(IC1_CFG0RD);
600 sleep_intctl_config1[1] = au_readl(IC1_CFG1RD);
601 sleep_intctl_config2[1] = au_readl(IC1_CFG2RD);
602 sleep_intctl_src[1] = au_readl(IC1_SRCRD);
603 sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD);
604 sleep_intctl_wake[1] = au_readl(IC1_WAKERD);
605 sleep_intctl_mask[1] = au_readl(IC1_MASKRD);
606}
607
608/* For most restore operations, we clear the entire register and
609 * then set the bits we found during the save.
610 */
611void
612restore_au1xxx_intctl(void)
613{
614 au_writel(0xffffffff, IC0_MASKCLR); au_sync();
615
616 au_writel(0xffffffff, IC0_CFG0CLR); au_sync();
617 au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync();
618 au_writel(0xffffffff, IC0_CFG1CLR); au_sync();
619 au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync();
620 au_writel(0xffffffff, IC0_CFG2CLR); au_sync();
621 au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync();
622 au_writel(0xffffffff, IC0_SRCCLR); au_sync();
623 au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync();
624 au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync();
625 au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync();
626 au_writel(0xffffffff, IC0_WAKECLR); au_sync();
627 au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync();
628 au_writel(0xffffffff, IC0_RISINGCLR); au_sync();
629 au_writel(0xffffffff, IC0_FALLINGCLR); au_sync();
630 au_writel(0x00000000, IC0_TESTBIT); au_sync();
631
632 au_writel(0xffffffff, IC1_MASKCLR); au_sync();
633
634 au_writel(0xffffffff, IC1_CFG0CLR); au_sync();
635 au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync();
636 au_writel(0xffffffff, IC1_CFG1CLR); au_sync();
637 au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync();
638 au_writel(0xffffffff, IC1_CFG2CLR); au_sync();
639 au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync();
640 au_writel(0xffffffff, IC1_SRCCLR); au_sync();
641 au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync();
642 au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync();
643 au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync();
644 au_writel(0xffffffff, IC1_WAKECLR); au_sync();
645 au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync();
646 au_writel(0xffffffff, IC1_RISINGCLR); au_sync();
647 au_writel(0xffffffff, IC1_FALLINGCLR); au_sync();
648 au_writel(0x00000000, IC1_TESTBIT); au_sync();
649
650 au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync();
651
652 au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
653}
654#endif /* CONFIG_PM */
diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c
new file mode 100644
index 000000000000..533721eef6ae
--- /dev/null
+++ b/arch/mips/au1000/common/pci.c
@@ -0,0 +1,97 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Alchemy/AMD Au1x00 pci support.
4 *
5 * Copyright 2001,2002,2003 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
10 *
11 * Support for all devices (greater than 16) added by David Gathright.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33#include <linux/config.h>
34#include <linux/types.h>
35#include <linux/pci.h>
36#include <linux/kernel.h>
37#include <linux/init.h>
38
39#include <asm/mach-au1x00/au1000.h>
40
41/* TBD */
42static struct resource pci_io_resource = {
43 "pci IO space",
44 (u32)PCI_IO_START,
45 (u32)PCI_IO_END,
46 IORESOURCE_IO
47};
48
49static struct resource pci_mem_resource = {
50 "pci memory space",
51 (u32)PCI_MEM_START,
52 (u32)PCI_MEM_END,
53 IORESOURCE_MEM
54};
55
56extern struct pci_ops au1x_pci_ops;
57
58static struct pci_controller au1x_controller = {
59 .pci_ops = &au1x_pci_ops,
60 .io_resource = &pci_io_resource,
61 .mem_resource = &pci_mem_resource,
62};
63
64#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
65static unsigned long virt_io_addr;
66#endif
67
68static int __init au1x_pci_setup(void)
69{
70#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
71 virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START,
72 Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1);
73
74 if (!virt_io_addr) {
75 printk(KERN_ERR "Unable to ioremap pci space\n");
76 return 1;
77 }
78
79#ifdef CONFIG_DMA_NONCOHERENT
80 /*
81 * Set the NC bit in controller for Au1500 pre-AC silicon
82 */
83 u32 prid = read_c0_prid();
84 if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
85 au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
86 printk("Non-coherent PCI accesses enabled\n");
87 }
88#endif
89
90 set_io_port_base(virt_io_addr);
91#endif
92
93 register_pci_controller(&au1x_controller);
94 return 0;
95}
96
97arch_initcall(au1x_pci_setup);
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
new file mode 100644
index 000000000000..0776b2db5641
--- /dev/null
+++ b/arch/mips/au1000/common/platform.c
@@ -0,0 +1,53 @@
1/*
2 * Platform device support for Au1x00 SoCs.
3 *
4 * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10#include <linux/device.h>
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/resource.h>
14
15#include <asm/mach-au1x00/au1000.h>
16
17static struct resource au1xxx_usb_ohci_resources[] = {
18 [0] = {
19 .start = USB_OHCI_BASE,
20 .end = USB_OHCI_BASE + USB_OHCI_LEN,
21 .flags = IORESOURCE_MEM,
22 },
23 [1] = {
24 .start = AU1000_USB_HOST_INT,
25 .end = AU1000_USB_HOST_INT,
26 .flags = IORESOURCE_IRQ,
27 },
28};
29
30/* The dmamask must be set for OHCI to work */
31static u64 ohci_dmamask = ~(u32)0;
32
33static struct platform_device au1xxx_usb_ohci_device = {
34 .name = "au1xxx-ohci",
35 .id = 0,
36 .dev = {
37 .dma_mask = &ohci_dmamask,
38 .coherent_dma_mask = 0xffffffff,
39 },
40 .num_resources = ARRAY_SIZE(au1xxx_usb_ohci_resources),
41 .resource = au1xxx_usb_ohci_resources,
42};
43
44static struct platform_device *au1xxx_platform_devices[] __initdata = {
45 &au1xxx_usb_ohci_device,
46};
47
48int au1xxx_platform_init(void)
49{
50 return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
51}
52
53arch_initcall(au1xxx_platform_init);
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
new file mode 100644
index 000000000000..c40daccbb5b1
--- /dev/null
+++ b/arch/mips/au1000/common/power.c
@@ -0,0 +1,493 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1000 Power Management routines.
4 *
5 * Copyright 2001 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * Some of the routines are right out of init/main.c, whose
10 * copyrights apply here.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 675 Mass Ave, Cambridge, MA 02139, USA.
31 */
32#include <linux/config.h>
33#include <linux/init.h>
34#include <linux/pm.h>
35#include <linux/slab.h>
36#include <linux/sysctl.h>
37
38#include <asm/string.h>
39#include <asm/uaccess.h>
40#include <asm/io.h>
41#include <asm/system.h>
42#include <asm/mach-au1x00/au1000.h>
43
44#ifdef CONFIG_PM
45
46#define DEBUG 1
47#ifdef DEBUG
48# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
49#else
50# define DPRINTK(fmt, args...)
51#endif
52
53static void calibrate_delay(void);
54
55extern void set_au1x00_speed(unsigned int new_freq);
56extern unsigned int get_au1x00_speed(void);
57extern unsigned long get_au1x00_uart_baud_base(void);
58extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
59extern unsigned long save_local_and_disable(int controller);
60extern void restore_local_and_enable(int controller, unsigned long mask);
61extern void local_enable_irq(unsigned int irq_nr);
62
63/* Quick acpi hack. This will have to change! */
64#define CTL_ACPI 9999
65#define ACPI_S1_SLP_TYP 19
66#define ACPI_SLEEP 21
67
68
69static DEFINE_SPINLOCK(pm_lock);
70
71/* We need to save/restore a bunch of core registers that are
72 * either volatile or reset to some state across a processor sleep.
73 * If reading a register doesn't provide a proper result for a
74 * later restore, we have to provide a function for loading that
75 * register and save a copy.
76 *
77 * We only have to save/restore registers that aren't otherwise
78 * done as part of a driver pm_* function.
79 */
80static uint sleep_aux_pll_cntrl;
81static uint sleep_cpu_pll_cntrl;
82static uint sleep_pin_function;
83static uint sleep_uart0_inten;
84static uint sleep_uart0_fifoctl;
85static uint sleep_uart0_linectl;
86static uint sleep_uart0_clkdiv;
87static uint sleep_uart0_enable;
88static uint sleep_usbhost_enable;
89static uint sleep_usbdev_enable;
90static uint sleep_static_memctlr[4][3];
91
92/* Define this to cause the value you write to /proc/sys/pm/sleep to
93 * set the TOY timer for the amount of time you want to sleep.
94 * This is done mainly for testing, but may be useful in other cases.
95 * The value is number of 32KHz ticks to sleep.
96 */
97#define SLEEP_TEST_TIMEOUT 1
98#ifdef SLEEP_TEST_TIMEOUT
99static int sleep_ticks;
100void wakeup_counter0_set(int ticks);
101#endif
102
103static void
104save_core_regs(void)
105{
106 extern void save_au1xxx_intctl(void);
107 extern void pm_eth0_shutdown(void);
108
109 /* Do the serial ports.....these really should be a pm_*
110 * registered function by the driver......but of course the
111 * standard serial driver doesn't understand our Au1xxx
112 * unique registers.
113 */
114 sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
115 sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
116 sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
117 sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
118 sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
119
120 /* Shutdown USB host/device.
121 */
122 sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
123
124 /* There appears to be some undocumented reset register....
125 */
126 au_writel(0, 0xb0100004); au_sync();
127 au_writel(0, USB_HOST_CONFIG); au_sync();
128
129 sleep_usbdev_enable = au_readl(USBD_ENABLE);
130 au_writel(0, USBD_ENABLE); au_sync();
131
132 /* Save interrupt controller state.
133 */
134 save_au1xxx_intctl();
135
136 /* Clocks and PLLs.
137 */
138 sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL);
139
140 /* We don't really need to do this one, but unless we
141 * write it again it won't have a valid value if we
142 * happen to read it.
143 */
144 sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL);
145
146 sleep_pin_function = au_readl(SYS_PINFUNC);
147
148 /* Save the static memory controller configuration.
149 */
150 sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
151 sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0);
152 sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0);
153 sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1);
154 sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1);
155 sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1);
156 sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2);
157 sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2);
158 sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2);
159 sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
160 sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
161 sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
162}
163
164static void
165restore_core_regs(void)
166{
167 extern void restore_au1xxx_intctl(void);
168 extern void wakeup_counter0_adjust(void);
169
170 au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync();
171 au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync();
172 au_writel(sleep_pin_function, SYS_PINFUNC); au_sync();
173
174 /* Restore the static memory controller configuration.
175 */
176 au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
177 au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
178 au_writel(sleep_static_memctlr[0][2], MEM_STADDR0);
179 au_writel(sleep_static_memctlr[1][0], MEM_STCFG1);
180 au_writel(sleep_static_memctlr[1][1], MEM_STTIME1);
181 au_writel(sleep_static_memctlr[1][2], MEM_STADDR1);
182 au_writel(sleep_static_memctlr[2][0], MEM_STCFG2);
183 au_writel(sleep_static_memctlr[2][1], MEM_STTIME2);
184 au_writel(sleep_static_memctlr[2][2], MEM_STADDR2);
185 au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
186 au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
187 au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
188
189 /* Enable the UART if it was enabled before sleep.
190 * I guess I should define module control bits........
191 */
192 if (sleep_uart0_enable & 0x02) {
193 au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
194 au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
195 au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
196 au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
197 au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
198 au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
199 au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
200 }
201
202 restore_au1xxx_intctl();
203 wakeup_counter0_adjust();
204}
205
206unsigned long suspend_mode;
207
208void wakeup_from_suspend(void)
209{
210 suspend_mode = 0;
211}
212
213int au_sleep(void)
214{
215 unsigned long wakeup, flags;
216 extern void save_and_sleep(void);
217
218 spin_lock_irqsave(&pm_lock,flags);
219
220 save_core_regs();
221
222 flush_cache_all();
223
224 /** The code below is all system dependent and we should probably
225 ** have a function call out of here to set this up. You need
226 ** to configure the GPIO or timer interrupts that will bring
227 ** you out of sleep.
228 ** For testing, the TOY counter wakeup is useful.
229 **/
230
231#if 0
232 au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
233
234 /* gpio 6 can cause a wake up event */
235 wakeup = au_readl(SYS_WAKEMSK);
236 wakeup &= ~(1 << 8); /* turn off match20 wakeup */
237 wakeup |= 1 << 6; /* turn on gpio 6 wakeup */
238#else
239 /* For testing, allow match20 to wake us up.
240 */
241#ifdef SLEEP_TEST_TIMEOUT
242 wakeup_counter0_set(sleep_ticks);
243#endif
244 wakeup = 1 << 8; /* turn on match20 wakeup */
245 wakeup = 0;
246#endif
247 au_writel(1, SYS_WAKESRC); /* clear cause */
248 au_sync();
249 au_writel(wakeup, SYS_WAKEMSK);
250 au_sync();
251
252 save_and_sleep();
253
254 /* after a wakeup, the cpu vectors back to 0x1fc00000 so
255 * it's up to the boot code to get us back here.
256 */
257 restore_core_regs();
258 spin_unlock_irqrestore(&pm_lock, flags);
259 return 0;
260}
261
262static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
263 void *buffer, size_t * len)
264{
265 int retval = 0;
266#ifdef SLEEP_TEST_TIMEOUT
267#define TMPBUFLEN2 16
268 char buf[TMPBUFLEN2], *p;
269#endif
270
271 if (!write) {
272 *len = 0;
273 } else {
274#ifdef SLEEP_TEST_TIMEOUT
275 if (*len > TMPBUFLEN2 - 1) {
276 return -EFAULT;
277 }
278 if (copy_from_user(buf, buffer, *len)) {
279 return -EFAULT;
280 }
281 buf[*len] = 0;
282 p = buf;
283 sleep_ticks = simple_strtoul(p, &p, 0);
284#endif
285 retval = pm_send_all(PM_SUSPEND, (void *) 2);
286
287 if (retval)
288 return retval;
289
290 au_sleep();
291 retval = pm_send_all(PM_RESUME, (void *) 0);
292 }
293 return retval;
294}
295
296static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
297 void *buffer, size_t * len)
298{
299 int retval = 0;
300 void au1k_wait(void);
301
302 if (!write) {
303 *len = 0;
304 } else {
305 retval = pm_send_all(PM_SUSPEND, (void *) 2);
306 if (retval)
307 return retval;
308 suspend_mode = 1;
309 au1k_wait();
310 retval = pm_send_all(PM_RESUME, (void *) 0);
311 }
312 return retval;
313}
314
315
316static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
317 void *buffer, size_t * len)
318{
319 int retval = 0, i;
320 unsigned long val, pll;
321#define TMPBUFLEN 64
322#define MAX_CPU_FREQ 396
323 char buf[TMPBUFLEN], *p;
324 unsigned long flags, intc0_mask, intc1_mask;
325 unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk,
326 old_refresh;
327 unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
328
329 spin_lock_irqsave(&pm_lock, flags);
330 if (!write) {
331 *len = 0;
332 } else {
333 /* Parse the new frequency */
334 if (*len > TMPBUFLEN - 1) {
335 spin_unlock_irqrestore(&pm_lock, flags);
336 return -EFAULT;
337 }
338 if (copy_from_user(buf, buffer, *len)) {
339 spin_unlock_irqrestore(&pm_lock, flags);
340 return -EFAULT;
341 }
342 buf[*len] = 0;
343 p = buf;
344 val = simple_strtoul(p, &p, 0);
345 if (val > MAX_CPU_FREQ) {
346 spin_unlock_irqrestore(&pm_lock, flags);
347 return -EFAULT;
348 }
349
350 pll = val / 12;
351 if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */
352 /* revisit this for higher speed cpus */
353 spin_unlock_irqrestore(&pm_lock, flags);
354 return -EFAULT;
355 }
356
357 old_baud_base = get_au1x00_uart_baud_base();
358 old_cpu_freq = get_au1x00_speed();
359
360 new_cpu_freq = pll * 12 * 1000000;
361 new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
362 set_au1x00_speed(new_cpu_freq);
363 set_au1x00_uart_baud_base(new_baud_base);
364
365 old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
366 new_refresh =
367 ((old_refresh * new_cpu_freq) /
368 old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff);
369
370 au_writel(pll, SYS_CPUPLL);
371 au_sync_delay(1);
372 au_writel(new_refresh, MEM_SDREFCFG);
373 au_sync_delay(1);
374
375 for (i = 0; i < 4; i++) {
376 if (au_readl
377 (UART_BASE + UART_MOD_CNTRL +
378 i * 0x00100000) == 3) {
379 old_clk =
380 au_readl(UART_BASE + UART_CLK +
381 i * 0x00100000);
382 // baud_rate = baud_base/clk
383 baud_rate = old_baud_base / old_clk;
384 /* we won't get an exact baud rate and the error
385 * could be significant enough that our new
386 * calculation will result in a clock that will
387 * give us a baud rate that's too far off from
388 * what we really want.
389 */
390 if (baud_rate > 100000)
391 baud_rate = 115200;
392 else if (baud_rate > 50000)
393 baud_rate = 57600;
394 else if (baud_rate > 30000)
395 baud_rate = 38400;
396 else if (baud_rate > 17000)
397 baud_rate = 19200;
398 else
399 (baud_rate = 9600);
400 // new_clk = new_baud_base/baud_rate
401 new_clk = new_baud_base / baud_rate;
402 au_writel(new_clk,
403 UART_BASE + UART_CLK +
404 i * 0x00100000);
405 au_sync_delay(10);
406 }
407 }
408 }
409
410
411 /* We don't want _any_ interrupts other than
412 * match20. Otherwise our calibrate_delay()
413 * calculation will be off, potentially a lot.
414 */
415 intc0_mask = save_local_and_disable(0);
416 intc1_mask = save_local_and_disable(1);
417 local_enable_irq(AU1000_TOY_MATCH2_INT);
418 spin_unlock_irqrestore(&pm_lock, flags);
419 calibrate_delay();
420 restore_local_and_enable(0, intc0_mask);
421 restore_local_and_enable(1, intc1_mask);
422 return retval;
423}
424
425
426static struct ctl_table pm_table[] = {
427 {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
428 {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
429 {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
430 {0}
431};
432
433static struct ctl_table pm_dir_table[] = {
434 {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
435 {0}
436};
437
438/*
439 * Initialize power interface
440 */
441static int __init pm_init(void)
442{
443 register_sysctl_table(pm_dir_table, 1);
444 return 0;
445}
446
447__initcall(pm_init);
448
449
450/*
451 * This is right out of init/main.c
452 */
453
454/* This is the number of bits of precision for the loops_per_jiffy. Each
455 bit takes on average 1.5/HZ seconds. This (like the original) is a little
456 better than 1% */
457#define LPS_PREC 8
458
459static void calibrate_delay(void)
460{
461 unsigned long ticks, loopbit;
462 int lps_precision = LPS_PREC;
463
464 loops_per_jiffy = (1 << 12);
465
466 while (loops_per_jiffy <<= 1) {
467 /* wait for "start of" clock tick */
468 ticks = jiffies;
469 while (ticks == jiffies)
470 /* nothing */ ;
471 /* Go .. */
472 ticks = jiffies;
473 __delay(loops_per_jiffy);
474 ticks = jiffies - ticks;
475 if (ticks)
476 break;
477 }
478
479/* Do a binary approximation to get loops_per_jiffy set to equal one clock
480 (up to lps_precision bits) */
481 loops_per_jiffy >>= 1;
482 loopbit = loops_per_jiffy;
483 while (lps_precision-- && (loopbit >>= 1)) {
484 loops_per_jiffy |= loopbit;
485 ticks = jiffies;
486 while (ticks == jiffies);
487 ticks = jiffies;
488 __delay(loops_per_jiffy);
489 if (jiffies != ticks) /* longer than 1 tick */
490 loops_per_jiffy &= ~loopbit;
491 }
492}
493#endif /* CONFIG_PM */
diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c
new file mode 100644
index 000000000000..22e5a85af4d5
--- /dev/null
+++ b/arch/mips/au1000/common/prom.c
@@ -0,0 +1,162 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * PROM library initialisation code, assuming a version of
5 * pmon is the boot code.
6 *
7 * Copyright 2000,2001 MontaVista Software Inc.
8 * Author: MontaVista Software, Inc.
9 * ppopov@mvista.com or source@mvista.com
10 *
11 * This file was derived from Carsten Langgaard's
12 * arch/mips/mips-boards/xx files.
13 *
14 * Carsten Langgaard, carstenl@mips.com
15 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version.
21 *
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
25 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * You should have received a copy of the GNU General Public License along
34 * with this program; if not, write to the Free Software Foundation, Inc.,
35 * 675 Mass Ave, Cambridge, MA 02139, USA.
36 */
37
38#include <linux/module.h>
39#include <linux/kernel.h>
40#include <linux/init.h>
41#include <linux/string.h>
42
43#include <asm/bootinfo.h>
44
45/* #define DEBUG_CMDLINE */
46
47extern int prom_argc;
48extern char **prom_argv, **prom_envp;
49
50typedef struct
51{
52 char *name;
53/* char *val; */
54}t_env_var;
55
56
57char * prom_getcmdline(void)
58{
59 return &(arcs_cmdline[0]);
60}
61
62void prom_init_cmdline(void)
63{
64 char *cp;
65 int actr;
66
67 actr = 1; /* Always ignore argv[0] */
68
69 cp = &(arcs_cmdline[0]);
70 while(actr < prom_argc) {
71 strcpy(cp, prom_argv[actr]);
72 cp += strlen(prom_argv[actr]);
73 *cp++ = ' ';
74 actr++;
75 }
76 if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
77 --cp;
78 *cp = '\0';
79
80}
81
82
83char *prom_getenv(char *envname)
84{
85 /*
86 * Return a pointer to the given environment variable.
87 * Environment variables are stored in the form of "memsize=64".
88 */
89
90 t_env_var *env = (t_env_var *)prom_envp;
91 int i;
92
93 i = strlen(envname);
94
95 while(env->name) {
96 if(strncmp(envname, env->name, i) == 0) {
97 return(env->name + strlen(envname) + 1);
98 }
99 env++;
100 }
101 return(NULL);
102}
103
104inline unsigned char str2hexnum(unsigned char c)
105{
106 if(c >= '0' && c <= '9')
107 return c - '0';
108 if(c >= 'a' && c <= 'f')
109 return c - 'a' + 10;
110 if(c >= 'A' && c <= 'F')
111 return c - 'A' + 10;
112 return 0; /* foo */
113}
114
115inline void str2eaddr(unsigned char *ea, unsigned char *str)
116{
117 int i;
118
119 for(i = 0; i < 6; i++) {
120 unsigned char num;
121
122 if((*str == '.') || (*str == ':'))
123 str++;
124 num = str2hexnum(*str++) << 4;
125 num |= (str2hexnum(*str++));
126 ea[i] = num;
127 }
128}
129
130int get_ethernet_addr(char *ethernet_addr)
131{
132 char *ethaddr_str;
133
134 ethaddr_str = prom_getenv("ethaddr");
135 if (!ethaddr_str) {
136 printk("ethaddr not set in boot prom\n");
137 return -1;
138 }
139 str2eaddr(ethernet_addr, ethaddr_str);
140
141#if 0
142 {
143 int i;
144
145 printk("get_ethernet_addr: ");
146 for (i=0; i<5; i++)
147 printk("%02x:", (unsigned char)*(ethernet_addr+i));
148 printk("%02x\n", *(ethernet_addr+i));
149 }
150#endif
151
152 return 0;
153}
154
155unsigned long __init prom_free_prom_memory(void)
156{
157 return 0;
158}
159
160EXPORT_SYMBOL(prom_getcmdline);
161EXPORT_SYMBOL(get_ethernet_addr);
162EXPORT_SYMBOL(str2eaddr);
diff --git a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c
new file mode 100644
index 000000000000..c2ae4624b77b
--- /dev/null
+++ b/arch/mips/au1000/common/puts.c
@@ -0,0 +1,145 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Low level uart routines to directly access a 16550 uart.
5 *
6 * Copyright 2001 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31#include <linux/types.h>
32#include <asm/mach-au1x00/au1000.h>
33
34#define SERIAL_BASE UART_BASE
35#define SER_CMD 0x7
36#define SER_DATA 0x1
37#define TX_BUSY 0x20
38
39#define TIMEOUT 0xffffff
40#define SLOW_DOWN
41
42static const char digits[16] = "0123456789abcdef";
43static volatile unsigned long * const com1 = (unsigned long *)SERIAL_BASE;
44
45
46#ifdef SLOW_DOWN
47static inline void slow_down(void)
48{
49 int k;
50 for (k=0; k<10000; k++);
51}
52#else
53#define slow_down()
54#endif
55
56void
57putch(const unsigned char c)
58{
59 unsigned char ch;
60 int i = 0;
61
62 do {
63 ch = com1[SER_CMD];
64 slow_down();
65 i++;
66 if (i>TIMEOUT) {
67 break;
68 }
69 } while (0 == (ch & TX_BUSY));
70 com1[SER_DATA] = c;
71}
72
73void
74puts(unsigned char *cp)
75{
76 unsigned char ch;
77 int i = 0;
78
79 while (*cp) {
80 do {
81 ch = com1[SER_CMD];
82 slow_down();
83 i++;
84 if (i>TIMEOUT) {
85 break;
86 }
87 } while (0 == (ch & TX_BUSY));
88 com1[SER_DATA] = *cp++;
89 }
90 putch('\r');
91 putch('\n');
92}
93
94void
95fputs(const char *cp)
96{
97 unsigned char ch;
98 int i = 0;
99
100 while (*cp) {
101
102 do {
103 ch = com1[SER_CMD];
104 slow_down();
105 i++;
106 if (i>TIMEOUT) {
107 break;
108 }
109 } while (0 == (ch & TX_BUSY));
110 com1[SER_DATA] = *cp++;
111 }
112}
113
114
115void
116put64(uint64_t ul)
117{
118 int cnt;
119 unsigned ch;
120
121 cnt = 16; /* 16 nibbles in a 64 bit long */
122 putch('0');
123 putch('x');
124 do {
125 cnt--;
126 ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
127 putch(digits[ch]);
128 } while (cnt > 0);
129}
130
131void
132put32(unsigned u)
133{
134 int cnt;
135 unsigned ch;
136
137 cnt = 8; /* 8 nibbles in a 32 bit long */
138 putch('0');
139 putch('x');
140 do {
141 cnt--;
142 ch = (unsigned char)(u >> cnt * 4) & 0x0F;
143 putch(digits[ch]);
144 } while (cnt > 0);
145}
diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c
new file mode 100644
index 000000000000..65b84db800e4
--- /dev/null
+++ b/arch/mips/au1000/common/reset.c
@@ -0,0 +1,195 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Au1000 reset routines.
5 *
6 * Copyright 2001 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30#include <linux/config.h>
31#include <linux/sched.h>
32#include <linux/mm.h>
33#include <asm/io.h>
34#include <asm/pgtable.h>
35#include <asm/processor.h>
36#include <asm/reboot.h>
37#include <asm/system.h>
38#include <asm/mach-au1x00/au1000.h>
39
40extern int au_sleep(void);
41extern void (*flush_cache_all)(void);
42
43void au1000_restart(char *command)
44{
45 /* Set all integrated peripherals to disabled states */
46 extern void board_reset (void);
47 u32 prid = read_c0_prid();
48
49 printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n");
50 switch (prid & 0xFF000000)
51 {
52 case 0x00000000: /* Au1000 */
53 au_writel(0x02, 0xb0000010); /* ac97_enable */
54 au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
55 asm("sync");
56 au_writel(0x00, 0xb017fffc); /* usbh_enable */
57 au_writel(0x00, 0xb0200058); /* usbd_enable */
58 au_writel(0x00, 0xb0300040); /* ir_enable */
59 au_writel(0x00, 0xb4004104); /* mac dma */
60 au_writel(0x00, 0xb4004114); /* mac dma */
61 au_writel(0x00, 0xb4004124); /* mac dma */
62 au_writel(0x00, 0xb4004134); /* mac dma */
63 au_writel(0x00, 0xb0520000); /* macen0 */
64 au_writel(0x00, 0xb0520004); /* macen1 */
65 au_writel(0x00, 0xb1000008); /* i2s_enable */
66 au_writel(0x00, 0xb1100100); /* uart0_enable */
67 au_writel(0x00, 0xb1200100); /* uart1_enable */
68 au_writel(0x00, 0xb1300100); /* uart2_enable */
69 au_writel(0x00, 0xb1400100); /* uart3_enable */
70 au_writel(0x02, 0xb1600100); /* ssi0_enable */
71 au_writel(0x02, 0xb1680100); /* ssi1_enable */
72 au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
73 au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
74 au_writel(0x00, 0xb1900028); /* sys_clksrc */
75 au_writel(0x10, 0xb1900060); /* sys_cpupll */
76 au_writel(0x00, 0xb1900064); /* sys_auxpll */
77 au_writel(0x00, 0xb1900100); /* sys_pininputen */
78 break;
79 case 0x01000000: /* Au1500 */
80 au_writel(0x02, 0xb0000010); /* ac97_enable */
81 au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
82 asm("sync");
83 au_writel(0x00, 0xb017fffc); /* usbh_enable */
84 au_writel(0x00, 0xb0200058); /* usbd_enable */
85 au_writel(0x00, 0xb4004104); /* mac dma */
86 au_writel(0x00, 0xb4004114); /* mac dma */
87 au_writel(0x00, 0xb4004124); /* mac dma */
88 au_writel(0x00, 0xb4004134); /* mac dma */
89 au_writel(0x00, 0xb1520000); /* macen0 */
90 au_writel(0x00, 0xb1520004); /* macen1 */
91 au_writel(0x00, 0xb1100100); /* uart0_enable */
92 au_writel(0x00, 0xb1400100); /* uart3_enable */
93 au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
94 au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
95 au_writel(0x00, 0xb1900028); /* sys_clksrc */
96 au_writel(0x10, 0xb1900060); /* sys_cpupll */
97 au_writel(0x00, 0xb1900064); /* sys_auxpll */
98 au_writel(0x00, 0xb1900100); /* sys_pininputen */
99 break;
100 case 0x02000000: /* Au1100 */
101 au_writel(0x02, 0xb0000010); /* ac97_enable */
102 au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
103 asm("sync");
104 au_writel(0x00, 0xb017fffc); /* usbh_enable */
105 au_writel(0x00, 0xb0200058); /* usbd_enable */
106 au_writel(0x00, 0xb0300040); /* ir_enable */
107 au_writel(0x00, 0xb4004104); /* mac dma */
108 au_writel(0x00, 0xb4004114); /* mac dma */
109 au_writel(0x00, 0xb4004124); /* mac dma */
110 au_writel(0x00, 0xb4004134); /* mac dma */
111 au_writel(0x00, 0xb0520000); /* macen0 */
112 au_writel(0x00, 0xb1000008); /* i2s_enable */
113 au_writel(0x00, 0xb1100100); /* uart0_enable */
114 au_writel(0x00, 0xb1200100); /* uart1_enable */
115 au_writel(0x00, 0xb1400100); /* uart3_enable */
116 au_writel(0x02, 0xb1600100); /* ssi0_enable */
117 au_writel(0x02, 0xb1680100); /* ssi1_enable */
118 au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
119 au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
120 au_writel(0x00, 0xb1900028); /* sys_clksrc */
121 au_writel(0x10, 0xb1900060); /* sys_cpupll */
122 au_writel(0x00, 0xb1900064); /* sys_auxpll */
123 au_writel(0x00, 0xb1900100); /* sys_pininputen */
124 break;
125 case 0x03000000: /* Au1550 */
126 au_writel(0x00, 0xb1a00004); /* psc 0 */
127 au_writel(0x00, 0xb1b00004); /* psc 1 */
128 au_writel(0x00, 0xb0a00004); /* psc 2 */
129 au_writel(0x00, 0xb0b00004); /* psc 3 */
130 au_writel(0x00, 0xb017fffc); /* usbh_enable */
131 au_writel(0x00, 0xb0200058); /* usbd_enable */
132 au_writel(0x00, 0xb4004104); /* mac dma */
133 au_writel(0x00, 0xb4004114); /* mac dma */
134 au_writel(0x00, 0xb4004124); /* mac dma */
135 au_writel(0x00, 0xb4004134); /* mac dma */
136 au_writel(0x00, 0xb1520000); /* macen0 */
137 au_writel(0x00, 0xb1520004); /* macen1 */
138 au_writel(0x00, 0xb1100100); /* uart0_enable */
139 au_writel(0x00, 0xb1200100); /* uart1_enable */
140 au_writel(0x00, 0xb1400100); /* uart3_enable */
141 au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
142 au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
143 au_writel(0x00, 0xb1900028); /* sys_clksrc */
144 au_writel(0x10, 0xb1900060); /* sys_cpupll */
145 au_writel(0x00, 0xb1900064); /* sys_auxpll */
146 au_writel(0x00, 0xb1900100); /* sys_pininputen */
147 break;
148
149 default:
150 break;
151 }
152
153 set_c0_status(ST0_BEV | ST0_ERL);
154 set_c0_config(CONF_CM_UNCACHED);
155 flush_cache_all();
156 write_c0_wired(0);
157
158 /* Give board a chance to do a hardware reset */
159 board_reset();
160
161 /* Jump to the beggining in case board_reset() is empty */
162 __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
163}
164
165void au1000_halt(void)
166{
167#if defined(CONFIG_MIPS_PB1550)
168 /* power off system */
169 printk("\n** Powering off Pb1550\n");
170 au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
171 au_sync();
172 while(1); /* should not get here */
173#endif
174 printk(KERN_NOTICE "\n** You can safely turn off the power\n");
175#ifdef CONFIG_MIPS_MIRAGE
176 au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
177#endif
178#ifdef CONFIG_PM
179 au_sleep();
180
181 /* should not get here */
182 printk(KERN_ERR "Unable to put cpu in sleep mode\n");
183 while(1);
184#else
185 while (1)
186 __asm__(".set\tmips3\n\t"
187 "wait\n\t"
188 ".set\tmips0");
189#endif
190}
191
192void au1000_power_off(void)
193{
194 au1000_halt();
195}
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
new file mode 100644
index 000000000000..dbc8b1bda963
--- /dev/null
+++ b/arch/mips/au1000/common/setup.c
@@ -0,0 +1,195 @@
1/*
2 * Copyright 2000 MontaVista Software Inc.
3 * Author: MontaVista Software, Inc.
4 * ppopov@mvista.com or source@mvista.com
5 *
6 * Updates to 2.6, Pete Popov, Embedded Alley Solutions, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/config.h>
29#include <linux/init.h>
30#include <linux/sched.h>
31#include <linux/ioport.h>
32#include <linux/mm.h>
33#include <linux/delay.h>
34#include <linux/interrupt.h>
35
36#include <asm/cpu.h>
37#include <asm/bootinfo.h>
38#include <asm/irq.h>
39#include <asm/mipsregs.h>
40#include <asm/reboot.h>
41#include <asm/pgtable.h>
42#include <asm/mach-au1x00/au1000.h>
43#include <asm/time.h>
44
45extern char * __init prom_getcmdline(void);
46extern void __init board_setup(void);
47extern void au1000_restart(char *);
48extern void au1000_halt(void);
49extern void au1000_power_off(void);
50extern struct resource ioport_resource;
51extern struct resource iomem_resource;
52extern void (*board_time_init)(void);
53extern void au1x_time_init(void);
54extern void (*board_timer_setup)(struct irqaction *irq);
55extern void au1x_timer_setup(struct irqaction *irq);
56extern void au1xxx_time_init(void);
57extern void au1xxx_timer_setup(struct irqaction *irq);
58extern void set_cpuspec(void);
59
60static int __init au1x00_setup(void)
61{
62 struct cpu_spec *sp;
63 char *argptr;
64 unsigned long prid, cpupll, bclk = 1;
65
66 set_cpuspec();
67 sp = cur_cpu_spec[0];
68
69 board_setup(); /* board specific setup */
70
71 prid = read_c0_prid();
72 cpupll = (au_readl(0xB1900060) & 0x3F) * 12;
73 printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll);
74
75 bclk = sp->cpu_bclk;
76 if (bclk)
77 {
78 /* Enable BCLK switching */
79 bclk = au_readl(0xB190003C);
80 au_writel(bclk | 0x60, 0xB190003C);
81 printk("BCLK switching enabled!\n");
82 }
83
84 if (sp->cpu_od) {
85 /* Various early Au1000 Errata corrected by this */
86 set_c0_config(1<<19); /* Set Config[OD] */
87 }
88 else {
89 /* Clear to obtain best system bus performance */
90 clear_c0_config(1<<19); /* Clear Config[OD] */
91 }
92
93 argptr = prom_getcmdline();
94
95#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
96 if ((argptr = strstr(argptr, "console=")) == NULL) {
97 argptr = prom_getcmdline();
98 strcat(argptr, " console=ttyS0,115200");
99 }
100#endif
101
102#ifdef CONFIG_FB_AU1100
103 if ((argptr = strstr(argptr, "video=")) == NULL) {
104 argptr = prom_getcmdline();
105 /* default panel */
106 /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
107#ifdef CONFIG_MIPS_HYDROGEN3
108 strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor");
109#else
110 strcat(argptr, " video=au1100fb:panel:s10,nohwcursor");
111#endif
112 }
113#endif
114
115#ifdef CONFIG_FB_E1356
116 if ((argptr = strstr(argptr, "video=")) == NULL) {
117 argptr = prom_getcmdline();
118#ifdef CONFIG_MIPS_PB1000
119 strcat(argptr, " video=e1356fb:system:pb1000,mmunalign:1");
120#else
121 strcat(argptr, " video=e1356fb:system:pb1500");
122#endif
123 }
124#endif
125
126#ifdef CONFIG_FB_XPERT98
127 if ((argptr = strstr(argptr, "video=")) == NULL) {
128 argptr = prom_getcmdline();
129 strcat(argptr, " video=atyfb:1024x768-8@70");
130 }
131#endif
132
133#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
134 /* au1000 does not support vra, au1500 and au1100 do */
135 strcat(argptr, " au1000_audio=vra");
136 argptr = prom_getcmdline();
137#endif
138 _machine_restart = au1000_restart;
139 _machine_halt = au1000_halt;
140 _machine_power_off = au1000_power_off;
141 board_time_init = au1xxx_time_init;
142 board_timer_setup = au1xxx_timer_setup;
143
144 /* IO/MEM resources. */
145 set_io_port_base(0);
146 ioport_resource.start = IOPORT_RESOURCE_START;
147 ioport_resource.end = IOPORT_RESOURCE_END;
148 iomem_resource.start = IOMEM_RESOURCE_START;
149 iomem_resource.end = IOMEM_RESOURCE_END;
150
151 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
152 au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
153 au_sync();
154 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
155 au_writel(0, SYS_TOYTRIM);
156
157 return 0;
158}
159
160early_initcall(au1x00_setup);
161
162#if defined(CONFIG_64BIT_PHYS_ADDR)
163/* This routine should be valid for all Au1x based boards */
164phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
165{
166 u32 start, end;
167
168 /* Don't fixup 36 bit addresses */
169 if ((phys_addr >> 32) != 0) return phys_addr;
170
171#ifdef CONFIG_PCI
172 start = (u32)Au1500_PCI_MEM_START;
173 end = (u32)Au1500_PCI_MEM_END;
174 /* check for pci memory window */
175 if ((phys_addr >= start) && ((phys_addr + size) < end)) {
176 return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START);
177 }
178#endif
179
180 /* All Au1x SOCs have a pcmcia controller */
181 /* We setup our 32 bit pseudo addresses to be equal to the
182 * 36 bit addr >> 4, to make it easier to check the address
183 * and fix it.
184 * The Au1x socket 0 phys attribute address is 0xF 4000 0000.
185 * The pseudo address we use is 0xF400 0000. Any address over
186 * 0xF400 0000 is a pcmcia pseudo address.
187 */
188 if ((phys_addr >= 0xF4000000) && (phys_addr < 0xFFFFFFFF)) {
189 return (phys_t)(phys_addr << 4);
190 }
191
192 /* default nop */
193 return phys_addr;
194}
195#endif
diff --git a/arch/mips/au1000/common/sleeper.S b/arch/mips/au1000/common/sleeper.S
new file mode 100644
index 000000000000..44dac3b0df3b
--- /dev/null
+++ b/arch/mips/au1000/common/sleeper.S
@@ -0,0 +1,149 @@
1/*
2 * Copyright 2002 Embedded Edge, LLC
3 * Author: dan@embeddededge.com
4 *
5 * Sleep helper for Au1xxx sleep mode.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12#include <asm/asm.h>
13#include <asm/mipsregs.h>
14#include <asm/addrspace.h>
15#include <asm/regdef.h>
16#include <asm/stackframe.h>
17
18 .text
19 .set macro
20 .set noat
21 .align 5
22
23/* Save all of the processor general registers and go to sleep.
24 * A wakeup condition will get us back here to restore the registers.
25 */
26LEAF(save_and_sleep)
27
28 subu sp, PT_SIZE
29 sw $1, PT_R1(sp)
30 sw $2, PT_R2(sp)
31 sw $3, PT_R3(sp)
32 sw $4, PT_R4(sp)
33 sw $5, PT_R5(sp)
34 sw $6, PT_R6(sp)
35 sw $7, PT_R7(sp)
36 sw $8, PT_R8(sp)
37 sw $9, PT_R9(sp)
38 sw $10, PT_R10(sp)
39 sw $11, PT_R11(sp)
40 sw $12, PT_R12(sp)
41 sw $13, PT_R13(sp)
42 sw $14, PT_R14(sp)
43 sw $15, PT_R15(sp)
44 sw $16, PT_R16(sp)
45 sw $17, PT_R17(sp)
46 sw $18, PT_R18(sp)
47 sw $19, PT_R19(sp)
48 sw $20, PT_R20(sp)
49 sw $21, PT_R21(sp)
50 sw $22, PT_R22(sp)
51 sw $23, PT_R23(sp)
52 sw $24, PT_R24(sp)
53 sw $25, PT_R25(sp)
54 sw $26, PT_R26(sp)
55 sw $27, PT_R27(sp)
56 sw $28, PT_R28(sp)
57 sw $29, PT_R29(sp)
58 sw $30, PT_R30(sp)
59 sw $31, PT_R31(sp)
60 mfc0 k0, CP0_STATUS
61 sw k0, 0x20(sp)
62 mfc0 k0, CP0_CONTEXT
63 sw k0, 0x1c(sp)
64 mfc0 k0, CP0_PAGEMASK
65 sw k0, 0x18(sp)
66 mfc0 k0, CP0_CONFIG
67 sw k0, 0x14(sp)
68
69 /* Now set up the scratch registers so the boot rom will
70 * return to this point upon wakeup.
71 */
72 la k0, 1f
73 lui k1, 0xb190
74 ori k1, 0x18
75 sw sp, 0(k1)
76 ori k1, 0x1c
77 sw k0, 0(k1)
78
79/* Put SDRAM into self refresh. Preload instructions into cache,
80 * issue a precharge, then auto refresh, then sleep commands to it.
81 */
82 la t0, sdsleep
83 .set mips3
84 cache 0x14, 0(t0)
85 cache 0x14, 32(t0)
86 cache 0x14, 64(t0)
87 cache 0x14, 96(t0)
88 .set mips0
89
90sdsleep:
91 lui k0, 0xb400
92 sw zero, 0x001c(k0) /* Precharge */
93 sw zero, 0x0020(k0) /* Auto refresh */
94 sw zero, 0x0030(k0) /* SDRAM sleep */
95 sync
96
97 lui k1, 0xb190
98 sw zero, 0x0078(k1) /* get ready to sleep */
99 sync
100 sw zero, 0x007c(k1) /* Put processor to sleep */
101 sync
102
103 /* This is where we return upon wakeup.
104 * Reload all of the registers and return.
105 */
1061: nop
107 lw k0, 0x20(sp)
108 mtc0 k0, CP0_STATUS
109 lw k0, 0x1c(sp)
110 mtc0 k0, CP0_CONTEXT
111 lw k0, 0x18(sp)
112 mtc0 k0, CP0_PAGEMASK
113 lw k0, 0x14(sp)
114 mtc0 k0, CP0_CONFIG
115 lw $1, PT_R1(sp)
116 lw $2, PT_R2(sp)
117 lw $3, PT_R3(sp)
118 lw $4, PT_R4(sp)
119 lw $5, PT_R5(sp)
120 lw $6, PT_R6(sp)
121 lw $7, PT_R7(sp)
122 lw $8, PT_R8(sp)
123 lw $9, PT_R9(sp)
124 lw $10, PT_R10(sp)
125 lw $11, PT_R11(sp)
126 lw $12, PT_R12(sp)
127 lw $13, PT_R13(sp)
128 lw $14, PT_R14(sp)
129 lw $15, PT_R15(sp)
130 lw $16, PT_R16(sp)
131 lw $17, PT_R17(sp)
132 lw $18, PT_R18(sp)
133 lw $19, PT_R19(sp)
134 lw $20, PT_R20(sp)
135 lw $21, PT_R21(sp)
136 lw $22, PT_R22(sp)
137 lw $23, PT_R23(sp)
138 lw $24, PT_R24(sp)
139 lw $25, PT_R25(sp)
140 lw $26, PT_R26(sp)
141 lw $27, PT_R27(sp)
142 lw $28, PT_R28(sp)
143 lw $29, PT_R29(sp)
144 lw $30, PT_R30(sp)
145 lw $31, PT_R31(sp)
146 addiu sp, PT_SIZE
147
148 jr ra
149END(save_and_sleep)
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
new file mode 100644
index 000000000000..fe418f1620c3
--- /dev/null
+++ b/arch/mips/au1000/common/time.c
@@ -0,0 +1,469 @@
1/*
2 *
3 * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com
4 * Copied and modified Carsten Langgaard's time.c
5 *
6 * Carsten Langgaard, carstenl@mips.com
7 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
8 *
9 * ########################################################################
10 *
11 * This program is free software; you can distribute it and/or modify it
12 * under the terms of the GNU General Public License (Version 2) as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 *
24 * ########################################################################
25 *
26 * Setting up the clock on the MIPS boards.
27 *
28 * Update. Always configure the kernel with CONFIG_NEW_TIME_C. This
29 * will use the user interface gettimeofday() functions from the
30 * arch/mips/kernel/time.c, and we provide the clock interrupt processing
31 * and the timer offset compute functions. If CONFIG_PM is selected,
32 * we also ensure the 32KHz timer is available. -- Dan
33 */
34
35#include <linux/types.h>
36#include <linux/config.h>
37#include <linux/init.h>
38#include <linux/kernel_stat.h>
39#include <linux/sched.h>
40#include <linux/spinlock.h>
41#include <linux/hardirq.h>
42
43#include <asm/compiler.h>
44#include <asm/mipsregs.h>
45#include <asm/ptrace.h>
46#include <asm/time.h>
47#include <asm/div64.h>
48#include <asm/mach-au1x00/au1000.h>
49
50#include <linux/mc146818rtc.h>
51#include <linux/timex.h>
52
53extern void startup_match20_interrupt(void);
54extern void do_softirq(void);
55extern volatile unsigned long wall_jiffies;
56unsigned long missed_heart_beats = 0;
57
58static unsigned long r4k_offset; /* Amount to increment compare reg each time */
59static unsigned long r4k_cur; /* What counter should be at next timer irq */
60int no_au1xxx_32khz;
61void (*au1k_wait_ptr)(void);
62
63/* Cycle counter value at the previous timer interrupt.. */
64static unsigned int timerhi = 0, timerlo = 0;
65
66#ifdef CONFIG_PM
67#define MATCH20_INC 328
68extern void startup_match20_interrupt(void);
69static unsigned long last_pc0, last_match20;
70#endif
71
72static DEFINE_SPINLOCK(time_lock);
73
74static inline void ack_r4ktimer(unsigned long newval)
75{
76 write_c0_compare(newval);
77}
78
79/*
80 * There are a lot of conceptually broken versions of the MIPS timer interrupt
81 * handler floating around. This one is rather different, but the algorithm
82 * is provably more robust.
83 */
84unsigned long wtimer;
85void mips_timer_interrupt(struct pt_regs *regs)
86{
87 int irq = 63;
88 unsigned long count;
89
90 irq_enter();
91 kstat_this_cpu.irqs[irq]++;
92
93 if (r4k_offset == 0)
94 goto null;
95
96 do {
97 count = read_c0_count();
98 timerhi += (count < timerlo); /* Wrap around */
99 timerlo = count;
100
101 kstat_this_cpu.irqs[irq]++;
102 do_timer(regs);
103#ifndef CONFIG_SMP
104 update_process_times(user_mode(regs));
105#endif
106 r4k_cur += r4k_offset;
107 ack_r4ktimer(r4k_cur);
108
109 } while (((unsigned long)read_c0_count()
110 - r4k_cur) < 0x7fffffff);
111
112 irq_exit();
113 return;
114
115null:
116 ack_r4ktimer(0);
117}
118
119#ifdef CONFIG_PM
120void counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
121{
122 unsigned long pc0;
123 int time_elapsed;
124 static int jiffie_drift = 0;
125
126 kstat.irqs[0][irq]++;
127 if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
128 /* should never happen! */
129 printk(KERN_WARNING "counter 0 w status eror\n");
130 return;
131 }
132
133 pc0 = au_readl(SYS_TOYREAD);
134 if (pc0 < last_match20) {
135 /* counter overflowed */
136 time_elapsed = (0xffffffff - last_match20) + pc0;
137 }
138 else {
139 time_elapsed = pc0 - last_match20;
140 }
141
142 while (time_elapsed > 0) {
143 do_timer(regs);
144#ifndef CONFIG_SMP
145 update_process_times(user_mode(regs));
146#endif
147 time_elapsed -= MATCH20_INC;
148 last_match20 += MATCH20_INC;
149 jiffie_drift++;
150 }
151
152 last_pc0 = pc0;
153 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
154 au_sync();
155
156 /* our counter ticks at 10.009765625 ms/tick, we we're running
157 * almost 10uS too slow per tick.
158 */
159
160 if (jiffie_drift >= 999) {
161 jiffie_drift -= 999;
162 do_timer(regs); /* increment jiffies by one */
163#ifndef CONFIG_SMP
164 update_process_times(user_mode(regs));
165#endif
166 }
167}
168
169/* When we wakeup from sleep, we have to "catch up" on all of the
170 * timer ticks we have missed.
171 */
172void
173wakeup_counter0_adjust(void)
174{
175 unsigned long pc0;
176 int time_elapsed;
177
178 pc0 = au_readl(SYS_TOYREAD);
179 if (pc0 < last_match20) {
180 /* counter overflowed */
181 time_elapsed = (0xffffffff - last_match20) + pc0;
182 }
183 else {
184 time_elapsed = pc0 - last_match20;
185 }
186
187 while (time_elapsed > 0) {
188 time_elapsed -= MATCH20_INC;
189 last_match20 += MATCH20_INC;
190 }
191
192 last_pc0 = pc0;
193 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
194 au_sync();
195
196}
197
198/* This is just for debugging to set the timer for a sleep delay.
199*/
200void
201wakeup_counter0_set(int ticks)
202{
203 unsigned long pc0;
204
205 pc0 = au_readl(SYS_TOYREAD);
206 last_pc0 = pc0;
207 au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2);
208 au_sync();
209}
210#endif
211
212/* I haven't found anyone that doesn't use a 12 MHz source clock,
213 * but just in case.....
214 */
215#ifdef CONFIG_AU1000_SRC_CLK
216#define AU1000_SRC_CLK CONFIG_AU1000_SRC_CLK
217#else
218#define AU1000_SRC_CLK 12000000
219#endif
220
221/*
222 * We read the real processor speed from the PLL. This is important
223 * because it is more accurate than computing it from the 32KHz
224 * counter, if it exists. If we don't have an accurate processor
225 * speed, all of the peripherals that derive their clocks based on
226 * this advertised speed will introduce error and sometimes not work
227 * properly. This function is futher convoluted to still allow configurations
228 * to do that in case they have really, really old silicon with a
229 * write-only PLL register, that we need the 32KHz when power management
230 * "wait" is enabled, and we need to detect if the 32KHz isn't present
231 * but requested......got it? :-) -- Dan
232 */
233unsigned long cal_r4koff(void)
234{
235 unsigned long count;
236 unsigned long cpu_speed;
237 unsigned long flags;
238 unsigned long counter;
239
240 spin_lock_irqsave(&time_lock, flags);
241
242 /* Power management cares if we don't have a 32KHz counter.
243 */
244 no_au1xxx_32khz = 0;
245 counter = au_readl(SYS_COUNTER_CNTRL);
246 if (counter & SYS_CNTRL_E0) {
247 int trim_divide = 16;
248
249 au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);
250
251 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
252 /* RTC now ticks at 32.768/16 kHz */
253 au_writel(trim_divide-1, SYS_RTCTRIM);
254 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
255
256 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
257 au_writel (0, SYS_TOYWRITE);
258 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
259
260#if defined(CONFIG_AU1000_USE32K)
261 {
262 unsigned long start, end;
263
264 start = au_readl(SYS_RTCREAD);
265 start += 2;
266 /* wait for the beginning of a new tick
267 */
268 while (au_readl(SYS_RTCREAD) < start);
269
270 /* Start r4k counter.
271 */
272 write_c0_count(0);
273
274 /* Wait 0.5 seconds.
275 */
276 end = start + (32768 / trim_divide)/2;
277
278 while (end > au_readl(SYS_RTCREAD));
279
280 count = read_c0_count();
281 cpu_speed = count * 2;
282 }
283#else
284 cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
285 AU1000_SRC_CLK;
286 count = cpu_speed / 2;
287#endif
288 }
289 else {
290 /* The 32KHz oscillator isn't running, so assume there
291 * isn't one and grab the processor speed from the PLL.
292 * NOTE: some old silicon doesn't allow reading the PLL.
293 */
294 cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
295 count = cpu_speed / 2;
296 no_au1xxx_32khz = 1;
297 }
298 mips_hpt_frequency = count;
299 // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16)
300 set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
301 spin_unlock_irqrestore(&time_lock, flags);
302 return (cpu_speed / HZ);
303}
304
305/* This is for machines which generate the exact clock. */
306#define USECS_PER_JIFFY (1000000/HZ)
307#define USECS_PER_JIFFY_FRAC (0x100000000LL*1000000/HZ&0xffffffff)
308
309static unsigned long
310div64_32(unsigned long v1, unsigned long v2, unsigned long v3)
311{
312 unsigned long r0;
313 do_div64_32(r0, v1, v2, v3);
314 return r0;
315}
316
317static unsigned long do_fast_cp0_gettimeoffset(void)
318{
319 u32 count;
320 unsigned long res, tmp;
321 unsigned long r0;
322
323 /* Last jiffy when do_fast_gettimeoffset() was called. */
324 static unsigned long last_jiffies=0;
325 unsigned long quotient;
326
327 /*
328 * Cached "1/(clocks per usec)*2^32" value.
329 * It has to be recalculated once each jiffy.
330 */
331 static unsigned long cached_quotient=0;
332
333 tmp = jiffies;
334
335 quotient = cached_quotient;
336
337 if (tmp && last_jiffies != tmp) {
338 last_jiffies = tmp;
339 if (last_jiffies != 0) {
340 r0 = div64_32(timerhi, timerlo, tmp);
341 quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0);
342 cached_quotient = quotient;
343 }
344 }
345
346 /* Get last timer tick in absolute kernel time */
347 count = read_c0_count();
348
349 /* .. relative to previous jiffy (32 bits is enough) */
350 count -= timerlo;
351
352 __asm__("multu\t%1,%2\n\t"
353 "mfhi\t%0"
354 : "=r" (res)
355 : "r" (count), "r" (quotient)
356 : "hi", "lo", GCC_REG_ACCUM);
357
358 /*
359 * Due to possible jiffies inconsistencies, we need to check
360 * the result so that we'll get a timer that is monotonic.
361 */
362 if (res >= USECS_PER_JIFFY)
363 res = USECS_PER_JIFFY-1;
364
365 return res;
366}
367
368#ifdef CONFIG_PM
369static unsigned long do_fast_pm_gettimeoffset(void)
370{
371 unsigned long pc0;
372 unsigned long offset;
373
374 pc0 = au_readl(SYS_TOYREAD);
375 au_sync();
376 offset = pc0 - last_pc0;
377 if (offset > 2*MATCH20_INC) {
378 printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n",
379 (unsigned)offset, (unsigned)last_pc0,
380 (unsigned)last_match20, (unsigned)pc0);
381 }
382 offset = (unsigned long)((offset * 305) / 10);
383 return offset;
384}
385#endif
386
387void au1xxx_timer_setup(struct irqaction *irq)
388{
389 unsigned int est_freq;
390 extern unsigned long (*do_gettimeoffset)(void);
391 extern void au1k_wait(void);
392
393 printk("calculating r4koff... ");
394 r4k_offset = cal_r4koff();
395 printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
396
397 //est_freq = 2*r4k_offset*HZ;
398 est_freq = r4k_offset*HZ;
399 est_freq += 5000; /* round */
400 est_freq -= est_freq%10000;
401 printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
402 (est_freq%1000000)*100/1000000);
403 set_au1x00_speed(est_freq);
404 set_au1x00_lcd_clock(); // program the LCD clock
405
406 r4k_cur = (read_c0_count() + r4k_offset);
407 write_c0_compare(r4k_cur);
408
409#ifdef CONFIG_PM
410 /*
411 * setup counter 0, since it keeps ticking after a
412 * 'wait' instruction has been executed. The CP0 timer and
413 * counter 1 do NOT continue running after 'wait'
414 *
415 * It's too early to call request_irq() here, so we handle
416 * counter 0 interrupt as a special irq and it doesn't show
417 * up under /proc/interrupts.
418 *
419 * Check to ensure we really have a 32KHz oscillator before
420 * we do this.
421 */
422 if (no_au1xxx_32khz) {
423 unsigned int c0_status;
424
425 printk("WARNING: no 32KHz clock found.\n");
426 do_gettimeoffset = do_fast_cp0_gettimeoffset;
427
428 /* Ensure we get CPO_COUNTER interrupts.
429 */
430 c0_status = read_c0_status();
431 c0_status |= IE_IRQ5;
432 write_c0_status(c0_status);
433 }
434 else {
435 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
436 au_writel(0, SYS_TOYWRITE);
437 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
438
439 au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
440 au_writel(~0, SYS_WAKESRC);
441 au_sync();
442 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
443
444 /* setup match20 to interrupt once every 10ms */
445 last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
446 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
447 au_sync();
448 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
449 startup_match20_interrupt();
450
451 do_gettimeoffset = do_fast_pm_gettimeoffset;
452
453 /* We can use the real 'wait' instruction.
454 */
455 au1k_wait_ptr = au1k_wait;
456 }
457
458#else
459 /* We have to do this here instead of in timer_init because
460 * the generic code in arch/mips/kernel/time.c will write
461 * over our function pointer.
462 */
463 do_gettimeoffset = do_fast_cp0_gettimeoffset;
464#endif
465}
466
467void __init au1xxx_time_init(void)
468{
469}
diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c
new file mode 100644
index 000000000000..447a9a4612a8
--- /dev/null
+++ b/arch/mips/au1000/common/usbdev.c
@@ -0,0 +1,1557 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1000 USB Device-Side (device layer)
4 *
5 * Copyright 2001-2002 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * stevel@mvista.com or source@mvista.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29#include <linux/kernel.h>
30#include <linux/ioport.h>
31#include <linux/sched.h>
32#include <linux/signal.h>
33#include <linux/errno.h>
34#include <linux/poll.h>
35#include <linux/init.h>
36#include <linux/slab.h>
37#include <linux/fcntl.h>
38#include <linux/module.h>
39#include <linux/spinlock.h>
40#include <linux/list.h>
41#include <linux/smp_lock.h>
42#define DEBUG
43#include <linux/usb.h>
44
45#include <asm/io.h>
46#include <asm/uaccess.h>
47#include <asm/irq.h>
48#include <asm/mipsregs.h>
49#include <asm/au1000.h>
50#include <asm/au1000_dma.h>
51#include <asm/au1000_usbdev.h>
52
53#ifdef DEBUG
54#undef VDEBUG
55#ifdef VDEBUG
56#define vdbg(fmt, arg...) printk(KERN_DEBUG __FILE__ ": " fmt "\n" , ## arg)
57#else
58#define vdbg(fmt, arg...) do {} while (0)
59#endif
60#else
61#define vdbg(fmt, arg...) do {} while (0)
62#endif
63
64#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL)
65
66#define EP_FIFO_DEPTH 8
67
68typedef enum {
69 SETUP_STAGE = 0,
70 DATA_STAGE,
71 STATUS_STAGE
72} ep0_stage_t;
73
74typedef struct {
75 int read_fifo;
76 int write_fifo;
77 int ctrl_stat;
78 int read_fifo_status;
79 int write_fifo_status;
80} endpoint_reg_t;
81
82typedef struct {
83 usbdev_pkt_t *head;
84 usbdev_pkt_t *tail;
85 int count;
86} pkt_list_t;
87
88typedef struct {
89 int active;
90 struct usb_endpoint_descriptor *desc;
91 endpoint_reg_t *reg;
92 /* Only one of these are used, unless this is the control ep */
93 pkt_list_t inlist;
94 pkt_list_t outlist;
95 unsigned int indma, outdma; /* DMA channel numbers for IN, OUT */
96 /* following are extracted from endpoint descriptor for easy access */
97 int max_pkt_size;
98 int type;
99 int direction;
100 /* WE assign endpoint addresses! */
101 int address;
102 spinlock_t lock;
103} endpoint_t;
104
105
106static struct usb_dev {
107 endpoint_t ep[6];
108 ep0_stage_t ep0_stage;
109
110 struct usb_device_descriptor * dev_desc;
111 struct usb_interface_descriptor* if_desc;
112 struct usb_config_descriptor * conf_desc;
113 u8 * full_conf_desc;
114 struct usb_string_descriptor * str_desc[6];
115
116 /* callback to function layer */
117 void (*func_cb)(usbdev_cb_type_t type, unsigned long arg,
118 void *cb_data);
119 void* cb_data;
120
121 usbdev_state_t state; // device state
122 int suspended; // suspended flag
123 int address; // device address
124 int interface;
125 int num_ep;
126 u8 alternate_setting;
127 u8 configuration; // configuration value
128 int remote_wakeup_en;
129} usbdev;
130
131
132static endpoint_reg_t ep_reg[] = {
133 // FIFO's 0 and 1 are EP0 default control
134 {USBD_EP0RD, USBD_EP0WR, USBD_EP0CS, USBD_EP0RDSTAT, USBD_EP0WRSTAT },
135 {0},
136 // FIFO 2 is EP2, IN
137 { -1, USBD_EP2WR, USBD_EP2CS, -1, USBD_EP2WRSTAT },
138 // FIFO 3 is EP3, IN
139 { -1, USBD_EP3WR, USBD_EP3CS, -1, USBD_EP3WRSTAT },
140 // FIFO 4 is EP4, OUT
141 {USBD_EP4RD, -1, USBD_EP4CS, USBD_EP4RDSTAT, -1 },
142 // FIFO 5 is EP5, OUT
143 {USBD_EP5RD, -1, USBD_EP5CS, USBD_EP5RDSTAT, -1 }
144};
145
146static struct {
147 unsigned int id;
148 const char *str;
149} ep_dma_id[] = {
150 { DMA_ID_USBDEV_EP0_TX, "USBDev EP0 IN" },
151 { DMA_ID_USBDEV_EP0_RX, "USBDev EP0 OUT" },
152 { DMA_ID_USBDEV_EP2_TX, "USBDev EP2 IN" },
153 { DMA_ID_USBDEV_EP3_TX, "USBDev EP3 IN" },
154 { DMA_ID_USBDEV_EP4_RX, "USBDev EP4 OUT" },
155 { DMA_ID_USBDEV_EP5_RX, "USBDev EP5 OUT" }
156};
157
158#define DIR_OUT 0
159#define DIR_IN (1<<3)
160
161#define CONTROL_EP USB_ENDPOINT_XFER_CONTROL
162#define BULK_EP USB_ENDPOINT_XFER_BULK
163
164static inline endpoint_t *
165epaddr_to_ep(struct usb_dev* dev, int ep_addr)
166{
167 if (ep_addr >= 0 && ep_addr < 2)
168 return &dev->ep[0];
169 if (ep_addr < 6)
170 return &dev->ep[ep_addr];
171 return NULL;
172}
173
174static const char* std_req_name[] = {
175 "GET_STATUS",
176 "CLEAR_FEATURE",
177 "RESERVED",
178 "SET_FEATURE",
179 "RESERVED",
180 "SET_ADDRESS",
181 "GET_DESCRIPTOR",
182 "SET_DESCRIPTOR",
183 "GET_CONFIGURATION",
184 "SET_CONFIGURATION",
185 "GET_INTERFACE",
186 "SET_INTERFACE",
187 "SYNCH_FRAME"
188};
189
190static inline const char*
191get_std_req_name(int req)
192{
193 return (req >= 0 && req <= 12) ? std_req_name[req] : "UNKNOWN";
194}
195
196#if 0
197static void
198dump_setup(struct usb_ctrlrequest* s)
199{
200 dbg("%s: requesttype=%d", __FUNCTION__, s->requesttype);
201 dbg("%s: request=%d %s", __FUNCTION__, s->request,
202 get_std_req_name(s->request));
203 dbg("%s: value=0x%04x", __FUNCTION__, s->wValue);
204 dbg("%s: index=%d", __FUNCTION__, s->index);
205 dbg("%s: length=%d", __FUNCTION__, s->length);
206}
207#endif
208
209static inline usbdev_pkt_t *
210alloc_packet(endpoint_t * ep, int data_size, void* data)
211{
212 usbdev_pkt_t* pkt = kmalloc(sizeof(usbdev_pkt_t) + data_size,
213 ALLOC_FLAGS);
214 if (!pkt)
215 return NULL;
216 pkt->ep_addr = ep->address;
217 pkt->size = data_size;
218 pkt->status = 0;
219 pkt->next = NULL;
220 if (data)
221 memcpy(pkt->payload, data, data_size);
222
223 return pkt;
224}
225
226
227/*
228 * Link a packet to the tail of the enpoint's packet list.
229 * EP spinlock must be held when calling.
230 */
231static void
232link_tail(endpoint_t * ep, pkt_list_t * list, usbdev_pkt_t * pkt)
233{
234 if (!list->tail) {
235 list->head = list->tail = pkt;
236 list->count = 1;
237 } else {
238 list->tail->next = pkt;
239 list->tail = pkt;
240 list->count++;
241 }
242}
243
244/*
245 * Unlink and return a packet from the head of the given packet
246 * list. It is the responsibility of the caller to free the packet.
247 * EP spinlock must be held when calling.
248 */
249static usbdev_pkt_t *
250unlink_head(pkt_list_t * list)
251{
252 usbdev_pkt_t *pkt;
253
254 pkt = list->head;
255 if (!pkt || !list->count) {
256 return NULL;
257 }
258
259 list->head = pkt->next;
260 if (!list->head) {
261 list->head = list->tail = NULL;
262 list->count = 0;
263 } else
264 list->count--;
265
266 return pkt;
267}
268
269/*
270 * Create and attach a new packet to the tail of the enpoint's
271 * packet list. EP spinlock must be held when calling.
272 */
273static usbdev_pkt_t *
274add_packet(endpoint_t * ep, pkt_list_t * list, int size)
275{
276 usbdev_pkt_t *pkt = alloc_packet(ep, size, NULL);
277 if (!pkt)
278 return NULL;
279
280 link_tail(ep, list, pkt);
281 return pkt;
282}
283
284
285/*
286 * Unlink and free a packet from the head of the enpoint's
287 * packet list. EP spinlock must be held when calling.
288 */
289static inline void
290free_packet(pkt_list_t * list)
291{
292 kfree(unlink_head(list));
293}
294
295/* EP spinlock must be held when calling. */
296static inline void
297flush_pkt_list(pkt_list_t * list)
298{
299 while (list->count)
300 free_packet(list);
301}
302
303/* EP spinlock must be held when calling */
304static inline void
305flush_write_fifo(endpoint_t * ep)
306{
307 if (ep->reg->write_fifo_status >= 0) {
308 au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF |
309 USBDEV_FSTAT_OF,
310 ep->reg->write_fifo_status);
311 //udelay(100);
312 //au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF,
313 // ep->reg->write_fifo_status);
314 }
315}
316
317/* EP spinlock must be held when calling */
318static inline void
319flush_read_fifo(endpoint_t * ep)
320{
321 if (ep->reg->read_fifo_status >= 0) {
322 au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF |
323 USBDEV_FSTAT_OF,
324 ep->reg->read_fifo_status);
325 //udelay(100);
326 //au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF,
327 // ep->reg->read_fifo_status);
328 }
329}
330
331
332/* EP spinlock must be held when calling. */
333static void
334endpoint_flush(endpoint_t * ep)
335{
336 // First, flush all packets
337 flush_pkt_list(&ep->inlist);
338 flush_pkt_list(&ep->outlist);
339
340 // Now flush the endpoint's h/w FIFO(s)
341 flush_write_fifo(ep);
342 flush_read_fifo(ep);
343}
344
345/* EP spinlock must be held when calling. */
346static void
347endpoint_stall(endpoint_t * ep)
348{
349 u32 cs;
350
351 warn(__FUNCTION__);
352
353 cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL;
354 au_writel(cs, ep->reg->ctrl_stat);
355}
356
357/* EP spinlock must be held when calling. */
358static void
359endpoint_unstall(endpoint_t * ep)
360{
361 u32 cs;
362
363 warn(__FUNCTION__);
364
365 cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL;
366 au_writel(cs, ep->reg->ctrl_stat);
367}
368
369static void
370endpoint_reset_datatoggle(endpoint_t * ep)
371{
372 // FIXME: is this possible?
373}
374
375
376/* EP spinlock must be held when calling. */
377static int
378endpoint_fifo_read(endpoint_t * ep)
379{
380 int read_count = 0;
381 u8 *bufptr;
382 usbdev_pkt_t *pkt = ep->outlist.tail;
383
384 if (!pkt)
385 return -EINVAL;
386
387 bufptr = &pkt->payload[pkt->size];
388 while (au_readl(ep->reg->read_fifo_status) & USBDEV_FSTAT_FCNT_MASK) {
389 *bufptr++ = au_readl(ep->reg->read_fifo) & 0xff;
390 read_count++;
391 pkt->size++;
392 }
393
394 return read_count;
395}
396
397#if 0
398/* EP spinlock must be held when calling. */
399static int
400endpoint_fifo_write(endpoint_t * ep, int index)
401{
402 int write_count = 0;
403 u8 *bufptr;
404 usbdev_pkt_t *pkt = ep->inlist.head;
405
406 if (!pkt)
407 return -EINVAL;
408
409 bufptr = &pkt->payload[index];
410 while ((au_readl(ep->reg->write_fifo_status) &
411 USBDEV_FSTAT_FCNT_MASK) < EP_FIFO_DEPTH) {
412 if (bufptr < pkt->payload + pkt->size) {
413 au_writel(*bufptr++, ep->reg->write_fifo);
414 write_count++;
415 } else {
416 break;
417 }
418 }
419
420 return write_count;
421}
422#endif
423
424/*
425 * This routine is called to restart transmission of a packet.
426 * The endpoint's TSIZE must be set to the new packet's size,
427 * and DMA to the write FIFO needs to be restarted.
428 * EP spinlock must be held when calling.
429 */
430static void
431kickstart_send_packet(endpoint_t * ep)
432{
433 u32 cs;
434 usbdev_pkt_t *pkt = ep->inlist.head;
435
436 vdbg("%s: ep%d, pkt=%p", __FUNCTION__, ep->address, pkt);
437
438 if (!pkt) {
439 err("%s: head=NULL! list->count=%d", __FUNCTION__,
440 ep->inlist.count);
441 return;
442 }
443
444 dma_cache_wback_inv((unsigned long)pkt->payload, pkt->size);
445
446 /*
447 * make sure FIFO is empty
448 */
449 flush_write_fifo(ep);
450
451 cs = au_readl(ep->reg->ctrl_stat) & USBDEV_CS_STALL;
452 cs |= (pkt->size << USBDEV_CS_TSIZE_BIT);
453 au_writel(cs, ep->reg->ctrl_stat);
454
455 if (get_dma_active_buffer(ep->indma) == 1) {
456 set_dma_count1(ep->indma, pkt->size);
457 set_dma_addr1(ep->indma, virt_to_phys(pkt->payload));
458 enable_dma_buffer1(ep->indma); // reenable
459 } else {
460 set_dma_count0(ep->indma, pkt->size);
461 set_dma_addr0(ep->indma, virt_to_phys(pkt->payload));
462 enable_dma_buffer0(ep->indma); // reenable
463 }
464 if (dma_halted(ep->indma))
465 start_dma(ep->indma);
466}
467
468
469/*
470 * This routine is called when a packet in the inlist has been
471 * completed. Frees the completed packet and starts sending the
472 * next. EP spinlock must be held when calling.
473 */
474static usbdev_pkt_t *
475send_packet_complete(endpoint_t * ep)
476{
477 usbdev_pkt_t *pkt = unlink_head(&ep->inlist);
478
479 if (pkt) {
480 pkt->status =
481 (au_readl(ep->reg->ctrl_stat) & USBDEV_CS_NAK) ?
482 PKT_STATUS_NAK : PKT_STATUS_ACK;
483
484 vdbg("%s: ep%d, %s pkt=%p, list count=%d", __FUNCTION__,
485 ep->address, (pkt->status & PKT_STATUS_NAK) ?
486 "NAK" : "ACK", pkt, ep->inlist.count);
487 }
488
489 /*
490 * The write fifo should already be drained if things are
491 * working right, but flush it anyway just in case.
492 */
493 flush_write_fifo(ep);
494
495 // begin transmitting next packet in the inlist
496 if (ep->inlist.count) {
497 kickstart_send_packet(ep);
498 }
499
500 return pkt;
501}
502
503/*
504 * Add a new packet to the tail of the given ep's packet
505 * inlist. The transmit complete interrupt frees packets from
506 * the head of this list. EP spinlock must be held when calling.
507 */
508static int
509send_packet(struct usb_dev* dev, usbdev_pkt_t *pkt, int async)
510{
511 pkt_list_t *list;
512 endpoint_t* ep;
513
514 if (!pkt || !(ep = epaddr_to_ep(dev, pkt->ep_addr)))
515 return -EINVAL;
516
517 if (!pkt->size)
518 return 0;
519
520 list = &ep->inlist;
521
522 if (!async && list->count) {
523 halt_dma(ep->indma);
524 flush_pkt_list(list);
525 }
526
527 link_tail(ep, list, pkt);
528
529 vdbg("%s: ep%d, pkt=%p, size=%d, list count=%d", __FUNCTION__,
530 ep->address, pkt, pkt->size, list->count);
531
532 if (list->count == 1) {
533 /*
534 * if the packet count is one, it means the list was empty,
535 * and no more data will go out this ep until we kick-start
536 * it again.
537 */
538 kickstart_send_packet(ep);
539 }
540
541 return pkt->size;
542}
543
544/*
545 * This routine is called to restart reception of a packet.
546 * EP spinlock must be held when calling.
547 */
548static void
549kickstart_receive_packet(endpoint_t * ep)
550{
551 usbdev_pkt_t *pkt;
552
553 // get and link a new packet for next reception
554 if (!(pkt = add_packet(ep, &ep->outlist, ep->max_pkt_size))) {
555 err("%s: could not alloc new packet", __FUNCTION__);
556 return;
557 }
558
559 if (get_dma_active_buffer(ep->outdma) == 1) {
560 clear_dma_done1(ep->outdma);
561 set_dma_count1(ep->outdma, ep->max_pkt_size);
562 set_dma_count0(ep->outdma, 0);
563 set_dma_addr1(ep->outdma, virt_to_phys(pkt->payload));
564 enable_dma_buffer1(ep->outdma); // reenable
565 } else {
566 clear_dma_done0(ep->outdma);
567 set_dma_count0(ep->outdma, ep->max_pkt_size);
568 set_dma_count1(ep->outdma, 0);
569 set_dma_addr0(ep->outdma, virt_to_phys(pkt->payload));
570 enable_dma_buffer0(ep->outdma); // reenable
571 }
572 if (dma_halted(ep->outdma))
573 start_dma(ep->outdma);
574}
575
576
577/*
578 * This routine is called when a packet in the outlist has been
579 * completed (received) and we need to prepare for a new packet
580 * to be received. Halts DMA and computes the packet size from the
581 * remaining DMA counter. Then prepares a new packet for reception
582 * and restarts DMA. FIXME: what if another packet comes in
583 * on top of the completed packet? Counter would be wrong.
584 * EP spinlock must be held when calling.
585 */
586static usbdev_pkt_t *
587receive_packet_complete(endpoint_t * ep)
588{
589 usbdev_pkt_t *pkt = ep->outlist.tail;
590 u32 cs;
591
592 halt_dma(ep->outdma);
593
594 cs = au_readl(ep->reg->ctrl_stat);
595
596 if (!pkt)
597 return NULL;
598
599 pkt->size = ep->max_pkt_size - get_dma_residue(ep->outdma);
600 if (pkt->size)
601 dma_cache_inv((unsigned long)pkt->payload, pkt->size);
602 /*
603 * need to pull out any remaining bytes in the FIFO.
604 */
605 endpoint_fifo_read(ep);
606 /*
607 * should be drained now, but flush anyway just in case.
608 */
609 flush_read_fifo(ep);
610
611 pkt->status = (cs & USBDEV_CS_NAK) ? PKT_STATUS_NAK : PKT_STATUS_ACK;
612 if (ep->address == 0 && (cs & USBDEV_CS_SU))
613 pkt->status |= PKT_STATUS_SU;
614
615 vdbg("%s: ep%d, %s pkt=%p, size=%d", __FUNCTION__,
616 ep->address, (pkt->status & PKT_STATUS_NAK) ?
617 "NAK" : "ACK", pkt, pkt->size);
618
619 kickstart_receive_packet(ep);
620
621 return pkt;
622}
623
624
625/*
626 ****************************************************************************
627 * Here starts the standard device request handlers. They are
628 * all called by do_setup() via a table of function pointers.
629 ****************************************************************************
630 */
631
632static ep0_stage_t
633do_get_status(struct usb_dev* dev, struct usb_ctrlrequest* setup)
634{
635 switch (setup->bRequestType) {
636 case 0x80: // Device
637 // FIXME: send device status
638 break;
639 case 0x81: // Interface
640 // FIXME: send interface status
641 break;
642 case 0x82: // End Point
643 // FIXME: send endpoint status
644 break;
645 default:
646 // Invalid Command
647 endpoint_stall(&dev->ep[0]); // Stall End Point 0
648 break;
649 }
650
651 return STATUS_STAGE;
652}
653
654static ep0_stage_t
655do_clear_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup)
656{
657 switch (setup->bRequestType) {
658 case 0x00: // Device
659 if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
660 dev->remote_wakeup_en = 0;
661 else
662 endpoint_stall(&dev->ep[0]);
663 break;
664 case 0x02: // End Point
665 if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
666 endpoint_t *ep =
667 epaddr_to_ep(dev,
668 le16_to_cpu(setup->wIndex) & 0xff);
669
670 endpoint_unstall(ep);
671 endpoint_reset_datatoggle(ep);
672 } else
673 endpoint_stall(&dev->ep[0]);
674 break;
675 }
676
677 return SETUP_STAGE;
678}
679
680static ep0_stage_t
681do_reserved(struct usb_dev* dev, struct usb_ctrlrequest* setup)
682{
683 // Invalid request, stall End Point 0
684 endpoint_stall(&dev->ep[0]);
685 return SETUP_STAGE;
686}
687
688static ep0_stage_t
689do_set_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup)
690{
691 switch (setup->bRequestType) {
692 case 0x00: // Device
693 if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
694 dev->remote_wakeup_en = 1;
695 else
696 endpoint_stall(&dev->ep[0]);
697 break;
698 case 0x02: // End Point
699 if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
700 endpoint_t *ep =
701 epaddr_to_ep(dev,
702 le16_to_cpu(setup->wIndex) & 0xff);
703
704 endpoint_stall(ep);
705 } else
706 endpoint_stall(&dev->ep[0]);
707 break;
708 }
709
710 return SETUP_STAGE;
711}
712
713static ep0_stage_t
714do_set_address(struct usb_dev* dev, struct usb_ctrlrequest* setup)
715{
716 int new_state = dev->state;
717 int new_addr = le16_to_cpu(setup->wValue);
718
719 dbg("%s: our address=%d", __FUNCTION__, new_addr);
720
721 if (new_addr > 127) {
722 // usb spec doesn't tell us what to do, so just go to
723 // default state
724 new_state = DEFAULT;
725 dev->address = 0;
726 } else if (dev->address != new_addr) {
727 dev->address = new_addr;
728 new_state = ADDRESS;
729 }
730
731 if (dev->state != new_state) {
732 dev->state = new_state;
733 /* inform function layer of usbdev state change */
734 dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
735 }
736
737 return SETUP_STAGE;
738}
739
740static ep0_stage_t
741do_get_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup)
742{
743 int strnum, desc_len = le16_to_cpu(setup->wLength);
744
745 switch (le16_to_cpu(setup->wValue) >> 8) {
746 case USB_DT_DEVICE:
747 // send device descriptor!
748 desc_len = desc_len > dev->dev_desc->bLength ?
749 dev->dev_desc->bLength : desc_len;
750 dbg("sending device desc, size=%d", desc_len);
751 send_packet(dev, alloc_packet(&dev->ep[0], desc_len,
752 dev->dev_desc), 0);
753 break;
754 case USB_DT_CONFIG:
755 // If the config descr index in low-byte of
756 // setup->wValue is valid, send config descr,
757 // otherwise stall ep0.
758 if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
759 // send config descriptor!
760 if (desc_len <= USB_DT_CONFIG_SIZE) {
761 dbg("sending partial config desc, size=%d",
762 desc_len);
763 send_packet(dev,
764 alloc_packet(&dev->ep[0],
765 desc_len,
766 dev->conf_desc),
767 0);
768 } else {
769 int len = le16_to_cpu(dev->conf_desc->wTotalLength);
770 dbg("sending whole config desc,"
771 " size=%d, our size=%d", desc_len, len);
772 desc_len = desc_len > len ? len : desc_len;
773 send_packet(dev,
774 alloc_packet(&dev->ep[0],
775 desc_len,
776 dev->full_conf_desc),
777 0);
778 }
779 } else
780 endpoint_stall(&dev->ep[0]);
781 break;
782 case USB_DT_STRING:
783 // If the string descr index in low-byte of setup->wValue
784 // is valid, send string descr, otherwise stall ep0.
785 strnum = le16_to_cpu(setup->wValue) & 0xff;
786 if (strnum >= 0 && strnum < 6) {
787 struct usb_string_descriptor *desc =
788 dev->str_desc[strnum];
789 desc_len = desc_len > desc->bLength ?
790 desc->bLength : desc_len;
791 dbg("sending string desc %d", strnum);
792 send_packet(dev,
793 alloc_packet(&dev->ep[0], desc_len,
794 desc), 0);
795 } else
796 endpoint_stall(&dev->ep[0]);
797 break;
798 default:
799 // Invalid request
800 err("invalid get desc=%d, stalled",
801 le16_to_cpu(setup->wValue) >> 8);
802 endpoint_stall(&dev->ep[0]); // Stall endpoint 0
803 break;
804 }
805
806 return STATUS_STAGE;
807}
808
809static ep0_stage_t
810do_set_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup)
811{
812 // TODO: implement
813 // there will be an OUT data stage (the descriptor to set)
814 return DATA_STAGE;
815}
816
817static ep0_stage_t
818do_get_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup)
819{
820 // send dev->configuration
821 dbg("sending config");
822 send_packet(dev, alloc_packet(&dev->ep[0], 1, &dev->configuration),
823 0);
824 return STATUS_STAGE;
825}
826
827static ep0_stage_t
828do_set_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup)
829{
830 // set active config to low-byte of setup->wValue
831 dev->configuration = le16_to_cpu(setup->wValue) & 0xff;
832 dbg("set config, config=%d", dev->configuration);
833 if (!dev->configuration && dev->state > DEFAULT) {
834 dev->state = ADDRESS;
835 /* inform function layer of usbdev state change */
836 dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
837 } else if (dev->configuration == 1) {
838 dev->state = CONFIGURED;
839 /* inform function layer of usbdev state change */
840 dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
841 } else {
842 // FIXME: "respond with request error" - how?
843 }
844
845 return SETUP_STAGE;
846}
847
848static ep0_stage_t
849do_get_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup)
850{
851 // interface must be zero.
852 if ((le16_to_cpu(setup->wIndex) & 0xff) || dev->state == ADDRESS) {
853 // FIXME: respond with "request error". how?
854 } else if (dev->state == CONFIGURED) {
855 // send dev->alternate_setting
856 dbg("sending alt setting");
857 send_packet(dev, alloc_packet(&dev->ep[0], 1,
858 &dev->alternate_setting), 0);
859 }
860
861 return STATUS_STAGE;
862
863}
864
865static ep0_stage_t
866do_set_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup)
867{
868 if (dev->state == ADDRESS) {
869 // FIXME: respond with "request error". how?
870 } else if (dev->state == CONFIGURED) {
871 dev->interface = le16_to_cpu(setup->wIndex) & 0xff;
872 dev->alternate_setting =
873 le16_to_cpu(setup->wValue) & 0xff;
874 // interface and alternate_setting must be zero
875 if (dev->interface || dev->alternate_setting) {
876 // FIXME: respond with "request error". how?
877 }
878 }
879
880 return SETUP_STAGE;
881}
882
883static ep0_stage_t
884do_synch_frame(struct usb_dev* dev, struct usb_ctrlrequest* setup)
885{
886 // TODO
887 return SETUP_STAGE;
888}
889
890typedef ep0_stage_t (*req_method_t)(struct usb_dev* dev,
891 struct usb_ctrlrequest* setup);
892
893
894/* Table of the standard device request handlers */
895static const req_method_t req_method[] = {
896 do_get_status,
897 do_clear_feature,
898 do_reserved,
899 do_set_feature,
900 do_reserved,
901 do_set_address,
902 do_get_descriptor,
903 do_set_descriptor,
904 do_get_configuration,
905 do_set_configuration,
906 do_get_interface,
907 do_set_interface,
908 do_synch_frame
909};
910
911
912// SETUP packet request dispatcher
913static void
914do_setup (struct usb_dev* dev, struct usb_ctrlrequest* setup)
915{
916 req_method_t m;
917
918 dbg("%s: req %d %s", __FUNCTION__, setup->bRequestType,
919 get_std_req_name(setup->bRequestType));
920
921 if ((setup->bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD ||
922 (setup->bRequestType & USB_RECIP_MASK) != USB_RECIP_DEVICE) {
923 err("%s: invalid requesttype 0x%02x", __FUNCTION__,
924 setup->bRequestType);
925 return;
926 }
927
928 if ((setup->bRequestType & 0x80) == USB_DIR_OUT && setup->wLength)
929 dbg("%s: OUT phase! length=%d", __FUNCTION__, setup->wLength);
930
931 if (setup->bRequestType < sizeof(req_method)/sizeof(req_method_t))
932 m = req_method[setup->bRequestType];
933 else
934 m = do_reserved;
935
936 dev->ep0_stage = (*m)(dev, setup);
937}
938
939/*
940 * A SETUP, DATA0, or DATA1 packet has been received
941 * on the default control endpoint's fifo.
942 */
943static void
944process_ep0_receive (struct usb_dev* dev)
945{
946 endpoint_t *ep0 = &dev->ep[0];
947 usbdev_pkt_t *pkt;
948
949 spin_lock(&ep0->lock);
950
951 // complete packet and prepare a new packet
952 pkt = receive_packet_complete(ep0);
953 if (!pkt) {
954 // FIXME: should put a warn/err here.
955 spin_unlock(&ep0->lock);
956 return;
957 }
958
959 // unlink immediately from endpoint.
960 unlink_head(&ep0->outlist);
961
962 // override current stage if h/w says it's a setup packet
963 if (pkt->status & PKT_STATUS_SU)
964 dev->ep0_stage = SETUP_STAGE;
965
966 switch (dev->ep0_stage) {
967 case SETUP_STAGE:
968 vdbg("SU bit is %s in setup stage",
969 (pkt->status & PKT_STATUS_SU) ? "set" : "not set");
970
971 if (pkt->size == sizeof(struct usb_ctrlrequest)) {
972#ifdef VDEBUG
973 if (pkt->status & PKT_STATUS_ACK)
974 vdbg("received SETUP");
975 else
976 vdbg("received NAK SETUP");
977#endif
978 do_setup(dev, (struct usb_ctrlrequest*)pkt->payload);
979 } else
980 err("%s: wrong size SETUP received", __FUNCTION__);
981 break;
982 case DATA_STAGE:
983 /*
984 * this setup has an OUT data stage. Of the standard
985 * device requests, only set_descriptor has this stage,
986 * so this packet is that descriptor. TODO: drop it for
987 * now, set_descriptor not implemented.
988 *
989 * Need to place a byte in the write FIFO here, to prepare
990 * to send a zero-length DATA ack packet to the host in the
991 * STATUS stage.
992 */
993 au_writel(0, ep0->reg->write_fifo);
994 dbg("received OUT stage DATAx on EP0, size=%d", pkt->size);
995 dev->ep0_stage = SETUP_STAGE;
996 break;
997 case STATUS_STAGE:
998 // this setup had an IN data stage, and host is ACK'ing
999 // the packet we sent during that stage.
1000 if (pkt->size != 0)
1001 warn("received non-zero ACK on EP0??");
1002#ifdef VDEBUG
1003 else
1004 vdbg("received ACK on EP0");
1005#endif
1006 dev->ep0_stage = SETUP_STAGE;
1007 break;
1008 }
1009
1010 spin_unlock(&ep0->lock);
1011 // we're done processing the packet, free it
1012 kfree(pkt);
1013}
1014
1015
1016/*
1017 * A DATA0/1 packet has been received on one of the OUT endpoints (4 or 5)
1018 */
1019static void
1020process_ep_receive (struct usb_dev* dev, endpoint_t *ep)
1021{
1022 usbdev_pkt_t *pkt;
1023
1024 spin_lock(&ep->lock);
1025 pkt = receive_packet_complete(ep);
1026 spin_unlock(&ep->lock);
1027
1028 dev->func_cb(CB_PKT_COMPLETE, (unsigned long)pkt, dev->cb_data);
1029}
1030
1031
1032
1033/* This ISR handles the receive complete and suspend events */
1034static void
1035req_sus_intr (int irq, void *dev_id, struct pt_regs *regs)
1036{
1037 struct usb_dev *dev = (struct usb_dev *) dev_id;
1038 u32 status;
1039
1040 status = au_readl(USBD_INTSTAT);
1041 au_writel(status, USBD_INTSTAT); // ack'em
1042
1043 if (status & (1<<0))
1044 process_ep0_receive(dev);
1045 if (status & (1<<4))
1046 process_ep_receive(dev, &dev->ep[4]);
1047 if (status & (1<<5))
1048 process_ep_receive(dev, &dev->ep[5]);
1049}
1050
1051
1052/* This ISR handles the DMA done events on EP0 */
1053static void
1054dma_done_ep0_intr(int irq, void *dev_id, struct pt_regs *regs)
1055{
1056 struct usb_dev *dev = (struct usb_dev *) dev_id;
1057 usbdev_pkt_t* pkt;
1058 endpoint_t *ep0 = &dev->ep[0];
1059 u32 cs0, buff_done;
1060
1061 spin_lock(&ep0->lock);
1062 cs0 = au_readl(ep0->reg->ctrl_stat);
1063
1064 // first check packet transmit done
1065 if ((buff_done = get_dma_buffer_done(ep0->indma)) != 0) {
1066 // transmitted a DATAx packet during DATA stage
1067 // on control endpoint 0
1068 // clear DMA done bit
1069 if (buff_done & DMA_D0)
1070 clear_dma_done0(ep0->indma);
1071 if (buff_done & DMA_D1)
1072 clear_dma_done1(ep0->indma);
1073
1074 pkt = send_packet_complete(ep0);
1075 if (pkt)
1076 kfree(pkt);
1077 }
1078
1079 /*
1080 * Now check packet receive done. Shouldn't get these,
1081 * the receive packet complete intr should happen
1082 * before the DMA done intr occurs.
1083 */
1084 if ((buff_done = get_dma_buffer_done(ep0->outdma)) != 0) {
1085 // clear DMA done bit
1086 if (buff_done & DMA_D0)
1087 clear_dma_done0(ep0->outdma);
1088 if (buff_done & DMA_D1)
1089 clear_dma_done1(ep0->outdma);
1090
1091 //process_ep0_receive(dev);
1092 }
1093
1094 spin_unlock(&ep0->lock);
1095}
1096
1097/* This ISR handles the DMA done events on endpoints 2,3,4,5 */
1098static void
1099dma_done_ep_intr(int irq, void *dev_id, struct pt_regs *regs)
1100{
1101 struct usb_dev *dev = (struct usb_dev *) dev_id;
1102 int i;
1103
1104 for (i = 2; i < 6; i++) {
1105 u32 buff_done;
1106 usbdev_pkt_t* pkt;
1107 endpoint_t *ep = &dev->ep[i];
1108
1109 if (!ep->active) continue;
1110
1111 spin_lock(&ep->lock);
1112
1113 if (ep->direction == USB_DIR_IN) {
1114 buff_done = get_dma_buffer_done(ep->indma);
1115 if (buff_done != 0) {
1116 // transmitted a DATAx pkt on the IN ep
1117 // clear DMA done bit
1118 if (buff_done & DMA_D0)
1119 clear_dma_done0(ep->indma);
1120 if (buff_done & DMA_D1)
1121 clear_dma_done1(ep->indma);
1122
1123 pkt = send_packet_complete(ep);
1124
1125 spin_unlock(&ep->lock);
1126 dev->func_cb(CB_PKT_COMPLETE,
1127 (unsigned long)pkt,
1128 dev->cb_data);
1129 spin_lock(&ep->lock);
1130 }
1131 } else {
1132 /*
1133 * Check packet receive done (OUT ep). Shouldn't get
1134 * these, the rx packet complete intr should happen
1135 * before the DMA done intr occurs.
1136 */
1137 buff_done = get_dma_buffer_done(ep->outdma);
1138 if (buff_done != 0) {
1139 // received a DATAx pkt on the OUT ep
1140 // clear DMA done bit
1141 if (buff_done & DMA_D0)
1142 clear_dma_done0(ep->outdma);
1143 if (buff_done & DMA_D1)
1144 clear_dma_done1(ep->outdma);
1145
1146 //process_ep_receive(dev, ep);
1147 }
1148 }
1149
1150 spin_unlock(&ep->lock);
1151 }
1152}
1153
1154
1155/***************************************************************************
1156 * Here begins the external interface functions
1157 ***************************************************************************
1158 */
1159
1160/*
1161 * allocate a new packet
1162 */
1163int
1164usbdev_alloc_packet(int ep_addr, int data_size, usbdev_pkt_t** pkt)
1165{
1166 endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr);
1167 usbdev_pkt_t* lpkt = NULL;
1168
1169 if (!ep || !ep->active || ep->address < 2)
1170 return -ENODEV;
1171 if (data_size > ep->max_pkt_size)
1172 return -EINVAL;
1173
1174 lpkt = *pkt = alloc_packet(ep, data_size, NULL);
1175 if (!lpkt)
1176 return -ENOMEM;
1177 return 0;
1178}
1179
1180
1181/*
1182 * packet send
1183 */
1184int
1185usbdev_send_packet(int ep_addr, usbdev_pkt_t * pkt)
1186{
1187 unsigned long flags;
1188 int count;
1189 endpoint_t * ep;
1190
1191 if (!pkt || !(ep = epaddr_to_ep(&usbdev, pkt->ep_addr)) ||
1192 !ep->active || ep->address < 2)
1193 return -ENODEV;
1194 if (ep->direction != USB_DIR_IN)
1195 return -EINVAL;
1196
1197 spin_lock_irqsave(&ep->lock, flags);
1198 count = send_packet(&usbdev, pkt, 1);
1199 spin_unlock_irqrestore(&ep->lock, flags);
1200
1201 return count;
1202}
1203
1204/*
1205 * packet receive
1206 */
1207int
1208usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt)
1209{
1210 unsigned long flags;
1211 usbdev_pkt_t* lpkt = NULL;
1212 endpoint_t *ep = epaddr_to_ep(&usbdev, ep_addr);
1213
1214 if (!ep || !ep->active || ep->address < 2)
1215 return -ENODEV;
1216 if (ep->direction != USB_DIR_OUT)
1217 return -EINVAL;
1218
1219 spin_lock_irqsave(&ep->lock, flags);
1220 if (ep->outlist.count > 1)
1221 lpkt = unlink_head(&ep->outlist);
1222 spin_unlock_irqrestore(&ep->lock, flags);
1223
1224 if (!lpkt) {
1225 /* no packet available */
1226 *pkt = NULL;
1227 return -ENODATA;
1228 }
1229
1230 *pkt = lpkt;
1231
1232 return lpkt->size;
1233}
1234
1235
1236/*
1237 * return total queued byte count on the endpoint.
1238 */
1239int
1240usbdev_get_byte_count(int ep_addr)
1241{
1242 unsigned long flags;
1243 pkt_list_t *list;
1244 usbdev_pkt_t *scan;
1245 int count = 0;
1246 endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr);
1247
1248 if (!ep || !ep->active || ep->address < 2)
1249 return -ENODEV;
1250
1251 if (ep->direction == USB_DIR_IN) {
1252 list = &ep->inlist;
1253
1254 spin_lock_irqsave(&ep->lock, flags);
1255 for (scan = list->head; scan; scan = scan->next)
1256 count += scan->size;
1257 spin_unlock_irqrestore(&ep->lock, flags);
1258 } else {
1259 list = &ep->outlist;
1260
1261 spin_lock_irqsave(&ep->lock, flags);
1262 if (list->count > 1) {
1263 for (scan = list->head; scan != list->tail;
1264 scan = scan->next)
1265 count += scan->size;
1266 }
1267 spin_unlock_irqrestore(&ep->lock, flags);
1268 }
1269
1270 return count;
1271}
1272
1273
1274void
1275usbdev_exit(void)
1276{
1277 endpoint_t *ep;
1278 int i;
1279
1280 au_writel(0, USBD_INTEN); // disable usb dev ints
1281 au_writel(0, USBD_ENABLE); // disable usb dev
1282
1283 free_irq(AU1000_USB_DEV_REQ_INT, &usbdev);
1284 free_irq(AU1000_USB_DEV_SUS_INT, &usbdev);
1285
1286 // free all control endpoint resources
1287 ep = &usbdev.ep[0];
1288 free_au1000_dma(ep->indma);
1289 free_au1000_dma(ep->outdma);
1290 endpoint_flush(ep);
1291
1292 // free ep resources
1293 for (i = 2; i < 6; i++) {
1294 ep = &usbdev.ep[i];
1295 if (!ep->active) continue;
1296
1297 if (ep->direction == USB_DIR_IN) {
1298 free_au1000_dma(ep->indma);
1299 } else {
1300 free_au1000_dma(ep->outdma);
1301 }
1302 endpoint_flush(ep);
1303 }
1304
1305 if (usbdev.full_conf_desc)
1306 kfree(usbdev.full_conf_desc);
1307}
1308
1309int
1310usbdev_init(struct usb_device_descriptor* dev_desc,
1311 struct usb_config_descriptor* config_desc,
1312 struct usb_interface_descriptor* if_desc,
1313 struct usb_endpoint_descriptor* ep_desc,
1314 struct usb_string_descriptor* str_desc[],
1315 void (*cb)(usbdev_cb_type_t, unsigned long, void *),
1316 void* cb_data)
1317{
1318 endpoint_t *ep0;
1319 int i, ret=0;
1320 u8* fcd;
1321
1322 if (dev_desc->bNumConfigurations > 1 ||
1323 config_desc->bNumInterfaces > 1 ||
1324 if_desc->bNumEndpoints > 4) {
1325 err("Only one config, one i/f, and no more "
1326 "than 4 ep's allowed");
1327 ret = -EINVAL;
1328 goto out;
1329 }
1330
1331 if (!cb) {
1332 err("Function-layer callback required");
1333 ret = -EINVAL;
1334 goto out;
1335 }
1336
1337 if (dev_desc->bMaxPacketSize0 != USBDEV_EP0_MAX_PACKET_SIZE) {
1338 warn("EP0 Max Packet size must be %d",
1339 USBDEV_EP0_MAX_PACKET_SIZE);
1340 dev_desc->bMaxPacketSize0 = USBDEV_EP0_MAX_PACKET_SIZE;
1341 }
1342
1343 memset(&usbdev, 0, sizeof(struct usb_dev));
1344
1345 usbdev.state = DEFAULT;
1346 usbdev.dev_desc = dev_desc;
1347 usbdev.if_desc = if_desc;
1348 usbdev.conf_desc = config_desc;
1349 for (i=0; i<6; i++)
1350 usbdev.str_desc[i] = str_desc[i];
1351 usbdev.func_cb = cb;
1352 usbdev.cb_data = cb_data;
1353
1354 /* Initialize default control endpoint */
1355 ep0 = &usbdev.ep[0];
1356 ep0->active = 1;
1357 ep0->type = CONTROL_EP;
1358 ep0->max_pkt_size = USBDEV_EP0_MAX_PACKET_SIZE;
1359 spin_lock_init(&ep0->lock);
1360 ep0->desc = NULL; // ep0 has no descriptor
1361 ep0->address = 0;
1362 ep0->direction = 0;
1363 ep0->reg = &ep_reg[0];
1364
1365 /* Initialize the other requested endpoints */
1366 for (i = 0; i < if_desc->bNumEndpoints; i++) {
1367 struct usb_endpoint_descriptor* epd = &ep_desc[i];
1368 endpoint_t *ep;
1369
1370 if ((epd->bEndpointAddress & 0x80) == USB_DIR_IN) {
1371 ep = &usbdev.ep[2];
1372 ep->address = 2;
1373 if (ep->active) {
1374 ep = &usbdev.ep[3];
1375 ep->address = 3;
1376 if (ep->active) {
1377 err("too many IN ep's requested");
1378 ret = -ENODEV;
1379 goto out;
1380 }
1381 }
1382 } else {
1383 ep = &usbdev.ep[4];
1384 ep->address = 4;
1385 if (ep->active) {
1386 ep = &usbdev.ep[5];
1387 ep->address = 5;
1388 if (ep->active) {
1389 err("too many OUT ep's requested");
1390 ret = -ENODEV;
1391 goto out;
1392 }
1393 }
1394 }
1395
1396 ep->active = 1;
1397 epd->bEndpointAddress &= ~0x0f;
1398 epd->bEndpointAddress |= (u8)ep->address;
1399 ep->direction = epd->bEndpointAddress & 0x80;
1400 ep->type = epd->bmAttributes & 0x03;
1401 ep->max_pkt_size = le16_to_cpu(epd->wMaxPacketSize);
1402 spin_lock_init(&ep->lock);
1403 ep->desc = epd;
1404 ep->reg = &ep_reg[ep->address];
1405 }
1406
1407 /*
1408 * initialize the full config descriptor
1409 */
1410 usbdev.full_conf_desc = fcd = kmalloc(le16_to_cpu(config_desc->wTotalLength),
1411 ALLOC_FLAGS);
1412 if (!fcd) {
1413 err("failed to alloc full config descriptor");
1414 ret = -ENOMEM;
1415 goto out;
1416 }
1417
1418 memcpy(fcd, config_desc, USB_DT_CONFIG_SIZE);
1419 fcd += USB_DT_CONFIG_SIZE;
1420 memcpy(fcd, if_desc, USB_DT_INTERFACE_SIZE);
1421 fcd += USB_DT_INTERFACE_SIZE;
1422 for (i = 0; i < if_desc->bNumEndpoints; i++) {
1423 memcpy(fcd, &ep_desc[i], USB_DT_ENDPOINT_SIZE);
1424 fcd += USB_DT_ENDPOINT_SIZE;
1425 }
1426
1427 /* Now we're ready to enable the controller */
1428 au_writel(0x0002, USBD_ENABLE);
1429 udelay(100);
1430 au_writel(0x0003, USBD_ENABLE);
1431 udelay(100);
1432
1433 /* build and send config table based on ep descriptors */
1434 for (i = 0; i < 6; i++) {
1435 endpoint_t *ep;
1436 if (i == 1)
1437 continue; // skip dummy ep
1438 ep = &usbdev.ep[i];
1439 if (ep->active) {
1440 au_writel((ep->address << 4) | 0x04, USBD_CONFIG);
1441 au_writel(((ep->max_pkt_size & 0x380) >> 7) |
1442 (ep->direction >> 4) | (ep->type << 4),
1443 USBD_CONFIG);
1444 au_writel((ep->max_pkt_size & 0x7f) << 1, USBD_CONFIG);
1445 au_writel(0x00, USBD_CONFIG);
1446 au_writel(ep->address, USBD_CONFIG);
1447 } else {
1448 u8 dir = (i==2 || i==3) ? DIR_IN : DIR_OUT;
1449 au_writel((i << 4) | 0x04, USBD_CONFIG);
1450 au_writel(((16 & 0x380) >> 7) | dir |
1451 (BULK_EP << 4), USBD_CONFIG);
1452 au_writel((16 & 0x7f) << 1, USBD_CONFIG);
1453 au_writel(0x00, USBD_CONFIG);
1454 au_writel(i, USBD_CONFIG);
1455 }
1456 }
1457
1458 /*
1459 * Enable Receive FIFO Complete interrupts only. Transmit
1460 * complete is being handled by the DMA done interrupts.
1461 */
1462 au_writel(0x31, USBD_INTEN);
1463
1464 /*
1465 * Controller is now enabled, request DMA and IRQ
1466 * resources.
1467 */
1468
1469 /* request the USB device transfer complete interrupt */
1470 if (request_irq(AU1000_USB_DEV_REQ_INT, req_sus_intr, SA_INTERRUPT,
1471 "USBdev req", &usbdev)) {
1472 err("Can't get device request intr");
1473 ret = -ENXIO;
1474 goto out;
1475 }
1476 /* request the USB device suspend interrupt */
1477 if (request_irq(AU1000_USB_DEV_SUS_INT, req_sus_intr, SA_INTERRUPT,
1478 "USBdev sus", &usbdev)) {
1479 err("Can't get device suspend intr");
1480 ret = -ENXIO;
1481 goto out;
1482 }
1483
1484 /* Request EP0 DMA and IRQ */
1485 if ((ep0->indma = request_au1000_dma(ep_dma_id[0].id,
1486 ep_dma_id[0].str,
1487 dma_done_ep0_intr,
1488 SA_INTERRUPT,
1489 &usbdev)) < 0) {
1490 err("Can't get %s DMA", ep_dma_id[0].str);
1491 ret = -ENXIO;
1492 goto out;
1493 }
1494 if ((ep0->outdma = request_au1000_dma(ep_dma_id[1].id,
1495 ep_dma_id[1].str,
1496 NULL, 0, NULL)) < 0) {
1497 err("Can't get %s DMA", ep_dma_id[1].str);
1498 ret = -ENXIO;
1499 goto out;
1500 }
1501
1502 // Flush the ep0 buffers and FIFOs
1503 endpoint_flush(ep0);
1504 // start packet reception on ep0
1505 kickstart_receive_packet(ep0);
1506
1507 /* Request DMA and IRQ for the other endpoints */
1508 for (i = 2; i < 6; i++) {
1509 endpoint_t *ep = &usbdev.ep[i];
1510 if (!ep->active)
1511 continue;
1512
1513 // Flush the endpoint buffers and FIFOs
1514 endpoint_flush(ep);
1515
1516 if (ep->direction == USB_DIR_IN) {
1517 ep->indma =
1518 request_au1000_dma(ep_dma_id[ep->address].id,
1519 ep_dma_id[ep->address].str,
1520 dma_done_ep_intr,
1521 SA_INTERRUPT,
1522 &usbdev);
1523 if (ep->indma < 0) {
1524 err("Can't get %s DMA",
1525 ep_dma_id[ep->address].str);
1526 ret = -ENXIO;
1527 goto out;
1528 }
1529 } else {
1530 ep->outdma =
1531 request_au1000_dma(ep_dma_id[ep->address].id,
1532 ep_dma_id[ep->address].str,
1533 NULL, 0, NULL);
1534 if (ep->outdma < 0) {
1535 err("Can't get %s DMA",
1536 ep_dma_id[ep->address].str);
1537 ret = -ENXIO;
1538 goto out;
1539 }
1540
1541 // start packet reception on OUT endpoint
1542 kickstart_receive_packet(ep);
1543 }
1544 }
1545
1546 out:
1547 if (ret)
1548 usbdev_exit();
1549 return ret;
1550}
1551
1552EXPORT_SYMBOL(usbdev_init);
1553EXPORT_SYMBOL(usbdev_exit);
1554EXPORT_SYMBOL(usbdev_alloc_packet);
1555EXPORT_SYMBOL(usbdev_receive_packet);
1556EXPORT_SYMBOL(usbdev_send_packet);
1557EXPORT_SYMBOL(usbdev_get_byte_count);
diff --git a/arch/mips/au1000/csb250/Makefile b/arch/mips/au1000/csb250/Makefile
new file mode 100644
index 000000000000..c0c4dcdccae8
--- /dev/null
+++ b/arch/mips/au1000/csb250/Makefile
@@ -0,0 +1,8 @@
1#
2# Copyright 2002 Cogent Computer Systems
3# dan@embeddededge.com
4#
5# Makefile for the Cogent CSB250 Au1500 board. Copied from Pb1500.
6#
7
8obj-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/csb250/board_setup.c b/arch/mips/au1000/csb250/board_setup.c
new file mode 100644
index 000000000000..90426eaffb23
--- /dev/null
+++ b/arch/mips/au1000/csb250/board_setup.c
@@ -0,0 +1,239 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Cogent CSB250 board setup.
5 *
6 * Copyright 2002 Cogent Computer Systems, Inc.
7 * dan@embeddededge.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29#include <linux/config.h>
30#include <linux/init.h>
31#include <linux/sched.h>
32#include <linux/ioport.h>
33#include <linux/mm.h>
34#include <linux/console.h>
35#include <linux/mc146818rtc.h>
36#include <linux/delay.h>
37
38#include <asm/cpu.h>
39#include <asm/bootinfo.h>
40#include <asm/irq.h>
41#include <asm/keyboard.h>
42#include <asm/mipsregs.h>
43#include <asm/reboot.h>
44#include <asm/pgtable.h>
45#include <asm/au1000.h>
46#include <asm/csb250.h>
47
48extern int (*board_pci_idsel)(unsigned int devsel, int assert);
49int csb250_pci_idsel(unsigned int devsel, int assert);
50
51void __init board_setup(void)
52{
53 u32 pin_func, pin_val;
54 u32 sys_freqctrl, sys_clksrc;
55
56
57 // set AUX clock to 12MHz * 8 = 96 MHz
58 au_writel(8, SYS_AUXPLL);
59 au_writel(0, SYS_PINSTATERD);
60 udelay(100);
61
62#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
63
64 /* GPIO201 is input for PCMCIA card detect */
65 /* GPIO203 is input for PCMCIA interrupt request */
66 au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR);
67
68 /* zero and disable FREQ2 */
69 sys_freqctrl = au_readl(SYS_FREQCTRL0);
70 sys_freqctrl &= ~0xFFF00000;
71 au_writel(sys_freqctrl, SYS_FREQCTRL0);
72
73 /* zero and disable USBH/USBD clocks */
74 sys_clksrc = au_readl(SYS_CLKSRC);
75 sys_clksrc &= ~0x00007FE0;
76 au_writel(sys_clksrc, SYS_CLKSRC);
77
78 sys_freqctrl = au_readl(SYS_FREQCTRL0);
79 sys_freqctrl &= ~0xFFF00000;
80
81 sys_clksrc = au_readl(SYS_CLKSRC);
82 sys_clksrc &= ~0x00007FE0;
83
84 // FREQ2 = aux/2 = 48 MHz
85 sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
86 au_writel(sys_freqctrl, SYS_FREQCTRL0);
87
88 /*
89 * Route 48MHz FREQ2 into USB Host and/or Device
90 */
91#ifdef CONFIG_USB_OHCI
92 sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
93#endif
94#ifdef CONFIG_AU1X00_USB_DEVICE
95 sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
96#endif
97 au_writel(sys_clksrc, SYS_CLKSRC);
98
99
100 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
101#ifndef CONFIG_AU1X00_USB_DEVICE
102 // 2nd USB port is USB host
103 pin_func |= 0x8000;
104#endif
105 au_writel(pin_func, SYS_PINFUNC);
106#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
107
108 /* Configure GPIO2....it's used by PCI among other things.
109 */
110
111 /* Make everything but GP200 (PCI RST) an input until we get
112 * the pins set correctly.
113 */
114 au_writel(0x00000001, GPIO2_DIR);
115
116 /* Set the pins used for output.
117 * A zero bit will leave PCI reset, LEDs off, power up USB,
118 * IDSEL disabled.
119 */
120 pin_val = ((3 << 30) | (7 << 19) | (1 << 17) | (1 << 16));
121 au_writel(pin_val, GPIO2_OUTPUT);
122
123 /* Set the output direction.
124 */
125 pin_val = ((3 << 14) | (7 << 3) | (1 << 1) | (1 << 0));
126 au_writel(pin_val, GPIO2_DIR);
127
128#ifdef CONFIG_PCI
129 /* Use FREQ1 for the PCI output clock. We use the
130 * CPU clock of 384 MHz divided by 12 to get 32 MHz PCI.
131 * If Michael changes the CPU speed, we need to adjust
132 * that here as well :-).
133 */
134
135 /* zero and disable FREQ1
136 */
137 sys_freqctrl = au_readl(SYS_FREQCTRL0);
138 sys_freqctrl &= ~0x000ffc00;
139 au_writel(sys_freqctrl, SYS_FREQCTRL0);
140
141 /* zero and disable PCI clock
142 */
143 sys_clksrc = au_readl(SYS_CLKSRC);
144 sys_clksrc &= ~0x000f8000;
145 au_writel(sys_clksrc, SYS_CLKSRC);
146
147 /* Get current values (which really should match above).
148 */
149 sys_freqctrl = au_readl(SYS_FREQCTRL0);
150 sys_freqctrl &= ~0x000ffc00;
151
152 sys_clksrc = au_readl(SYS_CLKSRC);
153 sys_clksrc &= ~0x000f8000;
154
155 /* FREQ1 = cpu/12 = 32 MHz
156 */
157 sys_freqctrl |= ((5<<12) | (1<<11) | (0<<10));
158 au_writel(sys_freqctrl, SYS_FREQCTRL0);
159
160 /* Just connect the clock without further dividing.
161 */
162 sys_clksrc |= ((3<<17) | (0<<16) | (0<<15));
163 au_writel(sys_clksrc, SYS_CLKSRC);
164
165 udelay(1);
166
167 /* Now that clocks should be running, take PCI out of reset.
168 */
169 pin_val = au_readl(GPIO2_OUTPUT);
170 pin_val |= ((1 << 16) | 1);
171 au_writel(pin_val, GPIO2_OUTPUT);
172
173 // Setup PCI bus controller
174 au_writel(0, Au1500_PCI_CMEM);
175 au_writel(0x00003fff, Au1500_CFG_BASE);
176
177 /* We run big endian without any of the software byte swapping,
178 * so configure the PCI bridge to help us out.
179 */
180 au_writel(0xf | (2<<6) | (1<<5) | (1<<4), Au1500_PCI_CFG);
181
182 au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
183 au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
184 au_writel(0x02a00356, Au1500_PCI_STATCMD);
185 au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
186 au_writel(0x00000008, Au1500_PCI_MBAR);
187 au_sync();
188
189 board_pci_idsel = csb250_pci_idsel;
190#endif
191
192 /* Enable sys bus clock divider when IDLE state or no bus activity. */
193 au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
194
195#ifdef CONFIG_RTC
196 // Enable the RTC if not already enabled
197 if (!(au_readl(0xac000028) & 0x20)) {
198 printk("enabling clock ...\n");
199 au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
200 }
201 // Put the clock in BCD mode
202 if (readl(0xac00002C) & 0x4) { /* reg B */
203 au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
204 au_sync();
205 }
206#endif
207}
208
209/* The IDSEL is selected in the GPIO2 register. We will make device
210 * 12 appear in slot 0 and device 13 appear in slot 1.
211 */
212int
213csb250_pci_idsel(unsigned int devsel, int assert)
214{
215 int retval;
216 unsigned int gpio2_pins;
217
218 retval = 1;
219
220 /* First, disable both selects, then assert the one requested.
221 */
222 au_writel(0xc000c000, GPIO2_OUTPUT);
223 au_sync();
224
225 if (assert) {
226 if (devsel == 12)
227 gpio2_pins = 0x40000000;
228 else if (devsel == 13)
229 gpio2_pins = 0x80000000;
230 else {
231 gpio2_pins = 0xc000c000;
232 retval = 0;
233 }
234 au_writel(gpio2_pins, GPIO2_OUTPUT);
235 }
236 au_sync();
237
238 return retval;
239}
diff --git a/arch/mips/au1000/csb250/init.c b/arch/mips/au1000/csb250/init.c
new file mode 100644
index 000000000000..4320057fc439
--- /dev/null
+++ b/arch/mips/au1000/csb250/init.c
@@ -0,0 +1,95 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Cogent CSB250 board setup
5 *
6 * Copyright 2002 Cogent Computer Systems, Inc.
7 * dan@embeddededge.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29
30#include <linux/init.h>
31#include <linux/mm.h>
32#include <linux/sched.h>
33#include <linux/bootmem.h>
34#include <asm/addrspace.h>
35#include <asm/bootinfo.h>
36#include <linux/string.h>
37#include <linux/kernel.h>
38#include <linux/sched.h>
39
40int prom_argc;
41char **prom_argv, **prom_envp;
42extern void __init prom_init_cmdline(void);
43extern char *prom_getenv(char *envname);
44
45/* When we get initrd working someday.........
46*/
47int my_initrd_start, my_initrd_size;
48
49/* Start arguments and environment.
50*/
51static char *csb_env[2];
52static char *csb_arg[4];
53static char *arg1 = "console=ttyS3,38400";
54static char *arg2 = "root=/dev/nfs rw ip=any";
55static char *env1 = "ethaddr=00:30:23:50:00:00";
56
57const char *get_system_type(void)
58{
59 return "Cogent CSB250";
60}
61
62int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
63{
64 unsigned char *memsize_str;
65 unsigned long memsize;
66
67 /* We use a0 and a1 to pass initrd start and size.
68 */
69 if (((uint) argc > 0) && ((uint)argv > 0)) {
70 my_initrd_start = (uint)argc;
71 my_initrd_size = (uint)argv;
72 }
73
74 /* First argv is ignored.
75 */
76 prom_argc = 3;
77 prom_argv = csb_arg;
78 prom_envp = csb_env;
79 csb_arg[1] = arg1;
80 csb_arg[2] = arg2;
81 csb_env[0] = env1;
82
83 mips_machgroup = MACH_GROUP_ALCHEMY;
84 mips_machtype = MACH_CSB250;
85
86 prom_init_cmdline();
87 memsize_str = prom_getenv("memsize");
88 if (!memsize_str) {
89 memsize = 0x02000000;
90 } else {
91 memsize = simple_strtol(memsize_str, NULL, 0);
92 }
93 add_memory_region(0, memsize, BOOT_MEM_RAM);
94 return 0;
95}
diff --git a/arch/mips/au1000/csb250/irqmap.c b/arch/mips/au1000/csb250/irqmap.c
new file mode 100644
index 000000000000..5cb1166be35c
--- /dev/null
+++ b/arch/mips/au1000/csb250/irqmap.c
@@ -0,0 +1,60 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51
52 { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
53 { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
54 { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
55 { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
56 { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
57 { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
58};
59
60int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/db1x00/Makefile b/arch/mips/au1000/db1x00/Makefile
new file mode 100644
index 000000000000..4c7d763f2113
--- /dev/null
+++ b/arch/mips/au1000/db1x00/Makefile
@@ -0,0 +1,9 @@
1#
2# Copyright 2000 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for the Alchemy Semiconductor Db1x00 board.
7
8lib-y := init.o board_setup.o irqmap.o
9obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c
new file mode 100644
index 000000000000..ac05ba0ff63f
--- /dev/null
+++ b/arch/mips/au1000/db1x00/board_setup.c
@@ -0,0 +1,127 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Alchemy Db1x00 board setup.
5 *
6 * Copyright 2000 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30#include <linux/config.h>
31#include <linux/init.h>
32#include <linux/sched.h>
33#include <linux/ioport.h>
34#include <linux/mm.h>
35#include <linux/console.h>
36#include <linux/mc146818rtc.h>
37#include <linux/delay.h>
38
39#include <asm/cpu.h>
40#include <asm/bootinfo.h>
41#include <asm/irq.h>
42#include <asm/mipsregs.h>
43#include <asm/reboot.h>
44#include <asm/pgtable.h>
45#include <asm/mach-au1x00/au1000.h>
46#include <asm/mach-db1x00/db1x00.h>
47
48/* not correct for db1550 */
49static BCSR * const bcsr = (BCSR *)0xAE000000;
50
51void board_reset (void)
52{
53 /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
54 au_writel(0x00000000, 0xAE00001C);
55}
56
57void __init board_setup(void)
58{
59 u32 pin_func;
60
61 pin_func = 0;
62 /* not valid for 1550 */
63#ifdef CONFIG_AU1X00_USB_DEVICE
64 // 2nd USB port is USB device
65 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
66 au_writel(pin_func, SYS_PINFUNC);
67#endif
68
69#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
70 /* set IRFIRSEL instead of GPIO15 */
71 pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8));
72 au_writel(pin_func, SYS_PINFUNC);
73 /* power off until the driver is in use */
74 bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK;
75 bcsr->resets |= BCSR_RESETS_IRDA_MODE_OFF;
76 au_sync();
77#endif
78 au_writel(0, 0xAE000010); /* turn off pcmcia power */
79
80#ifdef CONFIG_MIPS_MIRAGE
81 /* enable GPIO[31:0] inputs */
82 au_writel(0, SYS_PININPUTEN);
83
84 /* GPIO[20] is output, tristate the other input primary GPIO's */
85 au_writel((u32)(~(1<<20)), SYS_TRIOUTCLR);
86
87 /* set GPIO[210:208] instead of SSI_0 */
88 pin_func = au_readl(SYS_PINFUNC) | (u32)(1);
89
90 /* set GPIO[215:211] for LED's */
91 pin_func |= (u32)((5<<2));
92
93 /* set GPIO[214:213] for more LED's */
94 pin_func |= (u32)((5<<12));
95
96 /* set GPIO[207:200] instead of PCMCIA/LCD */
97 pin_func |= (u32)((3<<17));
98 au_writel(pin_func, SYS_PINFUNC);
99
100 /* Enable speaker amplifier. This should
101 * be part of the audio driver.
102 */
103 au_writel(au_readl(GPIO2_DIR) | 0x200, GPIO2_DIR);
104 au_writel(0x02000200, GPIO2_OUTPUT);
105#endif
106
107 au_sync();
108
109#ifdef CONFIG_MIPS_DB1000
110 printk("AMD Alchemy Au1000/Db1000 Board\n");
111#endif
112#ifdef CONFIG_MIPS_DB1500
113 printk("AMD Alchemy Au1500/Db1500 Board\n");
114#endif
115#ifdef CONFIG_MIPS_DB1100
116 printk("AMD Alchemy Au1100/Db1100 Board\n");
117#endif
118#ifdef CONFIG_MIPS_BOSPORUS
119 printk("AMD Alchemy Bosporus Board\n");
120#endif
121#ifdef CONFIG_MIPS_MIRAGE
122 printk("AMD Alchemy Mirage Board\n");
123#endif
124#ifdef CONFIG_MIPS_DB1550
125 printk("AMD Alchemy Au1550/Db1550 Board\n");
126#endif
127}
diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c
new file mode 100644
index 000000000000..51eee94a5e82
--- /dev/null
+++ b/arch/mips/au1000/db1x00/init.c
@@ -0,0 +1,74 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * PB1000 board setup
4 *
5 * Copyright 2001 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29
30#include <linux/init.h>
31#include <linux/mm.h>
32#include <linux/sched.h>
33#include <linux/bootmem.h>
34#include <asm/addrspace.h>
35#include <asm/bootinfo.h>
36#include <linux/config.h>
37#include <linux/string.h>
38#include <linux/kernel.h>
39
40int prom_argc;
41char **prom_argv, **prom_envp;
42extern void __init prom_init_cmdline(void);
43extern char *prom_getenv(char *envname);
44
45const char *get_system_type(void)
46{
47#ifdef CONFIG_MIPS_BOSPORUS
48 return "Alchemy Bosporus Gateway Reference";
49#else
50 return "Alchemy Db1x00";
51#endif
52}
53
54void __init prom_init(void)
55{
56 unsigned char *memsize_str;
57 unsigned long memsize;
58
59 prom_argc = fw_arg0;
60 prom_argv = (char **) fw_arg1;
61 prom_envp = (char **) fw_arg2;
62
63 mips_machgroup = MACH_GROUP_ALCHEMY;
64 mips_machtype = MACH_DB1000; /* set the platform # */
65
66 prom_init_cmdline();
67
68 memsize_str = prom_getenv("memsize");
69 if (!memsize_str)
70 memsize = 0x04000000;
71 else
72 memsize = simple_strtol(memsize_str, NULL, 0);
73 add_memory_region(0, memsize, BOOT_MEM_RAM);
74}
diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c
new file mode 100644
index 000000000000..8f6ef0dbe1f8
--- /dev/null
+++ b/arch/mips/au1000/db1x00/irqmap.c
@@ -0,0 +1,72 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/config.h>
29#include <linux/errno.h>
30#include <linux/init.h>
31#include <linux/irq.h>
32#include <linux/kernel_stat.h>
33#include <linux/module.h>
34#include <linux/signal.h>
35#include <linux/sched.h>
36#include <linux/types.h>
37#include <linux/interrupt.h>
38#include <linux/ioport.h>
39#include <linux/timex.h>
40#include <linux/slab.h>
41#include <linux/random.h>
42#include <linux/delay.h>
43#include <linux/bitops.h>
44
45#include <asm/bootinfo.h>
46#include <asm/io.h>
47#include <asm/mipsregs.h>
48#include <asm/system.h>
49#include <asm/mach-au1x00/au1000.h>
50
51au1xxx_irq_map_t au1xxx_irq_map[] = {
52
53#ifndef CONFIG_MIPS_MIRAGE
54#ifdef CONFIG_MIPS_DB1550
55 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
56 { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
57#else
58 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */
59 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */
60 { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
61
62 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */
63 { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */
64 { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
65#endif
66#else
67 { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */
68#endif
69
70};
71
72int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c
new file mode 100644
index 000000000000..ade35e432004
--- /dev/null
+++ b/arch/mips/au1000/db1x00/mirage_ts.c
@@ -0,0 +1,261 @@
1/*
2 * linux/arch/mips/au1000/db1x00/mirage_ts.c
3 *
4 * BRIEF MODULE DESCRIPTION
5 * Glue between Mirage board-specific touchscreen pieces
6 * and generic Wolfson Codec touchscreen support.
7 *
8 * Based on pb1100_ts.c used in Hydrogen II.
9 *
10 * Copyright (c) 2003 Embedded Edge, LLC
11 * dan@embeddededge.com
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33
34#include <linux/config.h>
35#include <linux/types.h>
36#include <linux/module.h>
37#include <linux/sched.h>
38#include <linux/kernel.h>
39#include <linux/init.h>
40#include <linux/fs.h>
41#include <linux/poll.h>
42#include <linux/proc_fs.h>
43#include <linux/smp.h>
44#include <linux/smp_lock.h>
45#include <linux/wait.h>
46
47#include <asm/segment.h>
48#include <asm/irq.h>
49#include <asm/uaccess.h>
50#include <asm/delay.h>
51#include <asm/au1000.h>
52
53/*
54 * Imported interface to Wolfson Codec driver.
55 */
56extern void *wm97xx_ts_get_handle(int which);
57extern int wm97xx_ts_ready(void* ts_handle);
58extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
59extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
60extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
61extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
62extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
63
64int wm97xx_comodule_present = 1;
65
66
67#define TS_NAME "mirage_ts"
68
69#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
70#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
71#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
72#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
73
74
75#define PEN_DOWN_IRQ AU1000_GPIO_7
76
77static struct task_struct *ts_task = 0;
78static DECLARE_COMPLETION(ts_complete);
79static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
80
81#ifdef CONFIG_WM97XX_FIVEWIRETS
82static int release_pressure = 1;
83#else
84static int release_pressure = 50;
85#endif
86
87typedef struct {
88 long x;
89 long y;
90} DOWN_EVENT;
91
92#define SAMPLE_RATE 50 /* samples per second */
93#define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */
94#define PEN_UP_TIMEOUT 10 /* in seconds */
95#define PEN_UP_SETTLE 5 /* samples per second */
96
97static struct {
98 int xscale;
99 int xtrans;
100 int yscale;
101 int ytrans;
102} mirage_ts_cal =
103{
104#if 0
105 xscale: 84,
106 xtrans: -157,
107 yscale: 66,
108 ytrans: -150,
109#else
110 xscale: 84,
111 xtrans: -150,
112 yscale: 66,
113 ytrans: -146,
114#endif
115};
116
117
118static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
119{
120//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
121 wake_up(&pendown_wait);
122}
123
124static int ts_thread(void *id)
125{
126 static int pen_was_down = 0;
127 static DOWN_EVENT pen_xy;
128 long x, y, z;
129 void *ts; /* handle */
130 struct task_struct *tsk = current;
131 int timeout = HZ / SAMPLE_RATE;
132
133 ts_task = tsk;
134
135 daemonize();
136 tsk->tty = NULL;
137 tsk->policy = SCHED_FIFO;
138 tsk->rt_priority = 1;
139 strcpy(tsk->comm, "touchscreen");
140
141 /* only want to receive SIGKILL */
142 spin_lock_irq(&tsk->sigmask_lock);
143 siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
144 recalc_sigpending(tsk);
145 spin_unlock_irq(&tsk->sigmask_lock);
146
147 /* get handle for codec */
148 ts = wm97xx_ts_get_handle(0);
149
150 /* proceed only after everybody is ready */
151 wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
152
153 /* board-specific calibration */
154 wm97xx_ts_set_cal(ts,
155 mirage_ts_cal.xscale,
156 mirage_ts_cal.xtrans,
157 mirage_ts_cal.yscale,
158 mirage_ts_cal.ytrans);
159
160 /* route Wolfson pendown interrupts to our GPIO */
161 au_sync();
162 wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
163 au_sync();
164 wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
165 au_sync();
166 wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
167 au_sync();
168
169 for (;;) {
170 interruptible_sleep_on_timeout(&pendown_wait, timeout);
171 disable_irq(PEN_DOWN_IRQ);
172 if (signal_pending(tsk)) {
173 break;
174 }
175
176 /* read codec */
177 if (!wm97xx_ts_read_data(ts, &x, &y, &z))
178 z = 0; /* treat no-data and pen-up the same */
179
180 if (signal_pending(tsk)) {
181 break;
182 }
183
184 if (z >= release_pressure) {
185 y = ~y; /* top to bottom */
186 if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
187 /* bounce ? */
188 x = pen_xy.x;
189 y = pen_xy.y;
190 --pen_was_down;
191 } else if (pen_was_down <= 1) {
192 pen_xy.x = x;
193 pen_xy.y = y;
194 if (pen_was_down)
195 wm97xx_ts_send_data(ts, x, y, z);
196 pen_was_down = PEN_DEBOUNCE;
197 }
198 //wm97xx_ts_send_data(ts, x, y, z);
199 timeout = HZ / SAMPLE_RATE;
200 } else {
201 if (pen_was_down) {
202 if (--pen_was_down)
203 z = release_pressure;
204 else //THXXX
205 wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
206 }
207 /* The pendown signal takes some time to settle after
208 * reading the pen pressure so wait a little
209 * before enabling the pen.
210 */
211 if (! pen_was_down) {
212// interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
213 timeout = HZ * PEN_UP_TIMEOUT;
214 }
215 }
216 enable_irq(PEN_DOWN_IRQ);
217 }
218 enable_irq(PEN_DOWN_IRQ);
219 ts_task = NULL;
220 complete(&ts_complete);
221 return 0;
222}
223
224static int __init ts_mirage_init(void)
225{
226 int ret;
227
228 /* pen down signal is connected to GPIO 7 */
229
230 ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
231 if (ret) {
232 err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
233 return ret;
234 }
235
236 lock_kernel();
237 ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
238 if (ret < 0) {
239 unlock_kernel();
240 return ret;
241 }
242 unlock_kernel();
243
244 info("Mirage touchscreen IRQ initialized.");
245
246 return 0;
247}
248
249static void __exit ts_mirage_exit(void)
250{
251 if (ts_task) {
252 send_sig(SIGKILL, ts_task, 1);
253 wait_for_completion(&ts_complete);
254 }
255
256 free_irq(PEN_DOWN_IRQ, NULL);
257}
258
259module_init(ts_mirage_init);
260module_exit(ts_mirage_exit);
261
diff --git a/arch/mips/au1000/hydrogen3/Makefile b/arch/mips/au1000/hydrogen3/Makefile
new file mode 100644
index 000000000000..974f79256bb3
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/Makefile
@@ -0,0 +1,9 @@
1#
2# Copyright 2000 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for the Alchemy Semiconductor PB1000 board.
7#
8
9obj-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/hydrogen3/board_setup.c b/arch/mips/au1000/hydrogen3/board_setup.c
new file mode 100644
index 000000000000..2efae1064647
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/board_setup.c
@@ -0,0 +1,70 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Alchemy Db1x00 board setup.
5 *
6 * Copyright 2000 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30#include <linux/config.h>
31#include <linux/init.h>
32#include <linux/sched.h>
33#include <linux/ioport.h>
34#include <linux/mm.h>
35#include <linux/console.h>
36#include <linux/mc146818rtc.h>
37#include <linux/delay.h>
38
39#include <asm/cpu.h>
40#include <asm/bootinfo.h>
41#include <asm/irq.h>
42#include <asm/keyboard.h>
43#include <asm/mipsregs.h>
44#include <asm/reboot.h>
45#include <asm/pgtable.h>
46#include <asm/au1000.h>
47
48void board_reset (void)
49{
50}
51
52void __init board_setup(void)
53{
54 u32 pin_func;
55
56#ifdef CONFIG_AU1X00_USB_DEVICE
57 // 2nd USB port is USB device
58 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
59 au_writel(pin_func, SYS_PINFUNC);
60#endif
61
62#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
63 /* set IRFIRSEL instead of GPIO15 */
64 pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8));
65 au_writel(pin_func, SYS_PINFUNC);
66 au_sync();
67#endif
68
69 printk("AMD Alchemy Hydrogen3 Board\n");
70}
diff --git a/arch/mips/au1000/hydrogen3/init.c b/arch/mips/au1000/hydrogen3/init.c
new file mode 100644
index 000000000000..eee4adf98711
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/init.c
@@ -0,0 +1,77 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * PB1000 board setup
5 *
6 * Copyright 2001 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31#include <linux/init.h>
32#include <linux/mm.h>
33#include <linux/sched.h>
34#include <linux/bootmem.h>
35#include <asm/addrspace.h>
36#include <asm/bootinfo.h>
37#include <linux/config.h>
38#include <linux/string.h>
39#include <linux/kernel.h>
40#include <linux/sched.h>
41
42int prom_argc;
43char **prom_argv, **prom_envp;
44extern void __init prom_init_cmdline(void);
45extern char *prom_getenv(char *envname);
46
47const char *get_system_type(void)
48{
49#ifdef CONFIG_MIPS_BOSPORUS
50 return "Alchemy Bosporus Gateway Reference";
51#else
52 return "Alchemy Db1x00";
53#endif
54}
55
56int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
57{
58 unsigned char *memsize_str;
59 unsigned long memsize;
60
61 prom_argc = argc;
62 prom_argv = argv;
63 prom_envp = envp;
64
65 mips_machgroup = MACH_GROUP_ALCHEMY;
66 mips_machtype = MACH_DB1000; /* set the platform # */
67 prom_init_cmdline();
68
69 memsize_str = prom_getenv("memsize");
70 if (!memsize_str) {
71 memsize = 0x04000000;
72 } else {
73 memsize = simple_strtol(memsize_str, NULL, 0);
74 }
75 add_memory_region(0, memsize, BOOT_MEM_RAM);
76 return 0;
77}
diff --git a/arch/mips/au1000/hydrogen3/irqmap.c b/arch/mips/au1000/hydrogen3/irqmap.c
new file mode 100644
index 000000000000..6eacaa0daa49
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/irqmap.c
@@ -0,0 +1,56 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51
52 /* { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, */
53 { AU1000_GPIO_21, INTC_INT_LOW_LEVEL, 0 },
54};
55
56int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile
new file mode 100644
index 000000000000..764bf9f7e281
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/Makefile
@@ -0,0 +1,10 @@
1#
2# Copyright 2003 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5# Bruno Randolf <bruno.randolf@4g-systems.biz>
6#
7# Makefile for 4G Systems MTX-1 board.
8#
9
10lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c
new file mode 100644
index 000000000000..638de7bb43f0
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/board_setup.c
@@ -0,0 +1,89 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * 4G Systems MTX-1 board setup.
5 *
6 * Copyright 2003 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 * Bruno Randolf <bruno.randolf@4g-systems.biz>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 */
31#include <linux/config.h>
32#include <linux/init.h>
33#include <linux/sched.h>
34#include <linux/ioport.h>
35#include <linux/mm.h>
36#include <linux/console.h>
37#include <linux/delay.h>
38
39#include <asm/cpu.h>
40#include <asm/bootinfo.h>
41#include <asm/irq.h>
42#include <asm/mipsregs.h>
43#include <asm/reboot.h>
44#include <asm/pgtable.h>
45#include <asm/mach-au1x00/au1000.h>
46
47void board_reset (void)
48{
49 /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
50 au_writel(0x00000000, 0xAE00001C);
51}
52
53void __init board_setup(void)
54{
55#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
56#ifdef CONFIG_AU1X00_USB_DEVICE
57 // 2nd USB port is USB device
58 au_writel(au_readl(SYS_PINFUNC) & (u32)(~0x8000), SYS_PINFUNC);
59#endif
60 // enable USB power switch
61 au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR );
62 au_writel( 0x100000, GPIO2_OUTPUT );
63#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
64
65#ifdef CONFIG_PCI
66#if defined(__MIPSEB__)
67 au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
68#else
69 au_writel(0xf, Au1500_PCI_CFG);
70#endif
71#endif
72
73 // initialize sys_pinfunc:
74 // disable second ethernet port (SYS_PF_NI2)
75 // set U3/GPIO23 to GPIO23 (SYS_PF_U3)
76 au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC );
77
78 // initialize GPIO
79 au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR );
80 au_writel( 0x00000001, SYS_OUTPUTCLR ); // set M66EN (PCI 66MHz) to OFF
81 au_writel( 0x00000008, SYS_OUTPUTSET ); // set PCI CLKRUN# to OFF
82 au_writel( 0x00000020, SYS_OUTPUTCLR ); // set eth PHY TX_ER to OFF
83
84 // enable LED and set it to green
85 au_writel( au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR );
86 au_writel( 0x18000800, GPIO2_OUTPUT );
87
88 printk("4G Systems MTX-1 Board\n");
89}
diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c
new file mode 100644
index 000000000000..02e7dbcff727
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/init.c
@@ -0,0 +1,71 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * 4G Systems MTX-1 board setup
5 *
6 * Copyright 2003 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 * Bruno Randolf <bruno.randolf@4g-systems.biz>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 */
31#include <linux/string.h>
32#include <linux/kernel.h>
33#include <linux/sched.h>
34#include <linux/init.h>
35#include <linux/mm.h>
36#include <linux/sched.h>
37#include <linux/bootmem.h>
38#include <asm/addrspace.h>
39#include <asm/bootinfo.h>
40
41int prom_argc;
42char **prom_argv, **prom_envp;
43extern void __init prom_init_cmdline(void);
44extern char *prom_getenv(char *envname);
45
46const char *get_system_type(void)
47{
48 return "MTX-1";
49}
50
51void __init prom_init(void)
52{
53 unsigned char *memsize_str;
54 unsigned long memsize;
55
56 prom_argc = fw_arg0;
57 prom_argv = (char **) fw_arg1;
58 prom_envp = (char **) fw_arg2;
59
60 mips_machgroup = MACH_GROUP_ALCHEMY;
61 mips_machtype = MACH_MTX1; /* set the platform # */
62
63 prom_init_cmdline();
64
65 memsize_str = prom_getenv("memsize");
66 if (!memsize_str)
67 memsize = 0x04000000;
68 else
69 memsize = simple_strtol(memsize_str, NULL, 0);
70 add_memory_region(0, memsize, BOOT_MEM_RAM);
71}
diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c
new file mode 100644
index 000000000000..ddcb9d089dc1
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/irqmap.c
@@ -0,0 +1,58 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/mach-au1x00/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51 { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
52 { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
53 { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
54 { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
55 { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
56};
57
58int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1000/Makefile b/arch/mips/au1000/pb1000/Makefile
new file mode 100644
index 000000000000..daa1a507e72f
--- /dev/null
+++ b/arch/mips/au1000/pb1000/Makefile
@@ -0,0 +1,8 @@
1#
2# Copyright 2000 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for the Alchemy Semiconductor PB1000 board.
7
8lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c
new file mode 100644
index 000000000000..2fa211b69329
--- /dev/null
+++ b/arch/mips/au1000/pb1000/board_setup.c
@@ -0,0 +1,182 @@
1/*
2 * Copyright 2000 MontaVista Software Inc.
3 * Author: MontaVista Software, Inc.
4 * ppopov@mvista.com or source@mvista.com
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
14 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
17 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26#include <linux/config.h>
27#include <linux/init.h>
28#include <linux/sched.h>
29#include <linux/ioport.h>
30#include <linux/mm.h>
31#include <linux/console.h>
32#include <linux/delay.h>
33
34#include <asm/cpu.h>
35#include <asm/bootinfo.h>
36#include <asm/irq.h>
37#include <asm/mipsregs.h>
38#include <asm/reboot.h>
39#include <asm/pgtable.h>
40#include <asm/mach-au1x00/au1000.h>
41#include <asm/mach-pb1x00/pb1000.h>
42
43void board_reset (void)
44{
45}
46
47void __init board_setup(void)
48{
49 u32 pin_func, static_cfg0;
50 u32 sys_freqctrl, sys_clksrc;
51 u32 prid = read_c0_prid();
52
53 // set AUX clock to 12MHz * 8 = 96 MHz
54 au_writel(8, SYS_AUXPLL);
55 au_writel(0, SYS_PINSTATERD);
56 udelay(100);
57
58#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
59 /* zero and disable FREQ2 */
60 sys_freqctrl = au_readl(SYS_FREQCTRL0);
61 sys_freqctrl &= ~0xFFF00000;
62 au_writel(sys_freqctrl, SYS_FREQCTRL0);
63
64 /* zero and disable USBH/USBD clocks */
65 sys_clksrc = au_readl(SYS_CLKSRC);
66 sys_clksrc &= ~0x00007FE0;
67 au_writel(sys_clksrc, SYS_CLKSRC);
68
69 sys_freqctrl = au_readl(SYS_FREQCTRL0);
70 sys_freqctrl &= ~0xFFF00000;
71
72 sys_clksrc = au_readl(SYS_CLKSRC);
73 sys_clksrc &= ~0x00007FE0;
74
75 switch (prid & 0x000000FF)
76 {
77 case 0x00: /* DA */
78 case 0x01: /* HA */
79 case 0x02: /* HB */
80 /* CPU core freq to 48MHz to slow it way down... */
81 au_writel(4, SYS_CPUPLL);
82
83 /*
84 * Setup 48MHz FREQ2 from CPUPLL for USB Host
85 */
86 /* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */
87 sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20));
88 au_writel(sys_freqctrl, SYS_FREQCTRL0);
89
90 /* CPU core freq to 384MHz */
91 au_writel(0x20, SYS_CPUPLL);
92
93 printk("Au1000: 48MHz OHCI workaround enabled\n");
94 break;
95
96 default: /* HC and newer */
97 // FREQ2 = aux/2 = 48 MHz
98 sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
99 au_writel(sys_freqctrl, SYS_FREQCTRL0);
100 break;
101 }
102
103 /*
104 * Route 48MHz FREQ2 into USB Host and/or Device
105 */
106#ifdef CONFIG_USB_OHCI
107 sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
108#endif
109#ifdef CONFIG_AU1X00_USB_DEVICE
110 sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
111#endif
112 au_writel(sys_clksrc, SYS_CLKSRC);
113
114 // configure pins GPIO[14:9] as GPIO
115 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080);
116
117#ifndef CONFIG_AU1X00_USB_DEVICE
118 // 2nd USB port is USB host
119 pin_func |= 0x8000;
120#endif
121 au_writel(pin_func, SYS_PINFUNC);
122 au_writel(0x2800, SYS_TRIOUTCLR);
123 au_writel(0x0030, SYS_OUTPUTCLR);
124#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
125
126 // make gpio 15 an input (for interrupt line)
127 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100);
128 // we don't need I2S, so make it available for GPIO[31:29]
129 pin_func |= (1<<5);
130 au_writel(pin_func, SYS_PINFUNC);
131
132 au_writel(0x8000, SYS_TRIOUTCLR);
133
134 static_cfg0 = au_readl(MEM_STCFG0) & (u32)(~0xc00);
135 au_writel(static_cfg0, MEM_STCFG0);
136
137 // configure RCE2* for LCD
138 au_writel(0x00000004, MEM_STCFG2);
139
140 // MEM_STTIME2
141 au_writel(0x09000000, MEM_STTIME2);
142
143 // Set 32-bit base address decoding for RCE2*
144 au_writel(0x10003ff0, MEM_STADDR2);
145
146 // PCI CPLD setup
147 // expand CE0 to cover PCI
148 au_writel(0x11803e40, MEM_STADDR1);
149
150 // burst visibility on
151 au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0);
152
153 au_writel(0x83, MEM_STCFG1); // ewait enabled, flash timing
154 au_writel(0x33030a10, MEM_STTIME1); // slower timing for FPGA
155
156 /* setup the static bus controller */
157 au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */
158 au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
159 au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
160
161#ifdef CONFIG_PCI
162 au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0
163 au_writel(0, SDRAM_MBAR); // set mbar to 0
164 au_writel(0x2, SDRAM_CMD); // enable memory accesses
165 au_sync_delay(1);
166#endif
167
168 /* Enable Au1000 BCLK switching - note: sed1356 must not use
169 * its BCLK (Au1000 LCLK) for any timings */
170 switch (prid & 0x000000FF)
171 {
172 case 0x00: /* DA */
173 case 0x01: /* HA */
174 case 0x02: /* HB */
175 break;
176 default: /* HC and newer */
177 /* Enable sys bus clock divider when IDLE state or no bus
178 activity. */
179 au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
180 break;
181 }
182}
diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c
new file mode 100644
index 000000000000..34713c5df0d7
--- /dev/null
+++ b/arch/mips/au1000/pb1000/init.c
@@ -0,0 +1,69 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * PB1000 board setup
4 *
5 * Copyright 2001 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29#include <linux/init.h>
30#include <linux/mm.h>
31#include <linux/sched.h>
32#include <linux/bootmem.h>
33#include <asm/addrspace.h>
34#include <asm/bootinfo.h>
35#include <linux/string.h>
36#include <linux/kernel.h>
37
38int prom_argc;
39char **prom_argv, **prom_envp;
40extern void __init prom_init_cmdline(void);
41extern char *prom_getenv(char *envname);
42
43const char *get_system_type(void)
44{
45 return "Alchemy Pb1000";
46}
47
48void __init prom_init(void)
49{
50 unsigned char *memsize_str;
51 unsigned long memsize;
52
53 prom_argc = (int) fw_arg0;
54 prom_argv = (char **) fw_arg1;
55 prom_envp = (char **) fw_arg2;
56
57 mips_machgroup = MACH_GROUP_ALCHEMY;
58 mips_machtype = MACH_PB1000;
59
60 prom_init_cmdline();
61 memsize_str = prom_getenv("memsize");
62 if (!memsize_str) {
63 memsize = 0x04000000;
64 } else {
65 memsize = simple_strtol(memsize_str, NULL, 0);
66 }
67 add_memory_region(0, memsize, BOOT_MEM_RAM);
68 return 0;
69}
diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c
new file mode 100644
index 000000000000..a3c460e3c23e
--- /dev/null
+++ b/arch/mips/au1000/pb1000/irqmap.c
@@ -0,0 +1,54 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/mach-au1x00/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51 { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
52};
53
54int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1100/Makefile b/arch/mips/au1000/pb1100/Makefile
new file mode 100644
index 000000000000..996236df6375
--- /dev/null
+++ b/arch/mips/au1000/pb1100/Makefile
@@ -0,0 +1,8 @@
1#
2# Copyright 2000,2001 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for the Alchemy Semiconductor Pb1100 board.
7
8lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c
new file mode 100644
index 000000000000..13c2f6ca7e33
--- /dev/null
+++ b/arch/mips/au1000/pb1100/board_setup.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright 2002 MontaVista Software Inc.
3 * Author: MontaVista Software, Inc.
4 * ppopov@mvista.com or source@mvista.com
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
14 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
17 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26#include <linux/config.h>
27#include <linux/init.h>
28#include <linux/sched.h>
29#include <linux/ioport.h>
30#include <linux/mm.h>
31#include <linux/console.h>
32#include <linux/delay.h>
33
34#include <asm/cpu.h>
35#include <asm/bootinfo.h>
36#include <asm/irq.h>
37#include <asm/mipsregs.h>
38#include <asm/reboot.h>
39#include <asm/pgtable.h>
40#include <asm/mach-au1x00/au1000.h>
41#include <asm/mach-pb1x00/pb1100.h>
42
43void board_reset (void)
44{
45 /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
46 au_writel(0x00000000, 0xAE00001C);
47}
48
49void __init board_setup(void)
50{
51 u32 pin_func;
52 u32 sys_freqctrl, sys_clksrc;
53
54 // set AUX clock to 12MHz * 8 = 96 MHz
55 au_writel(8, SYS_AUXPLL);
56 au_writel(0, SYS_PININPUTEN);
57 udelay(100);
58
59#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
60 // configure pins GPIO[14:9] as GPIO
61 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
62
63 /* zero and disable FREQ2 */
64 sys_freqctrl = au_readl(SYS_FREQCTRL0);
65 sys_freqctrl &= ~0xFFF00000;
66 au_writel(sys_freqctrl, SYS_FREQCTRL0);
67
68 /* zero and disable USBH/USBD/IrDA clock */
69 sys_clksrc = au_readl(SYS_CLKSRC);
70 sys_clksrc &= ~0x0000001F;
71 au_writel(sys_clksrc, SYS_CLKSRC);
72
73 sys_freqctrl = au_readl(SYS_FREQCTRL0);
74 sys_freqctrl &= ~0xFFF00000;
75
76 sys_clksrc = au_readl(SYS_CLKSRC);
77 sys_clksrc &= ~0x0000001F;
78
79 // FREQ2 = aux/2 = 48 MHz
80 sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
81 au_writel(sys_freqctrl, SYS_FREQCTRL0);
82
83 /*
84 * Route 48MHz FREQ2 into USBH/USBD/IrDA
85 */
86 sys_clksrc |= ((4<<2) | (0<<1) | 0 );
87 au_writel(sys_clksrc, SYS_CLKSRC);
88
89 /* setup the static bus controller */
90 au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */
91 au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
92 au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
93
94 // get USB Functionality pin state (device vs host drive pins)
95 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
96#ifndef CONFIG_AU1X00_USB_DEVICE
97 // 2nd USB port is USB host
98 pin_func |= 0x8000;
99#endif
100 au_writel(pin_func, SYS_PINFUNC);
101#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
102
103 /* Enable sys bus clock divider when IDLE state or no bus activity. */
104 au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
105
106 // Enable the RTC if not already enabled
107 if (!(readb(0xac000028) & 0x20)) {
108 writeb(readb(0xac000028) | 0x20, 0xac000028);
109 au_sync();
110 }
111 // Put the clock in BCD mode
112 if (readb(0xac00002C) & 0x4) { /* reg B */
113 writeb(readb(0xac00002c) & ~0x4, 0xac00002c);
114 au_sync();
115 }
116}
diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c
new file mode 100644
index 000000000000..1fae39a608cf
--- /dev/null
+++ b/arch/mips/au1000/pb1100/init.c
@@ -0,0 +1,70 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Pb1100 board setup
5 *
6 * Copyright 2002 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30#include <linux/init.h>
31#include <linux/mm.h>
32#include <linux/sched.h>
33#include <linux/bootmem.h>
34#include <asm/addrspace.h>
35#include <asm/bootinfo.h>
36#include <linux/string.h>
37#include <linux/kernel.h>
38
39int prom_argc;
40char **prom_argv, **prom_envp;
41extern void __init prom_init_cmdline(void);
42extern char *prom_getenv(char *envname);
43
44const char *get_system_type(void)
45{
46 return "Alchemy Pb1100";
47}
48
49void __init prom_init(void)
50{
51 unsigned char *memsize_str;
52 unsigned long memsize;
53
54 prom_argc = fw_arg0;
55 prom_argv = (char **) fw_arg1;
56 prom_envp = (int *) fw_arg3;
57
58 mips_machgroup = MACH_GROUP_ALCHEMY;
59 mips_machtype = MACH_PB1100;
60
61 prom_init_cmdline();
62
63 memsize_str = prom_getenv("memsize");
64 if (!memsize_str)
65 memsize = 0x04000000;
66 else
67 memsize = simple_strtol(memsize_str, NULL, 0);
68
69 add_memory_region(0, memsize, BOOT_MEM_RAM);
70}
diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c
new file mode 100644
index 000000000000..43be7158b9ab
--- /dev/null
+++ b/arch/mips/au1000/pb1100/irqmap.c
@@ -0,0 +1,57 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/mach-au1x00/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51 { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted#
52 { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG#
53 { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ#
54 { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, // DC_IRQ#
55};
56
57int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1500/Makefile b/arch/mips/au1000/pb1500/Makefile
new file mode 100644
index 000000000000..97a730813cd3
--- /dev/null
+++ b/arch/mips/au1000/pb1500/Makefile
@@ -0,0 +1,8 @@
1#
2# Copyright 2000,2001 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for the Alchemy Semiconductor Pb1500 board.
7
8lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c
new file mode 100644
index 000000000000..30bb87282b1f
--- /dev/null
+++ b/arch/mips/au1000/pb1500/board_setup.c
@@ -0,0 +1,138 @@
1/*
2 * Copyright 2000 MontaVista Software Inc.
3 * Author: MontaVista Software, Inc.
4 * ppopov@mvista.com or source@mvista.com
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
14 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
17 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26#include <linux/config.h>
27#include <linux/init.h>
28#include <linux/sched.h>
29#include <linux/ioport.h>
30#include <linux/mm.h>
31#include <linux/console.h>
32#include <linux/delay.h>
33
34#include <asm/cpu.h>
35#include <asm/bootinfo.h>
36#include <asm/irq.h>
37#include <asm/mipsregs.h>
38#include <asm/reboot.h>
39#include <asm/pgtable.h>
40#include <asm/mach-au1x00/au1000.h>
41#include <asm/mach-pb1x00/pb1500.h>
42
43void board_reset (void)
44{
45 /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
46 au_writel(0x00000000, 0xAE00001C);
47}
48
49void __init board_setup(void)
50{
51 u32 pin_func;
52 u32 sys_freqctrl, sys_clksrc;
53
54 sys_clksrc = sys_freqctrl = pin_func = 0;
55 // set AUX clock to 12MHz * 8 = 96 MHz
56 au_writel(8, SYS_AUXPLL);
57 au_writel(0, SYS_PINSTATERD);
58 udelay(100);
59
60#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
61
62 /* GPIO201 is input for PCMCIA card detect */
63 /* GPIO203 is input for PCMCIA interrupt request */
64 au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR);
65
66 /* zero and disable FREQ2 */
67 sys_freqctrl = au_readl(SYS_FREQCTRL0);
68 sys_freqctrl &= ~0xFFF00000;
69 au_writel(sys_freqctrl, SYS_FREQCTRL0);
70
71 /* zero and disable USBH/USBD clocks */
72 sys_clksrc = au_readl(SYS_CLKSRC);
73 sys_clksrc &= ~0x00007FE0;
74 au_writel(sys_clksrc, SYS_CLKSRC);
75
76 sys_freqctrl = au_readl(SYS_FREQCTRL0);
77 sys_freqctrl &= ~0xFFF00000;
78
79 sys_clksrc = au_readl(SYS_CLKSRC);
80 sys_clksrc &= ~0x00007FE0;
81
82 // FREQ2 = aux/2 = 48 MHz
83 sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
84 au_writel(sys_freqctrl, SYS_FREQCTRL0);
85
86 /*
87 * Route 48MHz FREQ2 into USB Host and/or Device
88 */
89#ifdef CONFIG_USB_OHCI
90 sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
91#endif
92#ifdef CONFIG_AU1X00_USB_DEVICE
93 sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
94#endif
95 au_writel(sys_clksrc, SYS_CLKSRC);
96
97
98 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
99#ifndef CONFIG_AU1X00_USB_DEVICE
100 // 2nd USB port is USB host
101 pin_func |= 0x8000;
102#endif
103 au_writel(pin_func, SYS_PINFUNC);
104#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
105
106
107
108#ifdef CONFIG_PCI
109 // Setup PCI bus controller
110 au_writel(0, Au1500_PCI_CMEM);
111 au_writel(0x00003fff, Au1500_CFG_BASE);
112#if defined(__MIPSEB__)
113 au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
114#else
115 au_writel(0xf, Au1500_PCI_CFG);
116#endif
117 au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
118 au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
119 au_writel(0x02a00356, Au1500_PCI_STATCMD);
120 au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
121 au_writel(0x00000008, Au1500_PCI_MBAR);
122 au_sync();
123#endif
124
125 /* Enable sys bus clock divider when IDLE state or no bus activity. */
126 au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
127
128 /* Enable the RTC if not already enabled */
129 if (!(au_readl(0xac000028) & 0x20)) {
130 printk("enabling clock ...\n");
131 au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
132 }
133 /* Put the clock in BCD mode */
134 if (readl(0xac00002C) & 0x4) { /* reg B */
135 au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
136 au_sync();
137 }
138}
diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c
new file mode 100644
index 000000000000..733d2e469db2
--- /dev/null
+++ b/arch/mips/au1000/pb1500/init.c
@@ -0,0 +1,69 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * PB1500 board setup
5 *
6 * Copyright 2001 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30#include <linux/init.h>
31#include <linux/mm.h>
32#include <linux/sched.h>
33#include <linux/bootmem.h>
34#include <asm/addrspace.h>
35#include <asm/bootinfo.h>
36#include <linux/string.h>
37#include <linux/kernel.h>
38
39int prom_argc;
40char **prom_argv, **prom_envp;
41extern void __init prom_init_cmdline(void);
42extern char *prom_getenv(char *envname);
43
44const char *get_system_type(void)
45{
46 return "Alchemy Pb1500";
47}
48
49void __init prom_init(void)
50{
51 unsigned char *memsize_str;
52 unsigned long memsize;
53
54 prom_argc = (int) fw_arg0;
55 prom_argv = (char **) fw_arg1;
56 prom_envp = (char **) fw_arg2;
57
58 mips_machgroup = MACH_GROUP_ALCHEMY;
59 mips_machtype = MACH_PB1500;
60
61 prom_init_cmdline();
62 memsize_str = prom_getenv("memsize");
63 if (!memsize_str) {
64 memsize = 0x04000000;
65 } else {
66 memsize = simple_strtol(memsize_str, NULL, 0);
67 }
68 add_memory_region(0, memsize, BOOT_MEM_RAM);
69}
diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c
new file mode 100644
index 000000000000..476e25001681
--- /dev/null
+++ b/arch/mips/au1000/pb1500/irqmap.c
@@ -0,0 +1,58 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/mach-au1x00/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51 { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
52 { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
53 { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
54 { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
55 { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
56};
57
58int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1550/Makefile b/arch/mips/au1000/pb1550/Makefile
new file mode 100644
index 000000000000..aa35bc6cb8cf
--- /dev/null
+++ b/arch/mips/au1000/pb1550/Makefile
@@ -0,0 +1,9 @@
1#
2# Copyright 2000 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for the Alchemy Semiconductor PB1000 board.
7#
8
9lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1550/board_setup.c b/arch/mips/au1000/pb1550/board_setup.c
new file mode 100644
index 000000000000..05fd27dc24e6
--- /dev/null
+++ b/arch/mips/au1000/pb1550/board_setup.c
@@ -0,0 +1,69 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * Alchemy Pb1550 board setup.
5 *
6 * Copyright 2000 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30#include <linux/init.h>
31#include <linux/sched.h>
32#include <linux/ioport.h>
33#include <linux/mm.h>
34#include <linux/console.h>
35#include <linux/mc146818rtc.h>
36#include <linux/delay.h>
37
38#include <asm/cpu.h>
39#include <asm/bootinfo.h>
40#include <asm/irq.h>
41#include <asm/mipsregs.h>
42#include <asm/reboot.h>
43#include <asm/pgtable.h>
44#include <asm/mach-au1x00/au1000.h>
45#include <asm/mach-pb1x00/pb1550.h>
46
47void board_reset (void)
48{
49 /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
50 au_writew(au_readw(0xAF00001C) & ~(1<<15), 0xAF00001C);
51}
52
53void __init board_setup(void)
54{
55 u32 pin_func;
56
57 /* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
58 * but it is board specific code, so put it here.
59 */
60 pin_func = au_readl(SYS_PINFUNC);
61 au_sync();
62 pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1;
63 au_writel(pin_func, SYS_PINFUNC);
64
65 au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
66 au_sync();
67
68 printk("AMD Alchemy Pb1550 Board\n");
69}
diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c
new file mode 100644
index 000000000000..41daa3371be3
--- /dev/null
+++ b/arch/mips/au1000/pb1550/init.c
@@ -0,0 +1,69 @@
1/*
2 *
3 * BRIEF MODULE DESCRIPTION
4 * PB1550 board setup
5 *
6 * Copyright 2001 MontaVista Software Inc.
7 * Author: MontaVista Software, Inc.
8 * ppopov@mvista.com or source@mvista.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30#include <linux/init.h>
31#include <linux/mm.h>
32#include <linux/sched.h>
33#include <linux/bootmem.h>
34#include <asm/addrspace.h>
35#include <asm/bootinfo.h>
36#include <linux/string.h>
37#include <linux/kernel.h>
38
39int prom_argc;
40char **prom_argv, **prom_envp;
41extern void __init prom_init_cmdline(void);
42extern char *prom_getenv(char *envname);
43
44const char *get_system_type(void)
45{
46 return "Alchemy Pb1550";
47}
48
49void __init prom_init(void)
50{
51 unsigned char *memsize_str;
52 unsigned long memsize;
53
54 prom_argc = (int) fw_arg0;
55 prom_argv = (char **) fw_arg1;
56 prom_envp = (char **) fw_arg2;
57
58 mips_machgroup = MACH_GROUP_ALCHEMY;
59 mips_machtype = MACH_PB1550;
60
61 prom_init_cmdline();
62 memsize_str = prom_getenv("memsize");
63 if (!memsize_str) {
64 memsize = 0x08000000;
65 } else {
66 memsize = simple_strtol(memsize_str, NULL, 0);
67 }
68 add_memory_region(0, memsize, BOOT_MEM_RAM);
69}
diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c
new file mode 100644
index 000000000000..889d4949ee76
--- /dev/null
+++ b/arch/mips/au1000/pb1550/irqmap.c
@@ -0,0 +1,55 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/mach-au1x00/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
52 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
53};
54
55int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/xxs1500/Makefile b/arch/mips/au1000/xxs1500/Makefile
new file mode 100644
index 000000000000..44d7f7056ae7
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/Makefile
@@ -0,0 +1,9 @@
1#
2# Copyright 2003 MontaVista Software Inc.
3# Author: MontaVista Software, Inc.
4# ppopov@mvista.com or source@mvista.com
5#
6# Makefile for MyCable XXS1500 board.
7#
8
9lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/au1000/xxs1500/board_setup.c
new file mode 100644
index 000000000000..9dadc82536f4
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/board_setup.c
@@ -0,0 +1,91 @@
1/*
2 * Copyright 2000-2003 MontaVista Software Inc.
3 * Author: MontaVista Software, Inc.
4 * ppopov@mvista.com or source@mvista.com
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
14 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
17 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26#include <linux/config.h>
27#include <linux/init.h>
28#include <linux/sched.h>
29#include <linux/ioport.h>
30#include <linux/mm.h>
31#include <linux/console.h>
32#include <linux/delay.h>
33
34#include <asm/cpu.h>
35#include <asm/bootinfo.h>
36#include <asm/irq.h>
37#include <asm/keyboard.h>
38#include <asm/mipsregs.h>
39#include <asm/reboot.h>
40#include <asm/pgtable.h>
41#include <asm/au1000.h>
42
43void board_reset (void)
44{
45 /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
46 au_writel(0x00000000, 0xAE00001C);
47}
48
49void __init board_setup(void)
50{
51 u32 pin_func;
52
53 // set multiple use pins (UART3/GPIO) to UART (it's used as UART too)
54 pin_func = au_readl(SYS_PINFUNC) & (u32)(~SYS_PF_UR3);
55 pin_func |= SYS_PF_UR3;
56 au_writel(pin_func, SYS_PINFUNC);
57
58 // enable UART
59 au_writel(0x01, UART3_ADDR+UART_MOD_CNTRL); // clock enable (CE)
60 mdelay(10);
61 au_writel(0x03, UART3_ADDR+UART_MOD_CNTRL); // CE and "enable"
62 mdelay(10);
63
64 // enable DTR = USB power up
65 au_writel(0x01, UART3_ADDR+UART_MCR); //? UART_MCR_DTR is 0x01???
66
67#ifdef CONFIG_PCMCIA_XXS1500
68 /* setup pcmcia signals */
69 au_writel(0, SYS_PININPUTEN);
70
71 /* gpio 0, 1, and 4 are inputs */
72 au_writel(1 | (1<<1) | (1<<4), SYS_TRIOUTCLR);
73
74 /* enable GPIO2 if not already enabled */
75 au_writel(1, GPIO2_ENABLE);
76 /* gpio2 208/9/10/11 are inputs */
77 au_writel((1<<8) | (1<<9) | (1<<10) | (1<<11), GPIO2_DIR);
78
79 /* turn off power */
80 au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<14))|(1<<30), GPIO2_OUTPUT);
81#endif
82
83
84#ifdef CONFIG_PCI
85#if defined(__MIPSEB__)
86 au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
87#else
88 au_writel(0xf, Au1500_PCI_CFG);
89#endif
90#endif
91}
diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c
new file mode 100644
index 000000000000..03f755291b51
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/init.c
@@ -0,0 +1,68 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * XXS1500 board setup
4 *
5 * Copyright 2003 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29#include <linux/init.h>
30#include <linux/mm.h>
31#include <linux/sched.h>
32#include <linux/bootmem.h>
33#include <asm/addrspace.h>
34#include <asm/bootinfo.h>
35#include <linux/string.h>
36#include <linux/kernel.h>
37
38int prom_argc;
39char **prom_argv, **prom_envp;
40extern void __init prom_init_cmdline(void);
41extern char *prom_getenv(char *envname);
42
43const char *get_system_type(void)
44{
45 return "XXS1500";
46}
47
48void __init prom_init(void)
49{
50 unsigned char *memsize_str;
51 unsigned long memsize;
52
53 prom_argc = fw_arg0;
54 prom_argv = (char **) fw_arg1;
55 prom_envp = (char **) fw_arg2;
56
57 mips_machgroup = MACH_GROUP_ALCHEMY;
58 mips_machtype = MACH_XXS1500; /* set the platform # */
59
60 prom_init_cmdline();
61
62 memsize_str = prom_getenv("memsize");
63 if (!memsize_str)
64 memsize = 0x04000000;
65 else
66 memsize = simple_strtol(memsize_str, NULL, 0);
67 add_memory_region(0, memsize, BOOT_MEM_RAM);
68}
diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c
new file mode 100644
index 000000000000..954800a0ab52
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/irqmap.c
@@ -0,0 +1,66 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx irq map table
4 *
5 * Copyright 2003 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/errno.h>
29#include <linux/init.h>
30#include <linux/irq.h>
31#include <linux/kernel_stat.h>
32#include <linux/module.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/types.h>
36#include <linux/interrupt.h>
37#include <linux/ioport.h>
38#include <linux/timex.h>
39#include <linux/slab.h>
40#include <linux/random.h>
41#include <linux/delay.h>
42#include <linux/bitops.h>
43
44#include <asm/bootinfo.h>
45#include <asm/io.h>
46#include <asm/mipsregs.h>
47#include <asm/system.h>
48#include <asm/au1000.h>
49
50au1xxx_irq_map_t au1xxx_irq_map[] = {
51 { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
52 { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
53 { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
54 { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
55 { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
56 { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
57
58 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
59 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
60 { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
61 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
62 { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
63 { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
64};
65
66int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);