pnp_device: don't treat missing PNP_MSC devicetree entry as error
[coreboot.git] / src / device / pnp_device.c
blobe56b00d774fdfa7152c239fbe4d005e662434468
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2004 Linux Networx
5 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
6 * Copyright (C) 2004 Li-Ta Lo <ollie@lanl.gov>
7 * Copyright (C) 2005 Tyan
8 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
9 * Copyright (C) 2013 Nico Huber <nico.h@gmx.de>
10 * Copyright (C) 2018 Felix Held <felix-coreboot@felixheld.de>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2 of the License.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
22 #include <console/console.h>
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <string.h>
26 #include <arch/io.h>
27 #include <device/device.h>
28 #include <device/pnp.h>
30 /* PNP config mode wrappers */
32 void pnp_enter_conf_mode(struct device *dev)
34 if (dev->ops->ops_pnp_mode)
35 dev->ops->ops_pnp_mode->enter_conf_mode(dev);
38 void pnp_exit_conf_mode(struct device *dev)
40 if (dev->ops->ops_pnp_mode)
41 dev->ops->ops_pnp_mode->exit_conf_mode(dev);
44 /* PNP fundamental operations */
46 void pnp_write_config(struct device *dev, u8 reg, u8 value)
48 outb(reg, dev->path.pnp.port);
49 outb(value, dev->path.pnp.port + 1);
52 u8 pnp_read_config(struct device *dev, u8 reg)
54 outb(reg, dev->path.pnp.port);
55 return inb(dev->path.pnp.port + 1);
58 void pnp_set_logical_device(struct device *dev)
60 pnp_write_config(dev, 0x07, dev->path.pnp.device & 0xff);
63 void pnp_set_enable(struct device *dev, int enable)
65 u8 tmp, bitpos;
67 tmp = pnp_read_config(dev, 0x30);
69 /* Handle virtual devices, which share the same LDN register. */
70 bitpos = (dev->path.pnp.device >> 8) & 0x7;
72 if (enable)
73 tmp |= (1 << bitpos);
74 else
75 tmp &= ~(1 << bitpos);
77 pnp_write_config(dev, 0x30, tmp);
80 int pnp_read_enable(struct device *dev)
82 u8 tmp, bitpos;
84 tmp = pnp_read_config(dev, 0x30);
86 /* Handle virtual devices, which share the same LDN register. */
87 bitpos = (dev->path.pnp.device >> 8) & 0x7;
89 return !!(tmp & (1 << bitpos));
92 void pnp_set_iobase(struct device *dev, u8 index, u16 iobase)
94 /* Index == 0x60 or 0x62. */
95 pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff);
96 pnp_write_config(dev, index + 1, iobase & 0xff);
99 void pnp_set_irq(struct device *dev, u8 index, u8 irq)
101 /* Index == 0x70 or 0x72. */
102 pnp_write_config(dev, index, irq);
105 void pnp_set_drq(struct device *dev, u8 index, u8 drq)
107 /* Index == 0x74. */
108 pnp_write_config(dev, index, drq & 0xff);
111 /* PNP device operations */
113 void pnp_read_resources(struct device *dev)
115 return;
118 static void pnp_set_resource(struct device *dev, struct resource *resource)
120 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
121 /* The PNP_MSC super IO registers have the IRQ flag set. If no
122 value is assigned in the devicetree, the corresponding
123 PNP_MSC register doesn't get written, which should be printed
124 as warning and not as error. */
125 if (resource->flags & IORESOURCE_IRQ &&
126 (resource->index != PNP_IDX_IRQ0) &&
127 (resource->index != PNP_IDX_IRQ1))
128 printk(BIOS_WARNING, "WARNING: %s %02lx %s size: "
129 "0x%010llx not assigned\n", dev_path(dev),
130 resource->index, resource_type(resource),
131 resource->size);
132 else
133 printk(BIOS_ERR, "ERROR: %s %02lx %s size: 0x%010llx "
134 "not assigned\n", dev_path(dev), resource->index,
135 resource_type(resource), resource->size);
136 return;
139 /* Now store the resource. */
140 if (resource->flags & IORESOURCE_IO) {
141 pnp_set_iobase(dev, resource->index, resource->base);
142 } else if (resource->flags & IORESOURCE_DRQ) {
143 pnp_set_drq(dev, resource->index, resource->base);
144 } else if (resource->flags & IORESOURCE_IRQ) {
145 pnp_set_irq(dev, resource->index, resource->base);
146 } else {
147 printk(BIOS_ERR, "ERROR: %s %02lx unknown resource type\n",
148 dev_path(dev), resource->index);
149 return;
151 resource->flags |= IORESOURCE_STORED;
153 report_resource_stored(dev, resource, "");
156 void pnp_set_resources(struct device *dev)
158 struct resource *res;
160 pnp_enter_conf_mode(dev);
162 /* Select the logical device (LDN). */
163 pnp_set_logical_device(dev);
165 /* Paranoia says I should disable the device here... */
166 for (res = dev->resource_list; res; res = res->next)
167 pnp_set_resource(dev, res);
169 pnp_exit_conf_mode(dev);
172 void pnp_enable_resources(struct device *dev)
174 pnp_enter_conf_mode(dev);
175 pnp_set_logical_device(dev);
176 pnp_set_enable(dev, 1);
177 pnp_exit_conf_mode(dev);
180 void pnp_enable(struct device *dev)
182 if (!dev->enabled) {
183 pnp_enter_conf_mode(dev);
184 pnp_set_logical_device(dev);
185 pnp_set_enable(dev, 0);
186 pnp_exit_conf_mode(dev);
190 void pnp_alt_enable(struct device *dev)
192 pnp_enter_conf_mode(dev);
193 pnp_set_logical_device(dev);
194 pnp_set_enable(dev, !!dev->enabled);
195 pnp_exit_conf_mode(dev);
198 struct device_operations pnp_ops = {
199 .read_resources = pnp_read_resources,
200 .set_resources = pnp_set_resources,
201 .enable_resources = pnp_enable_resources,
202 .enable = pnp_enable,
205 /* PNP chip operations */
207 static void pnp_get_ioresource(struct device *dev, u8 index, u16 mask)
209 struct resource *resource;
210 unsigned int bit;
212 /* If none of the mask bits is set, the resource would occupy the whole
213 IO space leading to IO resource conflicts with the other devices */
214 if (!mask) {
215 printk(BIOS_ERR, "ERROR: device %s index %d has no mask.\n",
216 dev_path(dev), index);
217 return;
220 resource = new_resource(dev, index);
221 resource->flags |= IORESOURCE_IO;
223 /* Calculate IO region size which is determined by the first one from
224 the LSB of the mask. */
225 for (bit = 0; bit <= 15 && (mask & (1 << bit)) == 0; ++bit)
228 resource->gran = bit;
229 resource->align = bit;
230 resource->size = 1 << bit;
232 /* Calculate IO region address limit which is determined by the first
233 one from the MSB of the mask. */
234 for (bit = 15; bit != 0 && (mask & (1 << bit)) == 0; --bit)
237 resource->limit = (1 << (bit + 1)) - 1;
239 /* The block of ones in the mask is expected to be continuous.
240 If there is any zero inbetween the block of ones, it is ignored
241 in the calculation of the resource size and limit. */
242 if (mask != (resource->limit ^ (resource->size - 1)))
243 printk(BIOS_WARNING,
244 "WARNING: mask of device %s index %d is wrong.\n",
245 dev_path(dev), index);
248 static void get_resources(struct device *dev, struct pnp_info *info)
250 struct resource *resource;
252 if (info->flags & PNP_IO0)
253 pnp_get_ioresource(dev, PNP_IDX_IO0, info->io0);
254 if (info->flags & PNP_IO1)
255 pnp_get_ioresource(dev, PNP_IDX_IO1, info->io1);
256 if (info->flags & PNP_IO2)
257 pnp_get_ioresource(dev, PNP_IDX_IO2, info->io2);
258 if (info->flags & PNP_IO3)
259 pnp_get_ioresource(dev, PNP_IDX_IO3, info->io3);
261 if (info->flags & PNP_IRQ0) {
262 resource = new_resource(dev, PNP_IDX_IRQ0);
263 resource->size = 1;
264 resource->flags |= IORESOURCE_IRQ;
266 if (info->flags & PNP_IRQ1) {
267 resource = new_resource(dev, PNP_IDX_IRQ1);
268 resource->size = 1;
269 resource->flags |= IORESOURCE_IRQ;
272 if (info->flags & PNP_DRQ0) {
273 resource = new_resource(dev, PNP_IDX_DRQ0);
274 resource->size = 1;
275 resource->flags |= IORESOURCE_DRQ;
277 if (info->flags & PNP_DRQ1) {
278 resource = new_resource(dev, PNP_IDX_DRQ1);
279 resource->size = 1;
280 resource->flags |= IORESOURCE_DRQ;
284 * These are not IRQs, but set the flag to have the
285 * resource allocator do the right thing.
287 if (info->flags & PNP_EN) {
288 resource = new_resource(dev, PNP_IDX_EN);
289 resource->size = 1;
290 resource->flags |= IORESOURCE_IRQ;
292 if (info->flags & PNP_MSC0) {
293 resource = new_resource(dev, PNP_IDX_MSC0);
294 resource->size = 1;
295 resource->flags |= IORESOURCE_IRQ;
297 if (info->flags & PNP_MSC1) {
298 resource = new_resource(dev, PNP_IDX_MSC1);
299 resource->size = 1;
300 resource->flags |= IORESOURCE_IRQ;
302 if (info->flags & PNP_MSC2) {
303 resource = new_resource(dev, PNP_IDX_MSC2);
304 resource->size = 1;
305 resource->flags |= IORESOURCE_IRQ;
307 if (info->flags & PNP_MSC3) {
308 resource = new_resource(dev, PNP_IDX_MSC3);
309 resource->size = 1;
310 resource->flags |= IORESOURCE_IRQ;
312 if (info->flags & PNP_MSC4) {
313 resource = new_resource(dev, PNP_IDX_MSC4);
314 resource->size = 1;
315 resource->flags |= IORESOURCE_IRQ;
317 if (info->flags & PNP_MSC5) {
318 resource = new_resource(dev, PNP_IDX_MSC5);
319 resource->size = 1;
320 resource->flags |= IORESOURCE_IRQ;
322 if (info->flags & PNP_MSC6) {
323 resource = new_resource(dev, PNP_IDX_MSC6);
324 resource->size = 1;
325 resource->flags |= IORESOURCE_IRQ;
327 if (info->flags & PNP_MSC7) {
328 resource = new_resource(dev, PNP_IDX_MSC7);
329 resource->size = 1;
330 resource->flags |= IORESOURCE_IRQ;
332 if (info->flags & PNP_MSC8) {
333 resource = new_resource(dev, PNP_IDX_MSC8);
334 resource->size = 1;
335 resource->flags |= IORESOURCE_IRQ;
337 if (info->flags & PNP_MSC9) {
338 resource = new_resource(dev, PNP_IDX_MSC9);
339 resource->size = 1;
340 resource->flags |= IORESOURCE_IRQ;
342 if (info->flags & PNP_MSCA) {
343 resource = new_resource(dev, PNP_IDX_MSCA);
344 resource->size = 1;
345 resource->flags |= IORESOURCE_IRQ;
347 if (info->flags & PNP_MSCB) {
348 resource = new_resource(dev, PNP_IDX_MSCB);
349 resource->size = 1;
350 resource->flags |= IORESOURCE_IRQ;
352 if (info->flags & PNP_MSCC) {
353 resource = new_resource(dev, PNP_IDX_MSCC);
354 resource->size = 1;
355 resource->flags |= IORESOURCE_IRQ;
357 if (info->flags & PNP_MSCD) {
358 resource = new_resource(dev, PNP_IDX_MSCD);
359 resource->size = 1;
360 resource->flags |= IORESOURCE_IRQ;
362 if (info->flags & PNP_MSCE) {
363 resource = new_resource(dev, PNP_IDX_MSCE);
364 resource->size = 1;
365 resource->flags |= IORESOURCE_IRQ;
369 void pnp_enable_devices(struct device *base_dev, struct device_operations *ops,
370 unsigned int functions, struct pnp_info *info)
372 struct device_path path;
373 struct device *dev;
374 int i;
376 path.type = DEVICE_PATH_PNP;
377 path.pnp.port = base_dev->path.pnp.port;
379 /* Setup the ops and resources on the newly allocated devices. */
380 for (i = 0; i < functions; i++) {
381 /* Skip logical devices this Super I/O doesn't have. */
382 if (info[i].function == -1)
383 continue;
385 path.pnp.device = info[i].function;
386 dev = alloc_find_dev(base_dev->bus, &path);
388 /* Don't initialize a device multiple times. */
389 if (dev->ops)
390 continue;
392 /* use LDN-specific ops override from corresponding pnp_info
393 entry if not NULL */
394 if (info[i].ops)
395 dev->ops = info[i].ops;
396 /* else use device ops */
397 else
398 dev->ops = ops;
400 get_resources(dev, &info[i]);