linux-dreambox: fixed slow dm900 boot with unpowered debug port (no cable plugged)
[opendreambox.git] / meta-dreambox / recipes-kernel / linux / linux-dreambox-3.14 / 0001-dm900-workarounds-for-boot-and-shutdown-problems-wit.patch
1 From 5c06119ae4de413c1c2b5ac4bb1bb0b6bb4f10dd Mon Sep 17 00:00:00 2001
2 From: Andreas Monzner <andreas.monzner@dream-property.net>
3 Date: Fri, 13 Jan 2017 15:58:03 +0100
4 Subject: [PATCH] dm900: workarounds for boot and shutdown problems with
5  unpowered mini usb debug port
6
7 ---
8  arch/arm/configs/dm900_defconfig    |   5 +-
9  drivers/tty/serial/8250/8250_core.c | 137 +++++++++++++++++++++++++++++-------
10  2 files changed, 115 insertions(+), 27 deletions(-)
11
12 diff --git a/arch/arm/configs/dm900_defconfig b/arch/arm/configs/dm900_defconfig
13 index d617b98..9fcbb62 100644
14 --- a/arch/arm/configs/dm900_defconfig
15 +++ b/arch/arm/configs/dm900_defconfig
16 @@ -1759,7 +1759,6 @@ CONFIG_RTL8192CE=m
17  # CONFIG_RTL8192SE is not set
18  # CONFIG_RTL8192DE is not set
19  # CONFIG_RTL8723AE is not set
20 -CONFIG_RTL8188EE=m
21  CONFIG_RTL8192CU=m
22  CONFIG_RTLWIFI=m
23  CONFIG_RTLWIFI_PCI=m
24 @@ -1925,11 +1924,11 @@ CONFIG_UNIX98_PTYS=y
25  CONFIG_SERIAL_8250=y
26  CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
27  CONFIG_SERIAL_8250_CONSOLE=y
28 -CONFIG_SERIAL_8250_PCI=y
29 +# CONFIG_SERIAL_8250_PCI is not set
30  CONFIG_SERIAL_8250_NR_UARTS=4
31  CONFIG_SERIAL_8250_RUNTIME_UARTS=4
32  # CONFIG_SERIAL_8250_EXTENDED is not set
33 -CONFIG_SERIAL_8250_DW=y
34 +# CONFIG_SERIAL_8250_DW is not set
35  # CONFIG_SERIAL_8250_EM is not set
36  
37  #
38 diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
39 index 70fde5a..5ca4533 100644
40 --- a/drivers/tty/serial/8250/8250_core.c
41 +++ b/drivers/tty/serial/8250/8250_core.c
42 @@ -158,8 +158,13 @@ static const struct serial8250_config uart_config[] = {
43         },
44         [PORT_16550A] = {
45                 .name           = "16550A",
46 +#ifdef CONFIG_BCM7439
47 +               .fifo_size      = 32,
48 +               .tx_loadsz      = 32,
49 +#else
50                 .fifo_size      = 16,
51                 .tx_loadsz      = 16,
52 +#endif
53                 .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
54                 .flags          = UART_CAP_FIFO,
55         },
56 @@ -1407,8 +1412,14 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
57                         else if (lsr & UART_LSR_FE)
58                                 flag = TTY_FRAME;
59                 }
60 -               if (uart_handle_sysrq_char(port, ch))
61 -                       goto ignore_char;
62 +#ifdef CONFIG_DREAMBOX_DM900
63 +               /* this caused kernel oops on dm900 boot when the debug mini usb port is not powered */
64 +               if (serial_index(port) != 0 || (up->ier & (UART_IER_RLSI | UART_IER_RDI)) == (UART_IER_RLSI | UART_IER_RDI))
65 +#endif
66 +               {
67 +                       if (uart_handle_sysrq_char(port, ch))
68 +                               goto ignore_char;
69 +               }
70  
71                 uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
72  
73 @@ -1428,6 +1439,31 @@ void serial8250_tx_chars(struct uart_8250_port *up)
74         struct circ_buf *xmit = &port->state->xmit;
75         int count;
76  
77 +#ifdef CONFIG_DREAMBOX_DM900
78 +       if (serial_index(port) == 0 && (up->ier & (UART_IER_RLSI | UART_IER_RDI)) != (UART_IER_RLSI | UART_IER_RDI))
79 +       {
80 +               if (port->x_char) {
81 +                       port->icount.tx++;
82 +                       port->x_char = 0;
83 +                       return;
84 +               }
85 +
86 +               if (uart_tx_stopped(port)) {
87 +                       serial8250_stop_tx(port);
88 +                       return;
89 +               }
90 +
91 +               while (!uart_circ_empty(xmit)) {
92 +                       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
93 +                       port->icount.tx++;
94 +               }
95 +
96 +               __stop_tx(up);
97 +
98 +               return;
99 +       }
100 +#endif
101 +
102         if (port->x_char) {
103                 serial_out(up, UART_TX, port->x_char);
104                 port->icount.tx++;
105 @@ -1472,20 +1508,31 @@ unsigned int serial8250_modem_status(struct uart_8250_port *up)
106         struct uart_port *port = &up->port;
107         unsigned int status = serial_in(up, UART_MSR);
108  
109 -       status |= up->msr_saved_flags;
110 -       up->msr_saved_flags = 0;
111 -       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
112 -           port->state != NULL) {
113 -               if (status & UART_MSR_TERI)
114 -                       port->icount.rng++;
115 -               if (status & UART_MSR_DDSR)
116 -                       port->icount.dsr++;
117 -               if (status & UART_MSR_DDCD)
118 -                       uart_handle_dcd_change(port, status & UART_MSR_DCD);
119 -               if (status & UART_MSR_DCTS)
120 -                       uart_handle_cts_change(port, status & UART_MSR_CTS);
121 -
122 -               wake_up_interruptible(&port->state->port.delta_msr_wait);
123 +#ifdef CONFIG_DREAMBOX_DM900
124 +       if (serial_index(port) == 0) {
125 +               if (status & 1) {
126 +                       up->ier = status & 0x10 ? (UART_IER_RLSI | UART_IER_RDI | UART_IER_MSI) : UART_IER_MSI;
127 +                       serial_port_out(port, UART_IER, up->ier);
128 +               }
129 +       }
130 +       else
131 +#endif
132 +       {
133 +               status |= up->msr_saved_flags;
134 +               up->msr_saved_flags = 0;
135 +               if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
136 +                   port->state != NULL) {
137 +                       if (status & UART_MSR_TERI)
138 +                               port->icount.rng++;
139 +                       if (status & UART_MSR_DDSR)
140 +                               port->icount.dsr++;
141 +                       if (status & UART_MSR_DDCD)
142 +                               uart_handle_dcd_change(port, status & UART_MSR_DCD);
143 +                       if (status & UART_MSR_DCTS)
144 +                               uart_handle_cts_change(port, status & UART_MSR_CTS);
145 +
146 +                       wake_up_interruptible(&port->state->port.delta_msr_wait);
147 +               }
148         }
149  
150         return status;
151 @@ -1947,7 +1994,13 @@ static int serial8250_startup(struct uart_port *port)
152         unsigned long flags;
153         unsigned char lsr, iir;
154         int retval;
155 -
156 +#if defined(CONFIG_DREAMBOX_DM900) && !defined(CONFIG_SERIAL_8250_CONSOLE)
157 +       if (serial_index(port) == 0) {
158 +               volatile uint32_t *p = ioremap_nocache(0xf0404120, PAGE_SIZE);
159 +               *p |= 0x200;
160 +               iounmap(p);
161 +       }
162 +#endif
163         if (port->type == PORT_8250_CIR)
164                 return -ENODEV;
165  
166 @@ -2178,6 +2231,16 @@ dont_test_tx_en:
167          * anyway, so we don't enable them here.
168          */
169         up->ier = UART_IER_RLSI | UART_IER_RDI;
170 +
171 +#ifdef CONFIG_DREAMBOX_DM900
172 +       if (serial_index(port) == 0) {
173 +               if (serial_port_in(port, UART_MSR) & 0x10)
174 +                       up->ier |= UART_IER_MSI;
175 +               else
176 +                       up->ier = UART_IER_MSI;
177 +       }
178 +#endif
179 +
180         serial_port_out(port, UART_IER, up->ier);
181  
182         if (port->flags & UPF_FOURPORT) {
183 @@ -2381,13 +2444,19 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
184         if ((termios->c_cflag & CREAD) == 0)
185                 port->ignore_status_mask |= UART_LSR_DR;
186  
187 -       /*
188 -        * CTS flow control flag and modem status interrupts
189 -        */
190 -       up->ier &= ~UART_IER_MSI;
191 -       if (!(up->bugs & UART_BUG_NOMSR) &&
192 -                       UART_ENABLE_MS(&up->port, termios->c_cflag))
193 -               up->ier |= UART_IER_MSI;
194 +#ifdef CONFIG_DREAMBOX_DM900
195 +       if (serial_index(port) != 0)
196 +#endif
197 +       {
198 +               /*
199 +                * CTS flow control flag and modem status interrupts
200 +                */
201 +               up->ier &= ~UART_IER_MSI;
202 +               if (!(up->bugs & UART_BUG_NOMSR) &&
203 +                               UART_ENABLE_MS(&up->port, termios->c_cflag))
204 +                       up->ier |= UART_IER_MSI;
205 +       }
206 +
207         if (up->capabilities & UART_CAP_UUE)
208                 up->ier |= UART_IER_UUE;
209         if (up->capabilities & UART_CAP_RTOIE)
210 @@ -2959,9 +3028,29 @@ static int __init serial8250_console_setup(struct console *co, char *options)
211         if (co->index >= nr_uarts)
212                 co->index = 0;
213         port = &serial8250_ports[co->index].port;
214 +
215         if (!port->iobase && !port->membase)
216                 return -ENODEV;
217  
218 +#ifdef CONFIG_DREAMBOX_DM900
219 +       if (serial_index(port) == 0) {
220 +               volatile uint32_t *p = ioremap_nocache(0xf0404120, PAGE_SIZE);
221 +               *p |= 0x200;
222 +               iounmap(p);
223 +
224 +               udelay(1);
225 +
226 +               if (!(serial_in(&serial8250_ports[co->index], UART_MSR) & 0x10)) {
227 +                       /*
228 +                        * workaround for magic boot delay when serial console is enabled and no cable is plugged to mini usb port
229 +                        * so disable the console when no cable is plugged
230 +                        *
231 +                        */
232 +                       return -ENODEV;
233 +               }
234 +       }
235 +#endif
236 +
237         if (options)
238                 uart_parse_options(options, &baud, &parity, &bits, &flow);
239  
240 -- 
241 2.1.4
242