soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / device / pnp_device.c
blob9405d88e55fec8baf2bc0dafd3b0098e3c203a6b
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/io.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pnp.h>
7 #include <stdint.h>
9 /* PNP config mode wrappers */
11 void pnp_enter_conf_mode(struct device *dev)
13 if (dev->ops->ops_pnp_mode)
14 dev->ops->ops_pnp_mode->enter_conf_mode(dev);
17 void pnp_exit_conf_mode(struct device *dev)
19 if (dev->ops->ops_pnp_mode)
20 dev->ops->ops_pnp_mode->exit_conf_mode(dev);
23 #if CONFIG(HAVE_ACPI_TABLES)
24 void pnp_ssdt_enter_conf_mode(struct device *dev, const char *idx, const char *data)
26 if (dev->ops->ops_pnp_mode && dev->ops->ops_pnp_mode->ssdt_enter_conf_mode)
27 dev->ops->ops_pnp_mode->ssdt_enter_conf_mode(dev, idx, data);
29 void pnp_ssdt_exit_conf_mode(struct device *dev, const char *idx, const char *data)
31 if (dev->ops->ops_pnp_mode && dev->ops->ops_pnp_mode->ssdt_exit_conf_mode)
32 dev->ops->ops_pnp_mode->ssdt_exit_conf_mode(dev, idx, data);
34 #endif
36 /* PNP fundamental operations */
38 void pnp_write_config(struct device *dev, u8 reg, u8 value)
40 outb(reg, dev->path.pnp.port);
41 outb(value, dev->path.pnp.port + 1);
44 u8 pnp_read_config(struct device *dev, u8 reg)
46 outb(reg, dev->path.pnp.port);
47 return inb(dev->path.pnp.port + 1);
50 void pnp_unset_and_set_config(struct device *dev, u8 reg, u8 unset, u8 set)
52 outb(reg, dev->path.pnp.port);
53 u8 value = inb(dev->path.pnp.port + 1);
54 value &= ~unset;
55 value |= set;
56 outb(value, dev->path.pnp.port + 1);
59 void pnp_set_logical_device(struct device *dev)
61 pnp_write_config(dev, 0x07, dev->path.pnp.device & 0xff);
64 void pnp_set_enable(struct device *dev, int enable)
66 u8 tmp, bitpos;
68 tmp = pnp_read_config(dev, PNP_IDX_EN);
70 /* Handle virtual devices, which share the same LDN register. */
71 bitpos = (dev->path.pnp.device >> 8) & 0x7;
73 if (enable)
74 tmp |= (1 << bitpos);
75 else
76 tmp &= ~(1 << bitpos);
78 pnp_write_config(dev, PNP_IDX_EN, tmp);
81 int pnp_read_enable(struct device *dev)
83 u8 tmp, bitpos;
85 tmp = pnp_read_config(dev, PNP_IDX_EN);
87 /* Handle virtual devices, which share the same LDN register. */
88 bitpos = (dev->path.pnp.device >> 8) & 0x7;
90 return !!(tmp & (1 << bitpos));
93 void pnp_set_iobase(struct device *dev, u8 index, u16 iobase)
95 /* Index == 0x60 or 0x62. */
96 pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff);
97 pnp_write_config(dev, index + 1, iobase & 0xff);
100 void pnp_set_irq(struct device *dev, u8 index, u8 irq)
102 /* Index == 0x70 or 0x72. */
103 pnp_write_config(dev, index, irq);
106 void pnp_set_drq(struct device *dev, u8 index, u8 drq)
108 /* Index == 0x74. */
109 pnp_write_config(dev, index, drq & 0xff);
112 /* PNP device operations */
114 void pnp_read_resources(struct device *dev)
116 return;
119 static void pnp_set_resource(struct device *dev, struct resource *resource)
121 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
122 /* The PNP_MSC Super IO registers have the IRQ flag set. If no
123 value is assigned in the devicetree, the corresponding
124 PNP_MSC register doesn't get written, which should be printed
125 as warning and not as error. */
126 if (resource->flags & IORESOURCE_IRQ &&
127 (resource->index != PNP_IDX_IRQ0) &&
128 (resource->index != PNP_IDX_IRQ1))
129 printk(BIOS_WARNING, "%s %02lx %s size: "
130 "0x%010llx not assigned in devicetree\n", dev_path(dev),
131 resource->index, resource_type(resource),
132 resource->size);
133 else
134 printk(BIOS_ERR, "%s %02lx %s size: 0x%010llx "
135 "not assigned in devicetree\n", dev_path(dev), resource->index,
136 resource_type(resource), resource->size);
137 return;
140 /* Now store the resource. */
141 if (resource->flags & IORESOURCE_IO) {
142 pnp_set_iobase(dev, resource->index, resource->base);
143 } else if (resource->flags & IORESOURCE_DRQ) {
144 pnp_set_drq(dev, resource->index, resource->base);
145 } else if (resource->flags & IORESOURCE_IRQ) {
146 pnp_set_irq(dev, resource->index, resource->base);
147 } else {
148 printk(BIOS_ERR, "%s %02lx unknown resource type\n",
149 dev_path(dev), resource->index);
150 return;
152 resource->flags |= IORESOURCE_STORED;
154 report_resource_stored(dev, resource, "");
157 void pnp_set_resources(struct device *dev)
159 struct resource *res;
161 pnp_enter_conf_mode(dev);
163 /* Select the logical device (LDN). */
164 pnp_set_logical_device(dev);
166 /* Paranoia says I should disable the device here... */
167 for (res = dev->resource_list; res; res = res->next)
168 pnp_set_resource(dev, res);
170 pnp_exit_conf_mode(dev);
173 void pnp_enable_resources(struct device *dev)
175 pnp_enter_conf_mode(dev);
176 pnp_set_logical_device(dev);
177 pnp_set_enable(dev, 1);
178 pnp_exit_conf_mode(dev);
181 void pnp_enable(struct device *dev)
183 if (!dev->enabled) {
184 pnp_enter_conf_mode(dev);
185 pnp_set_logical_device(dev);
186 pnp_set_enable(dev, 0);
187 pnp_exit_conf_mode(dev);
191 void pnp_alt_enable(struct device *dev)
193 pnp_enter_conf_mode(dev);
194 pnp_set_logical_device(dev);
195 pnp_set_enable(dev, !!dev->enabled);
196 pnp_exit_conf_mode(dev);
199 struct device_operations pnp_ops = {
200 .read_resources = pnp_read_resources,
201 .set_resources = pnp_set_resources,
202 .enable_resources = pnp_enable_resources,
203 .enable = pnp_enable,
206 /* PNP chip operations */
208 static void pnp_get_ioresource(struct device *dev, u8 index, u16 mask)
210 struct resource *resource;
211 unsigned int bit;
213 /* If none of the mask bits is set, the resource would occupy the whole
214 IO space leading to IO resource conflicts with the other devices */
215 if (!mask) {
216 printk(BIOS_ERR, "device %s index %d has no mask.\n",
217 dev_path(dev), index);
218 return;
221 resource = new_resource(dev, index);
222 resource->flags |= IORESOURCE_IO;
224 /* Calculate IO region size which is determined by the first one from
225 the LSB of the mask. */
226 for (bit = 0; bit <= 15 && (mask & (1 << bit)) == 0; ++bit)
229 resource->gran = bit;
230 resource->align = bit;
231 resource->size = 1 << bit;
233 /* Calculate IO region address limit which is determined by the first
234 one from the MSB of the mask. */
235 for (bit = 15; bit != 0 && (mask & (1 << bit)) == 0; --bit)
238 resource->limit = (1 << (bit + 1)) - 1;
240 /* The block of ones in the mask is expected to be continuous.
241 If there is any zero in between the block of ones, it is ignored
242 in the calculation of the resource size and limit. */
243 if (mask != (resource->limit ^ (resource->size - 1)))
244 printk(BIOS_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);
260 if (info->flags & PNP_IO4)
261 pnp_get_ioresource(dev, PNP_IDX_IO4, info->io4);
263 if (info->flags & PNP_IRQ0) {
264 resource = new_resource(dev, PNP_IDX_IRQ0);
265 resource->size = 1;
266 resource->flags |= IORESOURCE_IRQ;
268 if (info->flags & PNP_IRQ1) {
269 resource = new_resource(dev, PNP_IDX_IRQ1);
270 resource->size = 1;
271 resource->flags |= IORESOURCE_IRQ;
274 if (info->flags & PNP_DRQ0) {
275 resource = new_resource(dev, PNP_IDX_DRQ0);
276 resource->size = 1;
277 resource->flags |= IORESOURCE_DRQ;
279 if (info->flags & PNP_DRQ1) {
280 resource = new_resource(dev, PNP_IDX_DRQ1);
281 resource->size = 1;
282 resource->flags |= IORESOURCE_DRQ;
286 * These are not IRQs, but set the flag to have the
287 * resource allocator do the right thing.
289 if (info->flags & PNP_EN) {
290 resource = new_resource(dev, PNP_IDX_EN);
291 resource->size = 1;
292 resource->flags |= IORESOURCE_IRQ;
294 if (info->flags & PNP_MSC0) {
295 resource = new_resource(dev, PNP_IDX_MSC0);
296 resource->size = 1;
297 resource->flags |= IORESOURCE_IRQ;
299 if (info->flags & PNP_MSC1) {
300 resource = new_resource(dev, PNP_IDX_MSC1);
301 resource->size = 1;
302 resource->flags |= IORESOURCE_IRQ;
304 if (info->flags & PNP_MSC2) {
305 resource = new_resource(dev, PNP_IDX_MSC2);
306 resource->size = 1;
307 resource->flags |= IORESOURCE_IRQ;
309 if (info->flags & PNP_MSC3) {
310 resource = new_resource(dev, PNP_IDX_MSC3);
311 resource->size = 1;
312 resource->flags |= IORESOURCE_IRQ;
314 if (info->flags & PNP_MSC4) {
315 resource = new_resource(dev, PNP_IDX_MSC4);
316 resource->size = 1;
317 resource->flags |= IORESOURCE_IRQ;
319 if (info->flags & PNP_MSC5) {
320 resource = new_resource(dev, PNP_IDX_MSC5);
321 resource->size = 1;
322 resource->flags |= IORESOURCE_IRQ;
324 if (info->flags & PNP_MSC6) {
325 resource = new_resource(dev, PNP_IDX_MSC6);
326 resource->size = 1;
327 resource->flags |= IORESOURCE_IRQ;
329 if (info->flags & PNP_MSC7) {
330 resource = new_resource(dev, PNP_IDX_MSC7);
331 resource->size = 1;
332 resource->flags |= IORESOURCE_IRQ;
334 if (info->flags & PNP_MSC8) {
335 resource = new_resource(dev, PNP_IDX_MSC8);
336 resource->size = 1;
337 resource->flags |= IORESOURCE_IRQ;
339 if (info->flags & PNP_MSC9) {
340 resource = new_resource(dev, PNP_IDX_MSC9);
341 resource->size = 1;
342 resource->flags |= IORESOURCE_IRQ;
344 if (info->flags & PNP_MSCA) {
345 resource = new_resource(dev, PNP_IDX_MSCA);
346 resource->size = 1;
347 resource->flags |= IORESOURCE_IRQ;
349 if (info->flags & PNP_MSCB) {
350 resource = new_resource(dev, PNP_IDX_MSCB);
351 resource->size = 1;
352 resource->flags |= IORESOURCE_IRQ;
354 if (info->flags & PNP_MSCC) {
355 resource = new_resource(dev, PNP_IDX_MSCC);
356 resource->size = 1;
357 resource->flags |= IORESOURCE_IRQ;
359 if (info->flags & PNP_MSCD) {
360 resource = new_resource(dev, PNP_IDX_MSCD);
361 resource->size = 1;
362 resource->flags |= IORESOURCE_IRQ;
364 if (info->flags & PNP_MSCE) {
365 resource = new_resource(dev, PNP_IDX_MSCE);
366 resource->size = 1;
367 resource->flags |= IORESOURCE_IRQ;
371 void pnp_enable_devices(struct device *base_dev, struct device_operations *ops,
372 unsigned int functions, struct pnp_info *info)
374 struct device_path path;
375 struct device *dev;
376 int i;
378 path.type = DEVICE_PATH_PNP;
379 path.pnp.port = base_dev->path.pnp.port;
381 /* Setup the ops and resources on the newly allocated devices. */
382 for (i = 0; i < functions; i++) {
383 /* Skip logical devices this Super I/O doesn't have. */
384 if (info[i].function == PNP_SKIP_FUNCTION)
385 continue;
387 path.pnp.device = info[i].function;
388 dev = alloc_find_dev(base_dev->bus, &path);
390 /* Don't initialize a device multiple times. */
391 if (dev->ops)
392 continue;
394 /* use LDN-specific ops override from corresponding pnp_info
395 entry if not NULL */
396 if (info[i].ops)
397 dev->ops = info[i].ops;
398 /* else use device ops */
399 else
400 dev->ops = ops;
402 get_resources(dev, &info[i]);