e3acfa8c3a4211a78f77afe4d7f1034025fc80b5
[openwrt/svn-archive/archive.git] / target / linux / generic-2.4 / patches / 000-linux_mips.patch
1 --- a/arch/mips/au1000/common/au1xxx_irqmap.c
2 +++ b/arch/mips/au1000/common/au1xxx_irqmap.c
3 @@ -172,14 +172,14 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = {
4 { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
5 { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0},
6 { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0},
7 - { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 },
8 - { AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
9 - { AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
10 - { AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
11 - { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 },
12 - { AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
13 - { AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
14 - { AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
15 + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
16 + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
17 + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
18 + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
19 + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
20 + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
21 + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
22 + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
23 { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0},
24 { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
25 { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
26 @@ -200,14 +200,14 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = {
27 { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
28 { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0},
29 { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0},
30 - { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 },
31 - { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
32 - { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
33 - { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
34 - { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 },
35 - { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
36 - { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
37 - { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
38 + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
39 + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
40 + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
41 + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
42 + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
43 + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
44 + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
45 + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
46 { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0},
47 { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
48 { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
49 --- a/arch/mips/au1000/common/cputable.c
50 +++ b/arch/mips/au1000/common/cputable.c
51 @@ -39,7 +39,8 @@ struct cpu_spec cpu_specs[] = {
52 { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 },
53 { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 },
54 { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 },
55 - { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 },
56 + { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 },
57 + { 0xffffffff, 0x04030201, "Au1200 AC", 0, 0 },
58 { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 },
59 };
60
61 --- a/arch/mips/au1000/common/dbdma.c
62 +++ b/arch/mips/au1000/common/dbdma.c
63 @@ -41,6 +41,8 @@
64 #include <asm/au1xxx_dbdma.h>
65 #include <asm/system.h>
66
67 +#include <linux/module.h>
68 +
69 #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
70
71 /*
72 @@ -60,37 +62,10 @@ static spinlock_t au1xxx_dbdma_spin_lock
73 */
74 #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1))
75
76 -static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
77 -static int dbdma_initialized;
78 +static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
79 +static int dbdma_initialized=0;
80 static void au1xxx_dbdma_init(void);
81
82 -typedef struct dbdma_device_table {
83 - u32 dev_id;
84 - u32 dev_flags;
85 - u32 dev_tsize;
86 - u32 dev_devwidth;
87 - u32 dev_physaddr; /* If FIFO */
88 - u32 dev_intlevel;
89 - u32 dev_intpolarity;
90 -} dbdev_tab_t;
91 -
92 -typedef struct dbdma_chan_config {
93 - u32 chan_flags;
94 - u32 chan_index;
95 - dbdev_tab_t *chan_src;
96 - dbdev_tab_t *chan_dest;
97 - au1x_dma_chan_t *chan_ptr;
98 - au1x_ddma_desc_t *chan_desc_base;
99 - au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr;
100 - void *chan_callparam;
101 - void (*chan_callback)(int, void *, struct pt_regs *);
102 -} chan_tab_t;
103 -
104 -#define DEV_FLAGS_INUSE (1 << 0)
105 -#define DEV_FLAGS_ANYUSE (1 << 1)
106 -#define DEV_FLAGS_OUT (1 << 2)
107 -#define DEV_FLAGS_IN (1 << 3)
108 -
109 static dbdev_tab_t dbdev_tab[] = {
110 #ifdef CONFIG_SOC_AU1550
111 /* UARTS */
112 @@ -156,13 +131,13 @@ static dbdev_tab_t dbdev_tab[] = {
113 { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
114 { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
115
116 - { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
117 - { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
118 - { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
119 - { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
120 + { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
121 + { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 },
122 + { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 },
123 + { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 },
124
125 - { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
126 - { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
127 + { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
128 + { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
129
130 { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
131 { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
132 @@ -172,9 +147,9 @@ static dbdev_tab_t dbdev_tab[] = {
133 { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
134 { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
135
136 - { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
137 - { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
138 - { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
139 + { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 },
140 + { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 },
141 + { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 },
142 { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
143
144 { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
145 @@ -183,6 +158,24 @@ static dbdev_tab_t dbdev_tab[] = {
146
147 { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
148 { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
149 +
150 + /* Provide 16 user definable device types */
151 + { 0, 0, 0, 0, 0, 0, 0 },
152 + { 0, 0, 0, 0, 0, 0, 0 },
153 + { 0, 0, 0, 0, 0, 0, 0 },
154 + { 0, 0, 0, 0, 0, 0, 0 },
155 + { 0, 0, 0, 0, 0, 0, 0 },
156 + { 0, 0, 0, 0, 0, 0, 0 },
157 + { 0, 0, 0, 0, 0, 0, 0 },
158 + { 0, 0, 0, 0, 0, 0, 0 },
159 + { 0, 0, 0, 0, 0, 0, 0 },
160 + { 0, 0, 0, 0, 0, 0, 0 },
161 + { 0, 0, 0, 0, 0, 0, 0 },
162 + { 0, 0, 0, 0, 0, 0, 0 },
163 + { 0, 0, 0, 0, 0, 0, 0 },
164 + { 0, 0, 0, 0, 0, 0, 0 },
165 + { 0, 0, 0, 0, 0, 0, 0 },
166 + { 0, 0, 0, 0, 0, 0, 0 },
167 };
168
169 #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t))
170 @@ -202,6 +195,30 @@ find_dbdev_id (u32 id)
171 return NULL;
172 }
173
174 +u32
175 +au1xxx_ddma_add_device(dbdev_tab_t *dev)
176 +{
177 + u32 ret = 0;
178 + dbdev_tab_t *p=NULL;
179 + static u16 new_id=0x1000;
180 +
181 + p = find_dbdev_id(0);
182 + if ( NULL != p )
183 + {
184 + memcpy(p, dev, sizeof(dbdev_tab_t));
185 + p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id);
186 + ret = p->dev_id;
187 + new_id++;
188 +#if 0
189 + printk("add_device: id:%x flags:%x padd:%x\n",
190 + p->dev_id, p->dev_flags, p->dev_physaddr );
191 +#endif
192 + }
193 +
194 + return ret;
195 +}
196 +EXPORT_SYMBOL(au1xxx_ddma_add_device);
197 +
198 /* Allocate a channel and return a non-zero descriptor if successful.
199 */
200 u32
201 @@ -214,7 +231,7 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
202 int i;
203 dbdev_tab_t *stp, *dtp;
204 chan_tab_t *ctp;
205 - volatile au1x_dma_chan_t *cp;
206 + au1x_dma_chan_t *cp;
207
208 /* We do the intialization on the first channel allocation.
209 * We have to wait because of the interrupt handler initialization
210 @@ -224,9 +241,6 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
211 au1xxx_dbdma_init();
212 dbdma_initialized = 1;
213
214 - if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS))
215 - return 0;
216 -
217 if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
218 if ((dtp = find_dbdev_id(destid)) == NULL) return 0;
219
220 @@ -268,9 +282,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
221 /* If kmalloc fails, it is caught below same
222 * as a channel not available.
223 */
224 - ctp = (chan_tab_t *)kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
225 + ctp = (chan_tab_t *)
226 + kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
227 chan_tab_ptr[i] = ctp;
228 - ctp->chan_index = chan = i;
229 break;
230 }
231 }
232 @@ -278,10 +292,11 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
233
234 if (ctp != NULL) {
235 memset(ctp, 0, sizeof(chan_tab_t));
236 + ctp->chan_index = chan = i;
237 dcp = DDMA_CHANNEL_BASE;
238 dcp += (0x0100 * chan);
239 ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
240 - cp = (volatile au1x_dma_chan_t *)dcp;
241 + cp = (au1x_dma_chan_t *)dcp;
242 ctp->chan_src = stp;
243 ctp->chan_dest = dtp;
244 ctp->chan_callback = callback;
245 @@ -298,6 +313,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
246 i |= DDMA_CFG_DED;
247 if (dtp->dev_intpolarity)
248 i |= DDMA_CFG_DP;
249 + if ((stp->dev_flags & DEV_FLAGS_SYNC) ||
250 + (dtp->dev_flags & DEV_FLAGS_SYNC))
251 + i |= DDMA_CFG_SYNC;
252 cp->ddma_cfg = i;
253 au_sync();
254
255 @@ -308,14 +326,14 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 d
256 rv = (u32)(&chan_tab_ptr[chan]);
257 }
258 else {
259 - /* Release devices.
260 - */
261 + /* Release devices */
262 stp->dev_flags &= ~DEV_FLAGS_INUSE;
263 dtp->dev_flags &= ~DEV_FLAGS_INUSE;
264 }
265 }
266 return rv;
267 }
268 +EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc);
269
270 /* Set the device width if source or destination is a FIFO.
271 * Should be 8, 16, or 32 bits.
272 @@ -343,6 +361,7 @@ au1xxx_dbdma_set_devwidth(u32 chanid, in
273
274 return rv;
275 }
276 +EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth);
277
278 /* Allocate a descriptor ring, initializing as much as possible.
279 */
280 @@ -369,7 +388,8 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
281 * and if we try that first we are likely to not waste larger
282 * slabs of memory.
283 */
284 - desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL);
285 + desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t),
286 + GFP_KERNEL|GFP_DMA);
287 if (desc_base == 0)
288 return 0;
289
290 @@ -380,7 +400,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
291 kfree((const void *)desc_base);
292 i = entries * sizeof(au1x_ddma_desc_t);
293 i += (sizeof(au1x_ddma_desc_t) - 1);
294 - if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0)
295 + if ((desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA)) == 0)
296 return 0;
297
298 desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t));
299 @@ -460,9 +480,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
300 /* If source input is fifo, set static address.
301 */
302 if (stp->dev_flags & DEV_FLAGS_IN) {
303 - src0 = stp->dev_physaddr;
304 - src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC);
305 + if ( stp->dev_flags & DEV_FLAGS_BURSTABLE )
306 + src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST);
307 + else
308 + src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC);
309 +
310 }
311 + if (stp->dev_physaddr)
312 + src0 = stp->dev_physaddr;
313
314 /* Set up dest1. For now, assume no stride and increment.
315 * A channel attribute update can change this later.
316 @@ -486,10 +511,18 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
317 /* If destination output is fifo, set static address.
318 */
319 if (dtp->dev_flags & DEV_FLAGS_OUT) {
320 - dest0 = dtp->dev_physaddr;
321 + if ( dtp->dev_flags & DEV_FLAGS_BURSTABLE )
322 + dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST);
323 + else
324 dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC);
325 }
326 + if (dtp->dev_physaddr)
327 + dest0 = dtp->dev_physaddr;
328
329 +#if 0
330 + printk("did:%x sid:%x cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n",
331 + dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, src1, dest0, dest1 );
332 +#endif
333 for (i=0; i<entries; i++) {
334 dp->dscr_cmd0 = cmd0;
335 dp->dscr_cmd1 = cmd1;
336 @@ -498,6 +531,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
337 dp->dscr_dest0 = dest0;
338 dp->dscr_dest1 = dest1;
339 dp->dscr_stat = 0;
340 + dp->sw_context = dp->sw_status = 0;
341 dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1));
342 dp++;
343 }
344 @@ -510,13 +544,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int
345
346 return (u32)(ctp->chan_desc_base);
347 }
348 +EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc);
349
350 /* Put a source buffer into the DMA ring.
351 * This updates the source pointer and byte count. Normally used
352 * for memory to fifo transfers.
353 */
354 u32
355 -au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes)
356 +_au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags)
357 {
358 chan_tab_t *ctp;
359 au1x_ddma_desc_t *dp;
360 @@ -543,24 +578,40 @@ au1xxx_dbdma_put_source(u32 chanid, void
361 */
362 dp->dscr_source0 = virt_to_phys(buf);
363 dp->dscr_cmd1 = nbytes;
364 - dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
365 - ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */
366 -
367 + /* Check flags */
368 + if (flags & DDMA_FLAGS_IE)
369 + dp->dscr_cmd0 |= DSCR_CMD0_IE;
370 + if (flags & DDMA_FLAGS_NOIE)
371 + dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
372 /* Get next descriptor pointer.
373 */
374 ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
375
376 + /*
377 + * There is an errata on the Au1200/Au1550 parts that could result
378 + * in "stale" data being DMA'd. It has to do with the snoop logic on
379 + * the dache eviction buffer. NONCOHERENT_IO is on by default for
380 + * these parts. If it is fixedin the future, these dma_cache_inv will
381 + * just be nothing more than empty macros. See io.h.
382 + * */
383 + dma_cache_wback_inv(buf,nbytes);
384 + dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
385 + au_sync();
386 + dma_cache_wback_inv(dp, sizeof(dp));
387 + ctp->chan_ptr->ddma_dbell = 0;
388 +
389 /* return something not zero.
390 */
391 return nbytes;
392 }
393 +EXPORT_SYMBOL(_au1xxx_dbdma_put_source);
394
395 /* Put a destination buffer into the DMA ring.
396 * This updates the destination pointer and byte count. Normally used
397 * to place an empty buffer into the ring for fifo to memory transfers.
398 */
399 u32
400 -au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes)
401 +_au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags)
402 {
403 chan_tab_t *ctp;
404 au1x_ddma_desc_t *dp;
405 @@ -582,11 +633,33 @@ au1xxx_dbdma_put_dest(u32 chanid, void *
406 if (dp->dscr_cmd0 & DSCR_CMD0_V)
407 return 0;
408
409 - /* Load up buffer address and byte count.
410 - */
411 + /* Load up buffer address and byte count */
412 +
413 + /* Check flags */
414 + if (flags & DDMA_FLAGS_IE)
415 + dp->dscr_cmd0 |= DSCR_CMD0_IE;
416 + if (flags & DDMA_FLAGS_NOIE)
417 + dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
418 +
419 dp->dscr_dest0 = virt_to_phys(buf);
420 dp->dscr_cmd1 = nbytes;
421 +#if 0
422 + printk("cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n",
423 + dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0,
424 + dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1 );
425 +#endif
426 + /*
427 + * There is an errata on the Au1200/Au1550 parts that could result in
428 + * "stale" data being DMA'd. It has to do with the snoop logic on the
429 + * dache eviction buffer. NONCOHERENT_IO is on by default for these
430 + * parts. If it is fixedin the future, these dma_cache_inv will just
431 + * be nothing more than empty macros. See io.h.
432 + * */
433 + dma_cache_inv(buf,nbytes);
434 dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
435 + au_sync();
436 + dma_cache_wback_inv(dp, sizeof(dp));
437 + ctp->chan_ptr->ddma_dbell = 0;
438
439 /* Get next descriptor pointer.
440 */
441 @@ -596,6 +669,7 @@ au1xxx_dbdma_put_dest(u32 chanid, void *
442 */
443 return nbytes;
444 }
445 +EXPORT_SYMBOL(_au1xxx_dbdma_put_dest);
446
447 /* Get a destination buffer into the DMA ring.
448 * Normally used to get a full buffer from the ring during fifo
449 @@ -645,7 +719,7 @@ void
450 au1xxx_dbdma_stop(u32 chanid)
451 {
452 chan_tab_t *ctp;
453 - volatile au1x_dma_chan_t *cp;
454 + au1x_dma_chan_t *cp;
455 int halt_timeout = 0;
456
457 ctp = *((chan_tab_t **)chanid);
458 @@ -665,6 +739,7 @@ au1xxx_dbdma_stop(u32 chanid)
459 cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
460 au_sync();
461 }
462 +EXPORT_SYMBOL(au1xxx_dbdma_stop);
463
464 /* Start using the current descriptor pointer. If the dbdma encounters
465 * a not valid descriptor, it will stop. In this case, we can just
466 @@ -674,17 +749,17 @@ void
467 au1xxx_dbdma_start(u32 chanid)
468 {
469 chan_tab_t *ctp;
470 - volatile au1x_dma_chan_t *cp;
471 + au1x_dma_chan_t *cp;
472
473 ctp = *((chan_tab_t **)chanid);
474 -
475 cp = ctp->chan_ptr;
476 cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
477 cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */
478 au_sync();
479 - cp->ddma_dbell = 0xffffffff; /* Make it go */
480 + cp->ddma_dbell = 0;
481 au_sync();
482 }
483 +EXPORT_SYMBOL(au1xxx_dbdma_start);
484
485 void
486 au1xxx_dbdma_reset(u32 chanid)
487 @@ -703,15 +778,21 @@ au1xxx_dbdma_reset(u32 chanid)
488
489 do {
490 dp->dscr_cmd0 &= ~DSCR_CMD0_V;
491 + /* reset our SW status -- this is used to determine
492 + * if a descriptor is in use by upper level SW. Since
493 + * posting can reset 'V' bit.
494 + */
495 + dp->sw_status = 0;
496 dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
497 } while (dp != ctp->chan_desc_base);
498 }
499 +EXPORT_SYMBOL(au1xxx_dbdma_reset);
500
501 u32
502 au1xxx_get_dma_residue(u32 chanid)
503 {
504 chan_tab_t *ctp;
505 - volatile au1x_dma_chan_t *cp;
506 + au1x_dma_chan_t *cp;
507 u32 rv;
508
509 ctp = *((chan_tab_t **)chanid);
510 @@ -746,15 +827,16 @@ au1xxx_dbdma_chan_free(u32 chanid)
511
512 kfree(ctp);
513 }
514 +EXPORT_SYMBOL(au1xxx_dbdma_chan_free);
515
516 static void
517 dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
518 {
519 - u32 intstat;
520 + u32 intstat, flags;
521 u32 chan_index;
522 chan_tab_t *ctp;
523 au1x_ddma_desc_t *dp;
524 - volatile au1x_dma_chan_t *cp;
525 + au1x_dma_chan_t *cp;
526
527 intstat = dbdma_gptr->ddma_intstat;
528 au_sync();
529 @@ -773,18 +855,26 @@ dbdma_interrupt(int irq, void *dev_id, s
530 (ctp->chan_callback)(irq, ctp->chan_callparam, regs);
531
532 ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
533 -
534 }
535
536 -static void
537 -au1xxx_dbdma_init(void)
538 +static void au1xxx_dbdma_init(void)
539 {
540 + int irq_nr;
541 +
542 dbdma_gptr->ddma_config = 0;
543 dbdma_gptr->ddma_throttle = 0;
544 dbdma_gptr->ddma_inten = 0xffff;
545 au_sync();
546
547 - if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT,
548 +#if defined(CONFIG_SOC_AU1550)
549 + irq_nr = AU1550_DDMA_INT;
550 +#elif defined(CONFIG_SOC_AU1200)
551 + irq_nr = AU1200_DDMA_INT;
552 +#else
553 + #error Unknown Au1x00 SOC
554 +#endif
555 +
556 + if (request_irq(irq_nr, dbdma_interrupt, SA_INTERRUPT,
557 "Au1xxx dbdma", (void *)dbdma_gptr))
558 printk("Can't get 1550 dbdma irq");
559 }
560 @@ -795,7 +885,8 @@ au1xxx_dbdma_dump(u32 chanid)
561 chan_tab_t *ctp;
562 au1x_ddma_desc_t *dp;
563 dbdev_tab_t *stp, *dtp;
564 - volatile au1x_dma_chan_t *cp;
565 + au1x_dma_chan_t *cp;
566 + u32 i = 0;
567
568 ctp = *((chan_tab_t **)chanid);
569 stp = ctp->chan_src;
570 @@ -820,15 +911,64 @@ au1xxx_dbdma_dump(u32 chanid)
571 dp = ctp->chan_desc_base;
572
573 do {
574 - printk("dp %08x, cmd0 %08x, cmd1 %08x\n",
575 - (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
576 - printk("src0 %08x, src1 %08x, dest0 %08x\n",
577 - dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0);
578 - printk("dest1 %08x, stat %08x, nxtptr %08x\n",
579 - dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr);
580 + printk("Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n",
581 + i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
582 + printk("src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n",
583 + dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1);
584 + printk("stat %08x, nxtptr %08x\n",
585 + dp->dscr_stat, dp->dscr_nxtptr);
586 dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
587 } while (dp != ctp->chan_desc_base);
588 }
589
590 +/* Put a descriptor into the DMA ring.
591 + * This updates the source/destination pointers and byte count.
592 + */
593 +u32
594 +au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr )
595 +{
596 + chan_tab_t *ctp;
597 + au1x_ddma_desc_t *dp;
598 + u32 nbytes=0;
599 +
600 + /* I guess we could check this to be within the
601 + * range of the table......
602 + */
603 + ctp = *((chan_tab_t **)chanid);
604 +
605 + /* We should have multiple callers for a particular channel,
606 + * an interrupt doesn't affect this pointer nor the descriptor,
607 + * so no locking should be needed.
608 + */
609 + dp = ctp->put_ptr;
610 +
611 + /* If the descriptor is valid, we are way ahead of the DMA
612 + * engine, so just return an error condition.
613 + */
614 + if (dp->dscr_cmd0 & DSCR_CMD0_V)
615 + return 0;
616 +
617 + /* Load up buffer addresses and byte count.
618 + */
619 + dp->dscr_dest0 = dscr->dscr_dest0;
620 + dp->dscr_source0 = dscr->dscr_source0;
621 + dp->dscr_dest1 = dscr->dscr_dest1;
622 + dp->dscr_source1 = dscr->dscr_source1;
623 + dp->dscr_cmd1 = dscr->dscr_cmd1;
624 + nbytes = dscr->dscr_cmd1;
625 + /* Allow the caller to specifiy if an interrupt is generated */
626 + dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
627 + dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V;
628 + ctp->chan_ptr->ddma_dbell = 0;
629 +
630 + /* Get next descriptor pointer.
631 + */
632 + ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
633 +
634 + /* return something not zero.
635 + */
636 + return nbytes;
637 +}
638 +
639 #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
640
641 --- /dev/null
642 +++ b/arch/mips/au1000/common/gpio.c
643 @@ -0,0 +1,118 @@
644 +/*
645 + * This program is free software; you can redistribute it and/or modify it
646 + * under the terms of the GNU General Public License as published by the
647 + * Free Software Foundation; either version 2 of the License, or (at your
648 + * option) any later version.
649 + *
650 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
651 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
652 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
653 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
654 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
655 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
656 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
657 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
658 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
659 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
660 + *
661 + * You should have received a copy of the GNU General Public License along
662 + * with this program; if not, write to the Free Software Foundation, Inc.,
663 + * 675 Mass Ave, Cambridge, MA 02139, USA.
664 + */
665 +
666 +#include <asm/au1000.h>
667 +#include <asm/au1xxx_gpio.h>
668 +
669 +#define gpio1 sys
670 +#if !defined(CONFIG_SOC_AU1000)
671 +static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE;
672 +
673 +#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
674 +
675 +int au1xxx_gpio2_read(int signal)
676 +{
677 + signal -= 200;
678 +/* gpio2->dir &= ~(0x01 << signal); //Set GPIO to input */
679 + return ((gpio2->pinstate >> signal) & 0x01);
680 +}
681 +
682 +void au1xxx_gpio2_write(int signal, int value)
683 +{
684 + signal -= 200;
685 +
686 + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) |
687 + (value << signal);
688 +}
689 +
690 +void au1xxx_gpio2_tristate(int signal)
691 +{
692 + signal -= 200;
693 + gpio2->dir &= ~(0x01 << signal); /* Set GPIO to input */
694 +}
695 +#endif
696 +
697 +int au1xxx_gpio1_read(int signal)
698 +{
699 +/* gpio1->trioutclr |= (0x01 << signal); */
700 + return ((gpio1->pinstaterd >> signal) & 0x01);
701 +}
702 +
703 +void au1xxx_gpio1_write(int signal, int value)
704 +{
705 + if(value)
706 + gpio1->outputset = (0x01 << signal);
707 + else
708 + gpio1->outputclr = (0x01 << signal); /* Output a Zero */
709 +}
710 +
711 +void au1xxx_gpio1_tristate(int signal)
712 +{
713 + gpio1->trioutclr = (0x01 << signal); /* Tristate signal */
714 +}
715 +
716 +
717 +int au1xxx_gpio_read(int signal)
718 +{
719 + if(signal >= 200)
720 +#if defined(CONFIG_SOC_AU1000)
721 + return 0;
722 +#else
723 + return au1xxx_gpio2_read(signal);
724 +#endif
725 + else
726 + return au1xxx_gpio1_read(signal);
727 +}
728 +
729 +void au1xxx_gpio_write(int signal, int value)
730 +{
731 + if(signal >= 200)
732 +#if defined(CONFIG_SOC_AU1000)
733 + ;
734 +#else
735 + au1xxx_gpio2_write(signal, value);
736 +#endif
737 + else
738 + au1xxx_gpio1_write(signal, value);
739 +}
740 +
741 +void au1xxx_gpio_tristate(int signal)
742 +{
743 + if(signal >= 200)
744 +#if defined(CONFIG_SOC_AU1000)
745 + ;
746 +#else
747 + au1xxx_gpio2_tristate(signal);
748 +#endif
749 + else
750 + au1xxx_gpio1_tristate(signal);
751 +}
752 +
753 +void au1xxx_gpio1_set_inputs(void)
754 +{
755 + gpio1->pininputen = 0;
756 +}
757 +
758 +EXPORT_SYMBOL(au1xxx_gpio1_set_inputs);
759 +EXPORT_SYMBOL(au1xxx_gpio_tristate);
760 +EXPORT_SYMBOL(au1xxx_gpio_write);
761 +EXPORT_SYMBOL(au1xxx_gpio_read);
762 --- a/arch/mips/au1000/common/irq.c
763 +++ b/arch/mips/au1000/common/irq.c
764 @@ -303,8 +303,30 @@ static struct hw_interrupt_type level_ir
765 };
766
767 #ifdef CONFIG_PM
768 -void startup_match20_interrupt(void)
769 +void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *))
770 {
771 + static struct irqaction action;
772 + /* This is a big problem.... since we didn't use request_irq
773 + when kernel/irq.c calls probe_irq_xxx this interrupt will
774 + be probed for usage. This will end up disabling the device :(
775 +
776 + Give it a bogus "action" pointer -- this will keep it from
777 + getting auto-probed!
778 +
779 + By setting the status to match that of request_irq() we
780 + can avoid it. --cgray
781 + */
782 + action.dev_id = handler;
783 + action.flags = 0;
784 + action.mask = 0;
785 + action.name = "Au1xxx TOY";
786 + action.handler = handler;
787 + action.next = NULL;
788 +
789 + irq_desc[AU1000_TOY_MATCH2_INT].action = &action;
790 + irq_desc[AU1000_TOY_MATCH2_INT].status
791 + &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
792 +
793 local_enable_irq(AU1000_TOY_MATCH2_INT);
794 }
795 #endif
796 @@ -508,6 +530,7 @@ void intc0_req0_irqdispatch(struct pt_re
797
798 if (!intc0_req0) return;
799
800 +#ifdef AU1000_USB_DEV_REQ_INT
801 /*
802 * Because of the tight timing of SETUP token to reply
803 * transactions, the USB devices-side packet complete
804 @@ -518,6 +541,7 @@ void intc0_req0_irqdispatch(struct pt_re
805 do_IRQ(AU1000_USB_DEV_REQ_INT, regs);
806 return;
807 }
808 +#endif
809
810 irq = au_ffs(intc0_req0) - 1;
811 intc0_req0 &= ~(1<<irq);
812 @@ -536,17 +560,7 @@ void intc0_req1_irqdispatch(struct pt_re
813
814 irq = au_ffs(intc0_req1) - 1;
815 intc0_req1 &= ~(1<<irq);
816 -#ifdef CONFIG_PM
817 - if (irq == AU1000_TOY_MATCH2_INT) {
818 - mask_and_ack_rise_edge_irq(irq);
819 - counter0_irq(irq, NULL, regs);
820 - local_enable_irq(irq);
821 - }
822 - else
823 -#endif
824 - {
825 - do_IRQ(irq, regs);
826 - }
827 + do_IRQ(irq, regs);
828 }
829
830
831 --- a/arch/mips/au1000/common/Makefile
832 +++ b/arch/mips/au1000/common/Makefile
833 @@ -19,9 +19,9 @@ O_TARGET := au1000.o
834 export-objs = prom.o clocks.o power.o usbdev.o
835
836 obj-y := prom.o int-handler.o irq.o puts.o time.o reset.o cputable.o \
837 - au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o
838 + au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o gpio.o
839
840 -export-objs += dma.o dbdma.o
841 +export-objs += dma.o dbdma.o gpio.o
842
843 obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o
844 obj-$(CONFIG_KGDB) += dbg_io.o
845 --- a/arch/mips/au1000/common/pci_fixup.c
846 +++ b/arch/mips/au1000/common/pci_fixup.c
847 @@ -75,9 +75,13 @@ void __init pcibios_fixup(void)
848
849 #ifdef CONFIG_NONCOHERENT_IO
850 /*
851 - * Set the NC bit in controller for pre-AC silicon
852 + * Set the NC bit in controller for Au1500 pre-AC silicon
853 */
854 - au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
855 + u32 prid = read_c0_prid();
856 + if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
857 + au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
858 + printk("Non-coherent PCI accesses enabled\n");
859 + }
860 printk("Non-coherent PCI accesses enabled\n");
861 #endif
862
863 --- a/arch/mips/au1000/common/pci_ops.c
864 +++ b/arch/mips/au1000/common/pci_ops.c
865 @@ -162,6 +162,7 @@ unsigned long last_entryLo0, last_entryL
866 static int config_access(unsigned char access_type, struct pci_dev *dev,
867 unsigned char where, u32 * data)
868 {
869 + int error = PCIBIOS_SUCCESSFUL;
870 #if defined( CONFIG_SOC_AU1500 ) || defined( CONFIG_SOC_AU1550 )
871 unsigned char bus = dev->bus->number;
872 unsigned int dev_fn = dev->devfn;
873 @@ -170,7 +171,6 @@ static int config_access(unsigned char a
874 unsigned long offset, status;
875 unsigned long cfg_base;
876 unsigned long flags;
877 - int error = PCIBIOS_SUCCESSFUL;
878 unsigned long entryLo0, entryLo1;
879
880 if (device > 19) {
881 @@ -205,9 +205,8 @@ static int config_access(unsigned char a
882 last_entryLo0 = last_entryLo1 = 0xffffffff;
883 }
884
885 - /* Since the Au1xxx doesn't do the idsel timing exactly to spec,
886 - * many board vendors implement their own off-chip idsel, so call
887 - * it now. If it doesn't succeed, may as well bail out at this point.
888 + /* Allow board vendors to implement their own off-chip idsel.
889 + * If it doesn't succeed, may as well bail out at this point.
890 */
891 if (board_pci_idsel) {
892 if (board_pci_idsel(device, 1) == 0) {
893 @@ -271,8 +270,11 @@ static int config_access(unsigned char a
894 }
895
896 local_irq_restore(flags);
897 - return error;
898 +#else
899 + /* Fake out Config space access with no responder */
900 + *data = 0xFFFFFFFF;
901 #endif
902 + return error;
903 }
904 #endif
905
906 --- a/arch/mips/au1000/common/power.c
907 +++ b/arch/mips/au1000/common/power.c
908 @@ -50,7 +50,6 @@
909
910 static void calibrate_delay(void);
911
912 -extern void set_au1x00_speed(unsigned int new_freq);
913 extern unsigned int get_au1x00_speed(void);
914 extern unsigned long get_au1x00_uart_baud_base(void);
915 extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
916 @@ -116,6 +115,7 @@ save_core_regs(void)
917 sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
918 sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
919
920 +#ifndef CONFIG_SOC_AU1200
921 /* Shutdown USB host/device.
922 */
923 sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
924 @@ -127,6 +127,7 @@ save_core_regs(void)
925
926 sleep_usbdev_enable = au_readl(USBD_ENABLE);
927 au_writel(0, USBD_ENABLE); au_sync();
928 +#endif
929
930 /* Save interrupt controller state.
931 */
932 @@ -212,14 +213,12 @@ void wakeup_from_suspend(void)
933 int au_sleep(void)
934 {
935 unsigned long wakeup, flags;
936 - extern void save_and_sleep(void);
937 + extern unsigned int save_and_sleep(void);
938
939 spin_lock_irqsave(&pm_lock,flags);
940
941 save_core_regs();
942
943 - flush_cache_all();
944 -
945 /** The code below is all system dependent and we should probably
946 ** have a function call out of here to set this up. You need
947 ** to configure the GPIO or timer interrupts that will bring
948 @@ -227,27 +226,26 @@ int au_sleep(void)
949 ** For testing, the TOY counter wakeup is useful.
950 **/
951
952 -#if 0
953 +#if 1
954 au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
955
956 /* gpio 6 can cause a wake up event */
957 wakeup = au_readl(SYS_WAKEMSK);
958 wakeup &= ~(1 << 8); /* turn off match20 wakeup */
959 - wakeup |= 1 << 6; /* turn on gpio 6 wakeup */
960 + wakeup = 1 << 5; /* turn on gpio 6 wakeup */
961 #else
962 - /* For testing, allow match20 to wake us up.
963 - */
964 + /* For testing, allow match20 to wake us up. */
965 #ifdef SLEEP_TEST_TIMEOUT
966 wakeup_counter0_set(sleep_ticks);
967 #endif
968 wakeup = 1 << 8; /* turn on match20 wakeup */
969 wakeup = 0;
970 #endif
971 - au_writel(1, SYS_WAKESRC); /* clear cause */
972 + au_writel(0, SYS_WAKESRC); /* clear cause */
973 au_sync();
974 au_writel(wakeup, SYS_WAKEMSK);
975 au_sync();
976 -
977 + DPRINTK("Entering sleep!\n");
978 save_and_sleep();
979
980 /* after a wakeup, the cpu vectors back to 0x1fc00000 so
981 @@ -255,6 +253,7 @@ int au_sleep(void)
982 */
983 restore_core_regs();
984 spin_unlock_irqrestore(&pm_lock, flags);
985 + DPRINTK("Leaving sleep!\n");
986 return 0;
987 }
988
989 @@ -285,7 +284,6 @@ static int pm_do_sleep(ctl_table * ctl,
990
991 if (retval)
992 return retval;
993 -
994 au_sleep();
995 retval = pm_send_all(PM_RESUME, (void *) 0);
996 }
997 @@ -296,7 +294,6 @@ static int pm_do_suspend(ctl_table * ctl
998 void *buffer, size_t * len)
999 {
1000 int retval = 0;
1001 - void au1k_wait(void);
1002
1003 if (!write) {
1004 *len = 0;
1005 @@ -305,119 +302,9 @@ static int pm_do_suspend(ctl_table * ctl
1006 if (retval)
1007 return retval;
1008 suspend_mode = 1;
1009 - au1k_wait();
1010 - retval = pm_send_all(PM_RESUME, (void *) 0);
1011 - }
1012 - return retval;
1013 -}
1014
1015 -
1016 -static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
1017 - void *buffer, size_t * len)
1018 -{
1019 - int retval = 0, i;
1020 - unsigned long val, pll;
1021 -#define TMPBUFLEN 64
1022 -#define MAX_CPU_FREQ 396
1023 - char buf[TMPBUFLEN], *p;
1024 - unsigned long flags, intc0_mask, intc1_mask;
1025 - unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk,
1026 - old_refresh;
1027 - unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
1028 -
1029 - spin_lock_irqsave(&pm_lock, flags);
1030 - if (!write) {
1031 - *len = 0;
1032 - } else {
1033 - /* Parse the new frequency */
1034 - if (*len > TMPBUFLEN - 1) {
1035 - spin_unlock_irqrestore(&pm_lock, flags);
1036 - return -EFAULT;
1037 - }
1038 - if (copy_from_user(buf, buffer, *len)) {
1039 - spin_unlock_irqrestore(&pm_lock, flags);
1040 - return -EFAULT;
1041 - }
1042 - buf[*len] = 0;
1043 - p = buf;
1044 - val = simple_strtoul(p, &p, 0);
1045 - if (val > MAX_CPU_FREQ) {
1046 - spin_unlock_irqrestore(&pm_lock, flags);
1047 - return -EFAULT;
1048 - }
1049 -
1050 - pll = val / 12;
1051 - if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */
1052 - /* revisit this for higher speed cpus */
1053 - spin_unlock_irqrestore(&pm_lock, flags);
1054 - return -EFAULT;
1055 - }
1056 -
1057 - old_baud_base = get_au1x00_uart_baud_base();
1058 - old_cpu_freq = get_au1x00_speed();
1059 -
1060 - new_cpu_freq = pll * 12 * 1000000;
1061 - new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
1062 - set_au1x00_speed(new_cpu_freq);
1063 - set_au1x00_uart_baud_base(new_baud_base);
1064 -
1065 - old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
1066 - new_refresh =
1067 - ((old_refresh * new_cpu_freq) /
1068 - old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff);
1069 -
1070 - au_writel(pll, SYS_CPUPLL);
1071 - au_sync_delay(1);
1072 - au_writel(new_refresh, MEM_SDREFCFG);
1073 - au_sync_delay(1);
1074 -
1075 - for (i = 0; i < 4; i++) {
1076 - if (au_readl
1077 - (UART_BASE + UART_MOD_CNTRL +
1078 - i * 0x00100000) == 3) {
1079 - old_clk =
1080 - au_readl(UART_BASE + UART_CLK +
1081 - i * 0x00100000);
1082 - // baud_rate = baud_base/clk
1083 - baud_rate = old_baud_base / old_clk;
1084 - /* we won't get an exact baud rate and the error
1085 - * could be significant enough that our new
1086 - * calculation will result in a clock that will
1087 - * give us a baud rate that's too far off from
1088 - * what we really want.
1089 - */
1090 - if (baud_rate > 100000)
1091 - baud_rate = 115200;
1092 - else if (baud_rate > 50000)
1093 - baud_rate = 57600;
1094 - else if (baud_rate > 30000)
1095 - baud_rate = 38400;
1096 - else if (baud_rate > 17000)
1097 - baud_rate = 19200;
1098 - else
1099 - (baud_rate = 9600);
1100 - // new_clk = new_baud_base/baud_rate
1101 - new_clk = new_baud_base / baud_rate;
1102 - au_writel(new_clk,
1103 - UART_BASE + UART_CLK +
1104 - i * 0x00100000);
1105 - au_sync_delay(10);
1106 - }
1107 - }
1108 + retval = pm_send_all(PM_RESUME, (void *) 0);
1109 }
1110 -
1111 -
1112 - /* We don't want _any_ interrupts other than
1113 - * match20. Otherwise our calibrate_delay()
1114 - * calculation will be off, potentially a lot.
1115 - */
1116 - intc0_mask = save_local_and_disable(0);
1117 - intc1_mask = save_local_and_disable(1);
1118 - local_enable_irq(AU1000_TOY_MATCH2_INT);
1119 - spin_unlock_irqrestore(&pm_lock, flags);
1120 - calibrate_delay();
1121 - restore_local_and_enable(0, intc0_mask);
1122 - restore_local_and_enable(1, intc1_mask);
1123 return retval;
1124 }
1125
1126 @@ -425,7 +312,6 @@ static int pm_do_freq(ctl_table * ctl, i
1127 static struct ctl_table pm_table[] = {
1128 {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
1129 {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
1130 - {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
1131 {0}
1132 };
1133
1134 --- a/arch/mips/au1000/common/reset.c
1135 +++ b/arch/mips/au1000/common/reset.c
1136 @@ -37,8 +37,6 @@
1137 #include <asm/system.h>
1138 #include <asm/au1000.h>
1139
1140 -extern int au_sleep(void);
1141 -
1142 void au1000_restart(char *command)
1143 {
1144 /* Set all integrated peripherals to disabled states */
1145 @@ -144,6 +142,26 @@ void au1000_restart(char *command)
1146 au_writel(0x00, 0xb1900064); /* sys_auxpll */
1147 au_writel(0x00, 0xb1900100); /* sys_pininputen */
1148 break;
1149 + case 0x04000000: /* Au1200 */
1150 + au_writel(0x00, 0xb400300c); /* ddma */
1151 + au_writel(0x00, 0xb1a00004); /* psc 0 */
1152 + au_writel(0x00, 0xb1b00004); /* psc 1 */
1153 + au_writel(0x00d02000, 0xb4020004); /* ehci, ohci, udc, otg */
1154 + au_writel(0x00, 0xb5000004); /* lcd */
1155 + au_writel(0x00, 0xb060000c); /* sd0 */
1156 + au_writel(0x00, 0xb068000c); /* sd1 */
1157 + au_writel(0x00, 0xb1100100); /* swcnt */
1158 + au_writel(0x00, 0xb0300000); /* aes */
1159 + au_writel(0x00, 0xb4004000); /* cim */
1160 + au_writel(0x00, 0xb1100100); /* uart0_enable */
1161 + au_writel(0x00, 0xb1200100); /* uart1_enable */
1162 + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
1163 + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
1164 + au_writel(0x00, 0xb1900028); /* sys_clksrc */
1165 + au_writel(0x10, 0xb1900060); /* sys_cpupll */
1166 + au_writel(0x00, 0xb1900064); /* sys_auxpll */
1167 + au_writel(0x00, 0xb1900100); /* sys_pininputen */
1168 + break;
1169
1170 default:
1171 break;
1172 @@ -163,32 +181,23 @@ void au1000_restart(char *command)
1173
1174 void au1000_halt(void)
1175 {
1176 -#if defined(CONFIG_MIPS_PB1550)
1177 - /* power off system */
1178 - printk("\n** Powering off Pb1550\n");
1179 - au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
1180 - au_sync();
1181 - while(1); /* should not get here */
1182 -#endif
1183 - printk(KERN_NOTICE "\n** You can safely turn off the power\n");
1184 -#ifdef CONFIG_MIPS_MIRAGE
1185 - au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
1186 -#endif
1187 -#ifdef CONFIG_PM
1188 - au_sleep();
1189 -
1190 - /* should not get here */
1191 - printk(KERN_ERR "Unable to put cpu in sleep mode\n");
1192 - while(1);
1193 -#else
1194 - while (1)
1195 + /* Use WAIT in a low-power infinite spin loop */
1196 + while (1) {
1197 __asm__(".set\tmips3\n\t"
1198 "wait\n\t"
1199 ".set\tmips0");
1200 -#endif
1201 + }
1202 }
1203
1204 void au1000_power_off(void)
1205 {
1206 + extern void board_power_off (void);
1207 +
1208 + printk(KERN_NOTICE "\n** You can safely turn off the power\n");
1209 +
1210 + /* Give board a chance to power-off */
1211 + board_power_off();
1212 +
1213 + /* If board can't power-off, spin forever */
1214 au1000_halt();
1215 }
1216 --- a/arch/mips/au1000/common/setup.c
1217 +++ b/arch/mips/au1000/common/setup.c
1218 @@ -174,6 +174,40 @@ void __init au1x00_setup(void)
1219 initrd_end = (unsigned long)&__rd_end;
1220 #endif
1221
1222 +#if defined(CONFIG_SOC_AU1200)
1223 +#ifdef CONFIG_USB_EHCI_HCD
1224 + if ((argptr = strstr(argptr, "usb_ehci=")) == NULL) {
1225 + char usb_args[80];
1226 + argptr = prom_getcmdline();
1227 + memset(usb_args, 0, sizeof(usb_args));
1228 + sprintf(usb_args, " usb_ehci=base:0x%x,len:0x%x,irq:%d",
1229 + USB_EHCI_BASE, USB_EHCI_LEN, AU1000_USB_HOST_INT);
1230 + strcat(argptr, usb_args);
1231 + }
1232 +#ifdef CONFIG_USB_AMD5536UDC
1233 + /* enable EHC + OHC + UDC clocks, memory and bus mastering */
1234 +/* au_writel( 0x00DF207F, USB_MSR_BASE + 4); */
1235 + au_writel( 0xC0DF207F, USB_MSR_BASE + 4); // incl. prefetch
1236 +#else
1237 + /* enable EHC + OHC clocks, memory and bus mastering */
1238 +/* au_writel( 0x00DB200F, USB_MSR_BASE + 4); */
1239 + au_writel( 0xC0DB200F, USB_MSR_BASE + 4); /* incl. prefetch */
1240 +#endif
1241 + udelay(1000);
1242 +
1243 +#else /* CONFIG_USB_EHCI_HCD */
1244 +
1245 +#ifdef CONFIG_USB_AMD5536UDC
1246 +#ifndef CONFIG_USB_OHCI
1247 + /* enable UDC clocks, memory and bus mastering */
1248 +/* au_writel( 0x00DC2070, USB_MSR_BASE + 4); */
1249 + au_writel( 0xC0DC2070, USB_MSR_BASE + 4); // incl. prefetch
1250 + udelay(1000);
1251 +#endif
1252 +#endif
1253 +#endif /* CONFIG_USB_EHCI_HCD */
1254 +#endif /* CONFIG_SOC_AU1200 */
1255 +
1256 #if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
1257 #ifdef CONFIG_USB_OHCI
1258 if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) {
1259 @@ -187,19 +221,38 @@ void __init au1x00_setup(void)
1260 #endif
1261
1262 #ifdef CONFIG_USB_OHCI
1263 - // enable host controller and wait for reset done
1264 +#if defined(CONFIG_SOC_AU1200)
1265 +#ifndef CONFIG_USB_EHCI_HCD
1266 +#ifdef CONFIG_USB_AMD5536UDC
1267 + /* enable OHC + UDC clocks, memory and bus mastering */
1268 +/* au_writel( 0x00DD2073, USB_MSR_BASE + 4); */
1269 + au_writel( 0xC0DD2073, USB_MSR_BASE + 4); // incl. prefetch
1270 +#else
1271 + /* enable OHC clocks, memory and bus mastering */
1272 + au_writel( 0x00D12003, USB_MSR_BASE + 4);
1273 +#endif
1274 + udelay(1000);
1275 +printk("DEBUG: Reading Au1200 USB2 reg 0x%x\n", au_readl(USB_MSR_BASE + 4));
1276 +#endif
1277 +#else
1278 + /* Au1000, Au1500, Au1100, Au1550 */
1279 + /* enable host controller and wait for reset done */
1280 au_writel(0x08, USB_HOST_CONFIG);
1281 udelay(1000);
1282 au_writel(0x0E, USB_HOST_CONFIG);
1283 udelay(1000);
1284 - au_readl(USB_HOST_CONFIG); // throw away first read
1285 + au_readl(USB_HOST_CONFIG); /* throw away first read */
1286 while (!(au_readl(USB_HOST_CONFIG) & 0x10))
1287 au_readl(USB_HOST_CONFIG);
1288 +#endif /* CONFIG_SOC_AU1200 */
1289 #endif
1290 -#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
1291 +#else
1292 +
1293 +#endif /* defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) */
1294 +
1295
1296 #ifdef CONFIG_FB
1297 - // Needed if PCI video card in use
1298 + /* Needed if PCI video card in use */
1299 conswitchp = &dummy_con;
1300 #endif
1301
1302 @@ -209,8 +262,7 @@ void __init au1x00_setup(void)
1303 #endif
1304
1305 #ifdef CONFIG_BLK_DEV_IDE
1306 - /* Board setup takes precedence for unique devices.
1307 - */
1308 + /* Board setup takes precedence for unique devices. */
1309 if ((ide_ops == NULL) || (ide_ops == &no_ide_ops))
1310 ide_ops = &std_ide_ops;
1311 #endif
1312 --- a/arch/mips/au1000/common/sleeper.S
1313 +++ b/arch/mips/au1000/common/sleeper.S
1314 @@ -15,17 +15,48 @@
1315 #include <asm/addrspace.h>
1316 #include <asm/regdef.h>
1317 #include <asm/stackframe.h>
1318 +#include <asm/au1000.h>
1319 +
1320 +/*
1321 + * Note: This file is *not* conditional on CONFIG_PM since Alchemy sleep
1322 + * need not be tied to any particular power management scheme.
1323 + */
1324 +
1325 + .extern ___flush_cache_all
1326
1327 .text
1328 - .set macro
1329 - .set noat
1330 .align 5
1331
1332 -/* Save all of the processor general registers and go to sleep.
1333 - * A wakeup condition will get us back here to restore the registers.
1334 +/*
1335 + * Save the processor general registers and go to sleep. A wakeup
1336 + * condition will get us back here to restore the registers.
1337 */
1338 -LEAF(save_and_sleep)
1339
1340 +/* still need to fix alignment issues here */
1341 +save_and_sleep_frmsz = 48
1342 +NESTED(save_and_sleep, save_and_sleep_frmsz, ra)
1343 + .set noreorder
1344 + .set nomacro
1345 + .set noat
1346 + subu sp, save_and_sleep_frmsz
1347 + sw ra, save_and_sleep_frmsz-4(sp)
1348 + sw s0, save_and_sleep_frmsz-8(sp)
1349 + sw s1, save_and_sleep_frmsz-12(sp)
1350 + sw s2, save_and_sleep_frmsz-16(sp)
1351 + sw s3, save_and_sleep_frmsz-20(sp)
1352 + sw s4, save_and_sleep_frmsz-24(sp)
1353 + sw s5, save_and_sleep_frmsz-28(sp)
1354 + sw s6, save_and_sleep_frmsz-32(sp)
1355 + sw s7, save_and_sleep_frmsz-36(sp)
1356 + sw s8, save_and_sleep_frmsz-40(sp)
1357 + sw gp, save_and_sleep_frmsz-44(sp)
1358 +
1359 + /* We only need to save the registers that the calling function
1360 + * hasn't saved for us. 0 is always zero. 8 - 15, 24 and 25 are
1361 + * temporaries and can be used without saving. 26 and 27 are reserved
1362 + * for interrupt/trap handling and expected to change. 29 is the
1363 + * stack pointer which is handled as a special case here.
1364 + */
1365 subu sp, PT_SIZE
1366 sw $1, PT_R1(sp)
1367 sw $2, PT_R2(sp)
1368 @@ -34,14 +65,6 @@ LEAF(save_and_sleep)
1369 sw $5, PT_R5(sp)
1370 sw $6, PT_R6(sp)
1371 sw $7, PT_R7(sp)
1372 - sw $8, PT_R8(sp)
1373 - sw $9, PT_R9(sp)
1374 - sw $10, PT_R10(sp)
1375 - sw $11, PT_R11(sp)
1376 - sw $12, PT_R12(sp)
1377 - sw $13, PT_R13(sp)
1378 - sw $14, PT_R14(sp)
1379 - sw $15, PT_R15(sp)
1380 sw $16, PT_R16(sp)
1381 sw $17, PT_R17(sp)
1382 sw $18, PT_R18(sp)
1383 @@ -50,32 +73,47 @@ LEAF(save_and_sleep)
1384 sw $21, PT_R21(sp)
1385 sw $22, PT_R22(sp)
1386 sw $23, PT_R23(sp)
1387 - sw $24, PT_R24(sp)
1388 - sw $25, PT_R25(sp)
1389 - sw $26, PT_R26(sp)
1390 - sw $27, PT_R27(sp)
1391 sw $28, PT_R28(sp)
1392 - sw $29, PT_R29(sp)
1393 sw $30, PT_R30(sp)
1394 sw $31, PT_R31(sp)
1395 +#define PT_C0STATUS PT_LO
1396 +#define PT_CONTEXT PT_HI
1397 +#define PT_PAGEMASK PT_EPC
1398 +#define PT_CONFIG PT_BVADDR
1399 mfc0 k0, CP0_STATUS
1400 - sw k0, 0x20(sp)
1401 + sw k0, PT_C0STATUS(sp) // 0x20
1402 mfc0 k0, CP0_CONTEXT
1403 - sw k0, 0x1c(sp)
1404 + sw k0, PT_CONTEXT(sp) // 0x1c
1405 mfc0 k0, CP0_PAGEMASK
1406 - sw k0, 0x18(sp)
1407 + sw k0, PT_PAGEMASK(sp) // 0x18
1408 mfc0 k0, CP0_CONFIG
1409 - sw k0, 0x14(sp)
1410 + sw k0, PT_CONFIG(sp) // 0x14
1411 +
1412 + .set macro
1413 + .set at
1414 +
1415 + li t0, SYS_SLPPWR
1416 + sw zero, 0(t0) /* Get the processor ready to sleep */
1417 + sync
1418
1419 /* Now set up the scratch registers so the boot rom will
1420 * return to this point upon wakeup.
1421 + * sys_scratch0 : SP
1422 + * sys_scratch1 : RA
1423 + */
1424 + li t0, SYS_SCRATCH0
1425 + li t1, SYS_SCRATCH1
1426 + sw sp, 0(t0)
1427 + la k0, resume_from_sleep
1428 + sw k0, 0(t1)
1429 +
1430 +/*
1431 + * Flush DCACHE to make sure context is in memory
1432 */
1433 - la k0, 1f
1434 - lui k1, 0xb190
1435 - ori k1, 0x18
1436 - sw sp, 0(k1)
1437 - ori k1, 0x1c
1438 - sw k0, 0(k1)
1439 + la t1,___flush_cache_all /* _flush_cache_all is a function pointer */
1440 + lw t0,0(t1)
1441 + jal t0
1442 + nop
1443
1444 /* Put SDRAM into self refresh. Preload instructions into cache,
1445 * issue a precharge, then auto refresh, then sleep commands to it.
1446 @@ -88,30 +126,65 @@ LEAF(save_and_sleep)
1447 cache 0x14, 96(t0)
1448 .set mips0
1449
1450 + /* Put SDRAM to sleep */
1451 sdsleep:
1452 - lui k0, 0xb400
1453 - sw zero, 0x001c(k0) /* Precharge */
1454 - sw zero, 0x0020(k0) /* Auto refresh */
1455 - sw zero, 0x0030(k0) /* SDRAM sleep */
1456 + li a0, MEM_PHYS_ADDR
1457 + or a0, a0, 0xA0000000
1458 +#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || defined(CONFIG_SOC_AU1500)
1459 + lw k0, MEM_SDMODE0(a0)
1460 + sw zero, MEM_SDPRECMD(a0) /* Precharge */
1461 + sw zero, MEM_SDAUTOREF(a0) /* Auto Refresh */
1462 + sw zero, MEM_SDSLEEP(a0) /* Sleep */
1463 sync
1464 -
1465 - lui k1, 0xb190
1466 - sw zero, 0x0078(k1) /* get ready to sleep */
1467 +#endif
1468 +#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
1469 + sw zero, MEM_SDPRECMD(a0) /* Precharge */
1470 + sw zero, MEM_SDSREF(a0)
1471 +
1472 + #lw t0, MEM_SDSTAT(a0)
1473 + #and t0, t0, 0x01000000
1474 + li t0, 0x01000000
1475 +refresh_not_set:
1476 + lw t1, MEM_SDSTAT(a0)
1477 + and t2, t1, t0
1478 + beq zero, t2, refresh_not_set
1479 + nop
1480 +
1481 + li t0, ~0x30000000
1482 + lw t1, MEM_SDCONFIGA(a0)
1483 + and t1, t0, t1
1484 + sw t1, MEM_SDCONFIGA(a0)
1485 sync
1486 - sw zero, 0x007c(k1) /* Put processor to sleep */
1487 +#endif
1488 +
1489 + li t0, SYS_SLEEP
1490 + sw zero, 0(t0) /* Put processor to sleep */
1491 sync
1492 + nop
1493 + nop
1494 + nop
1495 + nop
1496 + nop
1497 + nop
1498 + nop
1499 + nop
1500 +
1501
1502 /* This is where we return upon wakeup.
1503 * Reload all of the registers and return.
1504 */
1505 -1: nop
1506 - lw k0, 0x20(sp)
1507 +resume_from_sleep:
1508 + nop
1509 + .set nomacro
1510 + .set noat
1511 +
1512 + lw k0, PT_C0STATUS(sp) // 0x20
1513 mtc0 k0, CP0_STATUS
1514 - lw k0, 0x1c(sp)
1515 + lw k0, PT_CONTEXT(sp) // 0x1c
1516 mtc0 k0, CP0_CONTEXT
1517 - lw k0, 0x18(sp)
1518 + lw k0, PT_PAGEMASK(sp) // 0x18
1519 mtc0 k0, CP0_PAGEMASK
1520 - lw k0, 0x14(sp)
1521 + lw k0, PT_CONFIG(sp) // 0x14
1522 mtc0 k0, CP0_CONFIG
1523 lw $1, PT_R1(sp)
1524 lw $2, PT_R2(sp)
1525 @@ -120,14 +193,6 @@ sdsleep:
1526 lw $5, PT_R5(sp)
1527 lw $6, PT_R6(sp)
1528 lw $7, PT_R7(sp)
1529 - lw $8, PT_R8(sp)
1530 - lw $9, PT_R9(sp)
1531 - lw $10, PT_R10(sp)
1532 - lw $11, PT_R11(sp)
1533 - lw $12, PT_R12(sp)
1534 - lw $13, PT_R13(sp)
1535 - lw $14, PT_R14(sp)
1536 - lw $15, PT_R15(sp)
1537 lw $16, PT_R16(sp)
1538 lw $17, PT_R17(sp)
1539 lw $18, PT_R18(sp)
1540 @@ -136,15 +201,36 @@ sdsleep:
1541 lw $21, PT_R21(sp)
1542 lw $22, PT_R22(sp)
1543 lw $23, PT_R23(sp)
1544 - lw $24, PT_R24(sp)
1545 - lw $25, PT_R25(sp)
1546 - lw $26, PT_R26(sp)
1547 - lw $27, PT_R27(sp)
1548 lw $28, PT_R28(sp)
1549 - lw $29, PT_R29(sp)
1550 lw $30, PT_R30(sp)
1551 lw $31, PT_R31(sp)
1552 +
1553 + .set macro
1554 + .set at
1555 +
1556 + /* clear the wake source, but save it as the return value of the function */
1557 + li t0, SYS_WAKESRC
1558 + lw v0, 0(t0)
1559 + sw v0, PT_R2(sp)
1560 + sw zero, 0(t0)
1561 +
1562 addiu sp, PT_SIZE
1563
1564 + lw gp, save_and_sleep_frmsz-44(sp)
1565 + lw s8, save_and_sleep_frmsz-40(sp)
1566 + lw s7, save_and_sleep_frmsz-36(sp)
1567 + lw s6, save_and_sleep_frmsz-32(sp)
1568 + lw s5, save_and_sleep_frmsz-28(sp)
1569 + lw s4, save_and_sleep_frmsz-24(sp)
1570 + lw s3, save_and_sleep_frmsz-20(sp)
1571 + lw s2, save_and_sleep_frmsz-16(sp)
1572 + lw s1, save_and_sleep_frmsz-12(sp)
1573 + lw s0, save_and_sleep_frmsz-8(sp)
1574 + lw ra, save_and_sleep_frmsz-4(sp)
1575 +
1576 + addu sp, save_and_sleep_frmsz
1577 jr ra
1578 + nop
1579 + .set reorder
1580 END(save_and_sleep)
1581 +
1582 --- a/arch/mips/au1000/common/time.c
1583 +++ b/arch/mips/au1000/common/time.c
1584 @@ -50,7 +50,6 @@
1585 #include <linux/mc146818rtc.h>
1586 #include <linux/timex.h>
1587
1588 -extern void startup_match20_interrupt(void);
1589 extern void do_softirq(void);
1590 extern volatile unsigned long wall_jiffies;
1591 unsigned long missed_heart_beats = 0;
1592 @@ -59,14 +58,14 @@ static unsigned long r4k_offset; /* Amou
1593 static unsigned long r4k_cur; /* What counter should be at next timer irq */
1594 extern rwlock_t xtime_lock;
1595 int no_au1xxx_32khz;
1596 -void (*au1k_wait_ptr)(void);
1597 +extern int allow_au1k_wait; /* default off for CP0 Counter */
1598
1599 /* Cycle counter value at the previous timer interrupt.. */
1600 static unsigned int timerhi = 0, timerlo = 0;
1601
1602 #ifdef CONFIG_PM
1603 #define MATCH20_INC 328
1604 -extern void startup_match20_interrupt(void);
1605 +extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *));
1606 static unsigned long last_pc0, last_match20;
1607 #endif
1608
1609 @@ -385,7 +384,6 @@ void __init au1xxx_timer_setup(void)
1610 {
1611 unsigned int est_freq;
1612 extern unsigned long (*do_gettimeoffset)(void);
1613 - extern void au1k_wait(void);
1614
1615 printk("calculating r4koff... ");
1616 r4k_offset = cal_r4koff();
1617 @@ -437,9 +435,6 @@ void __init au1xxx_timer_setup(void)
1618 au_writel(0, SYS_TOYWRITE);
1619 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
1620
1621 - au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
1622 - au_writel(~0, SYS_WAKESRC);
1623 - au_sync();
1624 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
1625
1626 /* setup match20 to interrupt once every 10ms */
1627 @@ -447,13 +442,13 @@ void __init au1xxx_timer_setup(void)
1628 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
1629 au_sync();
1630 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
1631 - startup_match20_interrupt();
1632 + startup_match20_interrupt(counter0_irq);
1633
1634 do_gettimeoffset = do_fast_pm_gettimeoffset;
1635
1636 /* We can use the real 'wait' instruction.
1637 */
1638 - au1k_wait_ptr = au1k_wait;
1639 + allow_au1k_wait = 1;
1640 }
1641
1642 #else
1643 --- a/arch/mips/au1000/db1x00/board_setup.c
1644 +++ b/arch/mips/au1000/db1x00/board_setup.c
1645 @@ -46,10 +46,22 @@
1646 #include <asm/au1000.h>
1647 #include <asm/db1x00.h>
1648
1649 -extern struct rtc_ops no_rtc_ops;
1650 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) && defined(CONFIG_MIPS_DB1550)
1651 +#include <asm/au1xxx_dbdma.h>
1652 +extern struct ide_ops *ide_ops;
1653 +extern struct ide_ops au1xxx_ide_ops;
1654 +extern u32 au1xxx_ide_virtbase;
1655 +extern u64 au1xxx_ide_physbase;
1656 +extern int au1xxx_ide_irq;
1657 +
1658 +/* Ddma */
1659 +chan_tab_t *ide_read_ch, *ide_write_ch;
1660 +u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
1661 +
1662 +dbdev_tab_t new_dbdev_tab_element = { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 };
1663 +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
1664
1665 -/* not correct for db1550 */
1666 -static BCSR * const bcsr = (BCSR *)0xAE000000;
1667 +extern struct rtc_ops no_rtc_ops;
1668
1669 void board_reset (void)
1670 {
1671 @@ -57,6 +69,13 @@ void board_reset (void)
1672 au_writel(0x00000000, 0xAE00001C);
1673 }
1674
1675 +void board_power_off (void)
1676 +{
1677 +#ifdef CONFIG_MIPS_MIRAGE
1678 + au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
1679 +#endif
1680 +}
1681 +
1682 void __init board_setup(void)
1683 {
1684 u32 pin_func;
1685 @@ -108,8 +127,42 @@ void __init board_setup(void)
1686 au_writel(0x02000200, GPIO2_OUTPUT);
1687 #endif
1688
1689 +#if defined(CONFIG_AU1XXX_SMC91111)
1690 +#define CPLD_CONTROL (0xAF00000C)
1691 + {
1692 + extern uint32_t au1xxx_smc91111_base;
1693 + extern unsigned int au1xxx_smc91111_irq;
1694 + extern int au1xxx_smc91111_nowait;
1695 +
1696 + au1xxx_smc91111_base = 0xAC000300;
1697 + au1xxx_smc91111_irq = AU1000_GPIO_8;
1698 + au1xxx_smc91111_nowait = 1;
1699 +
1700 + /* set up the Static Bus timing - only 396Mhz */
1701 + bcsr->resets |= 0x7;
1702 + au_writel(0x00010003, MEM_STCFG0);
1703 + au_writel(0x000c00c0, MEM_STCFG2);
1704 + au_writel(0x85E1900D, MEM_STTIME2);
1705 + }
1706 +#endif /* end CONFIG_SMC91111 */
1707 au_sync();
1708
1709 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) && defined(CONFIG_MIPS_DB1550)
1710 + /*
1711 + * Iniz IDE parameters
1712 + */
1713 + ide_ops = &au1xxx_ide_ops;
1714 + au1xxx_ide_irq = DAUGHTER_CARD_IRQ;
1715 + au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
1716 + au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
1717 +
1718 + /*
1719 + * change PIO or PIO+Ddma
1720 + * check the GPIO-6 pin condition. db1550:s6_dot
1721 + */
1722 + switch4ddma = (au_readl(SYS_PINSTATERD) & (1 << 6)) ? 1 : 0;
1723 +#endif
1724 +
1725 #ifdef CONFIG_MIPS_DB1000
1726 printk("AMD Alchemy Au1000/Db1000 Board\n");
1727 #endif
1728 --- a/arch/mips/au1000/db1x00/irqmap.c
1729 +++ b/arch/mips/au1000/db1x00/irqmap.c
1730 @@ -53,6 +53,7 @@ au1xxx_irq_map_t au1xxx_irq_map[] = {
1731 #ifdef CONFIG_MIPS_DB1550
1732 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 IRQ#
1733 { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 IRQ#
1734 + { AU1000_GPIO_8, INTC_INT_LOW_LEVEL, 0 }, // Daughtercard IRQ#
1735 #else
1736 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 Fully_Interted#
1737 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 STSCHG#
1738 --- a/arch/mips/au1000/db1x00/Makefile
1739 +++ b/arch/mips/au1000/db1x00/Makefile
1740 @@ -17,4 +17,11 @@ O_TARGET := db1x00.o
1741 obj-y := init.o board_setup.o irqmap.o
1742 obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
1743
1744 +ifdef CONFIG_MIPS_DB1100
1745 +ifdef CONFIG_MMC
1746 +obj-y += mmc_support.o
1747 +export-objs += mmc_support.o
1748 +endif
1749 +endif
1750 +
1751 include $(TOPDIR)/Rules.make
1752 --- /dev/null
1753 +++ b/arch/mips/au1000/db1x00/mmc_support.c
1754 @@ -0,0 +1,126 @@
1755 +/*
1756 + * BRIEF MODULE DESCRIPTION
1757 + *
1758 + * MMC support routines for DB1100.
1759 + *
1760 + *
1761 + * Copyright (c) 2003-2004 Embedded Edge, LLC.
1762 + * Author: Embedded Edge, LLC.
1763 + * Contact: dan@embeddededge.com
1764 + *
1765 + * This program is free software; you can redistribute it and/or modify it
1766 + * under the terms of the GNU General Public License as published by the
1767 + * Free Software Foundation; either version 2 of the License, or (at your
1768 + * option) any later version.
1769 + *
1770 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1771 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1772 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
1773 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1774 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1775 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
1776 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
1777 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1778 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1779 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1780 + *
1781 + * You should have received a copy of the GNU General Public License along
1782 + * with this program; if not, write to the Free Software Foundation, Inc.,
1783 + * 675 Mass Ave, Cambridge, MA 02139, USA.
1784 + *
1785 + */
1786 +
1787 +
1788 +#include <linux/config.h>
1789 +#include <linux/kernel.h>
1790 +#include <linux/module.h>
1791 +#include <linux/init.h>
1792 +
1793 +#include <asm/irq.h>
1794 +#include <asm/au1000.h>
1795 +#include <asm/au1100_mmc.h>
1796 +#include <asm/db1x00.h>
1797 +
1798 +
1799 +/* SD/MMC controller support functions */
1800 +
1801 +/*
1802 + * Detect card.
1803 + */
1804 +void mmc_card_inserted(int _n_, int *_res_)
1805 +{
1806 + u32 gpios = au_readl(SYS_PINSTATERD);
1807 + u32 emptybit = (_n_) ? (1<<20) : (1<<19);
1808 + *_res_ = ((gpios & emptybit) == 0);
1809 +}
1810 +
1811 +/*
1812 + * Check card write protection.
1813 + */
1814 +void mmc_card_writable(int _n_, int *_res_)
1815 +{
1816 + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
1817 + unsigned long mmc_wp, board_specific;
1818 +
1819 + if (_n_) {
1820 + mmc_wp = BCSR_BOARD_SD1_WP;
1821 + } else {
1822 + mmc_wp = BCSR_BOARD_SD0_WP;
1823 + }
1824 +
1825 + board_specific = au_readl((unsigned long)(&bcsr->specific));
1826 +
1827 + if (!(board_specific & mmc_wp)) {/* low means card writable */
1828 + *_res_ = 1;
1829 + } else {
1830 + *_res_ = 0;
1831 + }
1832 +}
1833 +
1834 +/*
1835 + * Apply power to card slot.
1836 + */
1837 +void mmc_power_on(int _n_)
1838 +{
1839 + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
1840 + unsigned long mmc_pwr, board_specific;
1841 +
1842 + if (_n_) {
1843 + mmc_pwr = BCSR_BOARD_SD1_PWR;
1844 + } else {
1845 + mmc_pwr = BCSR_BOARD_SD0_PWR;
1846 + }
1847 +
1848 + board_specific = au_readl((unsigned long)(&bcsr->specific));
1849 + board_specific |= mmc_pwr;
1850 +
1851 + au_writel(board_specific, (int)(&bcsr->specific));
1852 + au_sync_delay(1);
1853 +}
1854 +
1855 +/*
1856 + * Remove power from card slot.
1857 + */
1858 +void mmc_power_off(int _n_)
1859 +{
1860 + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
1861 + unsigned long mmc_pwr, board_specific;
1862 +
1863 + if (_n_) {
1864 + mmc_pwr = BCSR_BOARD_SD1_PWR;
1865 + } else {
1866 + mmc_pwr = BCSR_BOARD_SD0_PWR;
1867 + }
1868 +
1869 + board_specific = au_readl((unsigned long)(&bcsr->specific));
1870 + board_specific &= ~mmc_pwr;
1871 +
1872 + au_writel(board_specific, (int)(&bcsr->specific));
1873 + au_sync_delay(1);
1874 +}
1875 +
1876 +EXPORT_SYMBOL(mmc_card_inserted);
1877 +EXPORT_SYMBOL(mmc_card_writable);
1878 +EXPORT_SYMBOL(mmc_power_on);
1879 +EXPORT_SYMBOL(mmc_power_off);
1880 +
1881 --- /dev/null
1882 +++ b/arch/mips/au1000/ficmmp/au1200_ibutton.c
1883 @@ -0,0 +1,270 @@
1884 +/* ----------------------------------------------------------------------
1885 + * mtwilson_keys.c
1886 + *
1887 + * Copyright (C) 2003 Intrinsyc Software Inc.
1888 + *
1889 + * Intel Personal Media Player buttons
1890 + *
1891 + * This program is free software; you can redistribute it and/or modify
1892 + * it under the terms of the GNU General Public License version 2 as
1893 + * published by the Free Software Foundation.
1894 + *
1895 + * May 02, 2003 : Initial version [FB]
1896 + *
1897 + ------------------------------------------------------------------------*/
1898 +
1899 +#include <linux/config.h>
1900 +#include <linux/module.h>
1901 +#include <linux/kernel.h>
1902 +#include <linux/init.h>
1903 +#include <linux/fs.h>
1904 +#include <linux/sched.h>
1905 +#include <linux/miscdevice.h>
1906 +#include <linux/errno.h>
1907 +#include <linux/poll.h>
1908 +#include <linux/delay.h>
1909 +#include <linux/input.h>
1910 +
1911 +#include <asm/au1000.h>
1912 +#include <asm/uaccess.h>
1913 +#include <asm/au1xxx_gpio.h>
1914 +#include <asm/irq.h>
1915 +#include <asm/keyboard.h>
1916 +#include <linux/time.h>
1917 +
1918 +#define DRIVER_VERSION "V1.0"
1919 +#define DRIVER_AUTHOR "FIC"
1920 +#define DRIVER_DESC "FIC Travis Media Player Button Driver"
1921 +#define DRIVER_NAME "Au1200Button"
1922 +
1923 +#define BUTTON_MAIN (1<<1)
1924 +#define BUTTON_SELECT (1<<6)
1925 +#define BUTTON_GUIDE (1<<12)
1926 +#define BUTTON_DOWN (1<<17)
1927 +#define BUTTON_LEFT (1<<19)
1928 +#define BUTTON_RIGHT (1<<26)
1929 +#define BUTTON_UP (1<<28)
1930 +
1931 +#define BUTTON_MASK (\
1932 + BUTTON_MAIN \
1933 + | BUTTON_SELECT \
1934 + | BUTTON_GUIDE \
1935 + | BUTTON_DOWN \
1936 + | BUTTON_LEFT \
1937 + | BUTTON_RIGHT \
1938 + | BUTTON_UP \
1939 + )
1940 +
1941 +#define BUTTON_INVERT (\
1942 + BUTTON_MAIN \
1943 + | 0 \
1944 + | BUTTON_GUIDE \
1945 + | 0 \
1946 + | 0 \
1947 + | 0 \
1948 + | 0 \
1949 + )
1950 +
1951 +char button_map[32]={0,KEY_S,0,0,0,0,KEY_ENTER,0,0,0,0,0,KEY_G,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
1952 +//char button_map[32]={0,0,0,0,0,0,KEY_ENTER,0,0,0,0,0,KEY_G,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
1953 +
1954 +//char button_map[32]={0,KEY_TAB,0,0,0,0,KEY_M,0,0,0,0,0,KEY_S,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
1955 +//char button_map[32]={0,0,0,0,0,0,KEY_M,0,0,0,0,0,KEY_S,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0};
1956 +
1957 +#define BUTTON_COUNT (sizeof (button_map) / sizeof (button_map[0]))
1958 +
1959 +struct input_dev dev;
1960 +struct timeval cur_tv;
1961 +
1962 +static unsigned int old_tv_usec = 0;
1963 +
1964 +static unsigned int read_button_state(void)
1965 +{
1966 + unsigned int state;
1967 +
1968 + state = au_readl(SYS_PINSTATERD) & BUTTON_MASK; /* get gpio status */
1969 +
1970 + state ^= BUTTON_INVERT; /* invert main & guide button */
1971 +
1972 + /* printk("au1200_ibutton.c: button state [0x%X]\r\n",state); */
1973 + return state;
1974 +}
1975 +
1976 +//This function returns 0 if the allowed microseconds have elapsed since the last call to ths function, otherwise it returns 1 to indicate a bounce condition
1977 +static unsigned int bounce()
1978 +{
1979 +
1980 + unsigned int elapsed_time;
1981 +
1982 + do_gettimeofday (&cur_tv);
1983 +
1984 + if (!old_tv_usec) {
1985 + old_tv_usec = cur_tv.tv_usec;
1986 + return 0;
1987 + }
1988 +
1989 + if(cur_tv.tv_usec > old_tv_usec) {
1990 + /* If there hasn't been rollover */
1991 + elapsed_time = ((cur_tv.tv_usec - old_tv_usec));
1992 + }
1993 + else {
1994 + /* Accounting for rollover */
1995 + elapsed_time = ((1000000 - old_tv_usec + cur_tv.tv_usec));
1996 + }
1997 +
1998 + if (elapsed_time > 250000) {
1999 + old_tv_usec = 0; /* reset the bounce time */
2000 + return 0;
2001 + }
2002 +
2003 + return 1;
2004 +}
2005 +
2006 +/* button interrupt handler */
2007 +static void button_interrupt(int irq, void *dev, struct pt_regs *regs)
2008 +{
2009 +
2010 + unsigned int i,bit_mask, key_choice;
2011 + u32 button_state;
2012 +
2013 + /* Report state to upper level */
2014 +
2015 + button_state = read_button_state() & BUTTON_MASK; /* get new gpio status */
2016 +
2017 + /* Return if this is a repeated (bouncing) event */
2018 + if(bounce())
2019 + return;
2020 +
2021 + /* we want to make keystrokes */
2022 + for( i=0; i< BUTTON_COUNT; i++) {
2023 + bit_mask = 1<<i;
2024 + if (button_state & bit_mask) {
2025 + key_choice = button_map[i];
2026 + /* toggle key down */
2027 + input_report_key(dev, key_choice, 1);
2028 + /* toggle key up */
2029 + input_report_key(dev, key_choice, 0);
2030 + printk("ibutton gpio %d stat %x scan code %d\r\n",
2031 + i, button_state, key_choice);
2032 + /* Only report the first key event; it doesn't make
2033 + * sense for two keys to be pressed at the same time,
2034 + * and causes problems with the directional keys
2035 + * return;
2036 + */
2037 + }
2038 + }
2039 +}
2040 +
2041 +static int
2042 +button_translate(unsigned char scancode, unsigned char *keycode, char raw_mode)
2043 +{
2044 + static int prev_scancode;
2045 +
2046 + printk( "ibutton.c: translate: scancode=%x raw_mode=%x\n",
2047 + scancode, raw_mode);
2048 +
2049 + if (scancode == 0xe0 || scancode == 0xe1) {
2050 + prev_scancode = scancode;
2051 + return 0;
2052 + }
2053 +
2054 + if (scancode == 0x00 || scancode == 0xff) {
2055 + prev_scancode = 0;
2056 + return 0;
2057 + }
2058 +
2059 + *keycode = scancode;
2060 +
2061 + return 1;
2062 +}
2063 +
2064 +/* init button hardware */
2065 +static int button_hw_init(void)
2066 +{
2067 + unsigned int ipinfunc=0;
2068 +
2069 + printk("au1200_ibutton.c: Initializing buttons hardware\n");
2070 +
2071 + // initialize GPIO pin function assignments
2072 +
2073 + ipinfunc = au_readl(SYS_PINFUNC);
2074 +
2075 + ipinfunc &= ~(SYS_PINFUNC_DMA | SYS_PINFUNC_S0A | SYS_PINFUNC_S0B);
2076 + au_writel( ipinfunc ,SYS_PINFUNC);
2077 +
2078 + ipinfunc |= (SYS_PINFUNC_S0C);
2079 + au_writel( ipinfunc ,SYS_PINFUNC);
2080 +
2081 + return 0;
2082 +}
2083 +
2084 +/* button driver init */
2085 +static int __init button_init(void)
2086 +{
2087 + int ret, i;
2088 + unsigned int flag=0;
2089 +
2090 + printk("au1200_ibutton.c: button_init()\r\n");
2091 +
2092 + button_hw_init();
2093 +
2094 + /* register all button irq handler */
2095 +
2096 + for(i=0; i< sizeof(button_map)/sizeof(button_map[0]); i++)
2097 + {
2098 + /* register irq <-- gpio 1 ,6 ,12 , 17 ,19 , 26 ,28 */
2099 + if(button_map[i] != 0)
2100 + {
2101 + ret = request_irq(AU1000_GPIO_0 + i ,
2102 + &button_interrupt , SA_INTERRUPT ,
2103 + DRIVER_NAME , &dev);
2104 + if(ret) flag |= 1<<i;
2105 + }
2106 + }
2107 +
2108 + printk("au1200_ibutton.c: request_irq,ret:0x%x\r\n",ret);
2109 +
2110 + if (ret) {
2111 + printk("au1200_ibutton.c: request_irq:%X failed\r\n",flag);
2112 + return ret;
2113 + }
2114 +
2115 + dev.name = DRIVER_NAME;
2116 + dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
2117 +
2118 + for (i=0;i<sizeof(button_map)/sizeof(button_map[0]);i++)
2119 + {
2120 + dev.keybit[LONG(button_map[i])] |= BIT(button_map[i]);
2121 + }
2122 +
2123 + input_register_device(&dev);
2124 +
2125 + /* ready to receive interrupts */
2126 +
2127 + return 0;
2128 +}
2129 +
2130 +/* button driver exit */
2131 +static void __exit button_exit(void)
2132 +{
2133 + int i;
2134 +
2135 + for(i=0;i<sizeof(button_map)/sizeof(button_map[0]);i++)
2136 + {
2137 + if(button_map[i] != 0)
2138 + {
2139 + free_irq( AU1000_GPIO_0 + i, &dev);
2140 + }
2141 + }
2142 +
2143 + input_unregister_device(&dev);
2144 +
2145 + printk("au1200_ibutton.c: button_exit()\r\n");
2146 +}
2147 +
2148 +module_init(button_init);
2149 +module_exit(button_exit);
2150 +
2151 +MODULE_AUTHOR( DRIVER_AUTHOR );
2152 +MODULE_DESCRIPTION( DRIVER_DESC );
2153 +MODULE_LICENSE("GPL");
2154 --- /dev/null
2155 +++ b/arch/mips/au1000/ficmmp/au1xxx_dock.c
2156 @@ -0,0 +1,261 @@
2157 +/*
2158 + * Copyright (C) 2003 Metrowerks, All Rights Reserved.
2159 + *
2160 + * This program is free software; you can redistribute it and/or modify
2161 + * it under the terms of the GNU General Public License version 2 as
2162 + * published by the Free Software Foundation.
2163 + */
2164 +
2165 +#include <linux/config.h>
2166 +#include <linux/module.h>
2167 +#include <linux/init.h>
2168 +#include <linux/fs.h>
2169 +#include <linux/sched.h>
2170 +#include <linux/miscdevice.h>
2171 +#include <linux/errno.h>
2172 +#include <linux/poll.h>
2173 +#include <asm/au1000.h>
2174 +#include <asm/uaccess.h>
2175 +#include <asm/au1xxx_gpio.h>
2176 +
2177 +
2178 +#if defined(CONFIG_MIPS_FICMMP)
2179 + #define DOCK_GPIO 215
2180 +#else
2181 + #error Unsupported Au1xxx Platform
2182 +#endif
2183 +
2184 +#define MAKE_FLAG 0x20
2185 +
2186 +#undef DEBUG
2187 +
2188 +#define DEBUG 0
2189 +//#define DEBUG 1
2190 +
2191 +#if DEBUG
2192 +#define DPRINTK(format, args...) printk(__FUNCTION__ ": " format, ## args)
2193 +#else
2194 +#define DPRINTK(format, args...) do { } while (0)
2195 +#endif
2196 +
2197 +/* Please note that this driver is based on a timer and is not interrupt
2198 + * driven. If you are going to make use of this driver, you will need to have
2199 + * your application open the dock listing from the /dev directory first.
2200 + */
2201 +
2202 +struct au1xxx_dock {
2203 + struct fasync_struct *fasync;
2204 + wait_queue_head_t read_wait;
2205 + int open_count;
2206 + unsigned int debounce;
2207 + unsigned int current;
2208 + unsigned int last;
2209 +};
2210 +
2211 +static struct au1xxx_dock dock_info;
2212 +
2213 +
2214 +static void dock_timer_periodic(void *data);
2215 +
2216 +static struct tq_struct dock_task = {
2217 + routine: dock_timer_periodic,
2218 + data: NULL
2219 +};
2220 +
2221 +static int cleanup_flag = 0;
2222 +static DECLARE_WAIT_QUEUE_HEAD(cleanup_wait_queue);
2223 +
2224 +
2225 +static unsigned int read_dock_state(void)
2226 +{
2227 + u32 state;
2228 +
2229 + state = au1xxx_gpio_read(DOCK_GPIO);
2230 +
2231 + /* printk( "Current Dock State: %d\n", state ); */
2232 +
2233 + return state;
2234 +}
2235 +
2236 +
2237 +static void dock_timer_periodic(void *data)
2238 +{
2239 + struct au1xxx_dock *dock = (struct au1xxx_dock *)data;
2240 + unsigned long dock_state;
2241 +
2242 + /* If cleanup wants us to die */
2243 + if (cleanup_flag) {
2244 + /* now cleanup_module can return */
2245 + wake_up(&cleanup_wait_queue);
2246 + } else {
2247 + /* put ourselves back in the task queue */
2248 + queue_task(&dock_task, &tq_timer);
2249 + }
2250 +
2251 + /* read current dock */
2252 + dock_state = read_dock_state();
2253 +
2254 + /* if dock states hasn't changed */
2255 + /* save time and be done. */
2256 + if (dock_state == dock->current) {
2257 + return;
2258 + }
2259 +
2260 + if (dock_state == dock->debounce) {
2261 + dock->current = dock_state;
2262 + } else {
2263 + dock->debounce = dock_state;
2264 + }
2265 + if (dock->current != dock->last) {
2266 + if (waitqueue_active(&dock->read_wait)) {
2267 + wake_up_interruptible(&dock->read_wait);
2268 + }
2269 + }
2270 +}
2271 +
2272 +
2273 +static ssize_t au1xxx_dock_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
2274 +{
2275 + struct au1xxx_dock *dock = filp->private_data;
2276 + char event[3];
2277 + int last;
2278 + int cur;
2279 + int err;
2280 +
2281 +try_again:
2282 +
2283 + while (dock->current == dock->last) {
2284 + if (filp->f_flags & O_NONBLOCK) {
2285 + return -EAGAIN;
2286 + }
2287 + interruptible_sleep_on(&dock->read_wait);
2288 + if (signal_pending(current)) {
2289 + return -ERESTARTSYS;
2290 + }
2291 + }
2292 +
2293 + cur = dock->current;
2294 + last = dock->last;
2295 +
2296 + if(cur != last)
2297 + {
2298 + event[0] = cur ? 'D' : 'U';
2299 + event[1] = '\r';
2300 + event[2] = '\n';
2301 + }
2302 + else
2303 + goto try_again;
2304 +
2305 + dock->last = cur;
2306 + err = copy_to_user(buffer, &event, 3);
2307 + if (err) {
2308 + return err;
2309 + }
2310 +
2311 + return 3;
2312 +}
2313 +
2314 +
2315 +static int au1xxx_dock_open(struct inode *inode, struct file *filp)
2316 +{
2317 + struct au1xxx_dock *dock = &dock_info;
2318 +
2319 + MOD_INC_USE_COUNT;
2320 +
2321 + filp->private_data = dock;
2322 +
2323 + if (dock->open_count++ == 0) {
2324 + dock_task.data = dock;
2325 + cleanup_flag = 0;
2326 + queue_task(&dock_task, &tq_timer);
2327 + }
2328 +
2329 + return 0;
2330 +}
2331 +
2332 +
2333 +static unsigned int au1xxx_dock_poll(struct file *filp, poll_table *wait)
2334 +{
2335 + struct au1xxx_dock *dock = filp->private_data;
2336 + int ret = 0;
2337 +
2338 + DPRINTK("start\n");
2339 + poll_wait(filp, &dock->read_wait, wait);
2340 + if (dock->current != dock->last) {
2341 + ret = POLLIN | POLLRDNORM;
2342 + }
2343 + return ret;
2344 +}
2345 +
2346 +
2347 +static int au1xxx_dock_release(struct inode *inode, struct file *filp)
2348 +{
2349 + struct au1xxx_dock *dock = filp->private_data;
2350 +
2351 + DPRINTK("start\n");
2352 +
2353 + if (--dock->open_count == 0) {
2354 + cleanup_flag = 1;
2355 + sleep_on(&cleanup_wait_queue);
2356 + }
2357 + MOD_DEC_USE_COUNT;
2358 +
2359 + return 0;
2360 +}
2361 +
2362 +
2363 +
2364 +static struct file_operations au1xxx_dock_fops = {
2365 + owner: THIS_MODULE,
2366 + read: au1xxx_dock_read,
2367 + poll: au1xxx_dock_poll,
2368 + open: au1xxx_dock_open,
2369 + release: au1xxx_dock_release,
2370 +};
2371 +
2372 +/*
2373 + * The au1xxx dock is a misc device:
2374 + * Major 10 char
2375 + * Minor 22 /dev/dock
2376 + *
2377 + * This is /dev/misc/dock if devfs is used.
2378 + */
2379 +
2380 +static struct miscdevice au1xxx_dock_dev = {
2381 + minor: 23,
2382 + name: "dock",
2383 + fops: &au1xxx_dock_fops,
2384 +};
2385 +
2386 +static int __init au1xxx_dock_init(void)
2387 +{
2388 + struct au1xxx_dock *dock = &dock_info;
2389 + int ret;
2390 +
2391 + DPRINTK("Initializing dock driver\n");
2392 + dock->open_count = 0;
2393 + cleanup_flag = 0;
2394 + init_waitqueue_head(&dock->read_wait);
2395 +
2396 +
2397 + /* yamon configures GPIO pins for the dock
2398 + * no initialization needed
2399 + */
2400 +
2401 + ret = misc_register(&au1xxx_dock_dev);
2402 +
2403 + DPRINTK("dock driver fully initialized.\n");
2404 +
2405 + return ret;
2406 +}
2407 +
2408 +
2409 +static void __exit au1xxx_dock_exit(void)
2410 +{
2411 + DPRINTK("unloading dock driver\n");
2412 + misc_deregister(&au1xxx_dock_dev);
2413 +}
2414 +
2415 +
2416 +module_init(au1xxx_dock_init);
2417 +module_exit(au1xxx_dock_exit);
2418 --- /dev/null
2419 +++ b/arch/mips/au1000/ficmmp/board_setup.c
2420 @@ -0,0 +1,226 @@
2421 +/*
2422 + *
2423 + * BRIEF MODULE DESCRIPTION
2424 + * Alchemy Pb1200 board setup.
2425 + *
2426 + * This program is free software; you can redistribute it and/or modify it
2427 + * under the terms of the GNU General Public License as published by the
2428 + * Free Software Foundation; either version 2 of the License, or (at your
2429 + * option) any later version.
2430 + *
2431 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2432 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2433 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
2434 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2435 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2436 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2437 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2438 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2439 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2440 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2441 + *
2442 + * You should have received a copy of the GNU General Public License along
2443 + * with this program; if not, write to the Free Software Foundation, Inc.,
2444 + * 675 Mass Ave, Cambridge, MA 02139, USA.
2445 + */
2446 +#include <linux/config.h>
2447 +#include <linux/init.h>
2448 +#include <linux/sched.h>
2449 +#include <linux/ioport.h>
2450 +#include <linux/mm.h>
2451 +#include <linux/console.h>
2452 +#include <linux/mc146818rtc.h>
2453 +#include <linux/delay.h>
2454 +#include <linux/ide.h>
2455 +
2456 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
2457 +#include <linux/ide.h>
2458 +#endif
2459 +
2460 +#include <asm/cpu.h>
2461 +#include <asm/bootinfo.h>
2462 +#include <asm/irq.h>
2463 +#include <asm/keyboard.h>
2464 +#include <asm/mipsregs.h>
2465 +#include <asm/reboot.h>
2466 +#include <asm/pgtable.h>
2467 +#include <asm/au1000.h>
2468 +#include <asm/ficmmp.h>
2469 +#include <asm/au1xxx_dbdma.h>
2470 +#include <asm/au1xxx_gpio.h>
2471 +
2472 +extern struct rtc_ops no_rtc_ops;
2473 +
2474 +/* value currently in the board configuration register */
2475 +u16 ficmmp_config = 0;
2476 +
2477 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
2478 +extern struct ide_ops *ide_ops;
2479 +extern struct ide_ops au1xxx_ide_ops;
2480 +extern u32 au1xxx_ide_virtbase;
2481 +extern u64 au1xxx_ide_physbase;
2482 +extern int au1xxx_ide_irq;
2483 +
2484 +u32 led_base_addr;
2485 +/* Ddma */
2486 +chan_tab_t *ide_read_ch, *ide_write_ch;
2487 +u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
2488 +
2489 +dbdev_tab_t new_dbdev_tab_element = { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 };
2490 +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
2491 +
2492 +void board_reset (void)
2493 +{
2494 + au_writel(0, 0xAD80001C);
2495 +}
2496 +
2497 +void board_power_off (void)
2498 +{
2499 +}
2500 +
2501 +void __init board_setup(void)
2502 +{
2503 + char *argptr = NULL;
2504 + u32 pin_func;
2505 + rtc_ops = &no_rtc_ops;
2506 +
2507 + ficmmp_config_init(); //Initialize FIC control register
2508 +
2509 +#if 0
2510 + /* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
2511 + * but it is board specific code, so put it here.
2512 + */
2513 + pin_func = au_readl(SYS_PINFUNC);
2514 + au_sync();
2515 + pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1;
2516 + au_writel(pin_func, SYS_PINFUNC);
2517 +
2518 + au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
2519 + au_sync();
2520 +#endif
2521 +
2522 +#if defined( CONFIG_I2C_ALGO_AU1550 )
2523 + {
2524 + u32 freq0, clksrc;
2525 +
2526 + /* Select SMBUS in CPLD */
2527 + /* bcsr->resets &= ~(BCSR_RESETS_PCS0MUX); */
2528 +
2529 + pin_func = au_readl(SYS_PINFUNC);
2530 + au_sync();
2531 + pin_func &= ~(3<<17 | 1<<4);
2532 + /* Set GPIOs correctly */
2533 + pin_func |= 2<<17;
2534 + au_writel(pin_func, SYS_PINFUNC);
2535 + au_sync();
2536 +
2537 + /* The i2c driver depends on 50Mhz clock */
2538 + freq0 = au_readl(SYS_FREQCTRL0);
2539 + au_sync();
2540 + freq0 &= ~(SYS_FC_FRDIV1_MASK | SYS_FC_FS1 | SYS_FC_FE1);
2541 + freq0 |= (3<<SYS_FC_FRDIV1_BIT);
2542 + /* 396Mhz / (3+1)*2 == 49.5Mhz */
2543 + au_writel(freq0, SYS_FREQCTRL0);
2544 + au_sync();
2545 + freq0 |= SYS_FC_FE1;
2546 + au_writel(freq0, SYS_FREQCTRL0);
2547 + au_sync();
2548 +
2549 + clksrc = au_readl(SYS_CLKSRC);
2550 + au_sync();
2551 + clksrc &= ~0x01f00000;
2552 + /* bit 22 is EXTCLK0 for PSC0 */
2553 + clksrc |= (0x3 << 22);
2554 + au_writel(clksrc, SYS_CLKSRC);
2555 + au_sync();
2556 + }
2557 +#endif
2558 +
2559 +#ifdef CONFIG_FB_AU1200
2560 + argptr = prom_getcmdline();
2561 + strcat(argptr, " video=au1200fb:");
2562 +#endif
2563 +
2564 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
2565 + /*
2566 + * Iniz IDE parameters
2567 + */
2568 + ide_ops = &au1xxx_ide_ops;
2569 + au1xxx_ide_irq = FICMMP_IDE_INT;
2570 + au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
2571 + au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
2572 + switch4ddma = 0;
2573 + /*
2574 + ide_ops = &au1xxx_ide_ops;
2575 + au1xxx_ide_irq = FICMMP_IDE_INT;
2576 + au1xxx_ide_base = KSEG1ADDR(AU1XXX_ATA_BASE);
2577 + */
2578 + au1xxx_gpio_write(9, 1);
2579 + printk("B4001010: %X\n", *((u32*)0xB4001010));
2580 + printk("B4001014: %X\n", *((u32*)0xB4001014));
2581 + printk("B4001018: %X\n", *((u32*)0xB4001018));
2582 + printk("B1900100: %X\n", *((u32*)0xB1900100));
2583 +
2584 +#if 0
2585 + ficmmp_config_clear(FICMMP_CONFIG_IDERST);
2586 + mdelay(100);
2587 + ficmmp_config_set(FICMMP_CONFIG_IDERST);
2588 + mdelay(100);
2589 +#endif
2590 + /*
2591 + * change PIO or PIO+Ddma
2592 + * check the GPIO-5 pin condition. pb1200:s18_dot
2593 + */
2594 +/* switch4ddma = 0; //(au_readl(SYS_PINSTATERD) & (1 << 5)) ? 1 : 0; */
2595 +#endif
2596 +
2597 + /* The Pb1200 development board uses external MUX for PSC0 to
2598 + support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
2599 + */
2600 +#if defined(CONFIG_AU1550_PSC_SPI) && defined(CONFIG_I2C_ALGO_AU1550)
2601 + #error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
2602 + Refer to Pb1200 documentation.
2603 +#elif defined( CONFIG_AU1550_PSC_SPI )
2604 + //bcsr->resets |= BCSR_RESETS_PCS0MUX;
2605 +#elif defined( CONFIG_I2C_ALGO_AU1550 )
2606 + //bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
2607 +#endif
2608 + au_sync();
2609 +
2610 + printk("FIC Multimedia Player Board\n");
2611 + au1xxx_gpio_tristate(5);
2612 + printk("B1900100: %X\n", *((volatile u32*)0xB1900100));
2613 + printk("B190002C: %X\n", *((volatile u32*)0xB190002C));
2614 +}
2615 +
2616 +int
2617 +board_au1200fb_panel (void)
2618 +{
2619 + au1xxx_gpio_tristate(6);
2620 +
2621 + if (au1xxx_gpio_read(12) == 0)
2622 + return 9; /* FS453_640x480 (Composite/S-Video) */
2623 + else
2624 + return 7; /* Sharp 320x240 TFT */
2625 +}
2626 +
2627 +int
2628 +board_au1200fb_panel_init (void)
2629 +{
2630 + /*Enable data buffers*/
2631 + ficmmp_config_clear(FICMMP_CONFIG_LCMDATAOUT);
2632 + /*Take LCD out of reset*/
2633 + ficmmp_config_set(FICMMP_CONFIG_LCMPWREN | FICMMP_CONFIG_LCMEN);
2634 + return 0;
2635 +}
2636 +
2637 +int
2638 +board_au1200fb_panel_shutdown (void)
2639 +{
2640 + /*Disable data buffers*/
2641 + ficmmp_config_set(FICMMP_CONFIG_LCMDATAOUT);
2642 + /*Put LCD in reset, remove power*/
2643 + ficmmp_config_clear(FICMMP_CONFIG_LCMEN | FICMMP_CONFIG_LCMPWREN);
2644 + return 0;
2645 +}
2646 +
2647 --- /dev/null
2648 +++ b/arch/mips/au1000/ficmmp/init.c
2649 @@ -0,0 +1,76 @@
2650 +/*
2651 + *
2652 + * BRIEF MODULE DESCRIPTION
2653 + * PB1200 board setup
2654 + *
2655 + * This program is free software; you can redistribute it and/or modify it
2656 + * under the terms of the GNU General Public License as published by the
2657 + * Free Software Foundation; either version 2 of the License, or (at your
2658 + * option) any later version.
2659 + *
2660 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2661 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2662 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
2663 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2664 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2665 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2666 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2667 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2668 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2669 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2670 + *
2671 + * You should have received a copy of the GNU General Public License along
2672 + * with this program; if not, write to the Free Software Foundation, Inc.,
2673 + * 675 Mass Ave, Cambridge, MA 02139, USA.
2674 + */
2675 +
2676 +#include <linux/init.h>
2677 +#include <linux/mm.h>
2678 +#include <linux/sched.h>
2679 +#include <linux/bootmem.h>
2680 +#include <asm/addrspace.h>
2681 +#include <asm/bootinfo.h>
2682 +#include <linux/config.h>
2683 +#include <linux/string.h>
2684 +#include <linux/kernel.h>
2685 +#include <linux/sched.h>
2686 +
2687 +int prom_argc;
2688 +char **prom_argv, **prom_envp;
2689 +extern void __init prom_init_cmdline(void);
2690 +extern char *prom_getenv(char *envname);
2691 +
2692 +const char *get_system_type(void)
2693 +{
2694 + return "FIC Multimedia Player (Au1200)";
2695 +}
2696 +
2697 +u32 mae_memsize = 0;
2698 +
2699 +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
2700 +{
2701 + unsigned char *memsize_str;
2702 + unsigned long memsize;
2703 +
2704 + prom_argc = argc;
2705 + prom_argv = argv;
2706 + prom_envp = envp;
2707 +
2708 + mips_machgroup = MACH_GROUP_ALCHEMY;
2709 + mips_machtype = MACH_PB1000; /* set the platform # */
2710 + prom_init_cmdline();
2711 +
2712 + memsize_str = prom_getenv("memsize");
2713 + if (!memsize_str) {
2714 + memsize = 0x08000000;
2715 + } else {
2716 + memsize = simple_strtol(memsize_str, NULL, 0);
2717 + }
2718 +
2719 + /* reserved 32MB for MAE driver */
2720 + memsize -= (32 * 1024 * 1024);
2721 + add_memory_region(0, memsize, BOOT_MEM_RAM);
2722 + mae_memsize = memsize; /* for drivers/char/au1xxx_mae.c */
2723 + return 0;
2724 +}
2725 +
2726 --- /dev/null
2727 +++ b/arch/mips/au1000/ficmmp/irqmap.c
2728 @@ -0,0 +1,61 @@
2729 +/*
2730 + * BRIEF MODULE DESCRIPTION
2731 + * Au1xxx irq map table
2732 + *
2733 + * This program is free software; you can redistribute it and/or modify it
2734 + * under the terms of the GNU General Public License as published by the
2735 + * Free Software Foundation; either version 2 of the License, or (at your
2736 + * option) any later version.
2737 + *
2738 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2739 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2740 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
2741 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2742 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2743 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2744 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2745 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2746 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2747 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2748 + *
2749 + * You should have received a copy of the GNU General Public License along
2750 + * with this program; if not, write to the Free Software Foundation, Inc.,
2751 + * 675 Mass Ave, Cambridge, MA 02139, USA.
2752 + */
2753 +#include <linux/errno.h>
2754 +#include <linux/init.h>
2755 +#include <linux/irq.h>
2756 +#include <linux/kernel_stat.h>
2757 +#include <linux/module.h>
2758 +#include <linux/signal.h>
2759 +#include <linux/sched.h>
2760 +#include <linux/types.h>
2761 +#include <linux/interrupt.h>
2762 +#include <linux/ioport.h>
2763 +#include <linux/timex.h>
2764 +#include <linux/slab.h>
2765 +#include <linux/random.h>
2766 +#include <linux/delay.h>
2767 +
2768 +#include <asm/bitops.h>
2769 +#include <asm/bootinfo.h>
2770 +#include <asm/io.h>
2771 +#include <asm/mipsregs.h>
2772 +#include <asm/system.h>
2773 +#include <asm/au1000.h>
2774 +#include <asm/ficmmp.h>
2775 +
2776 +au1xxx_irq_map_t au1xxx_irq_map[] = {
2777 + { FICMMP_IDE_INT, INTC_INT_HIGH_LEVEL, 0 },
2778 + { AU1XXX_SMC91111_IRQ, INTC_INT_HIGH_LEVEL, 0 },
2779 + { AU1000_GPIO_1 , INTC_INT_FALL_EDGE, 0 }, // main button
2780 + { AU1000_GPIO_6 , INTC_INT_RISE_EDGE, 0 }, // select button
2781 + { AU1000_GPIO_12, INTC_INT_FALL_EDGE, 0 }, // guide button
2782 + { AU1000_GPIO_17, INTC_INT_RISE_EDGE, 0 }, // down button
2783 + { AU1000_GPIO_19, INTC_INT_RISE_EDGE, 0 }, // left button
2784 + { AU1000_GPIO_26, INTC_INT_RISE_EDGE, 0 }, // right button
2785 + { AU1000_GPIO_28, INTC_INT_RISE_EDGE, 0 }, // up button
2786 +};
2787 +
2788 +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
2789 +
2790 --- /dev/null
2791 +++ b/arch/mips/au1000/ficmmp/Makefile
2792 @@ -0,0 +1,25 @@
2793 +#
2794 +# Copyright 2000 MontaVista Software Inc.
2795 +# Author: MontaVista Software, Inc.
2796 +# ppopov@mvista.com or source@mvista.com
2797 +#
2798 +# Makefile for the Alchemy Semiconductor FIC board.
2799 +#
2800 +# Note! Dependencies are done automagically by 'make dep', which also
2801 +# removes any old dependencies. DON'T put your own dependencies here
2802 +# unless it's something special (ie not a .c file).
2803 +#
2804 +
2805 +USE_STANDARD_AS_RULE := true
2806 +
2807 +O_TARGET := ficmmp.o
2808 +
2809 +obj-y := init.o board_setup.o irqmap.o au1200_ibutton.o au1xxx_dock.o
2810 +
2811 +ifdef CONFIG_MMC
2812 +obj-y += mmc_support.o
2813 +export-objs +=mmc_support.o
2814 +endif
2815 +
2816 +
2817 +include $(TOPDIR)/Rules.make
2818 --- a/arch/mips/au1000/hydrogen3/board_setup.c
2819 +++ b/arch/mips/au1000/hydrogen3/board_setup.c
2820 @@ -51,12 +51,19 @@ void board_reset (void)
2821 {
2822 }
2823
2824 +void board_power_off (void)
2825 +{
2826 +}
2827 +
2828 void __init board_setup(void)
2829 {
2830 u32 pin_func;
2831
2832 rtc_ops = &no_rtc_ops;
2833
2834 + /* Set GPIO14 high to make CD/DAT1 high for MMC to work */
2835 + au_writel(1<<14, SYS_OUTPUTSET);
2836 +
2837 #ifdef CONFIG_AU1X00_USB_DEVICE
2838 // 2nd USB port is USB device
2839 pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
2840 --- /dev/null
2841 +++ b/arch/mips/au1000/hydrogen3/buttons.c
2842 @@ -0,0 +1,308 @@
2843 +/*
2844 + * Copyright (C) 2003 Metrowerks, All Rights Reserved.
2845 + *
2846 + * This program is free software; you can redistribute it and/or modify
2847 + * it under the terms of the GNU General Public License version 2 as
2848 + * published by the Free Software Foundation.
2849 + */
2850 +
2851 +#include <linux/config.h>
2852 +#include <linux/module.h>
2853 +#include <linux/init.h>
2854 +#include <linux/fs.h>
2855 +#include <linux/sched.h>
2856 +#include <linux/miscdevice.h>
2857 +#include <linux/errno.h>
2858 +#include <linux/poll.h>
2859 +#include <asm/au1000.h>
2860 +#include <asm/uaccess.h>
2861 +
2862 +#define BUTTON_SELECT (1<<1)
2863 +#define BUTTON_1 (1<<2)
2864 +#define BUTTON_2 (1<<3)
2865 +#define BUTTON_ONOFF (1<<6)
2866 +#define BUTTON_3 (1<<7)
2867 +#define BUTTON_4 (1<<8)
2868 +#define BUTTON_LEFT (1<<9)
2869 +#define BUTTON_DOWN (1<<10)
2870 +#define BUTTON_RIGHT (1<<11)
2871 +#define BUTTON_UP (1<<12)
2872 +
2873 +#define BUTTON_MASK (\
2874 + BUTTON_SELECT \
2875 + | BUTTON_1 \
2876 + | BUTTON_2 \
2877 + | BUTTON_ONOFF \
2878 + | BUTTON_3 \
2879 + | BUTTON_4 \
2880 + | BUTTON_LEFT \
2881 + | BUTTON_DOWN \
2882 + | BUTTON_RIGHT \
2883 + | BUTTON_UP \
2884 + )
2885 +
2886 +#define BUTTON_INVERT (\
2887 + BUTTON_SELECT \
2888 + | BUTTON_1 \
2889 + | BUTTON_2 \
2890 + | BUTTON_3 \
2891 + | BUTTON_4 \
2892 + | BUTTON_LEFT \
2893 + | BUTTON_DOWN \
2894 + | BUTTON_RIGHT \
2895 + | BUTTON_UP \
2896 + )
2897 +
2898 +
2899 +
2900 +#define MAKE_FLAG 0x20
2901 +
2902 +#undef DEBUG
2903 +
2904 +#define DEBUG 0
2905 +//#define DEBUG 1
2906 +
2907 +#if DEBUG
2908 +#define DPRINTK(format, args...) printk(__FUNCTION__ ": " format, ## args)
2909 +#else
2910 +#define DPRINTK(format, args...) do { } while (0)
2911 +#endif
2912 +
2913 +/* Please note that this driver is based on a timer and is not interrupt
2914 + * driven. If you are going to make use of this driver, you will need to have
2915 + * your application open the buttons listing from the /dev directory first.
2916 + */
2917 +
2918 +struct hydrogen3_buttons {
2919 + struct fasync_struct *fasync;
2920 + wait_queue_head_t read_wait;
2921 + int open_count;
2922 + unsigned int debounce;
2923 + unsigned int current;
2924 + unsigned int last;
2925 +};
2926 +
2927 +static struct hydrogen3_buttons buttons_info;
2928 +
2929 +
2930 +static void button_timer_periodic(void *data);
2931 +
2932 +static struct tq_struct button_task = {
2933 + routine: button_timer_periodic,
2934 + data: NULL
2935 +};
2936 +
2937 +static int cleanup_flag = 0;
2938 +static DECLARE_WAIT_QUEUE_HEAD(cleanup_wait_queue);
2939 +
2940 +
2941 +static unsigned int read_button_state(void)
2942 +{
2943 + unsigned long state;
2944 +
2945 + state = inl(SYS_PINSTATERD) & BUTTON_MASK;
2946 + state ^= BUTTON_INVERT;
2947 +
2948 + DPRINTK( "Current Button State: %d\n", state );
2949 +
2950 + return state;
2951 +}
2952 +
2953 +
2954 +static void button_timer_periodic(void *data)
2955 +{
2956 + struct hydrogen3_buttons *buttons = (struct hydrogen3_buttons *)data;
2957 + unsigned long button_state;
2958 +
2959 + // If cleanup wants us to die
2960 + if (cleanup_flag) {
2961 + wake_up(&cleanup_wait_queue); // now cleanup_module can return
2962 + } else {
2963 + queue_task(&button_task, &tq_timer); // put ourselves back in the task queue
2964 + }
2965 +
2966 + // read current buttons
2967 + button_state = read_button_state();
2968 +
2969 + // if no buttons are down and nothing to do then
2970 + // save time and be done.
2971 + if ((button_state == 0) && (buttons->current == 0)) {
2972 + return;
2973 + }
2974 +
2975 + if (button_state == buttons->debounce) {
2976 + buttons->current = button_state;
2977 + } else {
2978 + buttons->debounce = button_state;
2979 + }
2980 +// printk("0x%04x\n", button_state);
2981 + if (buttons->current != buttons->last) {
2982 + if (waitqueue_active(&buttons->read_wait)) {
2983 + wake_up_interruptible(&buttons->read_wait);
2984 + }
2985 + }
2986 +}
2987 +
2988 +
2989 +static ssize_t hydrogen3_buttons_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
2990 +{
2991 + struct hydrogen3_buttons *buttons = filp->private_data;
2992 + char events[16];
2993 + int index;
2994 + int last;
2995 + int cur;
2996 + int bit;
2997 + int bit_mask;
2998 + int err;
2999 +
3000 + DPRINTK("start\n");
3001 +
3002 +try_again:
3003 +
3004 + while (buttons->current == buttons->last) {
3005 + if (filp->f_flags & O_NONBLOCK) {
3006 + return -EAGAIN;
3007 + }
3008 + interruptible_sleep_on(&buttons->read_wait);
3009 + if (signal_pending(current)) {
3010 + return -ERESTARTSYS;
3011 + }
3012 + }
3013 +
3014 + cur = buttons->current;
3015 + last = buttons->last;
3016 +
3017 + index = 0;
3018 + bit_mask = 1;
3019 + for (bit = 0; (bit < 16) && count; bit++) {
3020 + if ((cur ^ last) & bit_mask) {
3021 + if (cur & bit_mask) {
3022 + events[index] = (bit | MAKE_FLAG) + 'A';
3023 + last |= bit_mask;
3024 + } else {
3025 + events[index] = bit + 'A';
3026 + last &= ~bit_mask;
3027 + }
3028 + index++;
3029 + count--;
3030 + }
3031 + bit_mask <<= 1;
3032 + }
3033 + buttons->last = last;
3034 +
3035 + if (index == 0) {
3036 + goto try_again;
3037 + }
3038 +
3039 + err = copy_to_user(buffer, events, index);
3040 + if (err) {
3041 + return err;
3042 + }
3043 +
3044 + return index;
3045 +}
3046 +
3047 +
3048 +static int hydrogen3_buttons_open(struct inode *inode, struct file *filp)
3049 +{
3050 + struct hydrogen3_buttons *buttons = &buttons_info;
3051 +
3052 + DPRINTK("start\n");
3053 + MOD_INC_USE_COUNT;
3054 +
3055 + filp->private_data = buttons;
3056 +
3057 + if (buttons->open_count++ == 0) {
3058 + button_task.data = buttons;
3059 + cleanup_flag = 0;
3060 + queue_task(&button_task, &tq_timer);
3061 + }
3062 +
3063 + return 0;
3064 +}
3065 +
3066 +
3067 +static unsigned int hydrogen3_buttons_poll(struct file *filp, poll_table *wait)
3068 +{
3069 + struct hydrogen3_buttons *buttons = filp->private_data;
3070 + int ret = 0;
3071 +
3072 + DPRINTK("start\n");
3073 + poll_wait(filp, &buttons->read_wait, wait);
3074 + if (buttons->current != buttons->last) {
3075 + ret = POLLIN | POLLRDNORM;
3076 + }
3077 + return ret;
3078 +}
3079 +
3080 +
3081 +static int hydrogen3_buttons_release(struct inode *inode, struct file *filp)
3082 +{
3083 + struct hydrogen3_buttons *buttons = filp->private_data;
3084 +
3085 + DPRINTK("start\n");
3086 +
3087 + if (--buttons->open_count == 0) {
3088 + cleanup_flag = 1;
3089 + sleep_on(&cleanup_wait_queue);
3090 + }
3091 + MOD_DEC_USE_COUNT;
3092 +
3093 + return 0;
3094 +}
3095 +
3096 +
3097 +
3098 +static struct file_operations hydrogen3_buttons_fops = {
3099 + owner: THIS_MODULE,
3100 + read: hydrogen3_buttons_read,
3101 + poll: hydrogen3_buttons_poll,
3102 + open: hydrogen3_buttons_open,
3103 + release: hydrogen3_buttons_release,
3104 +};
3105 +
3106 +/*
3107 + * The hydrogen3 buttons is a misc device:
3108 + * Major 10 char
3109 + * Minor 22 /dev/buttons
3110 + *
3111 + * This is /dev/misc/buttons if devfs is used.
3112 + */
3113 +
3114 +static struct miscdevice hydrogen3_buttons_dev = {
3115 + minor: 22,
3116 + name: "buttons",
3117 + fops: &hydrogen3_buttons_fops,
3118 +};
3119 +
3120 +static int __init hydrogen3_buttons_init(void)
3121 +{
3122 + struct hydrogen3_buttons *buttons = &buttons_info;
3123 + int ret;
3124 +
3125 + DPRINTK("Initializing buttons driver\n");
3126 + buttons->open_count = 0;
3127 + cleanup_flag = 0;
3128 + init_waitqueue_head(&buttons->read_wait);
3129 +
3130 +
3131 + // yamon configures GPIO pins for the buttons
3132 + // no initialization needed
3133 +
3134 + ret = misc_register(&hydrogen3_buttons_dev);
3135 +
3136 + DPRINTK("Buttons driver fully initialized.\n");
3137 +
3138 + return ret;
3139 +}
3140 +
3141 +
3142 +static void __exit hydrogen3_buttons_exit(void)
3143 +{
3144 + DPRINTK("unloading buttons driver\n");
3145 + misc_deregister(&hydrogen3_buttons_dev);
3146 +}
3147 +
3148 +
3149 +module_init(hydrogen3_buttons_init);
3150 +module_exit(hydrogen3_buttons_exit);
3151 --- a/arch/mips/au1000/hydrogen3/Makefile
3152 +++ b/arch/mips/au1000/hydrogen3/Makefile
3153 @@ -14,6 +14,11 @@ USE_STANDARD_AS_RULE := true
3154
3155 O_TARGET := hydrogen3.o
3156
3157 -obj-y := init.o board_setup.o irqmap.o
3158 +obj-y := init.o board_setup.o irqmap.o buttons.o
3159 +
3160 +ifdef CONFIG_MMC
3161 +obj-y += mmc_support.o
3162 +export-objs +=mmc_support.o
3163 +endif
3164
3165 include $(TOPDIR)/Rules.make
3166 --- /dev/null
3167 +++ b/arch/mips/au1000/hydrogen3/mmc_support.c
3168 @@ -0,0 +1,89 @@
3169 +/*
3170 + * BRIEF MODULE DESCRIPTION
3171 + *
3172 + * MMC support routines for Hydrogen3.
3173 + *
3174 + *
3175 + * Copyright (c) 2003-2004 Embedded Edge, LLC.
3176 + * Author: Embedded Edge, LLC.
3177 + * Contact: dan@embeddededge.com
3178 + *
3179 + * This program is free software; you can redistribute it and/or modify it
3180 + * under the terms of the GNU General Public License as published by the
3181 + * Free Software Foundation; either version 2 of the License, or (at your
3182 + * option) any later version.
3183 + *
3184 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3185 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3186 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
3187 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3188 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3189 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3190 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3191 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3192 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3193 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3194 + *
3195 + * You should have received a copy of the GNU General Public License along
3196 + * with this program; if not, write to the Free Software Foundation, Inc.,
3197 + * 675 Mass Ave, Cambridge, MA 02139, USA.
3198 + *
3199 + */
3200 +
3201 +
3202 +#include <linux/config.h>
3203 +#include <linux/kernel.h>
3204 +#include <linux/module.h>
3205 +#include <linux/init.h>
3206 +
3207 +#include <asm/irq.h>
3208 +#include <asm/au1000.h>
3209 +#include <asm/au1100_mmc.h>
3210 +
3211 +#define GPIO_17_WP 0x20000
3212 +
3213 +/* SD/MMC controller support functions */
3214 +
3215 +/*
3216 + * Detect card.
3217 + */
3218 +void mmc_card_inserted(int _n_, int *_res_)
3219 +{
3220 + u32 gpios = au_readl(SYS_PINSTATERD);
3221 + u32 emptybit = (1<<16);
3222 + *_res_ = ((gpios & emptybit) == 0);
3223 +}
3224 +
3225 +/*
3226 + * Check card write protection.
3227 + */
3228 +void mmc_card_writable(int _n_, int *_res_)
3229 +{
3230 + unsigned long mmc_wp, board_specific;
3231 + board_specific = au_readl(SYS_OUTPUTSET);
3232 + mmc_wp=GPIO_17_WP;
3233 + if (!(board_specific & mmc_wp)) {/* low means card writable */
3234 + *_res_ = 1;
3235 + } else {
3236 + *_res_ = 0;
3237 + }
3238 +}
3239 +/*
3240 + * Apply power to card slot.
3241 + */
3242 +void mmc_power_on(int _n_)
3243 +{
3244 +}
3245 +
3246 +/*
3247 + * Remove power from card slot.
3248 + */
3249 +void mmc_power_off(int _n_)
3250 +{
3251 +}
3252 +
3253 +EXPORT_SYMBOL(mmc_card_inserted);
3254 +EXPORT_SYMBOL(mmc_card_writable);
3255 +EXPORT_SYMBOL(mmc_power_on);
3256 +EXPORT_SYMBOL(mmc_power_off);
3257 +
3258 --- a/arch/mips/au1000/mtx-1/board_setup.c
3259 +++ b/arch/mips/au1000/mtx-1/board_setup.c
3260 @@ -48,6 +48,12 @@
3261
3262 extern struct rtc_ops no_rtc_ops;
3263
3264 +void board_reset (void)
3265 +{
3266 + /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
3267 + au_writel(0x00000000, 0xAE00001C);
3268 +}
3269 +
3270 void __init board_setup(void)
3271 {
3272 rtc_ops = &no_rtc_ops;
3273 --- a/arch/mips/au1000/mtx-1/irqmap.c
3274 +++ b/arch/mips/au1000/mtx-1/irqmap.c
3275 @@ -72,10 +72,10 @@ au1xxx_pci_irqmap(struct pci_dev *dev, u
3276 * A B C D
3277 */
3278 {
3279 - {INTA, INTB, INTC, INTD}, /* IDSEL 0 */
3280 - {INTA, INTB, INTC, INTD}, /* IDSEL 1 */
3281 - {INTA, INTB, INTC, INTD}, /* IDSEL 2 */
3282 - {INTA, INTB, INTC, INTD}, /* IDSEL 3 */
3283 + {INTA, INTB, INTX, INTX}, /* IDSEL 0 */
3284 + {INTB, INTA, INTX, INTX}, /* IDSEL 1 */
3285 + {INTC, INTD, INTX, INTX}, /* IDSEL 2 */
3286 + {INTD, INTC, INTX, INTX}, /* IDSEL 3 */
3287 };
3288 const long min_idsel = 0, max_idsel = 3, irqs_per_slot = 4;
3289 return PCI_IRQ_TABLE_LOOKUP;
3290 --- a/arch/mips/au1000/pb1000/board_setup.c
3291 +++ b/arch/mips/au1000/pb1000/board_setup.c
3292 @@ -58,6 +58,10 @@ void board_reset (void)
3293 {
3294 }
3295
3296 +void board_power_off (void)
3297 +{
3298 +}
3299 +
3300 void __init board_setup(void)
3301 {
3302 u32 pin_func, static_cfg0;
3303 --- a/arch/mips/au1000/pb1100/board_setup.c
3304 +++ b/arch/mips/au1000/pb1100/board_setup.c
3305 @@ -62,6 +62,10 @@ void board_reset (void)
3306 au_writel(0x00000000, 0xAE00001C);
3307 }
3308
3309 +void board_power_off (void)
3310 +{
3311 +}
3312 +
3313 void __init board_setup(void)
3314 {
3315 u32 pin_func;
3316 --- a/arch/mips/au1000/pb1100/Makefile
3317 +++ b/arch/mips/au1000/pb1100/Makefile
3318 @@ -16,4 +16,10 @@ O_TARGET := pb1100.o
3319
3320 obj-y := init.o board_setup.o irqmap.o
3321
3322 +
3323 +ifdef CONFIG_MMC
3324 +obj-y += mmc_support.o
3325 +export-objs += mmc_support.o
3326 +endif
3327 +
3328 include $(TOPDIR)/Rules.make
3329 --- /dev/null
3330 +++ b/arch/mips/au1000/pb1100/mmc_support.c
3331 @@ -0,0 +1,126 @@
3332 +/*
3333 + * BRIEF MODULE DESCRIPTION
3334 + *
3335 + * MMC support routines for PB1100.
3336 + *
3337 + *
3338 + * Copyright (c) 2003-2004 Embedded Edge, LLC.
3339 + * Author: Embedded Edge, LLC.
3340 + * Contact: dan@embeddededge.com
3341 + *
3342 + * This program is free software; you can redistribute it and/or modify it
3343 + * under the terms of the GNU General Public License as published by the
3344 + * Free Software Foundation; either version 2 of the License, or (at your
3345 + * option) any later version.
3346 + *
3347 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3348 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3349 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
3350 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3351 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3352 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3353 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3354 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3355 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3356 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3357 + *
3358 + * You should have received a copy of the GNU General Public License along
3359 + * with this program; if not, write to the Free Software Foundation, Inc.,
3360 + * 675 Mass Ave, Cambridge, MA 02139, USA.
3361 + *
3362 + */
3363 +
3364 +
3365 +#include <linux/config.h>
3366 +#include <linux/kernel.h>
3367 +#include <linux/module.h>
3368 +#include <linux/init.h>
3369 +
3370 +#include <asm/irq.h>
3371 +#include <asm/au1000.h>
3372 +#include <asm/au1100_mmc.h>
3373 +#include <asm/pb1100.h>
3374 +
3375 +
3376 +/* SD/MMC controller support functions */
3377 +
3378 +/*
3379 + * Detect card.
3380 + */
3381 +void mmc_card_inserted(int _n_, int *_res_)
3382 +{
3383 + u32 gpios = au_readl(SYS_PINSTATERD);
3384 + u32 emptybit = (_n_) ? (1<<15) : (1<<14);
3385 + *_res_ = ((gpios & emptybit) == 0);
3386 +}
3387 +
3388 +/*
3389 + * Check card write protection.
3390 + */
3391 +void mmc_card_writable(int _n_, int *_res_)
3392 +{
3393 + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
3394 + unsigned long mmc_wp, board_specific;
3395 +
3396 + if (_n_) {
3397 + mmc_wp = BCSR_PCMCIA_SD1_WP;
3398 + } else {
3399 + mmc_wp = BCSR_PCMCIA_SD0_WP;
3400 + }
3401 +
3402 + board_specific = au_readl((unsigned long)(&bcsr->pcmcia));
3403 +
3404 + if (!(board_specific & mmc_wp)) {/* low means card writable */
3405 + *_res_ = 1;
3406 + } else {
3407 + *_res_ = 0;
3408 + }
3409 +}
3410 +
3411 +/*
3412 + * Apply power to card slot.
3413 + */
3414 +void mmc_power_on(int _n_)
3415 +{
3416 + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
3417 + unsigned long mmc_pwr, board_specific;
3418 +
3419 + if (_n_) {
3420 + mmc_pwr = BCSR_PCMCIA_SD1_PWR;
3421 + } else {
3422 + mmc_pwr = BCSR_PCMCIA_SD0_PWR;
3423 + }
3424 +
3425 + board_specific = au_readl((unsigned long)(&bcsr->pcmcia));
3426 + board_specific |= mmc_pwr;
3427 +
3428 + au_writel(board_specific, (int)(&bcsr->pcmcia));
3429 + au_sync_delay(1);
3430 +}
3431 +
3432 +/*
3433 + * Remove power from card slot.
3434 + */
3435 +void mmc_power_off(int _n_)
3436 +{
3437 + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
3438 + unsigned long mmc_pwr, board_specific;
3439 +
3440 + if (_n_) {
3441 + mmc_pwr = BCSR_PCMCIA_SD1_PWR;
3442 + } else {
3443 + mmc_pwr = BCSR_PCMCIA_SD0_PWR;
3444 + }
3445 +
3446 + board_specific = au_readl((unsigned long)(&bcsr->pcmcia));
3447 + board_specific &= ~mmc_pwr;
3448 +
3449 + au_writel(board_specific, (int)(&bcsr->pcmcia));
3450 + au_sync_delay(1);
3451 +}
3452 +
3453 +EXPORT_SYMBOL(mmc_card_inserted);
3454 +EXPORT_SYMBOL(mmc_card_writable);
3455 +EXPORT_SYMBOL(mmc_power_on);
3456 +EXPORT_SYMBOL(mmc_power_off);
3457 +
3458 --- /dev/null
3459 +++ b/arch/mips/au1000/pb1200/board_setup.c
3460 @@ -0,0 +1,221 @@
3461 +/*
3462 + *
3463 + * BRIEF MODULE DESCRIPTION
3464 + * Alchemy Pb1200 board setup.
3465 + *
3466 + * This program is free software; you can redistribute it and/or modify it
3467 + * under the terms of the GNU General Public License as published by the
3468 + * Free Software Foundation; either version 2 of the License, or (at your
3469 + * option) any later version.
3470 + *
3471 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3472 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3473 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
3474 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3475 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3476 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3477 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3478 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3479 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3480 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3481 + *
3482 + * You should have received a copy of the GNU General Public License along
3483 + * with this program; if not, write to the Free Software Foundation, Inc.,
3484 + * 675 Mass Ave, Cambridge, MA 02139, USA.
3485 + */
3486 +#include <linux/config.h>
3487 +#include <linux/init.h>
3488 +#include <linux/sched.h>
3489 +#include <linux/ioport.h>
3490 +#include <linux/mm.h>
3491 +#include <linux/console.h>
3492 +#include <linux/mc146818rtc.h>
3493 +#include <linux/delay.h>
3494 +
3495 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
3496 +#include <linux/ide.h>
3497 +#endif
3498 +
3499 +#include <asm/cpu.h>
3500 +#include <asm/bootinfo.h>
3501 +#include <asm/irq.h>
3502 +#include <asm/keyboard.h>
3503 +#include <asm/mipsregs.h>
3504 +#include <asm/reboot.h>
3505 +#include <asm/pgtable.h>
3506 +#include <asm/au1000.h>
3507 +#include <asm/au1xxx_dbdma.h>
3508 +
3509 +#ifdef CONFIG_MIPS_PB1200
3510 +#include <asm/pb1200.h>
3511 +#endif
3512 +
3513 +#ifdef CONFIG_MIPS_DB1200
3514 +#include <asm/db1200.h>
3515 +#define PB1200_ETH_INT DB1200_ETH_INT
3516 +#define PB1200_IDE_INT DB1200_IDE_INT
3517 +#endif
3518 +
3519 +extern struct rtc_ops no_rtc_ops;
3520 +
3521 +extern void _board_init_irq(void);
3522 +extern void (*board_init_irq)(void);
3523 +
3524 +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX
3525 +extern struct ide_ops *ide_ops;
3526 +extern struct ide_ops au1xxx_ide_ops;
3527 +extern u32 au1xxx_ide_virtbase;
3528 +extern u64 au1xxx_ide_physbase;
3529 +extern int au1xxx_ide_irq;
3530 +
3531 +u32 led_base_addr;
3532 +/* Ddma */
3533 +chan_tab_t *ide_read_ch, *ide_write_ch;
3534 +u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
3535 +
3536 +dbdev_tab_t new_dbdev_tab_element = { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 };
3537 +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
3538 +
3539 +void board_reset (void)
3540 +{
3541 + bcsr->resets = 0;
3542 +}
3543 +
3544 +void board_power_off (void)
3545 +{
3546 + bcsr->resets = 0xC000;
3547 +}
3548 +
3549 +void __init board_setup(void)
3550 +{
3551 + char *argptr = NULL;
3552 + u32 pin_func;
3553 + rtc_ops = &no_rtc_ops;
3554 +
3555 +#if 0
3556 + /* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
3557 + * but it is board specific code, so put it here.
3558 + */
3559 + pin_func = au_readl(SYS_PINFUNC);
3560 + au_sync();
3561 + pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1;
3562 + au_writel(pin_func, SYS_PINFUNC);
3563 +
3564 + au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
3565 + au_sync();
3566 +#endif
3567 +
3568 +#if defined( CONFIG_I2C_ALGO_AU1550 )
3569 + {
3570 + u32 freq0, clksrc;
3571 +
3572 + /* Select SMBUS in CPLD */
3573 + bcsr->resets &= ~(BCSR_RESETS_PCS0MUX);
3574 +
3575 + pin_func = au_readl(SYS_PINFUNC);
3576 + au_sync();
3577 + pin_func &= ~(3<<17 | 1<<4);
3578 + /* Set GPIOs correctly */
3579 + pin_func |= 2<<17;
3580 + au_writel(pin_func, SYS_PINFUNC);
3581 + au_sync();
3582 +
3583 + /* The i2c driver depends on 50Mhz clock */
3584 + freq0 = au_readl(SYS_FREQCTRL0);
3585 + au_sync();
3586 + freq0 &= ~(SYS_FC_FRDIV1_MASK | SYS_FC_FS1 | SYS_FC_FE1);
3587 + freq0 |= (3<<SYS_FC_FRDIV1_BIT);
3588 + /* 396Mhz / (3+1)*2 == 49.5Mhz */
3589 + au_writel(freq0, SYS_FREQCTRL0);
3590 + au_sync();
3591 + freq0 |= SYS_FC_FE1;
3592 + au_writel(freq0, SYS_FREQCTRL0);
3593 + au_sync();
3594 +
3595 + clksrc = au_readl(SYS_CLKSRC);
3596 + au_sync();
3597 + clksrc &= ~0x01f00000;
3598 + /* bit 22 is EXTCLK0 for PSC0 */
3599 + clksrc |= (0x3 << 22);
3600 + au_writel(clksrc, SYS_CLKSRC);
3601 + au_sync();
3602 + }
3603 +#endif
3604 +
3605 +#ifdef CONFIG_FB_AU1200
3606 + argptr = prom_getcmdline();
3607 + strcat(argptr, " video=au1200fb:");
3608 +#endif
3609 +
3610 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
3611 + /*
3612 + * Iniz IDE parameters
3613 + */
3614 + ide_ops = &au1xxx_ide_ops;
3615 + au1xxx_ide_irq = PB1200_IDE_INT;
3616 + au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
3617 + au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
3618 + /*
3619 + * change PIO or PIO+Ddma
3620 + * check the GPIO-5 pin condition. pb1200:s18_dot */
3621 + switch4ddma = (au_readl(SYS_PINSTATERD) & (1 << 5)) ? 1 : 0;
3622 +#endif
3623 +
3624 + /* The Pb1200 development board uses external MUX for PSC0 to
3625 + support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
3626 + */
3627 +#if defined(CONFIG_AU1550_PSC_SPI) && defined(CONFIG_I2C_ALGO_AU1550)
3628 + #error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
3629 + Refer to Pb1200/Db1200 documentation.
3630 +#elif defined( CONFIG_AU1550_PSC_SPI )
3631 + bcsr->resets |= BCSR_RESETS_PCS0MUX;
3632 +#elif defined( CONFIG_I2C_ALGO_AU1550 )
3633 + bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
3634 +#endif
3635 + au_sync();
3636 +
3637 +#ifdef CONFIG_MIPS_PB1200
3638 + printk("AMD Alchemy Pb1200 Board\n");
3639 +#endif
3640 +#ifdef CONFIG_MIPS_DB1200
3641 + printk("AMD Alchemy Db1200 Board\n");
3642 +#endif
3643 +
3644 + /* Setup Pb1200 External Interrupt Controller */
3645 + {
3646 + extern void (*board_init_irq)(void);
3647 + extern void _board_init_irq(void);
3648 + board_init_irq = _board_init_irq;
3649 + }
3650 +}
3651 +
3652 +int
3653 +board_au1200fb_panel (void)
3654 +{
3655 + BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
3656 + int p;
3657 +
3658 + p = bcsr->switches;
3659 + p >>= 8;
3660 + p &= 0x0F;
3661 + return p;
3662 +}
3663 +
3664 +int
3665 +board_au1200fb_panel_init (void)
3666 +{
3667 + /* Apply power */
3668 + BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
3669 + bcsr->board |= (BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL);
3670 + return 0;
3671 +}
3672 +
3673 +int
3674 +board_au1200fb_panel_shutdown (void)
3675 +{
3676 + /* Remove power */
3677 + BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;
3678 + bcsr->board &= ~(BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD | BCSR_BOARD_LCDBL);
3679 + return 0;
3680 +}
3681 +
3682 --- /dev/null
3683 +++ b/arch/mips/au1000/pb1200/init.c
3684 @@ -0,0 +1,72 @@
3685 +/*
3686 + *
3687 + * BRIEF MODULE DESCRIPTION
3688 + * PB1200 board setup
3689 + *
3690 + * This program is free software; you can redistribute it and/or modify it
3691 + * under the terms of the GNU General Public License as published by the
3692 + * Free Software Foundation; either version 2 of the License, or (at your
3693 + * option) any later version.
3694 + *
3695 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3696 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3697 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
3698 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3699 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3700 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3701 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3702 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3703 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3704 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3705 + *
3706 + * You should have received a copy of the GNU General Public License along
3707 + * with this program; if not, write to the Free Software Foundation, Inc.,
3708 + * 675 Mass Ave, Cambridge, MA 02139, USA.
3709 + */
3710 +
3711 +#include <linux/init.h>
3712 +#include <linux/mm.h>
3713 +#include <linux/sched.h>
3714 +#include <linux/bootmem.h>
3715 +#include <asm/addrspace.h>
3716 +#include <asm/bootinfo.h>
3717 +#include <linux/config.h>
3718 +#include <linux/string.h>
3719 +#include <linux/kernel.h>
3720 +#include <linux/sched.h>
3721 +
3722 +int prom_argc;
3723 +char **prom_argv, **prom_envp;
3724 +extern void __init prom_init_cmdline(void);
3725 +extern char *prom_getenv(char *envname);
3726 +
3727 +const char *get_system_type(void)
3728 +{
3729 + return "AMD Alchemy Au1200/Pb1200";
3730 +}
3731 +
3732 +u32 mae_memsize = 0;
3733 +
3734 +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
3735 +{
3736 + unsigned char *memsize_str;
3737 + unsigned long memsize;
3738 +
3739 + prom_argc = argc;
3740 + prom_argv = argv;
3741 + prom_envp = envp;
3742 +
3743 + mips_machgroup = MACH_GROUP_ALCHEMY;
3744 + mips_machtype = MACH_PB1000; /* set the platform # */
3745 + prom_init_cmdline();
3746 +
3747 + memsize_str = prom_getenv("memsize");
3748 + if (!memsize_str) {
3749 + memsize = 0x08000000;
3750 + } else {
3751 + memsize = simple_strtol(memsize_str, NULL, 0);
3752 + }
3753 + add_memory_region(0, memsize, BOOT_MEM_RAM);
3754 + return 0;
3755 +}
3756 +
3757 --- /dev/null
3758 +++ b/arch/mips/au1000/pb1200/irqmap.c
3759 @@ -0,0 +1,180 @@
3760 +/*
3761 + * BRIEF MODULE DESCRIPTION
3762 + * Au1xxx irq map table
3763 + *
3764 + * This program is free software; you can redistribute it and/or modify it
3765 + * under the terms of the GNU General Public License as published by the
3766 + * Free Software Foundation; either version 2 of the License, or (at your
3767 + * option) any later version.
3768 + *
3769 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3770 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3771 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
3772 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3773 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3774 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3775 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3776 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3777 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3778 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3779 + *
3780 + * You should have received a copy of the GNU General Public License along
3781 + * with this program; if not, write to the Free Software Foundation, Inc.,
3782 + * 675 Mass Ave, Cambridge, MA 02139, USA.
3783 + */
3784 +#include <linux/errno.h>
3785 +#include <linux/init.h>
3786 +#include <linux/irq.h>
3787 +#include <linux/kernel_stat.h>
3788 +#include <linux/module.h>
3789 +#include <linux/signal.h>
3790 +#include <linux/sched.h>
3791 +#include <linux/types.h>
3792 +#include <linux/interrupt.h>
3793 +#include <linux/ioport.h>
3794 +#include <linux/timex.h>
3795 +#include <linux/slab.h>
3796 +#include <linux/random.h>
3797 +#include <linux/delay.h>
3798 +
3799 +#include <asm/bitops.h>
3800 +#include <asm/bootinfo.h>
3801 +#include <asm/io.h>
3802 +#include <asm/mipsregs.h>
3803 +#include <asm/system.h>
3804 +#include <asm/au1000.h>
3805 +
3806 +#ifdef CONFIG_MIPS_PB1200
3807 +#include <asm/pb1200.h>
3808 +#endif
3809 +
3810 +#ifdef CONFIG_MIPS_DB1200
3811 +#include <asm/db1200.h>
3812 +#define PB1200_INT_BEGIN DB1200_INT_BEGIN
3813 +#define PB1200_INT_END DB1200_INT_END
3814 +#endif
3815 +
3816 +au1xxx_irq_map_t au1xxx_irq_map[] = {
3817 + { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade
3818 +};
3819 +
3820 +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
3821 +
3822 +/*
3823 + * Support for External interrupts on the PbAu1200 Development platform.
3824 + */
3825 +static volatile int pb1200_cascade_en=0;
3826 +
3827 +void pb1200_cascade_handler( int irq, void *dev_id, struct pt_regs *regs)
3828 +{
3829 + unsigned short bisr = bcsr->int_status;
3830 + int extirq_nr = 0;
3831 +
3832 + /* Clear all the edge interrupts. This has no effect on level */
3833 + bcsr->int_status = bisr;
3834 + for( ; bisr; bisr &= (bisr-1) )
3835 + {
3836 + extirq_nr = (PB1200_INT_BEGIN-1) + au_ffs(bisr);
3837 + /* Ack and dispatch IRQ */
3838 + do_IRQ(extirq_nr,regs);
3839 + }
3840 +}
3841 +
3842 +inline void pb1200_enable_irq(unsigned int irq_nr)
3843 +{
3844 + bcsr->intset_mask = 1<<(irq_nr - PB1200_INT_BEGIN);
3845 + bcsr->intset = 1<<(irq_nr - PB1200_INT_BEGIN);
3846 +}
3847 +
3848 +inline void pb1200_disable_irq(unsigned int irq_nr)
3849 +{
3850 + bcsr->intclr_mask = 1<<(irq_nr - PB1200_INT_BEGIN);
3851 + bcsr->intclr = 1<<(irq_nr - PB1200_INT_BEGIN);
3852 +}
3853 +
3854 +static unsigned int pb1200_startup_irq( unsigned int irq_nr )
3855 +{
3856 + if (++pb1200_cascade_en == 1)
3857 + {
3858 + request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
3859 + 0, "Pb1200 Cascade", &pb1200_cascade_handler );
3860 +#ifdef CONFIG_MIPS_PB1200
3861 + /* We have a problem with CPLD rev3. Enable a workaround */
3862 + if( ((bcsr->whoami & BCSR_WHOAMI_CPLD)>>4) <= 3)
3863 + {
3864 + printk("\nWARNING!!!\n");
3865 + printk("\nWARNING!!!\n");
3866 + printk("\nWARNING!!!\n");
3867 + printk("\nWARNING!!!\n");
3868 + printk("\nWARNING!!!\n");
3869 + printk("\nWARNING!!!\n");
3870 + printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n");
3871 + printk("updated to latest revision. This software will not\n");
3872 + printk("work on anything less than CPLD rev4\n");
3873 + printk("\nWARNING!!!\n");
3874 + printk("\nWARNING!!!\n");
3875 + printk("\nWARNING!!!\n");
3876 + printk("\nWARNING!!!\n");
3877 + printk("\nWARNING!!!\n");
3878 + printk("\nWARNING!!!\n");
3879 + while(1);
3880 + }
3881 +#endif
3882 + }
3883 + pb1200_enable_irq(irq_nr);
3884 + return 0;
3885 +}
3886 +
3887 +static void pb1200_shutdown_irq( unsigned int irq_nr )
3888 +{
3889 + pb1200_disable_irq(irq_nr);
3890 + if (--pb1200_cascade_en == 0)
3891 + {
3892 + free_irq(AU1000_GPIO_7,&pb1200_cascade_handler );
3893 + }
3894 + return;
3895 +}
3896 +
3897 +static inline void pb1200_mask_and_ack_irq(unsigned int irq_nr)
3898 +{
3899 + pb1200_disable_irq( irq_nr );
3900 +}
3901 +
3902 +static void pb1200_end_irq(unsigned int irq_nr)
3903 +{
3904 + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
3905 + pb1200_enable_irq(irq_nr);
3906 + }
3907 +}
3908 +
3909 +static struct hw_interrupt_type external_irq_type =
3910 +{
3911 +#ifdef CONFIG_MIPS_PB1200
3912 + "Pb1200 Ext",
3913 +#endif
3914 +#ifdef CONFIG_MIPS_DB1200
3915 + "Db1200 Ext",
3916 +#endif
3917 + pb1200_startup_irq,
3918 + pb1200_shutdown_irq,
3919 + pb1200_enable_irq,
3920 + pb1200_disable_irq,
3921 + pb1200_mask_and_ack_irq,
3922 + pb1200_end_irq,
3923 + NULL
3924 +};
3925 +
3926 +void _board_init_irq(void)
3927 +{
3928 + int irq_nr;
3929 +
3930 + for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++)
3931 + {
3932 + irq_desc[irq_nr].handler = &external_irq_type;
3933 + pb1200_disable_irq(irq_nr);
3934 + }
3935 +
3936 + /* GPIO_7 can not be hooked here, so it is hooked upon first
3937 + request of any source attached to the cascade */
3938 +}
3939 +
3940 --- /dev/null
3941 +++ b/arch/mips/au1000/pb1200/Makefile
3942 @@ -0,0 +1,25 @@
3943 +#
3944 +# Copyright 2000 MontaVista Software Inc.
3945 +# Author: MontaVista Software, Inc.
3946 +# ppopov@mvista.com or source@mvista.com
3947 +#
3948 +# Makefile for the Alchemy Semiconductor PB1000 board.
3949 +#
3950 +# Note! Dependencies are done automagically by 'make dep', which also
3951 +# removes any old dependencies. DON'T put your own dependencies here
3952 +# unless it's something special (ie not a .c file).
3953 +#
3954 +
3955 +USE_STANDARD_AS_RULE := true
3956 +
3957 +O_TARGET := pb1200.o
3958 +
3959 +obj-y := init.o board_setup.o irqmap.o
3960 +
3961 +ifdef CONFIG_MMC
3962 +obj-y += mmc_support.o
3963 +export-objs +=mmc_support.o
3964 +endif
3965 +
3966 +
3967 +include $(TOPDIR)/Rules.make
3968 --- /dev/null
3969 +++ b/arch/mips/au1000/pb1200/mmc_support.c
3970 @@ -0,0 +1,141 @@
3971 +/*
3972 + * BRIEF MODULE DESCRIPTION
3973 + *
3974 + * MMC support routines for PB1200.
3975 + *
3976 + *
3977 + * Copyright (c) 2003-2004 Embedded Edge, LLC.
3978 + * Author: Embedded Edge, LLC.
3979 + * Contact: dan@embeddededge.com
3980 + *
3981 + * This program is free software; you can redistribute it and/or modify it
3982 + * under the terms of the GNU General Public License as published by the
3983 + * Free Software Foundation; either version 2 of the License, or (at your
3984 + * option) any later version.
3985 + *
3986 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3987 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3988 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
3989 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3990 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3991 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3992 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
3993 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3994 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3995 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3996 + *
3997 + * You should have received a copy of the GNU General Public License along
3998 + * with this program; if not, write to the Free Software Foundation, Inc.,
3999 + * 675 Mass Ave, Cambridge, MA 02139, USA.
4000 + *
4001 + */
4002 +
4003 +
4004 +#include <linux/config.h>
4005 +#include <linux/kernel.h>
4006 +#include <linux/module.h>
4007 +#include <linux/init.h>
4008 +
4009 +#include <asm/irq.h>
4010 +#include <asm/au1000.h>
4011 +#include <asm/au1100_mmc.h>
4012 +
4013 +#ifdef CONFIG_MIPS_PB1200
4014 +#include <asm/pb1200.h>
4015 +#endif
4016 +
4017 +#ifdef CONFIG_MIPS_DB1200
4018 +/* NOTE: DB1200 only has SD0 pinned out and usable */
4019 +#include <asm/db1200.h>
4020 +#endif
4021 +
4022 +/* SD/MMC controller support functions */
4023 +
4024 +/*
4025 + * Detect card.
4026 + */
4027 +void mmc_card_inserted(int socket, int *result)
4028 +{
4029 + u16 mask;
4030 +
4031 + if (socket)
4032 +#ifdef CONFIG_MIPS_DB1200
4033 + mask = 0;
4034 +#else
4035 + mask = BCSR_INT_SD1INSERT;
4036 +#endif
4037 + else
4038 + mask = BCSR_INT_SD0INSERT;
4039 +
4040 + *result = ((bcsr->sig_status & mask) != 0);
4041 +}
4042 +
4043 +/*
4044 + * Check card write protection.
4045 + */
4046 +void mmc_card_writable(int socket, int *result)
4047 +{
4048 + u16 mask;
4049 +
4050 + if (socket)
4051 +#ifdef CONFIG_MIPS_DB1200
4052 + mask = 0;
4053 +#else
4054 + mask = BCSR_STATUS_SD1WP;
4055 +#endif
4056 + else
4057 + mask = BCSR_STATUS_SD0WP;
4058 +
4059 + /* low means card writable */
4060 + if (!(bcsr->status & mask)) {
4061 + *result = 1;
4062 + } else {
4063 + *result = 0;
4064 + }
4065 +}
4066 +
4067 +/*
4068 + * Apply power to card slot.
4069 + */
4070 +void mmc_power_on(int socket)
4071 +{
4072 + u16 mask;
4073 +
4074 + if (socket)
4075 +#ifdef CONFIG_MIPS_DB1200
4076 + mask = 0;
4077 +#else
4078 + mask = BCSR_BOARD_SD1PWR;
4079 +#endif
4080 + else
4081 + mask = BCSR_BOARD_SD0PWR;
4082 +
4083 + bcsr->board |= mask;
4084 + au_sync_delay(1);
4085 +}
4086 +
4087 +/*
4088 + * Remove power from card slot.
4089 + */
4090 +void mmc_power_off(int socket)
4091 +{
4092 + u16 mask;
4093 +
4094 + if (socket)
4095 +#ifdef CONFIG_MIPS_DB1200
4096 + mask = 0;
4097 +#else
4098 + mask = BCSR_BOARD_SD1PWR;
4099 +#endif
4100 + else
4101 + mask = BCSR_BOARD_SD0PWR;
4102 +
4103 + bcsr->board &= ~mask;
4104 + au_sync_delay(1);
4105 +}
4106 +
4107 +EXPORT_SYMBOL(mmc_card_inserted);
4108 +EXPORT_SYMBOL(mmc_card_writable);
4109 +EXPORT_SYMBOL(mmc_power_on);
4110 +EXPORT_SYMBOL(mmc_power_off);
4111 +
4112 --- a/arch/mips/au1000/pb1500/board_setup.c
4113 +++ b/arch/mips/au1000/pb1500/board_setup.c
4114 @@ -62,6 +62,10 @@ void board_reset (void)
4115 au_writel(0x00000000, 0xAE00001C);
4116 }
4117
4118 +void board_power_off (void)
4119 +{
4120 +}
4121 +
4122 void __init board_setup(void)
4123 {
4124 u32 pin_func;
4125 --- a/arch/mips/au1000/pb1550/board_setup.c
4126 +++ b/arch/mips/au1000/pb1550/board_setup.c
4127 @@ -48,12 +48,31 @@
4128
4129 extern struct rtc_ops no_rtc_ops;
4130
4131 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
4132 +extern struct ide_ops *ide_ops;
4133 +extern struct ide_ops au1xxx_ide_ops;
4134 +extern u32 au1xxx_ide_virtbase;
4135 +extern u64 au1xxx_ide_physbase;
4136 +extern unsigned int au1xxx_ide_irq;
4137 +
4138 +u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma
4139 +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */
4140 +
4141 void board_reset (void)
4142 {
4143 /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
4144 au_writew(au_readw(0xAF00001C) & ~(1<<15), 0xAF00001C);
4145 }
4146
4147 +void board_power_off (void)
4148 +{
4149 + /* power off system */
4150 + printk("\n** Powering off Pb1550\n");
4151 + au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
4152 + au_sync();
4153 + while(1); /* should not get here */
4154 +}
4155 +
4156 void __init board_setup(void)
4157 {
4158 u32 pin_func;
4159 @@ -78,5 +97,36 @@ void __init board_setup(void)
4160 au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
4161 au_sync();
4162
4163 +#if defined(CONFIG_AU1XXX_SMC91111)
4164 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
4165 +#error "Resource conflict occured. Disable either Ethernet or IDE daughter card."
4166 +#else
4167 +#define CPLD_CONTROL (0xAF00000C)
4168 + {
4169 + /* set up the Static Bus timing */
4170 + /* only 396Mhz */
4171 + /* reset the DC */
4172 + au_writew(au_readw(CPLD_CONTROL) | 0x0f, CPLD_CONTROL);
4173 + au_writel(0x00010003, MEM_STCFG0);
4174 + au_writel(0x000c00c0, MEM_STCFG2);
4175 + au_writel(0x85E1900D, MEM_STTIME2);
4176 + }
4177 +#endif
4178 +#endif /* end CONFIG_SMC91111 */
4179 +
4180 +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX)
4181 + /*
4182 + * Iniz IDE parameters
4183 + */
4184 + ide_ops = &au1xxx_ide_ops;
4185 + au1xxx_ide_irq = DAUGHTER_CARD_IRQ;;
4186 + au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR;
4187 + au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR);
4188 + /*
4189 + * change PIO or PIO+Ddma
4190 + * check the GPIO-6 pin condition. pb1550:s15_dot
4191 + */
4192 + switch4ddma = (au_readl(SYS_PINSTATERD) & (1 << 6)) ? 1 : 0;
4193 +#endif
4194 printk("AMD Alchemy Pb1550 Board\n");
4195 }
4196 --- a/arch/mips/au1000/pb1550/irqmap.c
4197 +++ b/arch/mips/au1000/pb1550/irqmap.c
4198 @@ -50,6 +50,9 @@
4199 au1xxx_irq_map_t au1xxx_irq_map[] = {
4200 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
4201 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
4202 +#ifdef CONFIG_AU1XXX_SMC91111
4203 + { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
4204 +#endif
4205 };
4206
4207 int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
4208 --- a/arch/mips/config-shared.in
4209 +++ b/arch/mips/config-shared.in
4210 @@ -21,16 +21,19 @@ mainmenu_option next_comment
4211 comment 'Machine selection'
4212 dep_bool 'Support for Acer PICA 1 chipset (EXPERIMENTAL)' CONFIG_ACER_PICA_61 $CONFIG_EXPERIMENTAL
4213 dep_bool 'Support for Alchemy Bosporus board' CONFIG_MIPS_BOSPORUS $CONFIG_MIPS32
4214 +dep_bool 'Support for FIC Multimedia Player board' CONFIG_MIPS_FICMMP $CONFIG_MIPS32
4215 dep_bool 'Support for Alchemy Mirage board' CONFIG_MIPS_MIRAGE $CONFIG_MIPS32
4216 dep_bool 'Support for Alchemy Db1000 board' CONFIG_MIPS_DB1000 $CONFIG_MIPS32
4217 dep_bool 'Support for Alchemy Db1100 board' CONFIG_MIPS_DB1100 $CONFI