xref: /openbmc/qemu/hw/char/shakti_uart.c (revision 07f334d8)
1*07f334d8SVijai Kumar K /*
2*07f334d8SVijai Kumar K  * SHAKTI UART
3*07f334d8SVijai Kumar K  *
4*07f334d8SVijai Kumar K  * Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
5*07f334d8SVijai Kumar K  *
6*07f334d8SVijai Kumar K  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*07f334d8SVijai Kumar K  * of this software and associated documentation files (the "Software"), to deal
8*07f334d8SVijai Kumar K  * in the Software without restriction, including without limitation the rights
9*07f334d8SVijai Kumar K  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*07f334d8SVijai Kumar K  * copies of the Software, and to permit persons to whom the Software is
11*07f334d8SVijai Kumar K  * furnished to do so, subject to the following conditions:
12*07f334d8SVijai Kumar K  *
13*07f334d8SVijai Kumar K  * The above copyright notice and this permission notice shall be included in
14*07f334d8SVijai Kumar K  * all copies or substantial portions of the Software.
15*07f334d8SVijai Kumar K  *
16*07f334d8SVijai Kumar K  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*07f334d8SVijai Kumar K  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*07f334d8SVijai Kumar K  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*07f334d8SVijai Kumar K  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*07f334d8SVijai Kumar K  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*07f334d8SVijai Kumar K  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22*07f334d8SVijai Kumar K  * THE SOFTWARE.
23*07f334d8SVijai Kumar K  */
24*07f334d8SVijai Kumar K 
25*07f334d8SVijai Kumar K #include "qemu/osdep.h"
26*07f334d8SVijai Kumar K #include "hw/char/shakti_uart.h"
27*07f334d8SVijai Kumar K #include "hw/qdev-properties.h"
28*07f334d8SVijai Kumar K #include "hw/qdev-properties-system.h"
29*07f334d8SVijai Kumar K #include "qemu/log.h"
30*07f334d8SVijai Kumar K 
31*07f334d8SVijai Kumar K static uint64_t shakti_uart_read(void *opaque, hwaddr addr, unsigned size)
32*07f334d8SVijai Kumar K {
33*07f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
34*07f334d8SVijai Kumar K 
35*07f334d8SVijai Kumar K     switch (addr) {
36*07f334d8SVijai Kumar K     case SHAKTI_UART_BAUD:
37*07f334d8SVijai Kumar K         return s->uart_baud;
38*07f334d8SVijai Kumar K     case SHAKTI_UART_RX:
39*07f334d8SVijai Kumar K         qemu_chr_fe_accept_input(&s->chr);
40*07f334d8SVijai Kumar K         s->uart_status &= ~SHAKTI_UART_STATUS_RX_NOT_EMPTY;
41*07f334d8SVijai Kumar K         return s->uart_rx;
42*07f334d8SVijai Kumar K     case SHAKTI_UART_STATUS:
43*07f334d8SVijai Kumar K         return s->uart_status;
44*07f334d8SVijai Kumar K     case SHAKTI_UART_DELAY:
45*07f334d8SVijai Kumar K         return s->uart_delay;
46*07f334d8SVijai Kumar K     case SHAKTI_UART_CONTROL:
47*07f334d8SVijai Kumar K         return s->uart_control;
48*07f334d8SVijai Kumar K     case SHAKTI_UART_INT_EN:
49*07f334d8SVijai Kumar K         return s->uart_interrupt;
50*07f334d8SVijai Kumar K     case SHAKTI_UART_IQ_CYCLES:
51*07f334d8SVijai Kumar K         return s->uart_iq_cycles;
52*07f334d8SVijai Kumar K     case SHAKTI_UART_RX_THRES:
53*07f334d8SVijai Kumar K         return s->uart_rx_threshold;
54*07f334d8SVijai Kumar K     default:
55*07f334d8SVijai Kumar K         /* Also handles TX REG which is write only */
56*07f334d8SVijai Kumar K         qemu_log_mask(LOG_GUEST_ERROR,
57*07f334d8SVijai Kumar K                       "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
58*07f334d8SVijai Kumar K     }
59*07f334d8SVijai Kumar K 
60*07f334d8SVijai Kumar K     return 0;
61*07f334d8SVijai Kumar K }
62*07f334d8SVijai Kumar K 
63*07f334d8SVijai Kumar K static void shakti_uart_write(void *opaque, hwaddr addr,
64*07f334d8SVijai Kumar K                               uint64_t data, unsigned size)
65*07f334d8SVijai Kumar K {
66*07f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
67*07f334d8SVijai Kumar K     uint32_t value = data;
68*07f334d8SVijai Kumar K     uint8_t ch;
69*07f334d8SVijai Kumar K 
70*07f334d8SVijai Kumar K     switch (addr) {
71*07f334d8SVijai Kumar K     case SHAKTI_UART_BAUD:
72*07f334d8SVijai Kumar K         s->uart_baud = value;
73*07f334d8SVijai Kumar K         break;
74*07f334d8SVijai Kumar K     case SHAKTI_UART_TX:
75*07f334d8SVijai Kumar K         ch = value;
76*07f334d8SVijai Kumar K         qemu_chr_fe_write_all(&s->chr, &ch, 1);
77*07f334d8SVijai Kumar K         s->uart_status &= ~SHAKTI_UART_STATUS_TX_FULL;
78*07f334d8SVijai Kumar K         break;
79*07f334d8SVijai Kumar K     case SHAKTI_UART_STATUS:
80*07f334d8SVijai Kumar K         s->uart_status = value;
81*07f334d8SVijai Kumar K         break;
82*07f334d8SVijai Kumar K     case SHAKTI_UART_DELAY:
83*07f334d8SVijai Kumar K         s->uart_delay = value;
84*07f334d8SVijai Kumar K         break;
85*07f334d8SVijai Kumar K     case SHAKTI_UART_CONTROL:
86*07f334d8SVijai Kumar K         s->uart_control = value;
87*07f334d8SVijai Kumar K         break;
88*07f334d8SVijai Kumar K     case SHAKTI_UART_INT_EN:
89*07f334d8SVijai Kumar K         s->uart_interrupt = value;
90*07f334d8SVijai Kumar K         break;
91*07f334d8SVijai Kumar K     case SHAKTI_UART_IQ_CYCLES:
92*07f334d8SVijai Kumar K         s->uart_iq_cycles = value;
93*07f334d8SVijai Kumar K         break;
94*07f334d8SVijai Kumar K     case SHAKTI_UART_RX_THRES:
95*07f334d8SVijai Kumar K         s->uart_rx_threshold = value;
96*07f334d8SVijai Kumar K         break;
97*07f334d8SVijai Kumar K     default:
98*07f334d8SVijai Kumar K         qemu_log_mask(LOG_GUEST_ERROR,
99*07f334d8SVijai Kumar K                       "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
100*07f334d8SVijai Kumar K     }
101*07f334d8SVijai Kumar K }
102*07f334d8SVijai Kumar K 
103*07f334d8SVijai Kumar K static const MemoryRegionOps shakti_uart_ops = {
104*07f334d8SVijai Kumar K     .read = shakti_uart_read,
105*07f334d8SVijai Kumar K     .write = shakti_uart_write,
106*07f334d8SVijai Kumar K     .endianness = DEVICE_NATIVE_ENDIAN,
107*07f334d8SVijai Kumar K     .impl = {.min_access_size = 1, .max_access_size = 4},
108*07f334d8SVijai Kumar K     .valid = {.min_access_size = 1, .max_access_size = 4},
109*07f334d8SVijai Kumar K };
110*07f334d8SVijai Kumar K 
111*07f334d8SVijai Kumar K static void shakti_uart_reset(DeviceState *dev)
112*07f334d8SVijai Kumar K {
113*07f334d8SVijai Kumar K     ShaktiUartState *s = SHAKTI_UART(dev);
114*07f334d8SVijai Kumar K 
115*07f334d8SVijai Kumar K     s->uart_baud = SHAKTI_UART_BAUD_DEFAULT;
116*07f334d8SVijai Kumar K     s->uart_tx = 0x0;
117*07f334d8SVijai Kumar K     s->uart_rx = 0x0;
118*07f334d8SVijai Kumar K     s->uart_status = 0x0000;
119*07f334d8SVijai Kumar K     s->uart_delay = 0x0000;
120*07f334d8SVijai Kumar K     s->uart_control = SHAKTI_UART_CONTROL_DEFAULT;
121*07f334d8SVijai Kumar K     s->uart_interrupt = 0x0000;
122*07f334d8SVijai Kumar K     s->uart_iq_cycles = 0x00;
123*07f334d8SVijai Kumar K     s->uart_rx_threshold = 0x00;
124*07f334d8SVijai Kumar K }
125*07f334d8SVijai Kumar K 
126*07f334d8SVijai Kumar K static int shakti_uart_can_receive(void *opaque)
127*07f334d8SVijai Kumar K {
128*07f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
129*07f334d8SVijai Kumar K 
130*07f334d8SVijai Kumar K     return !(s->uart_status & SHAKTI_UART_STATUS_RX_NOT_EMPTY);
131*07f334d8SVijai Kumar K }
132*07f334d8SVijai Kumar K 
133*07f334d8SVijai Kumar K static void shakti_uart_receive(void *opaque, const uint8_t *buf, int size)
134*07f334d8SVijai Kumar K {
135*07f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
136*07f334d8SVijai Kumar K 
137*07f334d8SVijai Kumar K     s->uart_rx = *buf;
138*07f334d8SVijai Kumar K     s->uart_status |= SHAKTI_UART_STATUS_RX_NOT_EMPTY;
139*07f334d8SVijai Kumar K }
140*07f334d8SVijai Kumar K 
141*07f334d8SVijai Kumar K static void shakti_uart_realize(DeviceState *dev, Error **errp)
142*07f334d8SVijai Kumar K {
143*07f334d8SVijai Kumar K     ShaktiUartState *sus = SHAKTI_UART(dev);
144*07f334d8SVijai Kumar K     qemu_chr_fe_set_handlers(&sus->chr, shakti_uart_can_receive,
145*07f334d8SVijai Kumar K                              shakti_uart_receive, NULL, NULL, sus, NULL, true);
146*07f334d8SVijai Kumar K }
147*07f334d8SVijai Kumar K 
148*07f334d8SVijai Kumar K static void shakti_uart_instance_init(Object *obj)
149*07f334d8SVijai Kumar K {
150*07f334d8SVijai Kumar K     ShaktiUartState *sus = SHAKTI_UART(obj);
151*07f334d8SVijai Kumar K     memory_region_init_io(&sus->mmio,
152*07f334d8SVijai Kumar K                           obj,
153*07f334d8SVijai Kumar K                           &shakti_uart_ops,
154*07f334d8SVijai Kumar K                           sus,
155*07f334d8SVijai Kumar K                           TYPE_SHAKTI_UART,
156*07f334d8SVijai Kumar K                           0x1000);
157*07f334d8SVijai Kumar K     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &sus->mmio);
158*07f334d8SVijai Kumar K }
159*07f334d8SVijai Kumar K 
160*07f334d8SVijai Kumar K static Property shakti_uart_properties[] = {
161*07f334d8SVijai Kumar K     DEFINE_PROP_CHR("chardev", ShaktiUartState, chr),
162*07f334d8SVijai Kumar K     DEFINE_PROP_END_OF_LIST(),
163*07f334d8SVijai Kumar K };
164*07f334d8SVijai Kumar K 
165*07f334d8SVijai Kumar K static void shakti_uart_class_init(ObjectClass *klass, void *data)
166*07f334d8SVijai Kumar K {
167*07f334d8SVijai Kumar K     DeviceClass *dc = DEVICE_CLASS(klass);
168*07f334d8SVijai Kumar K     dc->reset = shakti_uart_reset;
169*07f334d8SVijai Kumar K     dc->realize = shakti_uart_realize;
170*07f334d8SVijai Kumar K     device_class_set_props(dc, shakti_uart_properties);
171*07f334d8SVijai Kumar K }
172*07f334d8SVijai Kumar K 
173*07f334d8SVijai Kumar K static const TypeInfo shakti_uart_info = {
174*07f334d8SVijai Kumar K     .name = TYPE_SHAKTI_UART,
175*07f334d8SVijai Kumar K     .parent = TYPE_SYS_BUS_DEVICE,
176*07f334d8SVijai Kumar K     .instance_size = sizeof(ShaktiUartState),
177*07f334d8SVijai Kumar K     .class_init = shakti_uart_class_init,
178*07f334d8SVijai Kumar K     .instance_init = shakti_uart_instance_init,
179*07f334d8SVijai Kumar K };
180*07f334d8SVijai Kumar K 
181*07f334d8SVijai Kumar K static void shakti_uart_register_types(void)
182*07f334d8SVijai Kumar K {
183*07f334d8SVijai Kumar K     type_register_static(&shakti_uart_info);
184*07f334d8SVijai Kumar K }
185*07f334d8SVijai Kumar K type_init(shakti_uart_register_types)
186