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