mantis_uart.c (4093B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 Mantis PCI bridge driver 4 5 Copyright (C) Manu Abraham (abraham.manu@gmail.com) 6 7*/ 8 9#include <linux/kernel.h> 10#include <linux/spinlock.h> 11#include <asm/io.h> 12 13#include <linux/signal.h> 14#include <linux/sched.h> 15#include <linux/interrupt.h> 16#include <linux/pci.h> 17 18#include <media/dmxdev.h> 19#include <media/dvbdev.h> 20#include <media/dvb_demux.h> 21#include <media/dvb_frontend.h> 22#include <media/dvb_net.h> 23 24#include "mantis_common.h" 25#include "mantis_reg.h" 26#include "mantis_uart.h" 27#include "mantis_input.h" 28 29struct mantis_uart_params { 30 enum mantis_baud baud_rate; 31 enum mantis_parity parity; 32}; 33 34static struct { 35 char string[7]; 36} rates[5] = { 37 { "9600" }, 38 { "19200" }, 39 { "38400" }, 40 { "57600" }, 41 { "115200" } 42}; 43 44static struct { 45 char string[5]; 46} parity[3] = { 47 { "NONE" }, 48 { "ODD" }, 49 { "EVEN" } 50}; 51 52static void mantis_uart_read(struct mantis_pci *mantis) 53{ 54 struct mantis_hwconfig *config = mantis->hwconfig; 55 int i, scancode = 0, err = 0; 56 57 /* get data */ 58 dprintk(MANTIS_DEBUG, 1, "UART Reading ..."); 59 for (i = 0; i < (config->bytes + 1); i++) { 60 int data = mmread(MANTIS_UART_RXD); 61 62 dprintk(MANTIS_DEBUG, 0, " <%02x>", data); 63 64 scancode = (scancode << 8) | (data & 0x3f); 65 err |= data; 66 67 if (data & (1 << 7)) 68 dprintk(MANTIS_ERROR, 1, "UART framing error"); 69 70 if (data & (1 << 6)) 71 dprintk(MANTIS_ERROR, 1, "UART parity error"); 72 } 73 dprintk(MANTIS_DEBUG, 0, "\n"); 74 75 if ((err & 0xC0) == 0) 76 mantis_input_process(mantis, scancode); 77} 78 79static void mantis_uart_work(struct work_struct *work) 80{ 81 struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work); 82 u32 stat; 83 unsigned long timeout; 84 85 stat = mmread(MANTIS_UART_STAT); 86 87 if (stat & MANTIS_UART_RXFIFO_FULL) 88 dprintk(MANTIS_ERROR, 1, "RX Fifo FULL"); 89 90 /* 91 * MANTIS_UART_RXFIFO_DATA is only set if at least 92 * config->bytes + 1 bytes are in the FIFO. 93 */ 94 95 /* FIXME: is 10ms good enough ? */ 96 timeout = jiffies + msecs_to_jiffies(10); 97 while (stat & MANTIS_UART_RXFIFO_DATA) { 98 mantis_uart_read(mantis); 99 stat = mmread(MANTIS_UART_STAT); 100 101 if (!time_is_after_jiffies(timeout)) 102 break; 103 } 104 105 /* re-enable UART (RX) interrupt */ 106 mantis_unmask_ints(mantis, MANTIS_INT_IRQ1); 107} 108 109static int mantis_uart_setup(struct mantis_pci *mantis, 110 struct mantis_uart_params *params) 111{ 112 u32 reg; 113 114 mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL); 115 116 reg = mmread(MANTIS_UART_BAUD); 117 118 switch (params->baud_rate) { 119 case MANTIS_BAUD_9600: 120 reg |= 0xd8; 121 break; 122 case MANTIS_BAUD_19200: 123 reg |= 0x6c; 124 break; 125 case MANTIS_BAUD_38400: 126 reg |= 0x36; 127 break; 128 case MANTIS_BAUD_57600: 129 reg |= 0x23; 130 break; 131 case MANTIS_BAUD_115200: 132 reg |= 0x11; 133 break; 134 default: 135 return -EINVAL; 136 } 137 138 mmwrite(reg, MANTIS_UART_BAUD); 139 140 return 0; 141} 142 143int mantis_uart_init(struct mantis_pci *mantis) 144{ 145 struct mantis_hwconfig *config = mantis->hwconfig; 146 struct mantis_uart_params params; 147 148 /* default parity: */ 149 params.baud_rate = config->baud_rate; 150 params.parity = config->parity; 151 dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s", 152 rates[params.baud_rate].string, 153 parity[params.parity].string); 154 155 INIT_WORK(&mantis->uart_work, mantis_uart_work); 156 157 /* disable interrupt */ 158 mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); 159 160 mantis_uart_setup(mantis, ¶ms); 161 162 /* default 1 byte */ 163 mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD); 164 165 /* flush buffer */ 166 mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL); 167 168 /* enable interrupt */ 169 mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL); 170 mantis_unmask_ints(mantis, MANTIS_INT_IRQ1); 171 172 schedule_work(&mantis->uart_work); 173 dprintk(MANTIS_DEBUG, 1, "UART successfully initialized"); 174 175 return 0; 176} 177EXPORT_SYMBOL_GPL(mantis_uart_init); 178 179void mantis_uart_exit(struct mantis_pci *mantis) 180{ 181 /* disable interrupt */ 182 mantis_mask_ints(mantis, MANTIS_INT_IRQ1); 183 mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); 184 flush_work(&mantis->uart_work); 185} 186EXPORT_SYMBOL_GPL(mantis_uart_exit);