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