Date:2009-12-01 07:55:06 (10 years 6 months ago)
Author:xiangfu
Commit:f5f60fa05d1e7eab5cc2b667f06b9b6483bf62d2
Message:103-serial.patch

Files: drivers/serial/8250.c (8 diffs)

Change Details

drivers/serial/8250.c
194194    [PORT_16550A] = {
195195        .name = "16550A",
196196        .fifo_size = 16,
197        .tx_loadsz = 16,
197        .tx_loadsz = 8,
198198        .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
199199        .flags = UART_CAP_FIFO,
200200    },
...... 
401401static void mem_serial_out(struct uart_port *p, int offset, int value)
402402{
403403    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
404408    writeb(value, p->membase + offset);
405409}
406410
...... 
22132217        serial_unlink_irq_chain(up);
22142218}
22152219
2220#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
2221static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */
2222static 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
22162297static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
22172298{
22182299    unsigned int quot;
...... 
22322313
22332314    return quot;
22342315}
2316#endif
22352317
22362318static void
22372319serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
...... 
22412323    unsigned char cval, fcr = 0;
22422324    unsigned long flags;
22432325    unsigned int baud, quot;
2326#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
2327    unsigned short *quot1;
2328#endif
22442329
22452330    switch (termios->c_cflag & CSIZE) {
22462331    case CS5:
...... 
22732358     * Ask the core to calculate the divisor for us.
22742359     */
22752360    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
22762365    quot = serial8250_get_divisor(port, baud);
2366#endif
22772367
22782368    /*
22792369     * Oxford Semi 952 rev B workaround
...... 
23512441    if (up->capabilities & UART_CAP_UUE)
23522442        up->ier |= UART_IER_UUE | UART_IER_RTOIE;
23532443
2444#ifdef CONFIG_JZSOC
2445    up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */
2446#endif
2447
23542448    serial_out(up, UART_IER, up->ier);
23552449
23562450    if (up->capabilities & UART_CAP_EFR) {
...... 
23852479        serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
23862480    }
23872481
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
23882489    serial_dl_write(up, quot);
2490#endif
23892491
23902492    /*
23912493     * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR

Archive Download the corresponding diff file



interactive