1 /*
2 * Copyright (c) 2025 Aesc Silicon
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT aesc_uart
8
9 #include <errno.h>
10 #include <ip_identification.h>
11 #include <soc.h>
12
13 #include <zephyr/device.h>
14 #include <zephyr/devicetree.h>
15 #include <zephyr/drivers/uart.h>
16 #include <zephyr/init.h>
17 #include <zephyr/kernel.h>
18
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(aesc_uart, CONFIG_UART_LOG_LEVEL);
21
22 struct uart_aesc_data {
23 DEVICE_MMIO_NAMED_RAM(regs);
24 };
25
26 struct uart_aesc_config {
27 DEVICE_MMIO_NAMED_ROM(regs);
28 uint64_t sys_clk_freq;
29 uint32_t current_speed;
30 };
31
32 struct uart_aesc_regs {
33 uint32_t data_width;
34 uint32_t sampling_sizes;
35 uint32_t fifo_depths;
36 uint32_t permissions;
37 uint32_t read_write;
38 uint32_t fifo_status;
39 uint32_t clock_div;
40 uint32_t frame_cfg;
41 uint32_t ip;
42 uint32_t ie;
43 };
44
45 #define DEV_CFG(dev) ((struct uart_aesc_config *)(dev)->config)
46 #define DEV_DATA(dev) ((struct uart_aesc_data *)(dev)->data)
47 #define DEV_UART(dev) \
48 ((struct uart_aesc_regs *)DEVICE_MMIO_NAMED_GET(dev, regs))
49
50 #define AESC_UART_IRQ_TX_EN BIT(0)
51 #define AESC_UART_IRQ_RX_EN BIT(1)
52 #define AESC_UART_FIFO_TX_COUNT_MASK GENMASK(23, 16)
53 #define AESC_UART_READ_FIFO_VALID_BIT BIT(16)
54
uart_aesc_poll_out(const struct device * dev,unsigned char c)55 static void uart_aesc_poll_out(const struct device *dev, unsigned char c)
56 {
57 struct uart_aesc_regs *uart = DEV_UART(dev);
58
59 while ((uart->fifo_status & AESC_UART_FIFO_TX_COUNT_MASK) == 0) {
60 /* Wait until transmit fifo is empty */
61 }
62 uart->read_write = c;
63 }
64
uart_aesc_poll_in(const struct device * dev,unsigned char * c)65 static int uart_aesc_poll_in(const struct device *dev, unsigned char *c)
66 {
67 const struct uart_aesc_regs *uart = DEV_UART(dev);
68 int val;
69
70 val = uart->read_write;
71 if (val & AESC_UART_READ_FIFO_VALID_BIT) {
72 *c = val & 0xFF;
73 return 0;
74 }
75
76 return -1;
77 }
78
uart_aesc_init(const struct device * dev)79 static int uart_aesc_init(const struct device *dev)
80 {
81 const struct uart_aesc_config *cfg = DEV_CFG(dev);
82 volatile uintptr_t *base_addr = (volatile uintptr_t *)DEV_UART(dev);
83 volatile struct uart_aesc_regs *uart;
84
85 DEVICE_MMIO_NAMED_MAP(dev, regs, K_MEM_CACHE_NONE);
86 LOG_DBG("IP core version: %i.%i.%i.",
87 ip_id_get_major_version(base_addr),
88 ip_id_get_minor_version(base_addr),
89 ip_id_get_patchlevel(base_addr)
90 );
91 DEVICE_MMIO_NAMED_GET(dev, regs) = ip_id_relocate_driver(base_addr);
92 LOG_DBG("Relocate driver to address 0x%lx.", DEVICE_MMIO_NAMED_GET(dev, regs));
93 uart = DEV_UART(dev);
94
95 uart->clock_div = cfg->sys_clk_freq / cfg->current_speed / 8;
96 uart->frame_cfg = 7;
97
98 return 0;
99 }
100
101 static DEVICE_API(uart, uart_aesc_driver_api) = {
102 .poll_in = uart_aesc_poll_in,
103 .poll_out = uart_aesc_poll_out,
104 .err_check = NULL,
105 };
106
107 #define AESC_UART_INIT(no) \
108 static struct uart_aesc_data uart_aesc_dev_data_##no; \
109 static struct uart_aesc_config uart_aesc_dev_cfg_##no = { \
110 DEVICE_MMIO_NAMED_ROM_INIT(regs, \
111 DT_INST(no, aesc_uart)), \
112 .sys_clk_freq = \
113 DT_PROP(DT_INST(no, aesc_uart), clock_frequency), \
114 .current_speed = \
115 DT_PROP(DT_INST(no, aesc_uart), current_speed), \
116 }; \
117 DEVICE_DT_INST_DEFINE(no, \
118 uart_aesc_init, \
119 NULL, \
120 &uart_aesc_dev_data_##no, \
121 &uart_aesc_dev_cfg_##no, \
122 PRE_KERNEL_1, \
123 CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
124 (void *)&uart_aesc_driver_api);
125
126 DT_INST_FOREACH_STATUS_OKAY(AESC_UART_INIT)
127