xref: /linux/drivers/tty/serial/8250/8250_men_mcb.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/device.h>
3 #include <linux/kernel.h>
4 #include <linux/module.h>
5 #include <linux/io.h>
6 #include <linux/mcb.h>
7 #include <linux/serial.h>
8 #include <linux/serial_core.h>
9 #include <linux/serial_8250.h>
10 
11 #define MEN_UART_ID_Z025 0x19
12 #define MEN_UART_ID_Z057 0x39
13 #define MEN_UART_ID_Z125 0x7d
14 
15 /*
16  * IP Cores Z025 and Z057 can have up to 4 UART
17  * The UARTs available are stored in a global
18  * register saved in physical address + 0x40
19  * Is saved as follows:
20  *
21  * 7                                                              0
22  * +------+-------+-------+-------+-------+-------+-------+-------+
23  * |UART4 | UART3 | UART2 | UART1 | U4irq | U3irq | U2irq | U1irq |
24  * +------+-------+-------+-------+-------+-------+-------+-------+
25  */
26 #define MEN_UART1_MASK	0x01
27 #define MEN_UART2_MASK	0x02
28 #define MEN_UART3_MASK	0x04
29 #define MEN_UART4_MASK	0x08
30 
31 #define MEN_Z025_MAX_UARTS		4
32 #define MEN_UART_MEM_SIZE		0x10
33 #define MEM_UART_REGISTER_SIZE		0x01
34 #define MEN_Z025_REGISTER_OFFSET	0x40
35 
36 #define MEN_UART1_OFFSET	0
37 #define MEN_UART2_OFFSET	(MEN_UART1_OFFSET + MEN_UART_MEM_SIZE)
38 #define MEN_UART3_OFFSET	(MEN_UART2_OFFSET + MEN_UART_MEM_SIZE)
39 #define MEN_UART4_OFFSET	(MEN_UART3_OFFSET + MEN_UART_MEM_SIZE)
40 
41 #define MEN_READ_REGISTER(addr)	readb(addr)
42 
43 struct serial_8250_men_mcb_data {
44 	int num_ports;
45 	int line[MEN_Z025_MAX_UARTS];
46 	unsigned int offset[MEN_Z025_MAX_UARTS];
47 };
48 
49 /*
50  * The Z125 16550-compatible UART has no fixed base clock assigned
51  * So, depending on the board we're on, we need to adjust the
52  * parameter in order to really set the correct baudrate, and
53  * do so if possible without user interaction
54  */
55 static u32 men_lookup_uartclk(struct mcb_device *mdev)
56 {
57 	/* use default value if board is not available below */
58 	u32 clkval = 1041666;
59 
60 	dev_info(&mdev->dev, "%s on board %s\n",
61 		dev_name(&mdev->dev),
62 		mdev->bus->name);
63 	if  (strncmp(mdev->bus->name, "F075", 4) == 0)
64 		clkval = 1041666;
65 	else if (strncmp(mdev->bus->name, "F216", 4) == 0)
66 		clkval = 1843200;
67 	else if (strncmp(mdev->bus->name, "F210", 4) == 0)
68 		clkval = 115200;
69 	else if (strstr(mdev->bus->name, "215"))
70 		clkval = 1843200;
71 	else
72 		dev_info(&mdev->dev,
73 			 "board not detected, using default uartclk\n");
74 
75 	clkval = clkval  << 4;
76 
77 	return clkval;
78 }
79 
80 static int read_uarts_available_from_register(struct resource *mem_res,
81 					      u8 *uarts_available)
82 {
83 	void __iomem *mem;
84 	int reg_value;
85 
86 	if (!request_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
87 				MEM_UART_REGISTER_SIZE,  KBUILD_MODNAME)) {
88 		return -EBUSY;
89 	}
90 
91 	mem = ioremap(mem_res->start + MEN_Z025_REGISTER_OFFSET,
92 		      MEM_UART_REGISTER_SIZE);
93 	if (!mem) {
94 		release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
95 				   MEM_UART_REGISTER_SIZE);
96 		return -ENOMEM;
97 	}
98 
99 	reg_value = MEN_READ_REGISTER(mem);
100 
101 	iounmap(mem);
102 
103 	release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
104 			   MEM_UART_REGISTER_SIZE);
105 
106 	*uarts_available = reg_value >> 4;
107 
108 	return 0;
109 }
110 
111 static int read_serial_data(struct mcb_device *mdev,
112 			    struct resource *mem_res,
113 			    struct serial_8250_men_mcb_data *serial_data)
114 {
115 	u8 uarts_available;
116 	int count = 0;
117 	int mask;
118 	int res;
119 	int i;
120 
121 	res = read_uarts_available_from_register(mem_res, &uarts_available);
122 	if (res < 0)
123 		return res;
124 
125 	for (i = 0; i < MEN_Z025_MAX_UARTS; i++) {
126 		mask = 0x1 << i;
127 		switch (uarts_available & mask) {
128 		case MEN_UART1_MASK:
129 			serial_data->offset[count] = MEN_UART1_OFFSET;
130 			count++;
131 			break;
132 		case MEN_UART2_MASK:
133 			serial_data->offset[count] = MEN_UART2_OFFSET;
134 			count++;
135 			break;
136 		case MEN_UART3_MASK:
137 			serial_data->offset[count] = MEN_UART3_OFFSET;
138 			count++;
139 			break;
140 		case MEN_UART4_MASK:
141 			serial_data->offset[count] = MEN_UART4_OFFSET;
142 			count++;
143 			break;
144 		default:
145 			return -EINVAL;
146 		}
147 	}
148 
149 	if (count <= 0 || count > MEN_Z025_MAX_UARTS) {
150 		dev_err(&mdev->dev, "unexpected number of ports: %u\n",
151 			count);
152 		return -ENODEV;
153 	}
154 
155 	serial_data->num_ports = count;
156 
157 	return 0;
158 }
159 
160 static int init_serial_data(struct mcb_device *mdev,
161 			    struct resource *mem_res,
162 			    struct serial_8250_men_mcb_data *serial_data)
163 {
164 	switch (mdev->id) {
165 	case MEN_UART_ID_Z125:
166 		serial_data->num_ports = 1;
167 		serial_data->offset[0] = 0;
168 		return 0;
169 	case MEN_UART_ID_Z025:
170 	case MEN_UART_ID_Z057:
171 		return read_serial_data(mdev, mem_res, serial_data);
172 	default:
173 		dev_err(&mdev->dev, "no supported device!\n");
174 		return -ENODEV;
175 	}
176 }
177 
178 static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
179 				     const struct mcb_device_id *id)
180 {
181 	struct uart_8250_port uart;
182 	struct serial_8250_men_mcb_data *data;
183 	struct resource *mem;
184 	int i;
185 	int res;
186 
187 	mem = mcb_get_resource(mdev, IORESOURCE_MEM);
188 	if (mem == NULL)
189 		return -ENXIO;
190 
191 	data = devm_kzalloc(&mdev->dev,
192 			    sizeof(struct serial_8250_men_mcb_data),
193 			    GFP_KERNEL);
194 	if (!data)
195 		return -ENOMEM;
196 
197 	res = init_serial_data(mdev, mem, data);
198 	if (res < 0)
199 		return res;
200 
201 	dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n",
202 		mdev->id, data->num_ports);
203 
204 	mcb_set_drvdata(mdev, data);
205 
206 	for (i = 0; i < data->num_ports; i++) {
207 		memset(&uart, 0, sizeof(struct uart_8250_port));
208 		spin_lock_init(&uart.port.lock);
209 
210 		uart.port.flags = UPF_SKIP_TEST |
211 				  UPF_SHARE_IRQ |
212 				  UPF_BOOT_AUTOCONF |
213 				  UPF_IOREMAP;
214 		uart.port.iotype = UPIO_MEM;
215 		uart.port.uartclk = men_lookup_uartclk(mdev);
216 		uart.port.irq = mcb_get_irq(mdev);
217 		uart.port.mapbase = (unsigned long) mem->start
218 					    + data->offset[i];
219 
220 		/* ok, register the port */
221 		res = serial8250_register_8250_port(&uart);
222 		if (res < 0) {
223 			dev_err(&mdev->dev, "unable to register UART port\n");
224 			return res;
225 		}
226 
227 		data->line[i] = res;
228 		dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data->line[i]);
229 	}
230 
231 	return 0;
232 }
233 
234 static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
235 {
236 	int i;
237 	struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
238 
239 	if (!data)
240 		return;
241 
242 	for (i = 0; i < data->num_ports; i++)
243 		serial8250_unregister_port(data->line[i]);
244 }
245 
246 static const struct mcb_device_id serial_8250_men_mcb_ids[] = {
247 	{ .device = MEN_UART_ID_Z025 },
248 	{ .device = MEN_UART_ID_Z057 },
249 	{ .device = MEN_UART_ID_Z125 },
250 	{ }
251 };
252 MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids);
253 
254 static struct mcb_driver mcb_driver = {
255 	.driver = {
256 		.name = "8250_men_mcb",
257 	},
258 	.probe = serial_8250_men_mcb_probe,
259 	.remove = serial_8250_men_mcb_remove,
260 	.id_table = serial_8250_men_mcb_ids,
261 };
262 module_mcb_driver(mcb_driver);
263 
264 MODULE_LICENSE("GPL v2");
265 MODULE_DESCRIPTION("MEN 8250 UART driver");
266 MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
267 MODULE_IMPORT_NS("MCB");
268