xref: /OK3568_Linux_fs/kernel/drivers/tty/serial/8250/8250_men_mcb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/device.h>
3*4882a593Smuzhiyun #include <linux/kernel.h>
4*4882a593Smuzhiyun #include <linux/module.h>
5*4882a593Smuzhiyun #include <linux/io.h>
6*4882a593Smuzhiyun #include <linux/mcb.h>
7*4882a593Smuzhiyun #include <linux/serial.h>
8*4882a593Smuzhiyun #include <linux/serial_core.h>
9*4882a593Smuzhiyun #include <linux/serial_8250.h>
10*4882a593Smuzhiyun #include <uapi/linux/serial_core.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #define MEN_UART_ID_Z025 0x19
13*4882a593Smuzhiyun #define MEN_UART_ID_Z057 0x39
14*4882a593Smuzhiyun #define MEN_UART_ID_Z125 0x7d
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define MEN_UART_MEM_SIZE 0x10
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun struct serial_8250_men_mcb_data {
19*4882a593Smuzhiyun 	struct uart_8250_port uart;
20*4882a593Smuzhiyun 	int line;
21*4882a593Smuzhiyun };
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun /*
24*4882a593Smuzhiyun  * The Z125 16550-compatible UART has no fixed base clock assigned
25*4882a593Smuzhiyun  * So, depending on the board we're on, we need to adjust the
26*4882a593Smuzhiyun  * parameter in order to really set the correct baudrate, and
27*4882a593Smuzhiyun  * do so if possible without user interaction
28*4882a593Smuzhiyun  */
men_lookup_uartclk(struct mcb_device * mdev)29*4882a593Smuzhiyun static u32 men_lookup_uartclk(struct mcb_device *mdev)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	/* use default value if board is not available below */
32*4882a593Smuzhiyun 	u32 clkval = 1041666;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	dev_info(&mdev->dev, "%s on board %s\n",
35*4882a593Smuzhiyun 		dev_name(&mdev->dev),
36*4882a593Smuzhiyun 		mdev->bus->name);
37*4882a593Smuzhiyun 	if  (strncmp(mdev->bus->name, "F075", 4) == 0)
38*4882a593Smuzhiyun 		clkval = 1041666;
39*4882a593Smuzhiyun 	else if (strncmp(mdev->bus->name, "F216", 4) == 0)
40*4882a593Smuzhiyun 		clkval = 1843200;
41*4882a593Smuzhiyun 	else if (strncmp(mdev->bus->name, "G215", 4) == 0)
42*4882a593Smuzhiyun 		clkval = 1843200;
43*4882a593Smuzhiyun 	else if (strncmp(mdev->bus->name, "F210", 4) == 0)
44*4882a593Smuzhiyun 		clkval = 115200;
45*4882a593Smuzhiyun 	else
46*4882a593Smuzhiyun 		dev_info(&mdev->dev,
47*4882a593Smuzhiyun 			 "board not detected, using default uartclk\n");
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	clkval = clkval  << 4;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	return clkval;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
get_num_ports(struct mcb_device * mdev,void __iomem * membase)54*4882a593Smuzhiyun static int get_num_ports(struct mcb_device *mdev,
55*4882a593Smuzhiyun 				  void __iomem *membase)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	switch (mdev->id) {
58*4882a593Smuzhiyun 	case MEN_UART_ID_Z125:
59*4882a593Smuzhiyun 		return 1U;
60*4882a593Smuzhiyun 	case MEN_UART_ID_Z025:
61*4882a593Smuzhiyun 		return readb(membase) >> 4;
62*4882a593Smuzhiyun 	case MEN_UART_ID_Z057:
63*4882a593Smuzhiyun 		return 4U;
64*4882a593Smuzhiyun 	default:
65*4882a593Smuzhiyun 		dev_err(&mdev->dev, "no supported device!\n");
66*4882a593Smuzhiyun 		return -ENODEV;
67*4882a593Smuzhiyun 	}
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
serial_8250_men_mcb_probe(struct mcb_device * mdev,const struct mcb_device_id * id)70*4882a593Smuzhiyun static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
71*4882a593Smuzhiyun 				     const struct mcb_device_id *id)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct serial_8250_men_mcb_data *data;
74*4882a593Smuzhiyun 	struct resource *mem;
75*4882a593Smuzhiyun 	int num_ports;
76*4882a593Smuzhiyun 	int i;
77*4882a593Smuzhiyun 	void __iomem *membase;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	mem = mcb_get_resource(mdev, IORESOURCE_MEM);
80*4882a593Smuzhiyun 	if (mem == NULL)
81*4882a593Smuzhiyun 		return -ENXIO;
82*4882a593Smuzhiyun 	membase = devm_ioremap_resource(&mdev->dev, mem);
83*4882a593Smuzhiyun 	if (IS_ERR(membase))
84*4882a593Smuzhiyun 		return PTR_ERR_OR_ZERO(membase);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	num_ports = get_num_ports(mdev, membase);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n",
89*4882a593Smuzhiyun 		mdev->id, num_ports);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	if (num_ports <= 0 || num_ports > 4) {
92*4882a593Smuzhiyun 		dev_err(&mdev->dev, "unexpected number of ports: %u\n",
93*4882a593Smuzhiyun 			num_ports);
94*4882a593Smuzhiyun 		return -ENODEV;
95*4882a593Smuzhiyun 	}
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	data = devm_kcalloc(&mdev->dev, num_ports,
98*4882a593Smuzhiyun 			    sizeof(struct serial_8250_men_mcb_data),
99*4882a593Smuzhiyun 			    GFP_KERNEL);
100*4882a593Smuzhiyun 	if (!data)
101*4882a593Smuzhiyun 		return -ENOMEM;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	mcb_set_drvdata(mdev, data);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	for (i = 0; i < num_ports; i++) {
106*4882a593Smuzhiyun 		data[i].uart.port.dev = mdev->dma_dev;
107*4882a593Smuzhiyun 		spin_lock_init(&data[i].uart.port.lock);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 		data[i].uart.port.type = PORT_16550;
110*4882a593Smuzhiyun 		data[i].uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ
111*4882a593Smuzhiyun 					  | UPF_FIXED_TYPE;
112*4882a593Smuzhiyun 		data[i].uart.port.iotype = UPIO_MEM;
113*4882a593Smuzhiyun 		data[i].uart.port.uartclk = men_lookup_uartclk(mdev);
114*4882a593Smuzhiyun 		data[i].uart.port.regshift = 0;
115*4882a593Smuzhiyun 		data[i].uart.port.irq = mcb_get_irq(mdev);
116*4882a593Smuzhiyun 		data[i].uart.port.membase = membase;
117*4882a593Smuzhiyun 		data[i].uart.port.fifosize = 60;
118*4882a593Smuzhiyun 		data[i].uart.port.mapbase = (unsigned long) mem->start
119*4882a593Smuzhiyun 					    + i * MEN_UART_MEM_SIZE;
120*4882a593Smuzhiyun 		data[i].uart.port.iobase = data[i].uart.port.mapbase;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 		/* ok, register the port */
123*4882a593Smuzhiyun 		data[i].line = serial8250_register_8250_port(&data[i].uart);
124*4882a593Smuzhiyun 		if (data[i].line < 0) {
125*4882a593Smuzhiyun 			dev_err(&mdev->dev, "unable to register UART port\n");
126*4882a593Smuzhiyun 			return data[i].line;
127*4882a593Smuzhiyun 		}
128*4882a593Smuzhiyun 		dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data[i].line);
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
serial_8250_men_mcb_remove(struct mcb_device * mdev)134*4882a593Smuzhiyun static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	int num_ports, i;
137*4882a593Smuzhiyun 	struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	if (!data)
140*4882a593Smuzhiyun 		return;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	num_ports = get_num_ports(mdev, data[0].uart.port.membase);
143*4882a593Smuzhiyun 	if (num_ports <= 0 || num_ports > 4) {
144*4882a593Smuzhiyun 		dev_err(&mdev->dev, "error retrieving number of ports!\n");
145*4882a593Smuzhiyun 		return;
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	for (i = 0; i < num_ports; i++)
149*4882a593Smuzhiyun 		serial8250_unregister_port(data[i].line);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static const struct mcb_device_id serial_8250_men_mcb_ids[] = {
153*4882a593Smuzhiyun 	{ .device = MEN_UART_ID_Z025 },
154*4882a593Smuzhiyun 	{ .device = MEN_UART_ID_Z057 },
155*4882a593Smuzhiyun 	{ .device = MEN_UART_ID_Z125 },
156*4882a593Smuzhiyun 	{ }
157*4882a593Smuzhiyun };
158*4882a593Smuzhiyun MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun static struct mcb_driver mcb_driver = {
161*4882a593Smuzhiyun 	.driver = {
162*4882a593Smuzhiyun 		.name = "8250_men_mcb",
163*4882a593Smuzhiyun 		.owner = THIS_MODULE,
164*4882a593Smuzhiyun 	},
165*4882a593Smuzhiyun 	.probe = serial_8250_men_mcb_probe,
166*4882a593Smuzhiyun 	.remove = serial_8250_men_mcb_remove,
167*4882a593Smuzhiyun 	.id_table = serial_8250_men_mcb_ids,
168*4882a593Smuzhiyun };
169*4882a593Smuzhiyun module_mcb_driver(mcb_driver);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
172*4882a593Smuzhiyun MODULE_DESCRIPTION("MEN 8250 UART driver");
173*4882a593Smuzhiyun MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
174*4882a593Smuzhiyun MODULE_ALIAS("mcb:16z125");
175*4882a593Smuzhiyun MODULE_ALIAS("mcb:16z025");
176*4882a593Smuzhiyun MODULE_ALIAS("mcb:16z057");
177*4882a593Smuzhiyun MODULE_IMPORT_NS(MCB);
178