summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250/8250_rsa.c
blob: d34093cc03ad9407f7117dda49554625c14e019a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
// SPDX-License-Identifier: GPL-2.0+

#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/moduleparam.h>

#include <linux/serial.h>
#include <linux/serial_8250.h>

#include "8250.h"

#define PORT_RSA_MAX 4
static unsigned long probe_rsa[PORT_RSA_MAX];
static unsigned int probe_rsa_count;

static int rsa8250_request_resource(struct uart_8250_port *up)
{
	struct uart_port *port = &up->port;
	unsigned long start = UART_RSA_BASE << port->regshift;
	unsigned int size = 8 << port->regshift;

	switch (port->iotype) {
	case UPIO_HUB6:
	case UPIO_PORT:
		start += port->iobase;
		if (!request_region(start, size, "serial-rsa"))
			return -EBUSY;
		return 0;
	default:
		return -EINVAL;
	}
}

static void rsa8250_release_resource(struct uart_8250_port *up)
{
	struct uart_port *port = &up->port;
	unsigned long offset = UART_RSA_BASE << port->regshift;
	unsigned int size = 8 << port->regshift;

	switch (port->iotype) {
	case UPIO_HUB6:
	case UPIO_PORT:
		release_region(port->iobase + offset, size);
		break;
	default:
		break;
	}
}

static void univ8250_config_port(struct uart_port *port, int flags)
{
	struct uart_8250_port *up = up_to_u8250p(port);
	unsigned int i;

	up->probe &= ~UART_PROBE_RSA;
	if (port->type == PORT_RSA) {
		if (rsa8250_request_resource(up) == 0)
			up->probe |= UART_PROBE_RSA;
	} else if (flags & UART_CONFIG_TYPE) {
		for (i = 0; i < probe_rsa_count; i++) {
			if (probe_rsa[i] == up->port.iobase) {
				if (rsa8250_request_resource(up) == 0)
					up->probe |= UART_PROBE_RSA;
				break;
			}
		}
	}

	univ8250_port_base_ops->config_port(port, flags);

	if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA)
		rsa8250_release_resource(up);
}

static int univ8250_request_port(struct uart_port *port)
{
	struct uart_8250_port *up = up_to_u8250p(port);
	int ret;

	ret = univ8250_port_base_ops->request_port(port);
	if (ret == 0 && port->type == PORT_RSA) {
		ret = rsa8250_request_resource(up);
		if (ret < 0)
			univ8250_port_base_ops->release_port(port);
	}

	return ret;
}

static void univ8250_release_port(struct uart_port *port)
{
	struct uart_8250_port *up = up_to_u8250p(port);

	if (port->type == PORT_RSA)
		rsa8250_release_resource(up);
	univ8250_port_base_ops->release_port(port);
}

void univ8250_rsa_support(struct uart_ops *ops)
{
	ops->config_port  = univ8250_config_port;
	ops->request_port = univ8250_request_port;
	ops->release_port = univ8250_release_port;
}

module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");

/*
 * Attempts to turn on the RSA FIFO.  Returns zero on failure.
 * We set the port uart clock rate if we succeed.
 */
static int __rsa_enable(struct uart_8250_port *up)
{
	unsigned char mode;
	int result;

	mode = serial_in(up, UART_RSA_MSR);
	result = mode & UART_RSA_MSR_FIFO;

	if (!result) {
		serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
		mode = serial_in(up, UART_RSA_MSR);
		result = mode & UART_RSA_MSR_FIFO;
	}

	if (result)
		up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;

	return result;
}

/*
 * If this is an RSA port, see if we can kick it up to the higher speed clock.
 */
void rsa_enable(struct uart_8250_port *up)
{
	if (up->port.type != PORT_RSA)
		return;

	if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
		uart_port_lock_irq(&up->port);
		__rsa_enable(up);
		uart_port_unlock_irq(&up->port);
	}
	if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
		serial_out(up, UART_RSA_FRR, 0);
}
EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_enable, "8250_base");

/*
 * Attempts to turn off the RSA FIFO and resets the RSA board back to 115kbps compat mode. It is
 * unknown why interrupts were disabled in here. However, the caller is expected to preserve this
 * behaviour by grabbing the spinlock before calling this function.
 */
void rsa_disable(struct uart_8250_port *up)
{
	unsigned char mode;
	int result;

	if (up->port.type != PORT_RSA)
		return;

	if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16)
		return;

	uart_port_lock_irq(&up->port);
	mode = serial_in(up, UART_RSA_MSR);
	result = !(mode & UART_RSA_MSR_FIFO);

	if (!result) {
		serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
		mode = serial_in(up, UART_RSA_MSR);
		result = !(mode & UART_RSA_MSR_FIFO);
	}

	if (result)
		up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
	uart_port_unlock_irq(&up->port);
}
EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_disable, "8250_base");

void rsa_autoconfig(struct uart_8250_port *up)
{
	/* Only probe for RSA ports if we got the region. */
	if (up->port.type != PORT_16550A)
		return;
	if (!(up->probe & UART_PROBE_RSA))
		return;

	if (__rsa_enable(up))
		up->port.type = PORT_RSA;
}
EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_autoconfig, "8250_base");

void rsa_reset(struct uart_8250_port *up)
{
	if (up->port.type != PORT_RSA)
		return;

	serial_out(up, UART_RSA_FRR, 0);
}
EXPORT_SYMBOL_GPL_FOR_MODULES(rsa_reset, "8250_base");

#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
#ifndef MODULE
/*
 * Keep the old "8250" name working as well for the module options so we don't
 * break people. We need to keep the names identical and the convenient macros
 * will happily refuse to let us do that by failing the build with redefinition
 * errors of global variables.  So we stick them inside a dummy function to
 * avoid those conflicts.  The options still get parsed, and the redefined
 * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
 *
 * This is hacky. I'm sorry.
 */
static void __used rsa8250_options(void)
{
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "8250_core."

	__module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
		&param_array_ops, .arr = &__param_arr_probe_rsa,
		0444, -1, 0);
}
#endif
#endif