| Date: | 2009-12-01 07:55:06 (2 years 5 months ago) |
|---|---|
| Author: | xiangfu |
| Commit: | f5f60fa05d1e7eab5cc2b667f06b9b6483bf62d2 |
| Message: | 103-serial.patch |
| Files: |
drivers/serial/8250.c (8 diffs) |
Change Details
| drivers/serial/8250.c | ||
|---|---|---|
| 194 | 194 | [PORT_16550A] = { |
| 195 | 195 | .name = "16550A", |
| 196 | 196 | .fifo_size = 16, |
| 197 | .tx_loadsz = 16, | |
| 197 | .tx_loadsz = 8, | |
| 198 | 198 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
| 199 | 199 | .flags = UART_CAP_FIFO, |
| 200 | 200 | }, |
| ... | ... | |
| 401 | 401 | static void mem_serial_out(struct uart_port *p, int offset, int value) |
| 402 | 402 | { |
| 403 | 403 | offset = map_8250_out_reg(p, offset) << p->regshift; |
| 404 | #if defined(CONFIG_JZSOC) | |
| 405 | if (offset == (UART_FCR << p->regshift)) | |
| 406 | value |= 0x10; /* set FCR.UUE */ | |
| 407 | #endif | |
| 404 | 408 | writeb(value, p->membase + offset); |
| 405 | 409 | } |
| 406 | 410 | |
| ... | ... | |
| 2213 | 2217 | serial_unlink_irq_chain(up); |
| 2214 | 2218 | } |
| 2215 | 2219 | |
| 2220 | #if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) | |
| 2221 | static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */ | |
| 2222 | static unsigned short * serial8250_get_divisor(struct uart_port *port, unsigned int baud) | |
| 2223 | { | |
| 2224 | int err, sum, i, j; | |
| 2225 | int a[12], b[12]; | |
| 2226 | unsigned short div, umr, uacr; | |
| 2227 | unsigned short umr_best, div_best, uacr_best; | |
| 2228 | long long t0, t1, t2, t3; | |
| 2229 | ||
| 2230 | sum = 0; | |
| 2231 | umr_best = div_best = uacr_best = 0; | |
| 2232 | div = 1; | |
| 2233 | ||
| 2234 | if ((port->uartclk % (16 * baud)) == 0) { | |
| 2235 | quot1[0] = port->uartclk / (16 * baud); | |
| 2236 | quot1[1] = 16; | |
| 2237 | quot1[2] = 0; | |
| 2238 | return quot1; | |
| 2239 | } | |
| 2240 | ||
| 2241 | while (1) { | |
| 2242 | umr = port->uartclk / (baud * div); | |
| 2243 | if (umr > 32) { | |
| 2244 | div++; | |
| 2245 | continue; | |
| 2246 | } | |
| 2247 | if (umr < 4) { | |
| 2248 | break; | |
| 2249 | } | |
| 2250 | for (i = 0; i < 12; i++) { | |
| 2251 | a[i] = umr; | |
| 2252 | b[i] = 0; | |
| 2253 | sum = 0; | |
| 2254 | for (j = 0; j <= i; j++) { | |
| 2255 | sum += a[j]; | |
| 2256 | } | |
| 2257 | ||
| 2258 | /* the precision could be 1/2^(36) due to the value of t0 */ | |
| 2259 | t0 = 0x1000000000LL; | |
| 2260 | t1 = (i + 1) * t0; | |
| 2261 | t2 = (sum * div) * t0; | |
| 2262 | t3 = div * t0; | |
| 2263 | do_div(t1, baud); | |
| 2264 | do_div(t2, port->uartclk); | |
| 2265 | do_div(t3, (2 * port->uartclk)); | |
| 2266 | err = t1 - t2 - t3; | |
| 2267 | ||
| 2268 | if (err > 0) { | |
| 2269 | a[i] += 1; | |
| 2270 | b[i] = 1; | |
| 2271 | } | |
| 2272 | } | |
| 2273 | ||
| 2274 | uacr = 0; | |
| 2275 | for (i = 0; i < 12; i++) { | |
| 2276 | if (b[i] == 1) { | |
| 2277 | uacr |= 1 << i; | |
| 2278 | } | |
| 2279 | } | |
| 2280 | ||
| 2281 | /* the best value of umr should be near 16, and the value of uacr should better be smaller */ | |
| 2282 | if (abs(umr - 16) < abs(umr_best - 16) || (abs(umr - 16) == abs(umr_best - 16) && uacr_best > uacr)) { | |
| 2283 | div_best = div; | |
| 2284 | umr_best = umr; | |
| 2285 | uacr_best = uacr; | |
| 2286 | } | |
| 2287 | div++; | |
| 2288 | } | |
| 2289 | ||
| 2290 | quot1[0] = div_best; | |
| 2291 | quot1[1] = umr_best; | |
| 2292 | quot1[2] = uacr_best; | |
| 2293 | ||
| 2294 | return quot1; | |
| 2295 | } | |
| 2296 | #else | |
| 2216 | 2297 | static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) |
| 2217 | 2298 | { |
| 2218 | 2299 | unsigned int quot; |
| ... | ... | |
| 2232 | 2313 | |
| 2233 | 2314 | return quot; |
| 2234 | 2315 | } |
| 2316 | #endif | |
| 2235 | 2317 | |
| 2236 | 2318 | static void |
| 2237 | 2319 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| ... | ... | |
| 2241 | 2323 | unsigned char cval, fcr = 0; |
| 2242 | 2324 | unsigned long flags; |
| 2243 | 2325 | unsigned int baud, quot; |
| 2326 | #if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) | |
| 2327 | unsigned short *quot1; | |
| 2328 | #endif | |
| 2244 | 2329 | |
| 2245 | 2330 | switch (termios->c_cflag & CSIZE) { |
| 2246 | 2331 | case CS5: |
| ... | ... | |
| 2273 | 2358 | * Ask the core to calculate the divisor for us. |
| 2274 | 2359 | */ |
| 2275 | 2360 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
| 2361 | #if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) | |
| 2362 | quot1 = serial8250_get_divisor(port, baud); | |
| 2363 | quot = quot1[0]; /* not usefull, just let gcc happy */ | |
| 2364 | #else | |
| 2276 | 2365 | quot = serial8250_get_divisor(port, baud); |
| 2366 | #endif | |
| 2277 | 2367 | |
| 2278 | 2368 | /* |
| 2279 | 2369 | * Oxford Semi 952 rev B workaround |
| ... | ... | |
| 2351 | 2441 | if (up->capabilities & UART_CAP_UUE) |
| 2352 | 2442 | up->ier |= UART_IER_UUE | UART_IER_RTOIE; |
| 2353 | 2443 | |
| 2444 | #ifdef CONFIG_JZSOC | |
| 2445 | up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */ | |
| 2446 | #endif | |
| 2447 | ||
| 2354 | 2448 | serial_out(up, UART_IER, up->ier); |
| 2355 | 2449 | |
| 2356 | 2450 | if (up->capabilities & UART_CAP_EFR) { |
| ... | ... | |
| 2385 | 2479 | serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ |
| 2386 | 2480 | } |
| 2387 | 2481 | |
| 2482 | #if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) | |
| 2483 | #define UART_UMR 9 | |
| 2484 | #define UART_UACR 10 | |
| 2485 | serial_dl_write(up, quot1[0]); | |
| 2486 | serial_outp(up, UART_UMR, quot1[1]); | |
| 2487 | serial_outp(up, UART_UACR, quot1[2]); | |
| 2488 | #else | |
| 2388 | 2489 | serial_dl_write(up, quot); |
| 2490 | #endif | |
| 2389 | 2491 | |
| 2390 | 2492 | /* |
| 2391 | 2493 | * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.2
jz-3.3
jz-3.4
jz47xx
jz47xx-2.6.38
master
9c46e24dbb1568054a85266cf79adce196c6f475
9845c1745d3d531a5b9544f5322c62bfb4d4e9bc
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
