1 #include <linux/device.h>
2 #include <linux/kernel.h>
3 #include <linux/module.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>
10 struct serial_8250_men_mcb_data
{
11 struct uart_8250_port uart
;
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
21 static u32
men_z125_lookup_uartclk(struct mcb_device
*mdev
)
23 /* use default value if board is not available below */
26 dev_info(&mdev
->dev
, "%s on board %s\n",
29 if (strncmp(mdev
->bus
->name
, "F075", 4) == 0)
31 else if (strncmp(mdev
->bus
->name
, "F216", 4) == 0)
33 else if (strncmp(mdev
->bus
->name
, "G215", 4) == 0)
37 "board not detected, using default uartclk\n");
44 static int serial_8250_men_mcb_probe(struct mcb_device
*mdev
,
45 const struct mcb_device_id
*id
)
47 struct serial_8250_men_mcb_data
*data
;
50 data
= devm_kzalloc(&mdev
->dev
,
51 sizeof(struct serial_8250_men_mcb_data
),
56 mcb_set_drvdata(mdev
, data
);
57 data
->uart
.port
.dev
= mdev
->dma_dev
;
58 spin_lock_init(&data
->uart
.port
.lock
);
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;
67 mem
= mcb_get_resource(mdev
, IORESOURCE_MEM
);
71 data
->uart
.port
.irq
= mcb_get_irq(mdev
);
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
);
77 data
->uart
.port
.mapbase
= (unsigned long) mem
->start
;
78 data
->uart
.port
.iobase
= data
->uart
.port
.mapbase
;
80 /* ok, register the port */
81 data
->line
= serial8250_register_8250_port(&data
->uart
);
85 dev_info(&mdev
->dev
, "found 16Z125 UART: ttyS%d\n", data
->line
);
90 static void serial_8250_men_mcb_remove(struct mcb_device
*mdev
)
92 struct serial_8250_men_mcb_data
*data
= mcb_get_drvdata(mdev
);
95 serial8250_unregister_port(data
->line
);
98 static const struct mcb_device_id serial_8250_men_mcb_ids
[] = {
102 MODULE_DEVICE_TABLE(mcb
, serial_8250_men_mcb_ids
);
104 static struct mcb_driver mcb_driver
= {
106 .name
= "8250_men_mcb",
107 .owner
= THIS_MODULE
,
109 .probe
= serial_8250_men_mcb_probe
,
110 .remove
= serial_8250_men_mcb_remove
,
111 .id_table
= serial_8250_men_mcb_ids
,
113 module_mcb_driver(mcb_driver
);
115 MODULE_LICENSE("GPL v2");
116 MODULE_DESCRIPTION("MEN 16z125 8250 UART driver");
117 MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
118 MODULE_ALIAS("mcb:16z125");