Date:2010-05-31 21:09:37 (13 years 6 months ago)
Author:Lars C.
Commit:a12c4561306d020ad232762c967d6132441965df
Message:Replace jz4740 specific hacks in the 8250 serial driver with platform code.

Files: arch/mips/include/asm/mach-jz4740/platform.h (2 diffs)
arch/mips/include/asm/mach-jz4740/serial.h (1 diff)
arch/mips/jz4740/Makefile (1 diff)
arch/mips/jz4740/board-qi_lb60.c (1 diff)
arch/mips/jz4740/clock.h (1 diff)
arch/mips/jz4740/platform.c (2 diffs)
arch/mips/jz4740/serial.c (1 diff)
arch/mips/jz4740/serial.h (1 diff)
arch/mips/jz4740/setup.c (1 diff)
drivers/serial/8250.c (7 diffs)

Change Details

arch/mips/include/asm/mach-jz4740/platform.h
11/*
2 * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ7420/JZ4740 platform device definitions
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 platform device definitions
44 *
55 * This program is free software; you can redistribute it and/or modify it
66 * under the terms of the GNU General Public License as published by the
...... 
3131extern struct platform_device jz4740_adc_device;
3232extern struct platform_device jz4740_battery_device;
3333
34void jz4740_serial_device_register(void);
35
3436#endif
arch/mips/include/asm/mach-jz4740/serial.h
1/*
2 * linux/include/asm-mips/mach-jz4740/serial.h
3 *
4 * Ingenic's JZ4740 common include.
5 *
6 * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc.
7 *
8 * Author: <yliu@ingenic.cn>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __ASM_BOARD_SERIAL_H__
16#define __ASM_BOARD_SERIAL_H__
17
18#ifndef CONFIG_SERIAL_MANY_PORTS
19#undef RS_TABLE_SIZE
20#define RS_TABLE_SIZE 1
21#endif
22
23#define JZ_BASE_BAUD (12000000/16)
24
25#define JZ_SERIAL_PORT_DEFNS \
26    { .baud_base = JZ_BASE_BAUD, .irq = IRQ_UART0, \
27      .flags = STD_COM_FLAGS, .iomem_base = (u8 *)UART0_BASE, \
28      .iomem_reg_shift = 2, .io_type = SERIAL_IO_MEM },
29
30#endif /* __ASM_BORAD_SERIAL_H__ */
arch/mips/jz4740/Makefile
77obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
88    gpio.o clock.o platform.o timer.o pwm.o
99
10obj-$(CONFIG_SERIAL_8250) += serial.o
11
1012obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
1113
1214# board specific support
arch/mips/jz4740/board-qi_lb60.c
437437    jz4740_battery_device.dev.platform_data = &qi_lb60_battery_pdata;
438438    jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata;
439439
440    jz4740_serial_device_register();
441
440442    spi_register_board_info(qi_lb60_spi_board_info,
441443                ARRAY_SIZE(qi_lb60_spi_board_info));
442444
arch/mips/jz4740/clock.h
1313 *
1414 */
1515
16#ifndef __JZ4740_CLOCK_H__
17#define __JZ4740_CLOCK_H__
16#ifndef __MIPS_JZ4740_CLOCK_H__
17#define __MIPS_JZ4740_CLOCK_H__
18
19#include <linux/list.h>
1820
1921struct jz4740_clock_board_data {
2022    unsigned long ext_rate;
arch/mips/jz4740/platform.c
2323#include <asm/mach-jz4740/base.h>
2424#include <asm/mach-jz4740/irq.h>
2525
26#include <linux/serial_core.h>
27#include <linux/serial_8250.h>
28
29#include "serial.h"
30#include "clock.h"
31
2632/* OHCI (USB full speed host controller) */
2733static struct resource jz4740_usb_ohci_resources[] = {
2834    [0] = {
...... 
244250        .parent = &jz4740_adc_device.dev
245251    },
246252};
253
254/* Serial */
255#define JZ4740_UART_DATA(_id) \
256    { \
257        .flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \
258        .iotype = UPIO_MEM, \
259        .regshift = 2, \
260        .serial_out = jz4740_serial_out, \
261        .type = PORT_16550A, \
262        .mapbase = CPHYSADDR(JZ4740_UART ## _id ## _BASE_ADDR), \
263        .irq = JZ4740_IRQ_UART ## _id, \
264    }
265
266static struct plat_serial8250_port jz4740_uart_data[] = {
267    JZ4740_UART_DATA(0),
268    JZ4740_UART_DATA(1),
269    {},
270};
271
272static struct platform_device jz4740_uart_device = {
273    .name = "serial8250",
274    .id = 0,
275    .dev = {
276        .platform_data = jz4740_uart_data,
277    },
278};
279
280void jz4740_serial_device_register(void)
281{
282    struct plat_serial8250_port *p;
283
284    for (p = jz4740_uart_data; p->flags != 0; ++p)
285        p->uartclk = jz4740_clock_bdata.ext_rate;
286
287    platform_device_register(&jz4740_uart_device);
288}
arch/mips/jz4740/serial.c
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 serial support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/io.h>
17#include <linux/serial_core.h>
18#include <linux/serial_reg.h>
19
20void jz4740_serial_out(struct uart_port *p, int offset, int value)
21{
22    switch (offset) {
23    case UART_FCR:
24        value |= 0x10; /* Enable uart module */
25        break;
26    case UART_IER:
27        value |= (value & 0x4) << 2;
28        break;
29    default:
30        break;
31    }
32    writeb(value, p->membase + (offset << p->regshift));
33}
arch/mips/jz4740/serial.h
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 serial support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#ifndef __MIPS_JZ4740_SERIAL_H__
17
18void jz4740_serial_out(struct uart_port *p, int offset, int value);
19
20#endif
21
arch/mips/jz4740/setup.c
1313 *
1414 */
1515
16
1716#include <linux/init.h>
1817#include <linux/kernel.h>
19#include <linux/serial.h>
20#include <linux/serial_core.h>
21#include <linux/serial_8250.h>
2218
2319#include <asm/mach-jz4740/base.h>
2420#include <asm/mach-jz4740/clock.h>
25#include <asm/mach-jz4740/serial.h>
2621
2722#include "reset.h"
2823#include "clock.h"
2924
30static void __init jz4740_serial_setup(void)
31{
32#ifdef CONFIG_SERIAL_8250
33    struct uart_port s;
34    memset(&s, 0, sizeof(s));
35    s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
36    s.iotype = SERIAL_IO_MEM;
37    s.regshift = 2;
38    s.uartclk = jz4740_clock_bdata.ext_rate;
39
40    s.line = 0;
41    s.membase = (u8 *)JZ4740_UART0_BASE_ADDR;
42    s.irq = JZ4740_IRQ_UART0;
43    if (early_serial_setup(&s) != 0) {
44        printk(KERN_ERR "Serial ttyS0 setup failed!\n");
45    }
46
47    s.line = 1;
48    s.membase = (u8 *)JZ4740_UART1_BASE_ADDR;
49    s.irq = JZ4740_IRQ_UART1;
50    if (early_serial_setup(&s) != 0) {
51        printk(KERN_ERR "Serial ttyS1 setup failed!\n");
52    }
53#endif
54}
5525void __init plat_mem_setup(void)
5626{
5727    jz4740_reset_init();
58    jz4740_serial_setup();
5928}
6029
6130const char *get_system_type(void)
drivers/serial/8250.c
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
414410    writeb(value, p->membase + offset);
415411}
416412
...... 
22132209        serial_unlink_irq_chain(up);
22142210}
22152211
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
22932212static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
22942213{
22952214    unsigned int quot;
...... 
23092228
23102229    return quot;
23112230}
2312#endif
23132231
23142232static void
23152233serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
...... 
23192237    unsigned char cval, fcr = 0;
23202238    unsigned long flags;
23212239    unsigned int baud, quot;
2322#if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730)
2323    unsigned short *quot1;
2324#endif
23252240
23262241    switch (termios->c_cflag & CSIZE) {
23272242    case CS5:
...... 
23562271    baud = uart_get_baud_rate(port, termios, old,
23572272                  port->uartclk / 16 / 0xffff,
23582273                  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
23632274    quot = serial8250_get_divisor(port, baud);
2364#endif
23652275
23662276    /*
23672277     * Oxford Semi 952 rev B workaround
...... 
24392349    if (up->capabilities & UART_CAP_UUE)
24402350        up->ier |= UART_IER_UUE | UART_IER_RTOIE;
24412351
2442#ifdef CONFIG_JZSOC
2443    up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */
2444#endif
2445
24462352    serial_out(up, UART_IER, up->ier);
24472353
24482354    if (up->capabilities & UART_CAP_EFR) {
...... 
24772383        serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
24782384    }
24792385
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
24872386    serial_dl_write(up, quot);
2488#endif
24892387
24902388    /*
24912389     * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR

Archive Download the corresponding diff file



interactive