187 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 Mantis PCI bridge driver4 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 least92 * 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);187