aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/8250/8250_men_mcb.c118
-rw-r--r--drivers/tty/serial/8250/Kconfig11
-rw-r--r--drivers/tty/serial/8250/Makefile1
3 files changed, 130 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c
new file mode 100644
index 000000000000..308977807994
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_men_mcb.c
@@ -0,0 +1,118 @@
1#include <linux/device.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/mcb.h>
5#include <linux/serial.h>
6#include <linux/serial_core.h>
7#include <linux/serial_8250.h>
8#include <uapi/linux/serial_core.h>
9
10struct serial_8250_men_mcb_data {
11 struct uart_8250_port uart;
12 int line;
13};
14
15/*
16 * The Z125 16550-compatible UART has no fixed base clock assigned
17 * So, depending on the board we're on, we need to adjust the
18 * parameter in order to really set the correct baudrate, and
19 * do so if possible without user interaction
20 */
21static u32 men_z125_lookup_uartclk(struct mcb_device *mdev)
22{
23 /* use default value if board is not available below */
24 u32 clkval = 1041666;
25
26 dev_info(&mdev->dev, "%s on board %s\n",
27 dev_name(&mdev->dev),
28 mdev->bus->name);
29 if (strncmp(mdev->bus->name, "F075", 4) == 0)
30 clkval = 1041666;
31 else if (strncmp(mdev->bus->name, "F216", 4) == 0)
32 clkval = 1843200;
33 else if (strncmp(mdev->bus->name, "G215", 4) == 0)
34 clkval = 1843200;
35 else
36 dev_info(&mdev->dev,
37 "board not detected, using default uartclk\n");
38
39 clkval = clkval << 4;
40
41 return clkval;
42}
43
44static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
45 const struct mcb_device_id *id)
46{
47 struct serial_8250_men_mcb_data *data;
48 struct resource *mem;
49
50 data = devm_kzalloc(&mdev->dev,
51 sizeof(struct serial_8250_men_mcb_data),
52 GFP_KERNEL);
53 if (!data)
54 return -ENOMEM;
55
56 mcb_set_drvdata(mdev, data);
57 data->uart.port.dev = mdev->dma_dev;
58 spin_lock_init(&data->uart.port.lock);
59
60 data->uart.port.type = PORT_16550;
61 data->uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
62 data->uart.port.iotype = UPIO_MEM;
63 data->uart.port.uartclk = men_z125_lookup_uartclk(mdev);
64 data->uart.port.regshift = 0;
65 data->uart.port.fifosize = 60;
66
67 mem = mcb_get_resource(mdev, IORESOURCE_MEM);
68 if (mem == NULL)
69 return -ENXIO;
70
71 data->uart.port.irq = mcb_get_irq(mdev);
72
73 data->uart.port.membase = devm_ioremap_resource(&mdev->dev, mem);
74 if (IS_ERR(data->uart.port.membase))
75 return PTR_ERR_OR_ZERO(data->uart.port.membase);
76
77 data->uart.port.mapbase = (unsigned long) mem->start;
78 data->uart.port.iobase = data->uart.port.mapbase;
79
80 /* ok, register the port */
81 data->line = serial8250_register_8250_port(&data->uart);
82 if (data->line < 0)
83 return data->line;
84
85 dev_info(&mdev->dev, "found 16Z125 UART: ttyS%d\n", data->line);
86
87 return 0;
88}
89
90static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
91{
92 struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
93
94 if (data)
95 serial8250_unregister_port(data->line);
96}
97
98static const struct mcb_device_id serial_8250_men_mcb_ids[] = {
99 { .device = 0x7d },
100 { }
101};
102MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids);
103
104static struct mcb_driver mcb_driver = {
105 .driver = {
106 .name = "8250_men_mcb",
107 .owner = THIS_MODULE,
108 },
109 .probe = serial_8250_men_mcb_probe,
110 .remove = serial_8250_men_mcb_remove,
111 .id_table = serial_8250_men_mcb_ids,
112};
113module_mcb_driver(mcb_driver);
114
115MODULE_LICENSE("GPL v2");
116MODULE_DESCRIPTION("MEN 16z125 8250 UART driver");
117MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
118MODULE_ALIAS("mcb:16z125");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index a1161ec0256f..a5c0ef1e7695 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -155,6 +155,17 @@ config SERIAL_8250_CS
155 155
156 If unsure, say N. 156 If unsure, say N.
157 157
158config SERIAL_8250_MEN_MCB
159 tristate "MEN Z125 UART device support"
160 depends on MCB && SERIAL_8250
161 help
162 This enables support for FPGA based UARTs found on many MEN
163 boards. This driver enables support for the Z125 UARTs.
164
165 To compile this driver as a module, chose M here: the
166 module will be called 8250_men_mcb.
167
168
158config SERIAL_8250_NR_UARTS 169config SERIAL_8250_NR_UARTS
159 int "Maximum number of 8250/16550 serial ports" 170 int "Maximum number of 8250/16550 serial ports"
160 depends on SERIAL_8250 171 depends on SERIAL_8250
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index a44a99a3e623..6a18d2d768fe 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
23obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o 23obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
24obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o 24obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
25obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o 25obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
26obj-$(CONFIG_SERIAL_8250_MEN_MCB) += 8250_men_mcb.o
26obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o 27obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
27obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o 28obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o
28obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o 29obj-$(CONFIG_SERIAL_8250_OMAP) += 8250_omap.o