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