linux_dsm_epyc7002/drivers/media/pci/mantis/mantis_uart.c

187 lines
4.0 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0-or-later
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
*/
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <media/dmxdev.h>
#include <media/dvbdev.h>
#include <media/dvb_demux.h>
#include <media/dvb_frontend.h>
#include <media/dvb_net.h>
#include "mantis_common.h"
#include "mantis_reg.h"
#include "mantis_uart.h"
#include "mantis_input.h"
struct mantis_uart_params {
enum mantis_baud baud_rate;
enum mantis_parity parity;
};
static struct {
char string[7];
} rates[5] = {
{ "9600" },
{ "19200" },
{ "38400" },
{ "57600" },
{ "115200" }
};
static struct {
char string[5];
} parity[3] = {
{ "NONE" },
{ "ODD" },
{ "EVEN" }
};
static void mantis_uart_read(struct mantis_pci *mantis)
{
struct mantis_hwconfig *config = mantis->hwconfig;
int i, scancode = 0, err = 0;
/* get data */
dprintk(MANTIS_DEBUG, 1, "UART Reading ...");
for (i = 0; i < (config->bytes + 1); i++) {
int data = mmread(MANTIS_UART_RXD);
dprintk(MANTIS_DEBUG, 0, " <%02x>", data);
scancode = (scancode << 8) | (data & 0x3f);
err |= data;
if (data & (1 << 7))
dprintk(MANTIS_ERROR, 1, "UART framing error");
if (data & (1 << 6))
dprintk(MANTIS_ERROR, 1, "UART parity error");
}
dprintk(MANTIS_DEBUG, 0, "\n");
if ((err & 0xC0) == 0)
mantis_input_process(mantis, scancode);
}
static void mantis_uart_work(struct work_struct *work)
{
struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work);
u32 stat;
unsigned long timeout;
stat = mmread(MANTIS_UART_STAT);
if (stat & MANTIS_UART_RXFIFO_FULL)
dprintk(MANTIS_ERROR, 1, "RX Fifo FULL");
/*
* MANTIS_UART_RXFIFO_DATA is only set if at least
* config->bytes + 1 bytes are in the FIFO.
*/
/* FIXME: is 10ms good enough ? */
timeout = jiffies + msecs_to_jiffies(10);
while (stat & MANTIS_UART_RXFIFO_DATA) {
mantis_uart_read(mantis);
stat = mmread(MANTIS_UART_STAT);
if (!time_is_after_jiffies(timeout))
break;
}
/* re-enable UART (RX) interrupt */
mantis_unmask_ints(mantis, MANTIS_INT_IRQ1);
}
static int mantis_uart_setup(struct mantis_pci *mantis,
struct mantis_uart_params *params)
{
u32 reg;
mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL);
reg = mmread(MANTIS_UART_BAUD);
switch (params->baud_rate) {
case MANTIS_BAUD_9600:
reg |= 0xd8;
break;
case MANTIS_BAUD_19200:
reg |= 0x6c;
break;
case MANTIS_BAUD_38400:
reg |= 0x36;
break;
case MANTIS_BAUD_57600:
reg |= 0x23;
break;
case MANTIS_BAUD_115200:
reg |= 0x11;
break;
default:
return -EINVAL;
}
mmwrite(reg, MANTIS_UART_BAUD);
return 0;
}
int mantis_uart_init(struct mantis_pci *mantis)
{
struct mantis_hwconfig *config = mantis->hwconfig;
struct mantis_uart_params params;
/* default parity: */
params.baud_rate = config->baud_rate;
params.parity = config->parity;
dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s",
rates[params.baud_rate].string,
parity[params.parity].string);
INIT_WORK(&mantis->uart_work, mantis_uart_work);
/* disable interrupt */
mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
mantis_uart_setup(mantis, &params);
/* default 1 byte */
mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD);
/* flush buffer */
mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL);
/* enable interrupt */
mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL);
mantis_unmask_ints(mantis, MANTIS_INT_IRQ1);
schedule_work(&mantis->uart_work);
dprintk(MANTIS_DEBUG, 1, "UART successfully initialized");
return 0;
}
EXPORT_SYMBOL_GPL(mantis_uart_init);
void mantis_uart_exit(struct mantis_pci *mantis)
{
/* disable interrupt */
mantis_mask_ints(mantis, MANTIS_INT_IRQ1);
mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
workqueue: deprecate flush[_delayed]_work_sync() flush[_delayed]_work_sync() are now spurious. Mark them deprecated and convert all users to flush[_delayed]_work(). If you're cc'd and wondering what's going on: Now all workqueues are non-reentrant and the regular flushes guarantee that the work item is not pending or running on any CPU on return, so there's no reason to use the sync flushes at all and they're going away. This patch doesn't make any functional difference. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Ian Campbell <ian.campbell@citrix.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Mattia Dongili <malattia@linux.it> Cc: Kent Yoder <key@linux.vnet.ibm.com> Cc: David Airlie <airlied@linux.ie> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Karsten Keil <isdn@linux-pingi.de> Cc: Bryan Wu <bryan.wu@canonical.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Alasdair Kergon <agk@redhat.com> Cc: Mauro Carvalho Chehab <mchehab@infradead.org> Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Cc: David Woodhouse <dwmw2@infradead.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: linux-wireless@vger.kernel.org Cc: Anton Vorontsov <cbou@mail.ru> Cc: Sangbeom Kim <sbkim73@samsung.com> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Eric Van Hensbergen <ericvh@gmail.com> Cc: Takashi Iwai <tiwai@suse.de> Cc: Steven Whitehouse <swhiteho@redhat.com> Cc: Petr Vandrovec <petr@vandrovec.name> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Avi Kivity <avi@redhat.com>
2012-08-21 04:51:24 +07:00
flush_work(&mantis->uart_work);
}
EXPORT_SYMBOL_GPL(mantis_uart_exit);