Date:2010-04-24 12:19:30 (10 years 2 months ago)
Author:Lars C.
Commit:ccfcbf1c1ee0e75c88dd68f12065d3deddf0fea6
Message:Add jz4740 serial driver

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

Change Details

drivers/serial/8250.c
200200    [PORT_16550A] = {
201201        .name = "16550A",
202202        .fifo_size = 16,
203        .tx_loadsz = 16,
203        .tx_loadsz = 8,
204204        .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
205205        .flags = UART_CAP_FIFO,
206206    },
...... 
407407static void mem_serial_out(struct uart_port *p, int offset, int value)
408408{
409409    offset = map_8250_out_reg(p, offset) << p->regshift;
410#if defined(CONFIG_JZSOC)
411        if (offset == (UART_FCR << p->regshift))
412            value |= 0x10; /* set FCR.UUE */
413#endif
410414    writeb(value, p->membase + offset);
411415}
412416
...... 
22092213        serial_unlink_irq_chain(up);
22102214}
22112215
2216#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
2217static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */
2218static unsigned short * serial8250_get_divisor(struct uart_port *port, unsigned int baud)
2219{
2220    int err, sum, i, j;
2221    int a[12], b[12];
2222    unsigned short div, umr, uacr;
2223    unsigned short umr_best, div_best, uacr_best;
2224    long long t0, t1, t2, t3;
2225
2226    sum = 0;
2227    umr_best = div_best = uacr_best = 0;
2228    div = 1;
2229
2230    if ((port->uartclk % (16 * baud)) == 0) {
2231        quot1[0] = port->uartclk / (16 * baud);
2232        quot1[1] = 16;
2233        quot1[2] = 0;
2234        return quot1;
2235    }
2236
2237    while (1) {
2238        umr = port->uartclk / (baud * div);
2239          if (umr > 32) {
2240            div++;
2241            continue;
2242        }
2243        if (umr < 4) {
2244            break;
2245        }
2246        for (i = 0; i < 12; i++) {
2247            a[i] = umr;
2248            b[i] = 0;
2249            sum = 0;
2250            for (j = 0; j <= i; j++) {
2251                sum += a[j];
2252            }
2253
2254                        /* the precision could be 1/2^(36) due to the value of t0 */
2255            t0 = 0x1000000000LL;
2256            t1 = (i + 1) * t0;
2257            t2 = (sum * div) * t0;
2258            t3 = div * t0;
2259            do_div(t1, baud);
2260            do_div(t2, port->uartclk);
2261            do_div(t3, (2 * port->uartclk));
2262            err = t1 - t2 - t3;
2263
2264            if (err > 0) {
2265                a[i] += 1;
2266                b[i] = 1;
2267            }
2268        }
2269
2270        uacr = 0;
2271        for (i = 0; i < 12; i++) {
2272            if (b[i] == 1) {
2273                uacr |= 1 << i;
2274            }
2275        }
2276
2277                /* the best value of umr should be near 16, and the value of uacr should better be smaller */
2278        if (abs(umr - 16) < abs(umr_best - 16) || (abs(umr - 16) == abs(umr_best - 16) && uacr_best > uacr)) {
2279            div_best = div;
2280            umr_best = umr;
2281            uacr_best = uacr;
2282        }
2283        div++;
2284    }
2285
2286    quot1[0] = div_best;
2287    quot1[1] = umr_best;
2288    quot1[2] = uacr_best;
2289
2290    return quot1;
2291}
2292#else
22122293static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
22132294{
22142295    unsigned int quot;
...... 
22282309
22292310    return quot;
22302311}
2312#endif
22312313
22322314static void
22332315serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
...... 
22372319    unsigned char cval, fcr = 0;
22382320    unsigned long flags;
22392321    unsigned int baud, quot;
2322#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
2323    unsigned short *quot1;
2324#endif
22402325
22412326    switch (termios->c_cflag & CSIZE) {
22422327    case CS5:
...... 
22712356    baud = uart_get_baud_rate(port, termios, old,
22722357                  port->uartclk / 16 / 0xffff,
22732358                  port->uartclk / 16);
2359#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
2360    quot1 = serial8250_get_divisor(port, baud);
2361    quot = quot1[0]; /* not usefull, just let gcc happy */
2362#else
22742363    quot = serial8250_get_divisor(port, baud);
2364#endif
22752365
22762366    /*
22772367     * Oxford Semi 952 rev B workaround
...... 
23492439    if (up->capabilities & UART_CAP_UUE)
23502440        up->ier |= UART_IER_UUE | UART_IER_RTOIE;
23512441
2442#ifdef CONFIG_JZSOC
2443    up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */
2444#endif
2445
23522446    serial_out(up, UART_IER, up->ier);
23532447
23542448    if (up->capabilities & UART_CAP_EFR) {
...... 
23832477        serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
23842478    }
23852479
2480#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
2481#define UART_UMR 9
2482#define UART_UACR 10
2483    serial_dl_write(up, quot1[0]);
2484    serial_outp(up, UART_UMR, quot1[1]);
2485    serial_outp(up, UART_UACR, quot1[2]);
2486#else
23862487    serial_dl_write(up, quot);
2488#endif
23872489
23882490    /*
23892491     * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR

Archive Download the corresponding diff file



interactive