diff options
Diffstat (limited to 'src/superio/NSC/pc87360/superio.c')
-rw-r--r-- | src/superio/NSC/pc87360/superio.c | 339 |
1 files changed, 46 insertions, 293 deletions
diff --git a/src/superio/NSC/pc87360/superio.c b/src/superio/NSC/pc87360/superio.c index 8765eb35cc..50d71ea927 100644 --- a/src/superio/NSC/pc87360/superio.c +++ b/src/superio/NSC/pc87360/superio.c @@ -1,324 +1,77 @@ /* Copyright 2000 AG Electronics Ltd. */ +/* Copyright 2003-2004 Linux Networx */ /* This code is distributed without warranty under the GPL v2 (see COPYING) */ #include <arch/io.h> #include <device/device.h> +#include <device/pnp.h> #include <device/chip.h> #include <console/console.h> #include <string.h> #include <bitops.h> +#include <uart8250.h> +#include <pc80/keyboard.h> #include "chip.h" +#include "pc87360.h" -void pnp_output(char address, char data) +static void init(device_t dev) { - outb(address, PNP_INDEX_REG); - outb(data, PNP_DATA_REG); -} - -static void sio_enable(struct chip *chip, enum chip_pass pass) -{ - - struct superio_NSC_pc87360_config *conf = (struct superio_NSC_pc87360_config *)chip->chip_info; - - switch (pass) { - case CONF_PASS_PRE_CONSOLE: - /* Enable Super IO Chip */ - pnp_output(0x07, 6); /* LD 6 = UART1 */ - pnp_output(0x30, 0); /* Dectivate */ - pnp_output(0x60, conf->port >> 8); /* IO Base */ - pnp_output(0x61, conf->port & 0xFF); /* IO Base */ - pnp_output(0x30, 1); /* Activate */ - break; - default: - /* nothing yet */ - break; - } -} - -static void pnp_write_config(device_t dev, unsigned char value, unsigned char reg) -{ - outb(reg, dev->path.u.pnp.port); - outb(value, dev->path.u.pnp.port + 1); -} - -static unsigned char pnp_read_config(device_t dev, unsigned char reg) -{ - outb(reg, dev->path.u.pnp.port); - return inb(dev->path.u.pnp.port + 1); -} - -static void pnp_set_logical_device(device_t dev) -{ - pnp_write_config(dev, dev->path.u.pnp.device, 0x07); -} - -static void pnp_set_enable(device_t dev, int enable) -{ - pnp_write_config(dev, enable?0x1:0x0, 0x30); -} - -static int pnp_read_enable(device_t dev) -{ - return !!pnp_read_config(dev, 0x30); -} - -#define FLOPPY_DEVICE 0 -#define PARALLEL_DEVICE 1 -#define COM2_DEVICE 2 -#define COM1_DEVICE 3 -#define SWC_DEVICE 4 -#define MOUSE_DEVICE 5 -#define KBC_DEVICE 6 -#define GPIO_DEVICE 7 -#define ACB_DEVICE 8 -#define FSCM_DEVICE 9 -#define WDT_DEVICE 10 - -struct io_info { - unsigned mask, set; -}; -struct pnp_info { - unsigned flags; -#define PNP_IO0 0x01 -#define PNP_IO1 0x02 -#define PNP_IRQ0 0x04 -#define PNP_IRQ1 0x08 -#define PNP_DRQ0 0x10 -#define PNP_DRQ1 0x20 - struct io_info io0, io1; -}; - -static struct pnp_info pnp_dev_info[] = { - [ 0] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07fa, 0}, }, - [ 1] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x04f8, 0}, }, - [ 2] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0 | PNP_DRQ1, { 0x7f8, 0 }, }, - [ 3] = { PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, }, - [ 4] = { PNP_IO0 | PNP_IRQ0, { 0xfff0, 0 }, }, - [ 5] = { PNP_IRQ0 }, - [ 6] = { PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7f8, 0 }, { 0x7f8, 0x4}, }, - [ 7] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } }, - [ 8] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } }, - [ 9] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } }, - [10] = { PNP_IO0 | PNP_IRQ0, { 0xfffc, 0 } }, -}; - -static struct resource *get_resource(device_t dev, unsigned index) -{ - struct resource *resource; - int i; - resource = 0; - for(i = 0; i < dev->resources; i++) { - resource = &dev->resource[i]; - if (resource->index == index) { - break; - } - } - if (!resource || (resource->index != index)) { - resource = &dev->resource[dev->resources]; - memset(resource, 0, sizeof(*resource)); - dev->resources++; - } - /* Initialize the resource values */ - if (!(resource->flags & IORESOURCE_FIXED)) { - resource->flags = 0; - resource->base = 0; - } - resource->size = 0; - resource->limit = 0; - resource->flags = 0; - resource->index = index; - resource->align = 0; - resource->gran = 0; - - return resource; -} - -static void pnp_read_ioresource(device_t dev, unsigned index, struct io_info *info) -{ - struct resource *resource; - uint32_t size; - resource = get_resource(dev, index); - - /* Initilize the resource */ - resource->limit = 0xffff; - resource->flags |= IORESOURCE_IO; - - /* Set the resource size and alignment */ - size = (0xffff & info->mask); - resource->size = (~(size | 0xfffff800) + 1); - resource->align = log2(resource->size); - resource->gran = resource->align; -} - - -static void pnp_read_resources(device_t dev) -{ - struct pnp_info *info; - struct resource *resource; - pnp_set_logical_device(dev); - - info = &pnp_dev_info[dev->path.u.pnp.device]; - - if (info->flags & PNP_IO0) { - pnp_read_ioresource(dev, 0x60, &info->io0); - } - if (info->flags & PNP_IO1) { - pnp_read_ioresource(dev, 0x62, &info->io1); - } - if (info->flags & PNP_IRQ0) { - resource = get_resource(dev, 0x70); - resource->size = 1; - resource->flags |= IORESOURCE_IRQ; - } - if (info->flags & PNP_IRQ1) { - resource = get_resource(dev, 0x72); - resource->size = 1; - resource->flags |= IORESOURCE_IRQ; - } - if (info->flags & PNP_DRQ0) { - resource = get_resource(dev, 0x74); - resource->size = 1; - resource->flags |= IORESOURCE_DRQ; - } - if (info->flags & PNP_DRQ1) { - resource = get_resource(dev, 0x75); - resource->size = 1; - resource->flags |= IORESOURCE_DRQ; - } -} - -static void pnp_set_iobase(device_t dev, unsigned iobase, unsigned index) -{ - /* Index == 0x60 or 0x62 */ - pnp_write_config(dev, (iobase >> 8) & 0xff, index); - pnp_write_config(dev, iobase & 0xff, index + 1); -} - -static void pnp_set_irq(device_t dev, unsigned irq, unsigned index) -{ - /* Index == 0x70 or 0x72 */ - pnp_write_config(dev, irq, index); -} - -static void pnp_set_drq(device_t dev, unsigned drq, unsigned index) -{ - /* Index == 0x74 */ - pnp_write_config(dev, drq & 0xff, index); -} - - -static void pnp_set_resource(device_t dev, struct resource *resource) -{ - if (!(resource->flags & IORESOURCE_SET)) { -#if 1 - printk_err("ERROR: %s %02x not allocated\n", - dev_path(dev), resource->index); -#endif - return; - } - if (resource->flags & IORESOURCE_IO) { - pnp_set_iobase(dev, resource->base, resource->index); - } - else if (resource->flags & IORESOURCE_DRQ) { - pnp_set_drq(dev, resource->base, resource->index); - } - else if (resource->flags & IORESOURCE_IRQ) { - pnp_set_irq(dev, resource->base, resource->index); - } - else { - printk_err("ERROR: %s %02x unknown resource type\n", - dev_path(dev), resource->index); + struct superio_NSC_pc87360_config *conf; + struct resource *res0, *res1; + /* Wishlist handle well known programming interfaces more + * generically. + */ + if (!dev->enable) { return; } - printk_debug( - "%s %02x <- [0x%08lx - 0x%08lx %s\n", - dev_path(dev), - resource->index, - resource->base, resource->base + resource->size - 1, - (resource->flags & IORESOURCE_IO)? "io": - (resource->flags & IORESOURCE_DRQ)? "drq": - (resource->flags & IORESOURCE_IRQ)? "irq": - (resource->flags & IORESOURCE_MEM)? "mem": - "???"); -} - -static void pnp_set_resources(device_t dev) -{ - int i; - pnp_set_logical_device(dev); - for(i = 0; i < dev->resources; i++) { - pnp_set_resource(dev, &dev->resource[i]); - } - -} -static void pnp_enable_resources(device_t dev) -{ - pnp_set_logical_device(dev); - pnp_set_enable(dev, 1); - -} -static void pnp_enable(device_t dev) -{ - pnp_set_logical_device(dev); - if (!dev->enable) { - pnp_set_enable(dev, 0); + conf = dev->chip->chip_info; + switch(dev->path.u.pnp.device) { + case PC87360_SP1: + res0 = get_resource(dev, PNP_IDX_IO0); + init_uart8250(res0->base, &conf->com1); + break; + case PC87360_SP2: + res0 = get_resource(dev, PNP_IDX_IO0); + init_uart8250(res0->base, &conf->com2); + break; + case PC87360_KBCK: + res0 = get_resource(dev, PNP_IDX_IO0); + res1 = get_resource(dev, PNP_IDX_IO1); + init_pc_keyboard(res0->base, res1->base, &conf->keyboard); + break; } } -static struct device_operations pnp_ops = { +static struct device_operations ops = { .read_resources = pnp_read_resources, .set_resources = pnp_set_resources, .enable_resources = pnp_enable_resources, .enable = pnp_enable, + .init = init, }; -#define MAX_FUNCTION 10 -static void enumerate(struct chip *chip) -{ - struct superio_NSC_pc87360_config *conf = (struct superio_NSC_pc87360_config *)chip->chip_info; - struct resource *resource; - struct device_path path; - device_t dev; - int i; - - chip_enumerate(chip); - path.type = DEVICE_PATH_PNP; - path.u.pnp.port = chip->dev->path.u.pnp.port; - - /* Set the ops on the newly allocated devices */ - for(i = 0; i <= WDT_DEVICE; i++) { - path.u.pnp.device = i; - dev = alloc_find_dev(chip->bus, &path); - dev->ops = &pnp_ops; - } +static struct pnp_info pnp_dev_info[] = { + { &ops, PC87360_FDC, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07fa, 0}, }, + { &ops, PC87360_PP, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x04f8, 0}, }, + { &ops, PC87360_SP2, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0 | PNP_DRQ1, { 0x7f8, 0 }, }, + { &ops, PC87360_SP1, PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, }, + { &ops, PC87360_SWC, PNP_IO0 | PNP_IRQ0, { 0xfff0, 0 }, }, + { &ops, PC87360_KBCM, PNP_IRQ0 }, + { &ops, PC87360_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7f8, 0 }, { 0x7f8, 0x4}, }, + { &ops, PC87360_GPIO, PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } }, + { &ops, PC87360_ACB, PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } }, + { &ops, PC87360_FSCM, PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } }, + { &ops, PC87360_WDT, PNP_IO0 | PNP_IRQ0, { 0xfffc, 0 } }, +}; - /* Processes the hard codes for com1 */ - path.u.pnp.device = COM1_DEVICE; - dev = alloc_find_dev(chip->bus, &path); - resource = get_resource(dev, 0x60); - if (conf->com1.base) { - resource->base = conf->com1.base; - resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET; - } - resource = get_resource(dev, 0x70); - if (conf->com1.irq) { - resource->base = conf->com1.irq; - resource->flags = IORESOURCE_IRQ | IORESOURCE_FIXED | IORESOURCE_SET; - } - /* Process the hard codes for the keyboard controller */ - path.u.pnp.device = KBC_DEVICE; - dev = alloc_find_dev(dev, &path); - resource = get_resource(dev, 0x60); - resource->base = 0x60; - resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET; - resource = get_resource(dev, 0x62); - resource->base = 0x64; - resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET; +static void enumerate(struct chip *chip) +{ + pnp_enumerate(chip, sizeof(pnp_dev_info)/sizeof(pnp_dev_info[0]), + &pnp_ops, pnp_dev_info); } struct chip_control superio_NSC_pc87360_control = { - .enable = sio_enable, .enumerate = enumerate, .name = "NSC 87360" }; |