1 /* This code is distributed without warranty under the GPL v2 (see COPYING) */
4 #include <device/device.h>
5 #include <device/chip.h>
6 #include <console/console.h>
11 void pnp_output(char address, char data)
13 outb(address, PNP_INDEX_REG);
14 outb(data, PNP_DATA_REG);
17 static void sio_enable(struct chip *chip, enum chip_pass pass)
20 struct superio_NSC_pc87360_config *conf = (struct superio_NSC_pc87360_config *)chip->chip_info;
23 case CONF_PASS_PRE_CONSOLE:
24 /* Enable Super IO Chip */
25 pnp_output(0x07, 6); /* LD 6 = UART1 */
26 pnp_output(0x30, 0); /* Dectivate */
27 pnp_output(0x60, conf->port >> 8); /* IO Base */
28 pnp_output(0x61, conf->port & 0xFF); /* IO Base */
29 pnp_output(0x30, 1); /* Activate */
37 static void pnp_write_config(device_t dev, unsigned char value, unsigned char reg)
39 outb(reg, dev->path.u.pnp.port);
40 outb(value, dev->path.u.pnp.port + 1);
43 static unsigned char pnp_read_config(device_t dev, unsigned char reg)
45 outb(reg, dev->path.u.pnp.port);
46 return inb(dev->path.u.pnp.port + 1);
49 static void pnp_set_logical_device(device_t dev)
51 pnp_write_config(dev, dev->path.u.pnp.device, 0x07);
54 static void pnp_set_enable(device_t dev, int enable)
56 pnp_write_config(dev, enable?0x1:0x0, 0x30);
59 static int pnp_read_enable(device_t dev)
61 return !!pnp_read_config(dev, 0x30);
64 #define FLOPPY_DEVICE 0
65 #define PARALLEL_DEVICE 1
69 #define MOUSE_DEVICE 5
87 struct io_info io0, io1;
90 static struct pnp_info pnp_dev_info[] = {
91 [ 0] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07fa, 0}, },
92 [ 1] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x04f8, 0}, },
93 [ 2] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0 | PNP_DRQ1, { 0x7f8, 0 }, },
94 [ 3] = { PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
95 [ 4] = { PNP_IO0 | PNP_IRQ0, { 0xfff0, 0 }, },
97 [ 6] = { PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7f8, 0 }, { 0x7f8, 0x4}, },
98 [ 7] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
99 [ 8] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
100 [ 9] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
101 [10] = { PNP_IO0 | PNP_IRQ0, { 0xfffc, 0 } },
104 static struct resource *get_resource(device_t dev, unsigned index)
106 struct resource *resource;
109 for(i = 0; i < dev->resources; i++) {
110 resource = &dev->resource[i];
111 if (resource->index == index) {
115 if (!resource || (resource->index != index)) {
116 resource = &dev->resource[dev->resources];
117 memset(resource, 0, sizeof(*resource));
120 /* Initialize the resource values */
121 if (!(resource->flags & IORESOURCE_FIXED)) {
128 resource->index = index;
135 static void pnp_read_ioresource(device_t dev, unsigned index, struct io_info *info)
137 struct resource *resource;
139 resource = get_resource(dev, index);
141 /* Initilize the resource */
142 resource->limit = 0xffff;
143 resource->flags |= IORESOURCE_IO;
145 /* Set the resource size and alignment */
146 size = (0xffff & info->mask);
147 resource->size = (~(size | 0xfffff800) + 1);
148 resource->align = log2(resource->size);
149 resource->gran = resource->align;
153 static void pnp_read_resources(device_t dev)
155 struct pnp_info *info;
156 struct resource *resource;
157 pnp_set_logical_device(dev);
159 info = &pnp_dev_info[dev->path.u.pnp.device];
161 if (info->flags & PNP_IO0) {
162 pnp_read_ioresource(dev, 0x60, &info->io0);
164 if (info->flags & PNP_IO1) {
165 pnp_read_ioresource(dev, 0x62, &info->io1);
167 if (info->flags & PNP_IRQ0) {
168 resource = get_resource(dev, 0x70);
170 resource->flags |= IORESOURCE_IRQ;
172 if (info->flags & PNP_IRQ1) {
173 resource = get_resource(dev, 0x72);
175 resource->flags |= IORESOURCE_IRQ;
177 if (info->flags & PNP_DRQ0) {
178 resource = get_resource(dev, 0x74);
180 resource->flags |= IORESOURCE_DRQ;
182 if (info->flags & PNP_DRQ1) {
183 resource = get_resource(dev, 0x75);
185 resource->flags |= IORESOURCE_DRQ;
189 static void pnp_set_iobase(device_t dev, unsigned iobase, unsigned index)
191 /* Index == 0x60 or 0x62 */
192 pnp_write_config(dev, (iobase >> 8) & 0xff, index);
193 pnp_write_config(dev, iobase & 0xff, index + 1);
196 static void pnp_set_irq(device_t dev, unsigned irq, unsigned index)
198 /* Index == 0x70 or 0x72 */
199 pnp_write_config(dev, irq, index);
202 static void pnp_set_drq(device_t dev, unsigned drq, unsigned index)
205 pnp_write_config(dev, drq & 0xff, index);
209 static void pnp_set_resource(device_t dev, struct resource *resource)
211 if (!(resource->flags & IORESOURCE_SET)) {
213 printk_err("ERROR: %s %02x not allocated\n",
214 dev_path(dev), resource->index);
218 if (resource->flags & IORESOURCE_IO) {
219 pnp_set_iobase(dev, resource->base, resource->index);
221 else if (resource->flags & IORESOURCE_DRQ) {
222 pnp_set_drq(dev, resource->base, resource->index);
224 else if (resource->flags & IORESOURCE_IRQ) {
225 pnp_set_irq(dev, resource->base, resource->index);
228 printk_err("ERROR: %s %02x unknown resource type\n",
229 dev_path(dev), resource->index);
233 "%s %02x <- [0x%08lx - 0x%08lx %s\n",
236 resource->base, resource->base + resource->size - 1,
237 (resource->flags & IORESOURCE_IO)? "io":
238 (resource->flags & IORESOURCE_DRQ)? "drq":
239 (resource->flags & IORESOURCE_IRQ)? "irq":
240 (resource->flags & IORESOURCE_MEM)? "mem":
244 static void pnp_set_resources(device_t dev)
247 pnp_set_logical_device(dev);
248 for(i = 0; i < dev->resources; i++) {
249 pnp_set_resource(dev, &dev->resource[i]);
253 static void pnp_enable_resources(device_t dev)
255 pnp_set_logical_device(dev);
256 pnp_set_enable(dev, 1);
259 static void pnp_enable(device_t dev)
261 pnp_set_logical_device(dev);
263 pnp_set_enable(dev, 0);
267 static struct device_operations pnp_ops = {
268 .read_resources = pnp_read_resources,
269 .set_resources = pnp_set_resources,
270 .enable_resources = pnp_enable_resources,
271 .enable = pnp_enable,
274 #define MAX_FUNCTION 10
275 static void enumerate(struct chip *chip)
277 struct superio_NSC_pc87360_config *conf = (struct superio_NSC_pc87360_config *)chip->chip_info;
278 struct resource *resource;
279 struct device_path path;
283 chip_enumerate(chip);
284 path.type = DEVICE_PATH_PNP;
285 path.u.pnp.port = chip->dev->path.u.pnp.port;
287 /* Set the ops on the newly allocated devices */
288 for(i = 0; i <= WDT_DEVICE; i++) {
289 path.u.pnp.device = i;
290 dev = alloc_find_dev(chip->bus, &path);
294 /* Processes the hard codes for com1 */
295 path.u.pnp.device = COM1_DEVICE;
296 dev = alloc_find_dev(chip->bus, &path);
297 resource = get_resource(dev, 0x60);
298 if (conf->com1.base) {
299 resource->base = conf->com1.base;
300 resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
302 resource = get_resource(dev, 0x70);
303 if (conf->com1.irq) {
304 resource->base = conf->com1.irq;
305 resource->flags = IORESOURCE_IRQ | IORESOURCE_FIXED | IORESOURCE_SET;
308 /* Process the hard codes for the keyboard controller */
309 path.u.pnp.device = KBC_DEVICE;
310 dev = alloc_find_dev(dev, &path);
311 resource = get_resource(dev, 0x60);
312 resource->base = 0x60;
313 resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
314 resource = get_resource(dev, 0x62);
315 resource->base = 0x64;
316 resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
319 struct chip_control superio_NSC_pc87360_control = {
320 .enable = sio_enable,
321 .enumerate = enumerate,
322 .name = "winbond w83627thf";