forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/tty/serial/8250/8250_bcm2835aux.c
....@@ -6,6 +6,10 @@
66 *
77 * Based on 8250_lpc18xx.c:
88 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
9
+ *
10
+ * The bcm2835aux is capable of RTS auto flow-control, but this driver doesn't
11
+ * take advantage of it yet. When adding support, be sure not to enable it
12
+ * simultaneously to rs485.
913 */
1014
1115 #include <linux/clk.h>
....@@ -16,14 +20,67 @@
1620
1721 #include "8250.h"
1822
23
+#define BCM2835_AUX_UART_CNTL 8
24
+#define BCM2835_AUX_UART_CNTL_RXEN 0x01 /* Receiver enable */
25
+#define BCM2835_AUX_UART_CNTL_TXEN 0x02 /* Transmitter enable */
26
+#define BCM2835_AUX_UART_CNTL_AUTORTS 0x04 /* RTS set by RX fill level */
27
+#define BCM2835_AUX_UART_CNTL_AUTOCTS 0x08 /* CTS stops transmitter */
28
+#define BCM2835_AUX_UART_CNTL_RTS3 0x00 /* RTS set until 3 chars left */
29
+#define BCM2835_AUX_UART_CNTL_RTS2 0x10 /* RTS set until 2 chars left */
30
+#define BCM2835_AUX_UART_CNTL_RTS1 0x20 /* RTS set until 1 chars left */
31
+#define BCM2835_AUX_UART_CNTL_RTS4 0x30 /* RTS set until 4 chars left */
32
+#define BCM2835_AUX_UART_CNTL_RTSINV 0x40 /* Invert auto RTS polarity */
33
+#define BCM2835_AUX_UART_CNTL_CTSINV 0x80 /* Invert auto CTS polarity */
34
+
35
+/**
36
+ * struct bcm2835aux_data - driver private data of BCM2835 auxiliary UART
37
+ * @clk: clock producer of the port's uartclk
38
+ * @line: index of the port's serial8250_ports[] entry
39
+ * @cntl: cached copy of CNTL register
40
+ */
1941 struct bcm2835aux_data {
20
- struct uart_8250_port uart;
2142 struct clk *clk;
2243 int line;
44
+ u32 cntl;
2345 };
46
+
47
+static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up)
48
+{
49
+ if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
50
+ struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev);
51
+
52
+ data->cntl &= ~BCM2835_AUX_UART_CNTL_RXEN;
53
+ serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl);
54
+ }
55
+
56
+ /*
57
+ * On the bcm2835aux, the MCR register contains no other
58
+ * flags besides RTS. So no need for a read-modify-write.
59
+ */
60
+ if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
61
+ serial8250_out_MCR(up, 0);
62
+ else
63
+ serial8250_out_MCR(up, UART_MCR_RTS);
64
+}
65
+
66
+static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up)
67
+{
68
+ if (up->port.rs485.flags & SER_RS485_RTS_AFTER_SEND)
69
+ serial8250_out_MCR(up, 0);
70
+ else
71
+ serial8250_out_MCR(up, UART_MCR_RTS);
72
+
73
+ if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
74
+ struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev);
75
+
76
+ data->cntl |= BCM2835_AUX_UART_CNTL_RXEN;
77
+ serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl);
78
+ }
79
+}
2480
2581 static int bcm2835aux_serial_probe(struct platform_device *pdev)
2682 {
83
+ struct uart_8250_port up = { };
2784 struct bcm2835aux_data *data;
2885 struct resource *res;
2986 int ret;
....@@ -34,33 +91,33 @@
3491 return -ENOMEM;
3592
3693 /* initialize data */
37
- spin_lock_init(&data->uart.port.lock);
38
- data->uart.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
39
- data->uart.port.dev = &pdev->dev;
40
- data->uart.port.regshift = 2;
41
- data->uart.port.type = PORT_16550;
42
- data->uart.port.iotype = UPIO_MEM;
43
- data->uart.port.fifosize = 8;
44
- data->uart.port.flags = UPF_SHARE_IRQ |
45
- UPF_FIXED_PORT |
46
- UPF_FIXED_TYPE |
47
- UPF_SKIP_TEST;
94
+ up.capabilities = UART_CAP_FIFO | UART_CAP_MINI;
95
+ up.port.dev = &pdev->dev;
96
+ up.port.regshift = 2;
97
+ up.port.type = PORT_16550;
98
+ up.port.iotype = UPIO_MEM;
99
+ up.port.fifosize = 8;
100
+ up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE |
101
+ UPF_SKIP_TEST | UPF_IOREMAP;
102
+ up.port.rs485_config = serial8250_em485_config;
103
+ up.rs485_start_tx = bcm2835aux_rs485_start_tx;
104
+ up.rs485_stop_tx = bcm2835aux_rs485_stop_tx;
105
+
106
+ /* initialize cached copy with power-on reset value */
107
+ data->cntl = BCM2835_AUX_UART_CNTL_RXEN | BCM2835_AUX_UART_CNTL_TXEN;
108
+
109
+ platform_set_drvdata(pdev, data);
48110
49111 /* get the clock - this also enables the HW */
50112 data->clk = devm_clk_get(&pdev->dev, NULL);
51
- ret = PTR_ERR_OR_ZERO(data->clk);
52
- if (ret) {
53
- dev_err(&pdev->dev, "could not get clk: %d\n", ret);
54
- return ret;
55
- }
113
+ if (IS_ERR(data->clk))
114
+ return dev_err_probe(&pdev->dev, PTR_ERR(data->clk), "could not get clk\n");
56115
57116 /* get the interrupt */
58117 ret = platform_get_irq(pdev, 0);
59
- if (ret < 0) {
60
- dev_err(&pdev->dev, "irq not found - %i", ret);
118
+ if (ret < 0)
61119 return ret;
62
- }
63
- data->uart.port.irq = ret;
120
+ up.port.irq = ret;
64121
65122 /* map the main registers */
66123 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
....@@ -68,15 +125,13 @@
68125 dev_err(&pdev->dev, "memory resource not found");
69126 return -EINVAL;
70127 }
71
- data->uart.port.membase = devm_ioremap_resource(&pdev->dev, res);
72
- ret = PTR_ERR_OR_ZERO(data->uart.port.membase);
73
- if (ret)
74
- return ret;
128
+ up.port.mapbase = res->start;
129
+ up.port.mapsize = resource_size(res);
75130
76131 /* Check for a fixed line number */
77132 ret = of_alias_get_id(pdev->dev.of_node, "serial");
78133 if (ret >= 0)
79
- data->uart.port.line = ret;
134
+ up.port.line = ret;
80135
81136 /* enable the clock as a last step */
82137 ret = clk_prepare_enable(data->clk);
....@@ -91,18 +146,15 @@
91146 * so we have to multiply the actual clock by 2
92147 * to get identical baudrates.
93148 */
94
- data->uart.port.uartclk = clk_get_rate(data->clk) * 2;
149
+ up.port.uartclk = clk_get_rate(data->clk) * 2;
95150
96151 /* register the port */
97
- ret = serial8250_register_8250_port(&data->uart);
152
+ ret = serial8250_register_8250_port(&up);
98153 if (ret < 0) {
99
- dev_err(&pdev->dev, "unable to register 8250 port - %d\n",
100
- ret);
154
+ dev_err_probe(&pdev->dev, ret, "unable to register 8250 port\n");
101155 goto dis_clk;
102156 }
103157 data->line = ret;
104
-
105
- platform_set_drvdata(pdev, data);
106158
107159 return 0;
108160
....@@ -137,6 +189,24 @@
137189 };
138190 module_platform_driver(bcm2835aux_serial_driver);
139191
192
+#ifdef CONFIG_SERIAL_8250_CONSOLE
193
+
194
+static int __init early_bcm2835aux_setup(struct earlycon_device *device,
195
+ const char *options)
196
+{
197
+ if (!device->port.membase)
198
+ return -ENODEV;
199
+
200
+ device->port.iotype = UPIO_MEM32;
201
+ device->port.regshift = 2;
202
+
203
+ return early_serial8250_setup(device, NULL);
204
+}
205
+
206
+OF_EARLYCON_DECLARE(bcm2835aux, "brcm,bcm2835-aux-uart",
207
+ early_bcm2835aux_setup);
208
+#endif
209
+
140210 MODULE_DESCRIPTION("BCM2835 auxiliar UART driver");
141211 MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
142212 MODULE_LICENSE("GPL v2");