From a17d6499367a857a471e33cdf35ebe2413eec185 Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Tue, 16 Oct 2001 21:50:28 +0000 Subject: [PATCH] adding support for the w83877tf --- src/superio/winbond/w83877tf/setup_serial.inc | 52 ++++ src/superio/winbond/w83877tf/superio.c | 260 ++++++++++++++++++ 2 files changed, 312 insertions(+) create mode 100644 src/superio/winbond/w83877tf/setup_serial.inc create mode 100644 src/superio/winbond/w83877tf/superio.c diff --git a/src/superio/winbond/w83877tf/setup_serial.inc b/src/superio/winbond/w83877tf/setup_serial.inc new file mode 100644 index 0000000000..3b44ee160e --- /dev/null +++ b/src/superio/winbond/w83877tf/setup_serial.inc @@ -0,0 +1,52 @@ +#define OUTIT(val, port) movb val, %al; \ + movw port, %dx; \ + outb %al, %dx + +/* the second outit is a cheap delay */ +#define OUTPNPADDR(val) OUTIT(val, $0x3f0); OUTIT(val, $0xeb) +#define OUTPNPDATA(val) OUTIT(val, $0x3f1); OUTIT(val, $0xeb) + +/* to do: move this to a common include file! */ +#define WRITESIOBYTE(register, value) movw register, %dx ;\ + movb value, %al ;\ + outb %al, %dx; OUTIT(%al, $0x80) + +#define WRITESIOWORD(register, value) movw register, %dx ;\ + movw value, %ax ;\ + outw %ax, %dx; OUTIT(%al, $0x80) + +/* turn on PnP */ + OUTPNPADDR($0x87) + OUTPNPADDR($0x87) + +/* select com1 */ + OUTPNPADDR($7) + OUTPNPDATA($2) +/* set the enable in reg. 0x30 */ + OUTPNPADDR($0x30) + OUTPNPDATA($1) +/* set the proper control bits for clock etc. in register 0x24 */ + OUTPNPADDR($0x24) + OUTPNPDATA($0xc4) +/* who knows if we need this, but the bios does it. Set PIN58S to GP13 */ + OUTPNPADDR($0x2b) + OUTPNPDATA($0x1) + +/* turn off PnP */ + OUTPNPADDR($0xaa) +/* all done that nonsense -- from here on it's standard pc80 */ +// set up register to set baud rate. + WRITESIOBYTE($0x3fb, $0x80) +// Set 115 kb +// I don't think this thing can run at that rate. +// WRITESIOWORD($0x3f8, $1) +// Set 38.4 kb + WRITESIOWORD($0x3f8, $3) +// now set no parity, one stop, 8 bits + WRITESIOBYTE($0x3fb, $3) +// now turn on RTS, DRT + WRITESIOBYTE($0x3fc, $3) +// Enable interrupts + WRITESIOBYTE($0x3f9, $0xf) +// should be done. Dump a char for fun. + WRITESIOBYTE($0x3f8, $48) diff --git a/src/superio/winbond/w83877tf/superio.c b/src/superio/winbond/w83877tf/superio.c new file mode 100644 index 0000000000..790a8b6a08 --- /dev/null +++ b/src/superio/winbond/w83877tf/superio.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include + +#define FLOPPY_DEVICE 0 +#define PARALLEL_DEVICE 1 +#define COM1_DEVICE 2 +#define COM2_DEVICE 3 +#define KBC_DEVICE 5 +#define CIR_DEVICE 6 +#define GAME_PORT_DEVICE 7 +#define GPIO_PORT2_DEVICE 8 +#define GPIO_PORT3_DEVICE 9 +#define ACPI_DEVICE 0xa +#define HW_MONITOR_DEVICE 0xb + + +#define FLOPPY_DEFAULT_IOBASE 0x3f0 +#define FLOPPY_DEFAULT_IRQ 6 +#define FLOPPY_DEFAULT_DRQ 2 +#define PARALLEL_DEFAULT_IOBASE 0x378 +#define PARALLEL_DEFAULT_IRQ 7 +#define PARALLEL_DEFAULT_DRQ 4 /* No dma */ +#define COM1_DEFAULT_IOBASE 0x3f8 +#define COM1_DEFAULT_IRQ 4 +#define COM1_DEFAULT_BAUD 115200 +#define COM2_DEFAULT_IOBASE 0x2f8 +#define COM2_DEFAULT_IRQ 3 +#define COM2_DEFAULT_BAUD 115200 +#define KBC_DEFAULT_IOBASE0 0x60 +#define KBC_DEFAULT_IOBASE1 0x64 +#define KBC_DEFAULT_IRQ0 0x1 +#define KBC_DEFAULT_IRQ1 0xc + + +static void enter_pnp(struct superio *sio) +{ + outb(0x87, sio->port); + outb(0x87, sio->port); +} + +static void exit_pnp(struct superio *sio) +{ + outb(0xaa, sio->port); +} + +static void write_config(struct superio *sio, + unsigned char value, unsigned char reg) +{ + outb(reg, sio->port); + outb(value, sio->port +1); +} + +static unsigned char read_config(struct superio *sio, unsigned char reg) +{ + outb(reg, sio->port); + return inb(sio->port +1); +} +static void set_logical_device(struct superio *sio, int device) +{ + write_config(sio, device, 0x07); +} + +static void set_enable(struct superio *sio, int enable) +{ + write_config(sio, enable?0x1:0x0, 0x30); +#if 0 + if (enable) { + printk_debug("enabled superio device: %d\n", + read_config(sio, 0x07)); + } +#endif +} + +static void set_iobase0(struct superio *sio, unsigned iobase) +{ + write_config(sio, (iobase >> 8) & 0xff, 0x60); + write_config(sio, iobase & 0xff, 0x61); +} + +static void set_iobase1(struct superio *sio, unsigned iobase) +{ + write_config(sio, (iobase >> 8) & 0xff, 0x62); + write_config(sio, iobase & 0xff, 0x63); +} + +static void set_irq0(struct superio *sio, unsigned irq) +{ + write_config(sio, irq, 0x70); +} + +static void set_irq1(struct superio *sio, unsigned irq) +{ + write_config(sio, irq, 0x72); +} + +static void set_drq(struct superio *sio, unsigned drq) +{ + write_config(sio, drq & 0xff, 0x74); +} + +static void setup_com(struct superio *sio, + struct com_ports *com, int device) +{ + int divisor = 115200/com->baud; + printk_debug("Enabling com device: %02x\n", device); + printk_debug(" iobase = 0x%04x irq=%d\n", com->base, com->irq); + /* Select the device */ + set_logical_device(sio, device); + /* Disable it while it is initialized */ + set_enable(sio, 0); + if (com->enable) { + set_iobase0(sio, com->base); + set_irq0(sio, com->irq); + /* We are initialized so enable the device */ + set_enable(sio, 1); + /* Now initialize the com port */ + uart_init(com->base, divisor); + } +} + +static void setup_floppy(struct superio *sio) +{ + /* Remember the default resources */ + unsigned iobase = FLOPPY_DEFAULT_IOBASE; + unsigned irq = FLOPPY_DEFAULT_IRQ; + unsigned drq = FLOPPY_DEFAULT_DRQ; + /* Select the device */ + set_logical_device(sio, FLOPPY_DEVICE); + /* Disable it while initializing */ + set_enable(sio, 0); + if (sio->floppy) { + set_iobase0(sio, iobase); + set_irq0(sio, irq); + set_drq(sio, drq); + set_enable(sio, 1); + } +} + +static void setup_parallel(struct superio *sio) +{ + /* Remember the default resources */ + unsigned iobase = PARALLEL_DEFAULT_IOBASE; + unsigned irq = PARALLEL_DEFAULT_IRQ; + unsigned drq = PARALLEL_DEFAULT_DRQ; + /* Select the device */ + set_logical_device(sio, PARALLEL_DEVICE); + /* Disable it while initializing */ + set_enable(sio, 0); + if (sio->lpt) { + set_iobase0(sio, iobase); + set_irq0(sio, irq); + set_drq(sio, drq); + set_enable(sio, 1); + } +} + +static void setup_keyboard(struct superio *sio) +{ + /* Remember the default resources */ + unsigned iobase0 = KBC_DEFAULT_IOBASE0; + unsigned iobase1 = KBC_DEFAULT_IOBASE1; + unsigned irq0 = KBC_DEFAULT_IRQ0; + unsigned irq1 = KBC_DEFAULT_IRQ1; + /* Select the device */ + set_logical_device(sio, KBC_DEVICE); + /* Disable it while initializing */ + set_enable(sio, 0); + if (sio->keyboard) { + set_iobase0(sio, iobase0); + set_iobase1(sio, iobase1); + set_irq0(sio, irq0); + set_irq1(sio, irq1); + set_enable(sio, 1); + /* Initialize the keyboard */ + pc_keyboard_init(); + } +} + + +#if 0 +static void setup_acpi_registers(struct superio *sio) +{ + set_logical_device(sio, ACPI_DEVICE); + /* Enable power on after power fail */ + write_config(sio, (1 << 7)|(0 <<5), 0xe4); + set_enable(sio, 1); +} +#endif + +static void enable_devices(struct superio *sio) +{ + if (sio->port == 0) { + sio->port = sio->super->defaultport; + } + if (sio->com1.base == 0) sio->com1.base = COM1_DEFAULT_IOBASE; + if (sio->com1.irq == 0) sio->com1.irq = COM1_DEFAULT_IRQ; + if (sio->com1.baud == 0) sio->com1.baud = COM1_DEFAULT_BAUD; + if (sio->com2.base == 0) sio->com2.base = COM2_DEFAULT_IOBASE; + if (sio->com2.irq == 0) sio->com2.irq = COM2_DEFAULT_IRQ; + if (sio->com2.baud == 0) sio->com2.baud = COM2_DEFAULT_BAUD; + + enter_pnp(sio); + + /* enable/disable floppy */ + setup_floppy(sio); + + /* enable or disable parallel */ + setup_parallel(sio); + + /* enable/disable com1 */ + setup_com(sio, &sio->com1, COM1_DEVICE); + + /* enable/disable com2 */ + setup_com(sio, &sio->com2, COM2_DEVICE); + + /* enable/disable keyboard */ + setup_keyboard(sio); + + /* enable/disable cir */ + set_logical_device(sio, CIR_DEVICE); + set_enable(sio, sio->cir); + + /* game */ + set_logical_device(sio, GAME_PORT_DEVICE); + set_enable(sio, sio->game); + + /* gpio_port2 */ + set_logical_device(sio, GPIO_PORT2_DEVICE); + set_enable(sio, sio->gpio2); + + /* gpio_port3 */ + set_logical_device(sio, GPIO_PORT3_DEVICE); + set_enable(sio, sio->gpio3); + + /* enable/disable acpi */ + set_logical_device(sio, ACPI_DEVICE); + set_enable(sio, sio->acpi); + + /* enable/disable hw monitor */ + set_logical_device(sio, HW_MONITOR_DEVICE); + set_enable(sio, sio->hwmonitor); + +#if 0 + /* setup acpi registers so I am certain to get + * power on after power fail. + */ + setup_acpi_registers(sio); +#endif + + // what's this. + write_config(sio, 1, 0x30); + exit_pnp(sio); +} + +/* The base address is either 0x2e or 0x4e */ +struct superio_control superio_winbond_w83627hf_control = { + (void *)0, enable_devices, (void *)0, 0x2e, "w83627hf" +};