blob: 31d927d029a38b28e000b58af5f8dc383ba623c9 [file] [log] [blame]
Angel Pons210a0082020-04-02 23:48:24 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Nico Huber016ef9e2017-09-19 14:13:34 +02002
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
10static 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
16 struct resource *const res_io = new_resource(dev, 0);
17 struct resource *const res_irq = new_resource(dev, 1);
18 const unsigned int uart = dev->path.generic.subid;
Maxim Polyakov7b27f4b2020-09-27 12:14:09 +030019
Nico Huber016ef9e2017-09-19 14:13:34 +020020 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)) {
Maxim Polyakov7b27f4b2020-09-27 12:14:09 +030025 printk(BIOS_ERR, "KEMPLD: Bad io value '%d' for UART#%u\n.", io, uart);
Nico Huber016ef9e2017-09-19 14:13:34 +020026 dev->enabled = false;
27 return;
28 }
29
30 const int irq = config->uart[uart].irq;
31 if (irq >= 16) {
Maxim Polyakov7b27f4b2020-09-27 12:14:09 +030032 printk(BIOS_ERR, "KEMPLD: Bad irq value '%d' for UART#%u\n.", irq, uart);
Nico Huber016ef9e2017-09-19 14:13:34 +020033 dev->enabled = false;
34 return;
35 }
36
37 res_io->base = io_addr[io];
38 res_io->size = 8;
39 res_io->flags = IORESOURCE_IO | IORESOURCE_FIXED |
40 IORESOURCE_STORED | IORESOURCE_ASSIGNED;
41 res_irq->base = irq;
42 res_irq->size = 1;
43 res_irq->flags = IORESOURCE_IO | 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);
Maxim Polyakov7b27f4b2020-09-27 12:14:09 +030051 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);
Nico Huber016ef9e2017-09-19 14:13:34 +020055
56 kempld_release_mutex();
57}
58
59static 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
71static struct device_operations kempld_uart_ops = {
72 .read_resources = kempld_uart_read_resources,
73 .enable_resources = kempld_uart_enable_resources,
74};
75
76static 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 }
Arthur Heymansfff20212021-03-15 14:56:16 +010085 __fallthrough;
Nico Huber016ef9e2017-09-19 14:13:34 +020086 case 1:
87 if (dev->path.generic.subid == 0) {
88 kempld_i2c_device_init(dev);
89 break;
90 }
Arthur Heymansfff20212021-03-15 14:56:16 +010091 __fallthrough;
Nico Huber016ef9e2017-09-19 14:13:34 +020092 default:
Maxim Polyakov7b27f4b2020-09-27 12:14:09 +030093 printk(BIOS_WARNING, "KEMPLD: Spurious device %s.\n", dev_path(dev));
Nico Huber016ef9e2017-09-19 14:13:34 +020094 break;
95 }
Maxim Polyakov9941e5a2020-11-14 18:42:10 +030096 } 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 }
Nico Huber016ef9e2017-09-19 14:13:34 +0200104 }
105}
106
107struct chip_operations ec_kontron_kempld_ops = {
108 CHIP_NAME("Kontron KEMPLD")
109 .enable_dev = kempld_enable_dev,
110};