Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / media / pci / mantis / mantis_uart.c
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
29 struct mantis_uart_params {
30         enum mantis_baud        baud_rate;
31         enum mantis_parity      parity;
32 };
33
34 static struct {
35         char string[7];
36 } rates[5] = {
37         { "9600" },
38         { "19200" },
39         { "38400" },
40         { "57600" },
41         { "115200" }
42 };
43
44 static struct {
45         char string[5];
46 } parity[3] = {
47         { "NONE" },
48         { "ODD" },
49         { "EVEN" }
50 };
51
52 static 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
79 static 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
109 static 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
143 int 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, &params);
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 }
177 EXPORT_SYMBOL_GPL(mantis_uart_init);
178
179 void 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 }
186 EXPORT_SYMBOL_GPL(mantis_uart_exit);