xref: /openbmc/qemu/hw/char/shakti_uart.c (revision 5515ff16)
107f334d8SVijai Kumar K /*
207f334d8SVijai Kumar K  * SHAKTI UART
307f334d8SVijai Kumar K  *
407f334d8SVijai Kumar K  * Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
507f334d8SVijai Kumar K  *
607f334d8SVijai Kumar K  * Permission is hereby granted, free of charge, to any person obtaining a copy
707f334d8SVijai Kumar K  * of this software and associated documentation files (the "Software"), to deal
807f334d8SVijai Kumar K  * in the Software without restriction, including without limitation the rights
907f334d8SVijai Kumar K  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1007f334d8SVijai Kumar K  * copies of the Software, and to permit persons to whom the Software is
1107f334d8SVijai Kumar K  * furnished to do so, subject to the following conditions:
1207f334d8SVijai Kumar K  *
1307f334d8SVijai Kumar K  * The above copyright notice and this permission notice shall be included in
1407f334d8SVijai Kumar K  * all copies or substantial portions of the Software.
1507f334d8SVijai Kumar K  *
1607f334d8SVijai Kumar K  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1707f334d8SVijai Kumar K  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1807f334d8SVijai Kumar K  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1907f334d8SVijai Kumar K  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2007f334d8SVijai Kumar K  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2107f334d8SVijai Kumar K  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2207f334d8SVijai Kumar K  * THE SOFTWARE.
2307f334d8SVijai Kumar K  */
2407f334d8SVijai Kumar K 
2507f334d8SVijai Kumar K #include "qemu/osdep.h"
2607f334d8SVijai Kumar K #include "hw/char/shakti_uart.h"
2707f334d8SVijai Kumar K #include "hw/qdev-properties.h"
2807f334d8SVijai Kumar K #include "hw/qdev-properties-system.h"
2907f334d8SVijai Kumar K #include "qemu/log.h"
3007f334d8SVijai Kumar K 
shakti_uart_read(void * opaque,hwaddr addr,unsigned size)3107f334d8SVijai Kumar K static uint64_t shakti_uart_read(void *opaque, hwaddr addr, unsigned size)
3207f334d8SVijai Kumar K {
3307f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
3407f334d8SVijai Kumar K 
3507f334d8SVijai Kumar K     switch (addr) {
3607f334d8SVijai Kumar K     case SHAKTI_UART_BAUD:
3707f334d8SVijai Kumar K         return s->uart_baud;
3807f334d8SVijai Kumar K     case SHAKTI_UART_RX:
3907f334d8SVijai Kumar K         qemu_chr_fe_accept_input(&s->chr);
4007f334d8SVijai Kumar K         s->uart_status &= ~SHAKTI_UART_STATUS_RX_NOT_EMPTY;
4107f334d8SVijai Kumar K         return s->uart_rx;
4207f334d8SVijai Kumar K     case SHAKTI_UART_STATUS:
4307f334d8SVijai Kumar K         return s->uart_status;
4407f334d8SVijai Kumar K     case SHAKTI_UART_DELAY:
4507f334d8SVijai Kumar K         return s->uart_delay;
4607f334d8SVijai Kumar K     case SHAKTI_UART_CONTROL:
4707f334d8SVijai Kumar K         return s->uart_control;
4807f334d8SVijai Kumar K     case SHAKTI_UART_INT_EN:
4907f334d8SVijai Kumar K         return s->uart_interrupt;
5007f334d8SVijai Kumar K     case SHAKTI_UART_IQ_CYCLES:
5107f334d8SVijai Kumar K         return s->uart_iq_cycles;
5207f334d8SVijai Kumar K     case SHAKTI_UART_RX_THRES:
5307f334d8SVijai Kumar K         return s->uart_rx_threshold;
5407f334d8SVijai Kumar K     default:
5507f334d8SVijai Kumar K         /* Also handles TX REG which is write only */
5607f334d8SVijai Kumar K         qemu_log_mask(LOG_GUEST_ERROR,
5707f334d8SVijai Kumar K                       "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
5807f334d8SVijai Kumar K     }
5907f334d8SVijai Kumar K 
6007f334d8SVijai Kumar K     return 0;
6107f334d8SVijai Kumar K }
6207f334d8SVijai Kumar K 
shakti_uart_write(void * opaque,hwaddr addr,uint64_t data,unsigned size)6307f334d8SVijai Kumar K static void shakti_uart_write(void *opaque, hwaddr addr,
6407f334d8SVijai Kumar K                               uint64_t data, unsigned size)
6507f334d8SVijai Kumar K {
6607f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
6707f334d8SVijai Kumar K     uint32_t value = data;
6807f334d8SVijai Kumar K     uint8_t ch;
6907f334d8SVijai Kumar K 
7007f334d8SVijai Kumar K     switch (addr) {
7107f334d8SVijai Kumar K     case SHAKTI_UART_BAUD:
7207f334d8SVijai Kumar K         s->uart_baud = value;
7307f334d8SVijai Kumar K         break;
7407f334d8SVijai Kumar K     case SHAKTI_UART_TX:
7507f334d8SVijai Kumar K         ch = value;
7607f334d8SVijai Kumar K         qemu_chr_fe_write_all(&s->chr, &ch, 1);
7707f334d8SVijai Kumar K         s->uart_status &= ~SHAKTI_UART_STATUS_TX_FULL;
7807f334d8SVijai Kumar K         break;
7907f334d8SVijai Kumar K     case SHAKTI_UART_STATUS:
8007f334d8SVijai Kumar K         s->uart_status = value;
8107f334d8SVijai Kumar K         break;
8207f334d8SVijai Kumar K     case SHAKTI_UART_DELAY:
8307f334d8SVijai Kumar K         s->uart_delay = value;
8407f334d8SVijai Kumar K         break;
8507f334d8SVijai Kumar K     case SHAKTI_UART_CONTROL:
8607f334d8SVijai Kumar K         s->uart_control = value;
8707f334d8SVijai Kumar K         break;
8807f334d8SVijai Kumar K     case SHAKTI_UART_INT_EN:
8907f334d8SVijai Kumar K         s->uart_interrupt = value;
9007f334d8SVijai Kumar K         break;
9107f334d8SVijai Kumar K     case SHAKTI_UART_IQ_CYCLES:
9207f334d8SVijai Kumar K         s->uart_iq_cycles = value;
9307f334d8SVijai Kumar K         break;
9407f334d8SVijai Kumar K     case SHAKTI_UART_RX_THRES:
9507f334d8SVijai Kumar K         s->uart_rx_threshold = value;
9607f334d8SVijai Kumar K         break;
9707f334d8SVijai Kumar K     default:
9807f334d8SVijai Kumar K         qemu_log_mask(LOG_GUEST_ERROR,
9907f334d8SVijai Kumar K                       "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
10007f334d8SVijai Kumar K     }
10107f334d8SVijai Kumar K }
10207f334d8SVijai Kumar K 
10307f334d8SVijai Kumar K static const MemoryRegionOps shakti_uart_ops = {
10407f334d8SVijai Kumar K     .read = shakti_uart_read,
10507f334d8SVijai Kumar K     .write = shakti_uart_write,
10607f334d8SVijai Kumar K     .endianness = DEVICE_NATIVE_ENDIAN,
10707f334d8SVijai Kumar K     .impl = {.min_access_size = 1, .max_access_size = 4},
10807f334d8SVijai Kumar K     .valid = {.min_access_size = 1, .max_access_size = 4},
10907f334d8SVijai Kumar K };
11007f334d8SVijai Kumar K 
shakti_uart_reset(DeviceState * dev)11107f334d8SVijai Kumar K static void shakti_uart_reset(DeviceState *dev)
11207f334d8SVijai Kumar K {
11307f334d8SVijai Kumar K     ShaktiUartState *s = SHAKTI_UART(dev);
11407f334d8SVijai Kumar K 
11507f334d8SVijai Kumar K     s->uart_baud = SHAKTI_UART_BAUD_DEFAULT;
11607f334d8SVijai Kumar K     s->uart_tx = 0x0;
11707f334d8SVijai Kumar K     s->uart_rx = 0x0;
11807f334d8SVijai Kumar K     s->uart_status = 0x0000;
11907f334d8SVijai Kumar K     s->uart_delay = 0x0000;
12007f334d8SVijai Kumar K     s->uart_control = SHAKTI_UART_CONTROL_DEFAULT;
12107f334d8SVijai Kumar K     s->uart_interrupt = 0x0000;
12207f334d8SVijai Kumar K     s->uart_iq_cycles = 0x00;
12307f334d8SVijai Kumar K     s->uart_rx_threshold = 0x00;
12407f334d8SVijai Kumar K }
12507f334d8SVijai Kumar K 
shakti_uart_can_receive(void * opaque)12607f334d8SVijai Kumar K static int shakti_uart_can_receive(void *opaque)
12707f334d8SVijai Kumar K {
12807f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
12907f334d8SVijai Kumar K 
13007f334d8SVijai Kumar K     return !(s->uart_status & SHAKTI_UART_STATUS_RX_NOT_EMPTY);
13107f334d8SVijai Kumar K }
13207f334d8SVijai Kumar K 
shakti_uart_receive(void * opaque,const uint8_t * buf,int size)13307f334d8SVijai Kumar K static void shakti_uart_receive(void *opaque, const uint8_t *buf, int size)
13407f334d8SVijai Kumar K {
13507f334d8SVijai Kumar K     ShaktiUartState *s = opaque;
13607f334d8SVijai Kumar K 
13707f334d8SVijai Kumar K     s->uart_rx = *buf;
13807f334d8SVijai Kumar K     s->uart_status |= SHAKTI_UART_STATUS_RX_NOT_EMPTY;
13907f334d8SVijai Kumar K }
14007f334d8SVijai Kumar K 
shakti_uart_realize(DeviceState * dev,Error ** errp)14107f334d8SVijai Kumar K static void shakti_uart_realize(DeviceState *dev, Error **errp)
14207f334d8SVijai Kumar K {
14307f334d8SVijai Kumar K     ShaktiUartState *sus = SHAKTI_UART(dev);
14407f334d8SVijai Kumar K     qemu_chr_fe_set_handlers(&sus->chr, shakti_uart_can_receive,
14507f334d8SVijai Kumar K                              shakti_uart_receive, NULL, NULL, sus, NULL, true);
14607f334d8SVijai Kumar K }
14707f334d8SVijai Kumar K 
shakti_uart_instance_init(Object * obj)14807f334d8SVijai Kumar K static void shakti_uart_instance_init(Object *obj)
14907f334d8SVijai Kumar K {
15007f334d8SVijai Kumar K     ShaktiUartState *sus = SHAKTI_UART(obj);
15107f334d8SVijai Kumar K     memory_region_init_io(&sus->mmio,
15207f334d8SVijai Kumar K                           obj,
15307f334d8SVijai Kumar K                           &shakti_uart_ops,
15407f334d8SVijai Kumar K                           sus,
15507f334d8SVijai Kumar K                           TYPE_SHAKTI_UART,
15607f334d8SVijai Kumar K                           0x1000);
15707f334d8SVijai Kumar K     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &sus->mmio);
15807f334d8SVijai Kumar K }
15907f334d8SVijai Kumar K 
16007f334d8SVijai Kumar K static Property shakti_uart_properties[] = {
16107f334d8SVijai Kumar K     DEFINE_PROP_CHR("chardev", ShaktiUartState, chr),
16207f334d8SVijai Kumar K     DEFINE_PROP_END_OF_LIST(),
16307f334d8SVijai Kumar K };
16407f334d8SVijai Kumar K 
shakti_uart_class_init(ObjectClass * klass,void * data)16507f334d8SVijai Kumar K static void shakti_uart_class_init(ObjectClass *klass, void *data)
16607f334d8SVijai Kumar K {
16707f334d8SVijai Kumar K     DeviceClass *dc = DEVICE_CLASS(klass);
16807f334d8SVijai Kumar K     dc->reset = shakti_uart_reset;
16907f334d8SVijai Kumar K     dc->realize = shakti_uart_realize;
17007f334d8SVijai Kumar K     device_class_set_props(dc, shakti_uart_properties);
171*5515ff16SBin Meng     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
17207f334d8SVijai Kumar K }
17307f334d8SVijai Kumar K 
17407f334d8SVijai Kumar K static const TypeInfo shakti_uart_info = {
17507f334d8SVijai Kumar K     .name = TYPE_SHAKTI_UART,
17607f334d8SVijai Kumar K     .parent = TYPE_SYS_BUS_DEVICE,
17707f334d8SVijai Kumar K     .instance_size = sizeof(ShaktiUartState),
17807f334d8SVijai Kumar K     .class_init = shakti_uart_class_init,
17907f334d8SVijai Kumar K     .instance_init = shakti_uart_instance_init,
18007f334d8SVijai Kumar K };
18107f334d8SVijai Kumar K 
shakti_uart_register_types(void)18207f334d8SVijai Kumar K static void shakti_uart_register_types(void)
18307f334d8SVijai Kumar K {
18407f334d8SVijai Kumar K     type_register_static(&shakti_uart_info);
18507f334d8SVijai Kumar K }
18607f334d8SVijai Kumar K type_init(shakti_uart_register_types)
187