2 * Serial port driver for BCM2835AUX UART
4 * Copyright (C) 2016 Martin Sperl <kernel@martin.sperl.org>
6 * Based on 8250_lpc18xx.c:
7 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
15 #include <linux/clk.h>
17 #include <linux/module.h>
19 #include <linux/platform_device.h>
23 struct bcm2835aux_data
{
24 struct uart_8250_port uart
;
29 static int bcm2835aux_serial_probe(struct platform_device
*pdev
)
31 struct bcm2835aux_data
*data
;
35 /* allocate the custom structure */
36 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
41 spin_lock_init(&data
->uart
.port
.lock
);
42 data
->uart
.capabilities
= UART_CAP_FIFO
;
43 data
->uart
.port
.dev
= &pdev
->dev
;
44 data
->uart
.port
.regshift
= 2;
45 data
->uart
.port
.type
= PORT_16550
;
46 data
->uart
.port
.iotype
= UPIO_MEM
;
47 data
->uart
.port
.fifosize
= 8;
48 data
->uart
.port
.flags
= UPF_SHARE_IRQ
|
53 /* get the clock - this also enables the HW */
54 data
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
55 ret
= PTR_ERR_OR_ZERO(data
->clk
);
57 dev_err(&pdev
->dev
, "could not get clk: %d\n", ret
);
61 /* get the interrupt */
62 ret
= platform_get_irq(pdev
, 0);
64 dev_err(&pdev
->dev
, "irq not found - %i", ret
);
67 data
->uart
.port
.irq
= ret
;
69 /* map the main registers */
70 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
72 dev_err(&pdev
->dev
, "memory resource not found");
75 data
->uart
.port
.membase
= devm_ioremap_resource(&pdev
->dev
, res
);
76 ret
= PTR_ERR_OR_ZERO(data
->uart
.port
.membase
);
80 /* Check for a fixed line number */
81 ret
= of_alias_get_id(pdev
->dev
.of_node
, "serial");
83 data
->uart
.port
.line
= ret
;
85 /* enable the clock as a last step */
86 ret
= clk_prepare_enable(data
->clk
);
88 dev_err(&pdev
->dev
, "unable to enable uart clock - %d\n",
93 /* the HW-clock divider for bcm2835aux is 8,
94 * but 8250 expects a divider of 16,
95 * so we have to multiply the actual clock by 2
96 * to get identical baudrates.
98 data
->uart
.port
.uartclk
= clk_get_rate(data
->clk
) * 2;
100 /* register the port */
101 ret
= serial8250_register_8250_port(&data
->uart
);
103 dev_err(&pdev
->dev
, "unable to register 8250 port - %d\n",
109 platform_set_drvdata(pdev
, data
);
114 clk_disable_unprepare(data
->clk
);
118 static int bcm2835aux_serial_remove(struct platform_device
*pdev
)
120 struct bcm2835aux_data
*data
= platform_get_drvdata(pdev
);
122 serial8250_unregister_port(data
->uart
.port
.line
);
123 clk_disable_unprepare(data
->clk
);
128 static const struct of_device_id bcm2835aux_serial_match
[] = {
129 { .compatible
= "brcm,bcm2835-aux-uart" },
132 MODULE_DEVICE_TABLE(of
, bcm2835aux_serial_match
);
134 static struct platform_driver bcm2835aux_serial_driver
= {
136 .name
= "bcm2835-aux-uart",
137 .of_match_table
= bcm2835aux_serial_match
,
139 .probe
= bcm2835aux_serial_probe
,
140 .remove
= bcm2835aux_serial_remove
,
142 module_platform_driver(bcm2835aux_serial_driver
);
144 MODULE_DESCRIPTION("BCM2835 auxiliar UART driver");
145 MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
146 MODULE_LICENSE("GPL v2");