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