blob: 9c209e16c5f25c27e213009202f217f164eb330f [file] [log] [blame]
Angel Pons210a0082020-04-02 23:48:24 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Nico Huber016ef9e2017-09-19 14:13:34 +02003
4#include <console/console.h>
5#include <device/device.h>
6
7#include "chip.h"
8#include "kempld.h"
9#include "kempld_internal.h"
10
11static void kempld_uart_read_resources(struct device *dev)
12{
13 static const unsigned int io_addr[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
14
15 const struct ec_kontron_kempld_config *const config = dev->chip_info;
16
17 struct resource *const res_io = new_resource(dev, 0);
18 struct resource *const res_irq = new_resource(dev, 1);
19 const unsigned int uart = dev->path.generic.subid;
20 if (!config || !res_io || !res_irq || uart >= KEMPLD_NUM_UARTS)
21 return;
22
23 const enum kempld_uart_io io = config->uart[uart].io;
24 if (io >= ARRAY_SIZE(io_addr)) {
25 printk(BIOS_ERR, "KEMPLD: Bad io value '%d' for UART#%u\n.",
26 io, uart);
27 dev->enabled = false;
28 return;
29 }
30
31 const int irq = config->uart[uart].irq;
32 if (irq >= 16) {
33 printk(BIOS_ERR, "KEMPLD: Bad irq value '%d' for UART#%u\n.",
34 irq, uart);
35 dev->enabled = false;
36 return;
37 }
38
39 res_io->base = io_addr[io];
40 res_io->size = 8;
41 res_io->flags = IORESOURCE_IO | IORESOURCE_FIXED |
42 IORESOURCE_STORED | IORESOURCE_ASSIGNED;
43 res_irq->base = irq;
44 res_irq->size = 1;
45 res_irq->flags = IORESOURCE_IO | IORESOURCE_FIXED |
46 IORESOURCE_STORED | IORESOURCE_ASSIGNED;
47
48 if (kempld_get_mutex(100) < 0)
49 return;
50
51 const uint8_t reg = uart ? KEMPLD_UART_1 : KEMPLD_UART_0;
52 const uint8_t val = kempld_read8(reg);
53 kempld_write8(reg, (val & ~(KEMPLD_UART_IO_MASK | KEMPLD_UART_IRQ_MASK))
54 | io << KEMPLD_UART_IO_SHIFT
55 | irq << KEMPLD_UART_IRQ_SHIFT);
56
57 kempld_release_mutex();
58}
59
60static void kempld_uart_enable_resources(struct device *dev)
61{
62 if (kempld_get_mutex(100) < 0)
63 return;
64
65 const unsigned int uart = dev->path.generic.subid;
66 const uint8_t reg = uart ? KEMPLD_UART_1 : KEMPLD_UART_0;
67 kempld_write8(reg, kempld_read8(reg) | KEMPLD_UART_ENABLE);
68
69 kempld_release_mutex();
70}
71
72static struct device_operations kempld_uart_ops = {
73 .read_resources = kempld_uart_read_resources,
74 .enable_resources = kempld_uart_enable_resources,
75};
76
77static void kempld_enable_dev(struct device *const dev)
78{
79 if (dev->path.type == DEVICE_PATH_GENERIC) {
80 switch (dev->path.generic.id) {
81 case 0:
82 if (dev->path.generic.subid < KEMPLD_NUM_UARTS) {
83 dev->ops = &kempld_uart_ops;
84 break;
85 }
Nico Huber5fb34e82019-09-19 16:35:28 +020086 /* Fall through. */
Nico Huber016ef9e2017-09-19 14:13:34 +020087 case 1:
88 if (dev->path.generic.subid == 0) {
89 kempld_i2c_device_init(dev);
90 break;
91 }
Nico Huber5fb34e82019-09-19 16:35:28 +020092 /* Fall through. */
Nico Huber016ef9e2017-09-19 14:13:34 +020093 default:
94 printk(BIOS_WARNING,
95 "KEMPLD: Spurious device %s.\n",
96 dev_path(dev));
97 break;
98 }
99 }
100}
101
102struct chip_operations ec_kontron_kempld_ops = {
103 CHIP_NAME("Kontron KEMPLD")
104 .enable_dev = kempld_enable_dev,
105};