| 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 | ||
|---|---|---|
| 1 | 1 | /* |
| 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 | |
| 4 | 4 | * |
| 5 | 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | 6 | * under the terms of the GNU General Public License as published by the |
| ... | ... | |
| 31 | 31 | extern struct platform_device jz4740_adc_device; |
| 32 | 32 | extern struct platform_device jz4740_battery_device; |
| 33 | 33 | |
| 34 | void jz4740_serial_device_register(void); | |
| 35 | ||
| 34 | 36 | #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 | ||
|---|---|---|
| 7 | 7 | obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ |
| 8 | 8 | gpio.o clock.o platform.o timer.o pwm.o |
| 9 | 9 | |
| 10 | obj-$(CONFIG_SERIAL_8250) += serial.o | |
| 11 | ||
| 10 | 12 | obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o |
| 11 | 13 | |
| 12 | 14 | # board specific support |
| arch/mips/jz4740/board-qi_lb60.c | ||
|---|---|---|
| 437 | 437 | jz4740_battery_device.dev.platform_data = &qi_lb60_battery_pdata; |
| 438 | 438 | jz4740_mmc_device.dev.platform_data = &qi_lb60_mmc_pdata; |
| 439 | 439 | |
| 440 | jz4740_serial_device_register(); | |
| 441 | ||
| 440 | 442 | spi_register_board_info(qi_lb60_spi_board_info, |
| 441 | 443 | ARRAY_SIZE(qi_lb60_spi_board_info)); |
| 442 | 444 | |
| arch/mips/jz4740/clock.h | ||
|---|---|---|
| 13 | 13 | * |
| 14 | 14 | */ |
| 15 | 15 | |
| 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> | |
| 18 | 20 | |
| 19 | 21 | struct jz4740_clock_board_data { |
| 20 | 22 | unsigned long ext_rate; |
| arch/mips/jz4740/platform.c | ||
|---|---|---|
| 23 | 23 | #include <asm/mach-jz4740/base.h> |
| 24 | 24 | #include <asm/mach-jz4740/irq.h> |
| 25 | 25 | |
| 26 | #include <linux/serial_core.h> | |
| 27 | #include <linux/serial_8250.h> | |
| 28 | ||
| 29 | #include "serial.h" | |
| 30 | #include "clock.h" | |
| 31 | ||
| 26 | 32 | /* OHCI (USB full speed host controller) */ |
| 27 | 33 | static struct resource jz4740_usb_ohci_resources[] = { |
| 28 | 34 | [0] = { |
| ... | ... | |
| 244 | 250 | .parent = &jz4740_adc_device.dev |
| 245 | 251 | }, |
| 246 | 252 | }; |
| 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 | ||
| 266 | static struct plat_serial8250_port jz4740_uart_data[] = { | |
| 267 | JZ4740_UART_DATA(0), | |
| 268 | JZ4740_UART_DATA(1), | |
| 269 | {}, | |
| 270 | }; | |
| 271 | ||
| 272 | static struct platform_device jz4740_uart_device = { | |
| 273 | .name = "serial8250", | |
| 274 | .id = 0, | |
| 275 | .dev = { | |
| 276 | .platform_data = jz4740_uart_data, | |
| 277 | }, | |
| 278 | }; | |
| 279 | ||
| 280 | void 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 | ||
| 20 | void 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 | ||
| 18 | void jz4740_serial_out(struct uart_port *p, int offset, int value); | |
| 19 | ||
| 20 | #endif | |
| 21 | ||
| arch/mips/jz4740/setup.c | ||
|---|---|---|
| 13 | 13 | * |
| 14 | 14 | */ |
| 15 | 15 | |
| 16 | ||
| 17 | 16 | #include <linux/init.h> |
| 18 | 17 | #include <linux/kernel.h> |
| 19 | #include <linux/serial.h> | |
| 20 | #include <linux/serial_core.h> | |
| 21 | #include <linux/serial_8250.h> | |
| 22 | 18 | |
| 23 | 19 | #include <asm/mach-jz4740/base.h> |
| 24 | 20 | #include <asm/mach-jz4740/clock.h> |
| 25 | #include <asm/mach-jz4740/serial.h> | |
| 26 | 21 | |
| 27 | 22 | #include "reset.h" |
| 28 | 23 | #include "clock.h" |
| 29 | 24 | |
| 30 | static 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 | } | |
| 55 | 25 | void __init plat_mem_setup(void) |
| 56 | 26 | { |
| 57 | 27 | jz4740_reset_init(); |
| 58 | jz4740_serial_setup(); | |
| 59 | 28 | } |
| 60 | 29 | |
| 61 | 30 | const char *get_system_type(void) |
| drivers/serial/8250.c | ||
|---|---|---|
| 407 | 407 | static void mem_serial_out(struct uart_port *p, int offset, int value) |
| 408 | 408 | { |
| 409 | 409 | 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 | |
| 414 | 410 | writeb(value, p->membase + offset); |
| 415 | 411 | } |
| 416 | 412 | |
| ... | ... | |
| 2213 | 2209 | serial_unlink_irq_chain(up); |
| 2214 | 2210 | } |
| 2215 | 2211 | |
| 2216 | #if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) | |
| 2217 | static unsigned short quot1[3] = {0}; /* quot[0]:baud_div, quot[1]:umr, quot[2]:uacr */ | |
| 2218 | static 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 | |
| 2293 | 2212 | static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) |
| 2294 | 2213 | { |
| 2295 | 2214 | unsigned int quot; |
| ... | ... | |
| 2309 | 2228 | |
| 2310 | 2229 | return quot; |
| 2311 | 2230 | } |
| 2312 | #endif | |
| 2313 | 2231 | |
| 2314 | 2232 | static void |
| 2315 | 2233 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| ... | ... | |
| 2319 | 2237 | unsigned char cval, fcr = 0; |
| 2320 | 2238 | unsigned long flags; |
| 2321 | 2239 | unsigned int baud, quot; |
| 2322 | #if defined(CONFIG_JZSOC) && !defined(CONFIG_SOC_JZ4730) | |
| 2323 | unsigned short *quot1; | |
| 2324 | #endif | |
| 2325 | 2240 | |
| 2326 | 2241 | switch (termios->c_cflag & CSIZE) { |
| 2327 | 2242 | case CS5: |
| ... | ... | |
| 2356 | 2271 | baud = uart_get_baud_rate(port, termios, old, |
| 2357 | 2272 | port->uartclk / 16 / 0xffff, |
| 2358 | 2273 | 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 | |
| 2363 | 2274 | quot = serial8250_get_divisor(port, baud); |
| 2364 | #endif | |
| 2365 | 2275 | |
| 2366 | 2276 | /* |
| 2367 | 2277 | * Oxford Semi 952 rev B workaround |
| ... | ... | |
| 2439 | 2349 | if (up->capabilities & UART_CAP_UUE) |
| 2440 | 2350 | up->ier |= UART_IER_UUE | UART_IER_RTOIE; |
| 2441 | 2351 | |
| 2442 | #ifdef CONFIG_JZSOC | |
| 2443 | up->ier |= UART_IER_RTOIE; /* Set this flag, or very slow */ | |
| 2444 | #endif | |
| 2445 | ||
| 2446 | 2352 | serial_out(up, UART_IER, up->ier); |
| 2447 | 2353 | |
| 2448 | 2354 | if (up->capabilities & UART_CAP_EFR) { |
| ... | ... | |
| 2477 | 2383 | serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ |
| 2478 | 2384 | } |
| 2479 | 2385 | |
| 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 | |
| 2487 | 2386 | serial_dl_write(up, quot); |
| 2488 | #endif | |
| 2489 | 2387 | |
| 2490 | 2388 | /* |
| 2491 | 2389 | * 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.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9
