Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/arch/arm/mach-footbridge/netwinder-hw.c
0004  *
0005  * Netwinder machine fixup
0006  *
0007  * Copyright (C) 1998, 1999 Russell King, Phil Blundell
0008  */
0009 #include <linux/module.h>
0010 #include <linux/ioport.h>
0011 #include <linux/kernel.h>
0012 #include <linux/delay.h>
0013 #include <linux/init.h>
0014 #include <linux/io.h>
0015 #include <linux/spinlock.h>
0016 #include <linux/slab.h>
0017 #include <linux/leds.h>
0018 
0019 #include <asm/hardware/dec21285.h>
0020 #include <asm/mach-types.h>
0021 #include <asm/setup.h>
0022 #include <asm/system_misc.h>
0023 
0024 #include <asm/mach/arch.h>
0025 
0026 #include "common.h"
0027 
0028 #define IRDA_IO_BASE        0x180
0029 #define GP1_IO_BASE     0x338
0030 #define GP2_IO_BASE     0x33a
0031 
0032 /*
0033  * Winbond WB83977F accessibility stuff
0034  */
0035 static inline void wb977_open(void)
0036 {
0037     outb(0x87, 0x370);
0038     outb(0x87, 0x370);
0039 }
0040 
0041 static inline void wb977_close(void)
0042 {
0043     outb(0xaa, 0x370);
0044 }
0045 
0046 static inline void wb977_wb(int reg, int val)
0047 {
0048     outb(reg, 0x370);
0049     outb(val, 0x371);
0050 }
0051 
0052 static inline void wb977_ww(int reg, int val)
0053 {
0054     outb(reg, 0x370);
0055     outb(val >> 8, 0x371);
0056     outb(reg + 1, 0x370);
0057     outb(val & 255, 0x371);
0058 }
0059 
0060 #define wb977_device_select(dev)    wb977_wb(0x07, dev)
0061 #define wb977_device_disable()      wb977_wb(0x30, 0x00)
0062 #define wb977_device_enable()       wb977_wb(0x30, 0x01)
0063 
0064 /*
0065  * This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
0066  */
0067 DEFINE_RAW_SPINLOCK(nw_gpio_lock);
0068 EXPORT_SYMBOL(nw_gpio_lock);
0069 
0070 static unsigned int current_gpio_op;
0071 static unsigned int current_gpio_io;
0072 static unsigned int current_cpld;
0073 
0074 void nw_gpio_modify_op(unsigned int mask, unsigned int set)
0075 {
0076     unsigned int new_gpio, changed;
0077 
0078     new_gpio = (current_gpio_op & ~mask) | set;
0079     changed = new_gpio ^ current_gpio_op;
0080     current_gpio_op = new_gpio;
0081 
0082     if (changed & 0xff)
0083         outb(new_gpio, GP1_IO_BASE);
0084     if (changed & 0xff00)
0085         outb(new_gpio >> 8, GP2_IO_BASE);
0086 }
0087 EXPORT_SYMBOL(nw_gpio_modify_op);
0088 
0089 static inline void __gpio_modify_io(int mask, int in)
0090 {
0091     unsigned int new_gpio, changed;
0092     int port;
0093 
0094     new_gpio = (current_gpio_io & ~mask) | in;
0095     changed = new_gpio ^ current_gpio_io;
0096     current_gpio_io = new_gpio;
0097 
0098     changed >>= 1;
0099     new_gpio >>= 1;
0100 
0101     wb977_device_select(7);
0102 
0103     for (port = 0xe1; changed && port < 0xe8; changed >>= 1) {
0104         wb977_wb(port, new_gpio & 1);
0105 
0106         port += 1;
0107         new_gpio >>= 1;
0108     }
0109 
0110     wb977_device_select(8);
0111 
0112     for (port = 0xe8; changed && port < 0xec; changed >>= 1) {
0113         wb977_wb(port, new_gpio & 1);
0114 
0115         port += 1;
0116         new_gpio >>= 1;
0117     }
0118 }
0119 
0120 void nw_gpio_modify_io(unsigned int mask, unsigned int in)
0121 {
0122     /* Open up the SuperIO chip */
0123     wb977_open();
0124 
0125     __gpio_modify_io(mask, in);
0126 
0127     /* Close up the EFER gate */
0128     wb977_close();
0129 }
0130 EXPORT_SYMBOL(nw_gpio_modify_io);
0131 
0132 unsigned int nw_gpio_read(void)
0133 {
0134     return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
0135 }
0136 EXPORT_SYMBOL(nw_gpio_read);
0137 
0138 /*
0139  * Initialise the Winbond W83977F global registers
0140  */
0141 static inline void wb977_init_global(void)
0142 {
0143     /*
0144      * Enable R/W config registers
0145      */
0146     wb977_wb(0x26, 0x40);
0147 
0148     /*
0149      * Power down FDC (not used)
0150      */
0151     wb977_wb(0x22, 0xfe);
0152 
0153     /*
0154      * GP12, GP11, CIRRX, IRRXH, GP10
0155      */
0156     wb977_wb(0x2a, 0xc1);
0157 
0158     /*
0159      * GP23, GP22, GP21, GP20, GP13
0160      */
0161     wb977_wb(0x2b, 0x6b);
0162 
0163     /*
0164      * GP17, GP16, GP15, GP14
0165      */
0166     wb977_wb(0x2c, 0x55);
0167 }
0168 
0169 /*
0170  * Initialise the Winbond W83977F printer port
0171  */
0172 static inline void wb977_init_printer(void)
0173 {
0174     wb977_device_select(1);
0175 
0176     /*
0177      * mode 1 == EPP
0178      */
0179     wb977_wb(0xf0, 0x01);
0180 }
0181 
0182 /*
0183  * Initialise the Winbond W83977F keyboard controller
0184  */
0185 static inline void wb977_init_keyboard(void)
0186 {
0187     wb977_device_select(5);
0188 
0189     /*
0190      * Keyboard controller address
0191      */
0192     wb977_ww(0x60, 0x0060);
0193     wb977_ww(0x62, 0x0064);
0194 
0195     /*
0196      * Keyboard IRQ 1, active high, edge trigger
0197      */
0198     wb977_wb(0x70, 1);
0199     wb977_wb(0x71, 0x02);
0200 
0201     /*
0202      * Mouse IRQ 5, active high, edge trigger
0203      */
0204     wb977_wb(0x72, 5);
0205     wb977_wb(0x73, 0x02);
0206 
0207     /*
0208      * KBC 8MHz
0209      */
0210     wb977_wb(0xf0, 0x40);
0211 
0212     /*
0213      * Enable device
0214      */
0215     wb977_device_enable();
0216 }
0217 
0218 /*
0219  * Initialise the Winbond W83977F Infra-Red device
0220  */
0221 static inline void wb977_init_irda(void)
0222 {
0223     wb977_device_select(6);
0224 
0225     /*
0226      * IR base address
0227      */
0228     wb977_ww(0x60, IRDA_IO_BASE);
0229 
0230     /*
0231      * IRDA IRQ 6, active high, edge trigger
0232      */
0233     wb977_wb(0x70, 6);
0234     wb977_wb(0x71, 0x02);
0235 
0236     /*
0237      * RX DMA - ISA DMA 0
0238      */
0239     wb977_wb(0x74, 0x00);
0240 
0241     /*
0242      * TX DMA - Disable Tx DMA
0243      */
0244     wb977_wb(0x75, 0x04);
0245 
0246     /*
0247      * Append CRC, Enable bank selection
0248      */
0249     wb977_wb(0xf0, 0x03);
0250 
0251     /*
0252      * Enable device
0253      */
0254     wb977_device_enable();
0255 }
0256 
0257 /*
0258  * Initialise Winbond W83977F general purpose IO
0259  */
0260 static inline void wb977_init_gpio(void)
0261 {
0262     unsigned long flags;
0263 
0264     /*
0265      * Set up initial I/O definitions
0266      */
0267     current_gpio_io = -1;
0268     __gpio_modify_io(-1, GPIO_DONE | GPIO_WDTIMER);
0269 
0270     wb977_device_select(7);
0271 
0272     /*
0273      * Group1 base address
0274      */
0275     wb977_ww(0x60, GP1_IO_BASE);
0276     wb977_ww(0x62, 0);
0277     wb977_ww(0x64, 0);
0278 
0279     /*
0280      * GP10 (Orage button) IRQ 10, active high, edge trigger
0281      */
0282     wb977_wb(0x70, 10);
0283     wb977_wb(0x71, 0x02);
0284 
0285     /*
0286      * GP10: Debounce filter enabled, IRQ, input
0287      */
0288     wb977_wb(0xe0, 0x19);
0289 
0290     /*
0291      * Enable Group1
0292      */
0293     wb977_device_enable();
0294 
0295     wb977_device_select(8);
0296 
0297     /*
0298      * Group2 base address
0299      */
0300     wb977_ww(0x60, GP2_IO_BASE);
0301 
0302     /*
0303      * Clear watchdog timer regs
0304      *  - timer disable
0305      */
0306     wb977_wb(0xf2, 0x00);
0307 
0308     /*
0309      *  - disable LED, no mouse nor keyboard IRQ
0310      */
0311     wb977_wb(0xf3, 0x00);
0312 
0313     /*
0314      *  - timer counting, disable power LED, disable timeouot
0315      */
0316     wb977_wb(0xf4, 0x00);
0317 
0318     /*
0319      * Enable group2
0320      */
0321     wb977_device_enable();
0322 
0323     /*
0324      * Set Group1/Group2 outputs
0325      */
0326     raw_spin_lock_irqsave(&nw_gpio_lock, flags);
0327     nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
0328     raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
0329 }
0330 
0331 /*
0332  * Initialise the Winbond W83977F chip.
0333  */
0334 static void __init wb977_init(void)
0335 {
0336     request_region(0x370, 2, "W83977AF configuration");
0337 
0338     /*
0339      * Open up the SuperIO chip
0340      */
0341     wb977_open();
0342 
0343     /*
0344      * Initialise the global registers
0345      */
0346     wb977_init_global();
0347 
0348     /*
0349      * Initialise the various devices in
0350      * the multi-IO chip.
0351      */
0352     wb977_init_printer();
0353     wb977_init_keyboard();
0354     wb977_init_irda();
0355     wb977_init_gpio();
0356 
0357     /*
0358      * Close up the EFER gate
0359      */
0360     wb977_close();
0361 }
0362 
0363 void nw_cpld_modify(unsigned int mask, unsigned int set)
0364 {
0365     int msk;
0366 
0367     current_cpld = (current_cpld & ~mask) | set;
0368 
0369     nw_gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
0370     nw_gpio_modify_op(GPIO_IOLOAD, 0);
0371 
0372     for (msk = 8; msk; msk >>= 1) {
0373         int bit = current_cpld & msk;
0374 
0375         nw_gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
0376         nw_gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
0377     }
0378 
0379     nw_gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
0380     nw_gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
0381     nw_gpio_modify_op(GPIO_IOLOAD, 0);
0382 }
0383 EXPORT_SYMBOL(nw_cpld_modify);
0384 
0385 static void __init cpld_init(void)
0386 {
0387     unsigned long flags;
0388 
0389     raw_spin_lock_irqsave(&nw_gpio_lock, flags);
0390     nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
0391     raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
0392 }
0393 
0394 static unsigned char rwa_unlock[] __initdata =
0395 { 0x00, 0x00, 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b,
0396   0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74,
0397   0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
0398 
0399 #ifndef DEBUG
0400 #define dprintk(x...)
0401 #else
0402 #define dprintk(x...) printk(x)
0403 #endif
0404 
0405 #define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
0406 
0407 static inline void rwa010_unlock(void)
0408 {
0409     int i;
0410 
0411     WRITE_RWA(2, 2);
0412     mdelay(10);
0413 
0414     for (i = 0; i < sizeof(rwa_unlock); i++) {
0415         outb(rwa_unlock[i], 0x279);
0416         udelay(10);
0417     }
0418 }
0419 
0420 static inline void rwa010_read_ident(void)
0421 {
0422     unsigned char si[9];
0423     int i, j;
0424 
0425     WRITE_RWA(3, 0);
0426     WRITE_RWA(0, 128);
0427 
0428     outb(1, 0x279);
0429 
0430     mdelay(1);
0431 
0432     dprintk("Identifier: ");
0433     for (i = 0; i < 9; i++) {
0434         si[i] = 0;
0435         for (j = 0; j < 8; j++) {
0436             int bit;
0437             udelay(250);
0438             inb(0x203);
0439             udelay(250);
0440             bit = inb(0x203);
0441             dprintk("%02X ", bit);
0442             bit = (bit == 0xaa) ? 1 : 0;
0443             si[i] |= bit << j;
0444         }
0445         dprintk("(%02X) ", si[i]);
0446     }
0447     dprintk("\n");
0448 }
0449 
0450 static inline void rwa010_global_init(void)
0451 {
0452     WRITE_RWA(6, 2);    // Assign a card no = 2
0453 
0454     dprintk("Card no = %d\n", inb(0x203));
0455 
0456     /* disable the modem section of the chip */
0457     WRITE_RWA(7, 3);
0458     WRITE_RWA(0x30, 0);
0459 
0460     /* disable the cdrom section of the chip */
0461     WRITE_RWA(7, 4);
0462     WRITE_RWA(0x30, 0);
0463 
0464     /* disable the MPU-401 section of the chip */
0465     WRITE_RWA(7, 2);
0466     WRITE_RWA(0x30, 0);
0467 }
0468 
0469 static inline void rwa010_game_port_init(void)
0470 {
0471     int i;
0472 
0473     WRITE_RWA(7, 5);
0474 
0475     dprintk("Slider base: ");
0476     WRITE_RWA(0x61, 1);
0477     i = inb(0x203);
0478 
0479     WRITE_RWA(0x60, 2);
0480     dprintk("%02X%02X (201)\n", inb(0x203), i);
0481 
0482     WRITE_RWA(0x30, 1);
0483 }
0484 
0485 static inline void rwa010_waveartist_init(int base, int irq, int dma)
0486 {
0487     int i;
0488 
0489     WRITE_RWA(7, 0);
0490 
0491     dprintk("WaveArtist base: ");
0492     WRITE_RWA(0x61, base & 255);
0493     i = inb(0x203);
0494 
0495     WRITE_RWA(0x60, base >> 8);
0496     dprintk("%02X%02X (%X),", inb(0x203), i, base);
0497 
0498     WRITE_RWA(0x70, irq);
0499     dprintk(" irq: %d (%d),", inb(0x203), irq);
0500 
0501     WRITE_RWA(0x74, dma);
0502     dprintk(" dma: %d (%d)\n", inb(0x203), dma);
0503 
0504     WRITE_RWA(0x30, 1);
0505 }
0506 
0507 static inline void rwa010_soundblaster_init(int sb_base, int al_base, int irq, int dma)
0508 {
0509     int i;
0510 
0511     WRITE_RWA(7, 1);
0512 
0513     dprintk("SoundBlaster base: ");
0514     WRITE_RWA(0x61, sb_base & 255);
0515     i = inb(0x203);
0516 
0517     WRITE_RWA(0x60, sb_base >> 8);
0518     dprintk("%02X%02X (%X),", inb(0x203), i, sb_base);
0519 
0520     dprintk(" irq: ");
0521     WRITE_RWA(0x70, irq);
0522     dprintk("%d (%d),", inb(0x203), irq);
0523 
0524     dprintk(" 8-bit DMA: ");
0525     WRITE_RWA(0x74, dma);
0526     dprintk("%d (%d)\n", inb(0x203), dma);
0527 
0528     dprintk("AdLib base: ");
0529     WRITE_RWA(0x63, al_base & 255);
0530     i = inb(0x203);
0531 
0532     WRITE_RWA(0x62, al_base >> 8);
0533     dprintk("%02X%02X (%X)\n", inb(0x203), i, al_base);
0534 
0535     WRITE_RWA(0x30, 1);
0536 }
0537 
0538 static void rwa010_soundblaster_reset(void)
0539 {
0540     int i;
0541 
0542     outb(1, 0x226);
0543     udelay(3);
0544     outb(0, 0x226);
0545 
0546     for (i = 0; i < 5; i++) {
0547         if (inb(0x22e) & 0x80)
0548             break;
0549         mdelay(1);
0550     }
0551     if (i == 5)
0552         printk("SoundBlaster: DSP reset failed\n");
0553 
0554     dprintk("SoundBlaster DSP reset: %02X (AA)\n", inb(0x22a));
0555 
0556     for (i = 0; i < 5; i++) {
0557         if ((inb(0x22c) & 0x80) == 0)
0558             break;
0559         mdelay(1);
0560     }
0561 
0562     if (i == 5)
0563         printk("SoundBlaster: DSP not ready\n");
0564     else {
0565         outb(0xe1, 0x22c);
0566 
0567         dprintk("SoundBlaster DSP id: ");
0568         i = inb(0x22a);
0569         udelay(1);
0570         i |= inb(0x22a) << 8;
0571         dprintk("%04X\n", i);
0572 
0573         for (i = 0; i < 5; i++) {
0574             if ((inb(0x22c) & 0x80) == 0)
0575                 break;
0576             mdelay(1);
0577         }
0578 
0579         if (i == 5)
0580             printk("SoundBlaster: could not turn speaker off\n");
0581 
0582         outb(0xd3, 0x22c);
0583     }
0584 
0585     /* turn on OPL3 */
0586     outb(5, 0x38a);
0587     outb(1, 0x38b);
0588 }
0589 
0590 static void __init rwa010_init(void)
0591 {
0592     rwa010_unlock();
0593     rwa010_read_ident();
0594     rwa010_global_init();
0595     rwa010_game_port_init();
0596     rwa010_waveartist_init(0x250, 3, 7);
0597     rwa010_soundblaster_init(0x220, 0x388, 3, 1);
0598     rwa010_soundblaster_reset();
0599 }
0600 
0601 /*
0602  * Initialise any other hardware after we've got the PCI bus
0603  * initialised.  We may need the PCI bus to talk to this other
0604  * hardware.
0605  */
0606 static int __init nw_hw_init(void)
0607 {
0608     if (machine_is_netwinder()) {
0609         wb977_init();
0610         cpld_init();
0611         rwa010_init();
0612     }
0613     return 0;
0614 }
0615 
0616 __initcall(nw_hw_init);
0617 
0618 /*
0619  * Older NeTTroms either do not provide a parameters
0620  * page, or they don't supply correct information in
0621  * the parameter page.
0622  */
0623 static void __init
0624 fixup_netwinder(struct tag *tags, char **cmdline)
0625 {
0626 #ifdef CONFIG_ISAPNP
0627     extern int isapnp_disable;
0628 
0629     /*
0630      * We must not use the kernels ISAPnP code
0631      * on the NetWinder - it will reset the settings
0632      * for the WaveArtist chip and render it inoperable.
0633      */
0634     isapnp_disable = 1;
0635 #endif
0636 }
0637 
0638 static void netwinder_restart(enum reboot_mode mode, const char *cmd)
0639 {
0640     if (mode == REBOOT_SOFT) {
0641         /* Jump into the ROM */
0642         soft_restart(0x41000000);
0643     } else {
0644         local_irq_disable();
0645         local_fiq_disable();
0646 
0647         /* open up the SuperIO chip */
0648         outb(0x87, 0x370);
0649         outb(0x87, 0x370);
0650 
0651         /* aux function group 1 (logical device 7) */
0652         outb(0x07, 0x370);
0653         outb(0x07, 0x371);
0654 
0655         /* set GP16 for WD-TIMER output */
0656         outb(0xe6, 0x370);
0657         outb(0x00, 0x371);
0658 
0659         /* set a RED LED and toggle WD_TIMER for rebooting */
0660         outb(0xc4, 0x338);
0661     }
0662 }
0663 
0664 /* LEDs */
0665 #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
0666 struct netwinder_led {
0667     struct led_classdev     cdev;
0668     u8                      mask;
0669 };
0670 
0671 /*
0672  * The triggers lines up below will only be used if the
0673  * LED triggers are compiled in.
0674  */
0675 static const struct {
0676     const char *name;
0677     const char *trigger;
0678 } netwinder_leds[] = {
0679     { "netwinder:green", "heartbeat", },
0680     { "netwinder:red", "cpu0", },
0681 };
0682 
0683 /*
0684  * The LED control in Netwinder is reversed:
0685  *  - setting bit means turn off LED
0686  *  - clearing bit means turn on LED
0687  */
0688 static void netwinder_led_set(struct led_classdev *cdev,
0689         enum led_brightness b)
0690 {
0691     struct netwinder_led *led = container_of(cdev,
0692             struct netwinder_led, cdev);
0693     unsigned long flags;
0694     u32 reg;
0695 
0696     raw_spin_lock_irqsave(&nw_gpio_lock, flags);
0697     reg = nw_gpio_read();
0698     if (b != LED_OFF)
0699         reg &= ~led->mask;
0700     else
0701         reg |= led->mask;
0702     nw_gpio_modify_op(led->mask, reg);
0703     raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
0704 }
0705 
0706 static enum led_brightness netwinder_led_get(struct led_classdev *cdev)
0707 {
0708     struct netwinder_led *led = container_of(cdev,
0709             struct netwinder_led, cdev);
0710     unsigned long flags;
0711     u32 reg;
0712 
0713     raw_spin_lock_irqsave(&nw_gpio_lock, flags);
0714     reg = nw_gpio_read();
0715     raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
0716 
0717     return (reg & led->mask) ? LED_OFF : LED_FULL;
0718 }
0719 
0720 static int __init netwinder_leds_init(void)
0721 {
0722     int i;
0723 
0724     if (!machine_is_netwinder())
0725         return -ENODEV;
0726 
0727     for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) {
0728         struct netwinder_led *led;
0729 
0730         led = kzalloc(sizeof(*led), GFP_KERNEL);
0731         if (!led)
0732             break;
0733 
0734         led->cdev.name = netwinder_leds[i].name;
0735         led->cdev.brightness_set = netwinder_led_set;
0736         led->cdev.brightness_get = netwinder_led_get;
0737         led->cdev.default_trigger = netwinder_leds[i].trigger;
0738 
0739         if (i == 0)
0740             led->mask = GPIO_GREEN_LED;
0741         else
0742             led->mask = GPIO_RED_LED;
0743 
0744         if (led_classdev_register(NULL, &led->cdev) < 0) {
0745             kfree(led);
0746             break;
0747         }
0748     }
0749 
0750     return 0;
0751 }
0752 
0753 /*
0754  * Since we may have triggers on any subsystem, defer registration
0755  * until after subsystem_init.
0756  */
0757 fs_initcall(netwinder_leds_init);
0758 #endif
0759 
0760 MACHINE_START(NETWINDER, "Rebel-NetWinder")
0761     /* Maintainer: Russell King/Rebel.com */
0762     .atag_offset    = 0x100,
0763     .video_start    = 0x000a0000,
0764     .video_end  = 0x000bffff,
0765     .reserve_lp0    = 1,
0766     .reserve_lp2    = 1,
0767     .fixup      = fixup_netwinder,
0768     .map_io     = footbridge_map_io,
0769     .init_irq   = footbridge_init_irq,
0770     .init_time  = isa_timer_init,
0771     .restart    = netwinder_restart,
0772 MACHINE_END