Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin: (52 commits)
  Blackfin: encode cpu-rev into uImage name
  Blackfin: bf54x: don't ack GPIO ints when unmasking them
  Blackfin: sram_free_with_lsl: do not ignore return value of sram_free
  Blackfin: boards: add missing "static" to peripheral lists
  Blackfin: DNP5370: new board port
  Blackfin: bf518f-ezbrd: fix dsa resources
  Blackfin: move "-m elf32bfin" to general LDFLAGS
  Blackfin: kgdb_test: make sure to initialize num2
  Blackfin: kgdb: disable preempt schedule when running single step in kgdb
  Blackfin: kgdb: disable interrupt when single stepping in ADEOS
  Blackfin: SMP: kgdb: apply anomaly 257 work around
  Blackfin: fix building IPIPE code when XIP is enabled
  Blackfin: SMP: kgdb: flush core internal write buffer before flushinv
  Blackfin: sport_uart resources: remove unused secondary RX/TX pins
  Blackfin: tll6527m: fix spelling in unused code (struct name)
  Blackfin: bf527-ezkit: add adau1373 chip address
  Blackfin: no-mpu: fix masking of small uncached dma region
  Blackfin: pm: drop irq save/restore in standby and suspend to mem callback
  MAINTAINERS: update Analog Devices support info
  Blackfin: dpmc.h: pull in new pll.h
  ...
This commit is contained in:
Linus Torvalds 2011-01-10 17:06:08 -08:00
commit 0be8c8bd1d
157 changed files with 9963 additions and 11015 deletions

View file

@ -776,24 +776,7 @@ config BFIN_UART0_CTSRTS
bool "Enable UART0 hardware flow control"
depends on SERIAL_BFIN_UART0
help
Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
signal.
config UART0_CTS_PIN
int "UART0 CTS pin"
depends on BFIN_UART0_CTSRTS && !BF548
default 23
help
The default pin is GPIO_GP7.
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
config UART0_RTS_PIN
int "UART0 RTS pin"
depends on BFIN_UART0_CTSRTS && !BF548
default 22
help
The default pin is GPIO_GP6.
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
Enable hardware flow control in the driver.
config SERIAL_BFIN_UART1
bool "Enable UART1"
@ -805,22 +788,7 @@ config BFIN_UART1_CTSRTS
bool "Enable UART1 hardware flow control"
depends on SERIAL_BFIN_UART1
help
Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
signal.
config UART1_CTS_PIN
int "UART1 CTS pin"
depends on BFIN_UART1_CTSRTS && !BF548
default -1
help
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
config UART1_RTS_PIN
int "UART1 RTS pin"
depends on BFIN_UART1_CTSRTS && !BF548
default -1
help
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
Enable hardware flow control in the driver.
config SERIAL_BFIN_UART2
bool "Enable UART2"
@ -832,22 +800,7 @@ config BFIN_UART2_CTSRTS
bool "Enable UART2 hardware flow control"
depends on SERIAL_BFIN_UART2
help
Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
signal.
config UART2_CTS_PIN
int "UART2 CTS pin"
depends on BFIN_UART2_CTSRTS && !BF548
default -1
help
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
config UART2_RTS_PIN
int "UART2 RTS pin"
depends on BFIN_UART2_CTSRTS && !BF548
default -1
help
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
Enable hardware flow control in the driver.
config SERIAL_BFIN_UART3
bool "Enable UART3"
@ -859,22 +812,7 @@ config BFIN_UART3_CTSRTS
bool "Enable UART3 hardware flow control"
depends on SERIAL_BFIN_UART3
help
Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
signal.
config UART3_CTS_PIN
int "UART3 CTS pin"
depends on BFIN_UART3_CTSRTS && !BF548
default -1
help
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
config UART3_RTS_PIN
int "UART3 RTS pin"
depends on BFIN_UART3_CTSRTS && !BF548
default -1
help
Refer to arch/blackfin/mach-*/include/mach/gpio.h to see the GPIO map.
Enable hardware flow control in the driver.
config SERIAL_IMX
bool "IMX serial port support"

View file

@ -1,7 +1,7 @@
/*
* Blackfin On-Chip Serial Driver
*
* Copyright 2006-2008 Analog Devices Inc.
* Copyright 2006-2010 Analog Devices Inc.
*
* Enter bugs at http://blackfin.uclinux.org/
*
@ -12,6 +12,9 @@
#define SUPPORT_SYSRQ
#endif
#define DRIVER_NAME "bfin-uart"
#define pr_fmt(fmt) DRIVER_NAME ": " fmt
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/gfp.h>
@ -23,21 +26,20 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/kgdb.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
#include <linux/kgdb.h>
#include <asm/irq_regs.h>
#endif
#include <asm/gpio.h>
#include <mach/bfin_serial_5xx.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/portmux.h>
#include <asm/cacheflush.h>
#include <asm/dma.h>
#define port_membase(uart) (((struct bfin_serial_port *)(uart))->port.membase)
#define get_lsr_cache(uart) (((struct bfin_serial_port *)(uart))->lsr)
#define put_lsr_cache(uart, v) (((struct bfin_serial_port *)(uart))->lsr = (v))
#include <asm/bfin_serial.h>
#ifdef CONFIG_SERIAL_BFIN_MODULE
# undef CONFIG_EARLY_PRINTK
@ -48,12 +50,11 @@
#endif
/* UART name and device definitions */
#define BFIN_SERIAL_NAME "ttyBF"
#define BFIN_SERIAL_DEV_NAME "ttyBF"
#define BFIN_SERIAL_MAJOR 204
#define BFIN_SERIAL_MINOR 64
static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource);
static struct bfin_serial_port *bfin_serial_ports[BFIN_UART_NR_PORTS];
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
@ -743,14 +744,14 @@ static int bfin_serial_startup(struct uart_port *port)
}
}
if (uart->rts_pin >= 0) {
gpio_request(uart->rts_pin, DRIVER_NAME);
gpio_direction_output(uart->rts_pin, 0);
}
#endif
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
if (request_irq(uart->status_irq,
if (uart->cts_pin >= 0 && request_irq(uart->status_irq,
bfin_serial_mctrl_cts_int,
IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
uart->cts_pin = -1;
pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n");
}
@ -796,11 +797,9 @@ static void bfin_serial_shutdown(struct uart_port *port)
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
if (uart->cts_pin >= 0)
free_irq(gpio_to_irq(uart->cts_pin), uart);
if (uart->rts_pin >= 0)
gpio_free(uart->rts_pin);
#endif
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
if (UART_GET_IER(uart) & EDSSI)
if (uart->cts_pin >= 0)
free_irq(uart->status_irq, uart);
#endif
}
@ -962,33 +961,33 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
*/
static void bfin_serial_set_ldisc(struct uart_port *port, int ld)
{
int line = port->line;
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
unsigned short val;
switch (ld) {
case N_IRDA:
val = UART_GET_GCTL(&bfin_serial_ports[line]);
val = UART_GET_GCTL(uart);
val |= (IREN | RPOLC);
UART_PUT_GCTL(&bfin_serial_ports[line], val);
UART_PUT_GCTL(uart, val);
break;
default:
val = UART_GET_GCTL(&bfin_serial_ports[line]);
val = UART_GET_GCTL(uart);
val &= ~(IREN | RPOLC);
UART_PUT_GCTL(&bfin_serial_ports[line], val);
UART_PUT_GCTL(uart, val);
}
}
static void bfin_serial_reset_irda(struct uart_port *port)
{
int line = port->line;
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
unsigned short val;
val = UART_GET_GCTL(&bfin_serial_ports[line]);
val = UART_GET_GCTL(uart);
val &= ~(IREN | RPOLC);
UART_PUT_GCTL(&bfin_serial_ports[line], val);
UART_PUT_GCTL(uart, val);
SSYNC();
val |= (IREN | RPOLC);
UART_PUT_GCTL(&bfin_serial_ports[line], val);
UART_PUT_GCTL(uart, val);
SSYNC();
}
@ -1070,85 +1069,6 @@ static struct uart_ops bfin_serial_pops = {
#endif
};
static void __init bfin_serial_hw_init(void)
{
#ifdef CONFIG_SERIAL_BFIN_UART0
peripheral_request(P_UART0_TX, DRIVER_NAME);
peripheral_request(P_UART0_RX, DRIVER_NAME);
#endif
#ifdef CONFIG_SERIAL_BFIN_UART1
peripheral_request(P_UART1_TX, DRIVER_NAME);
peripheral_request(P_UART1_RX, DRIVER_NAME);
# if defined(CONFIG_BFIN_UART1_CTSRTS) && defined(CONFIG_BF54x)
peripheral_request(P_UART1_RTS, DRIVER_NAME);
peripheral_request(P_UART1_CTS, DRIVER_NAME);
# endif
#endif
#ifdef CONFIG_SERIAL_BFIN_UART2
peripheral_request(P_UART2_TX, DRIVER_NAME);
peripheral_request(P_UART2_RX, DRIVER_NAME);
#endif
#ifdef CONFIG_SERIAL_BFIN_UART3
peripheral_request(P_UART3_TX, DRIVER_NAME);
peripheral_request(P_UART3_RX, DRIVER_NAME);
# if defined(CONFIG_BFIN_UART3_CTSRTS) && defined(CONFIG_BF54x)
peripheral_request(P_UART3_RTS, DRIVER_NAME);
peripheral_request(P_UART3_CTS, DRIVER_NAME);
# endif
#endif
}
static void __init bfin_serial_init_ports(void)
{
static int first = 1;
int i;
if (!first)
return;
first = 0;
bfin_serial_hw_init();
for (i = 0; i < nr_active_ports; i++) {
spin_lock_init(&bfin_serial_ports[i].port.lock);
bfin_serial_ports[i].port.uartclk = get_sclk();
bfin_serial_ports[i].port.fifosize = BFIN_UART_TX_FIFO_SIZE;
bfin_serial_ports[i].port.ops = &bfin_serial_pops;
bfin_serial_ports[i].port.line = i;
bfin_serial_ports[i].port.iotype = UPIO_MEM;
bfin_serial_ports[i].port.membase =
(void __iomem *)bfin_serial_resource[i].uart_base_addr;
bfin_serial_ports[i].port.mapbase =
bfin_serial_resource[i].uart_base_addr;
bfin_serial_ports[i].port.irq =
bfin_serial_resource[i].uart_irq;
bfin_serial_ports[i].status_irq =
bfin_serial_resource[i].uart_status_irq;
bfin_serial_ports[i].port.flags = UPF_BOOT_AUTOCONF;
#ifdef CONFIG_SERIAL_BFIN_DMA
bfin_serial_ports[i].tx_done = 1;
bfin_serial_ports[i].tx_count = 0;
bfin_serial_ports[i].tx_dma_channel =
bfin_serial_resource[i].uart_tx_dma_channel;
bfin_serial_ports[i].rx_dma_channel =
bfin_serial_resource[i].uart_rx_dma_channel;
init_timer(&(bfin_serial_ports[i].rx_dma_timer));
#endif
#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
bfin_serial_ports[i].cts_pin =
bfin_serial_resource[i].uart_cts_pin;
bfin_serial_ports[i].rts_pin =
bfin_serial_resource[i].uart_rts_pin;
#endif
}
}
#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
/*
* If the port was already initialised (eg, by a boot loader),
@ -1196,6 +1116,34 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
static struct uart_driver bfin_serial_reg;
static void bfin_serial_console_putchar(struct uart_port *port, int ch)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
while (!(UART_GET_LSR(uart) & THRE))
barrier();
UART_PUT_CHAR(uart, ch);
}
#endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) ||
defined (CONFIG_EARLY_PRINTK) */
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
#define CLASS_BFIN_CONSOLE "bfin-console"
/*
* Interrupts are disabled on entering
*/
static void
bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
{
struct bfin_serial_port *uart = bfin_serial_ports[co->index];
unsigned long flags;
spin_lock_irqsave(&uart->port.lock, flags);
uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);
spin_unlock_irqrestore(&uart->port.lock, flags);
}
static int __init
bfin_serial_console_setup(struct console *co, char *options)
{
@ -1215,9 +1163,12 @@ bfin_serial_console_setup(struct console *co, char *options)
* if so, search for the first available port that does have
* console support.
*/
if (co->index == -1 || co->index >= nr_active_ports)
co->index = 0;
uart = &bfin_serial_ports[co->index];
if (co->index < 0 || co->index >= BFIN_UART_NR_PORTS)
return -ENODEV;
uart = bfin_serial_ports[co->index];
if (!uart)
return -ENODEV;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@ -1226,36 +1177,9 @@ bfin_serial_console_setup(struct console *co, char *options)
return uart_set_options(&uart->port, co, baud, parity, bits, flow);
}
#endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) ||
defined (CONFIG_EARLY_PRINTK) */
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
static void bfin_serial_console_putchar(struct uart_port *port, int ch)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
while (!(UART_GET_LSR(uart) & THRE))
barrier();
UART_PUT_CHAR(uart, ch);
SSYNC();
}
/*
* Interrupts are disabled on entering
*/
static void
bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
{
struct bfin_serial_port *uart = &bfin_serial_ports[co->index];
unsigned long flags;
spin_lock_irqsave(&uart->port.lock, flags);
uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);
spin_unlock_irqrestore(&uart->port.lock, flags);
}
static struct console bfin_serial_console = {
.name = BFIN_SERIAL_NAME,
.name = BFIN_SERIAL_DEV_NAME,
.write = bfin_serial_console_write,
.device = uart_console_device,
.setup = bfin_serial_console_setup,
@ -1263,44 +1187,30 @@ static struct console bfin_serial_console = {
.index = -1,
.data = &bfin_serial_reg,
};
static int __init bfin_serial_rs_console_init(void)
{
bfin_serial_init_ports();
register_console(&bfin_serial_console);
return 0;
}
console_initcall(bfin_serial_rs_console_init);
#define BFIN_SERIAL_CONSOLE &bfin_serial_console
#else
#define BFIN_SERIAL_CONSOLE NULL
#endif /* CONFIG_SERIAL_BFIN_CONSOLE */
#ifdef CONFIG_EARLY_PRINTK
static struct bfin_serial_port bfin_earlyprintk_port;
#define CLASS_BFIN_EARLYPRINTK "bfin-earlyprintk"
#ifdef CONFIG_EARLY_PRINTK
static __init void early_serial_putc(struct uart_port *port, int ch)
/*
* Interrupts are disabled on entering
*/
static void
bfin_earlyprintk_console_write(struct console *co, const char *s, unsigned int count)
{
unsigned timeout = 0xffff;
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
unsigned long flags;
while ((!(UART_GET_LSR(uart) & THRE)) && --timeout)
cpu_relax();
UART_PUT_CHAR(uart, ch);
}
if (bfin_earlyprintk_port.port.line != co->index)
return;
static __init void early_serial_write(struct console *con, const char *s,
unsigned int n)
{
struct bfin_serial_port *uart = &bfin_serial_ports[con->index];
unsigned int i;
for (i = 0; i < n; i++, s++) {
if (*s == '\n')
early_serial_putc(&uart->port, '\r');
early_serial_putc(&uart->port, *s);
}
spin_lock_irqsave(&bfin_earlyprintk_port.port.lock, flags);
uart_console_write(&bfin_earlyprintk_port.port, s, count,
bfin_serial_console_putchar);
spin_unlock_irqrestore(&bfin_earlyprintk_port.port.lock, flags);
}
/*
@ -1311,18 +1221,326 @@ static __init void early_serial_write(struct console *con, const char *s,
*/
static struct __initdata console bfin_early_serial_console = {
.name = "early_BFuart",
.write = early_serial_write,
.write = bfin_earlyprintk_console_write,
.device = uart_console_device,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &bfin_serial_reg,
};
#endif
static struct uart_driver bfin_serial_reg = {
.owner = THIS_MODULE,
.driver_name = DRIVER_NAME,
.dev_name = BFIN_SERIAL_DEV_NAME,
.major = BFIN_SERIAL_MAJOR,
.minor = BFIN_SERIAL_MINOR,
.nr = BFIN_UART_NR_PORTS,
.cons = BFIN_SERIAL_CONSOLE,
};
static int bfin_serial_suspend(struct platform_device *pdev, pm_message_t state)
{
struct bfin_serial_port *uart = platform_get_drvdata(pdev);
return uart_suspend_port(&bfin_serial_reg, &uart->port);
}
static int bfin_serial_resume(struct platform_device *pdev)
{
struct bfin_serial_port *uart = platform_get_drvdata(pdev);
return uart_resume_port(&bfin_serial_reg, &uart->port);
}
static int bfin_serial_probe(struct platform_device *pdev)
{
struct resource *res;
struct bfin_serial_port *uart = NULL;
int ret = 0;
if (pdev->id < 0 || pdev->id >= BFIN_UART_NR_PORTS) {
dev_err(&pdev->dev, "Wrong bfin uart platform device id.\n");
return -ENOENT;
}
if (bfin_serial_ports[pdev->id] == NULL) {
uart = kzalloc(sizeof(*uart), GFP_KERNEL);
if (!uart) {
dev_err(&pdev->dev,
"fail to malloc bfin_serial_port\n");
return -ENOMEM;
}
bfin_serial_ports[pdev->id] = uart;
#ifdef CONFIG_EARLY_PRINTK
if (!(bfin_earlyprintk_port.port.membase
&& bfin_earlyprintk_port.port.line == pdev->id)) {
/*
* If the peripheral PINs of current port is allocated
* in earlyprintk probe stage, don't do it again.
*/
#endif
ret = peripheral_request_list(
(unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev,
"fail to request bfin serial peripherals\n");
goto out_error_free_mem;
}
#ifdef CONFIG_EARLY_PRINTK
}
#endif
spin_lock_init(&uart->port.lock);
uart->port.uartclk = get_sclk();
uart->port.fifosize = BFIN_UART_TX_FIFO_SIZE;
uart->port.ops = &bfin_serial_pops;
uart->port.line = pdev->id;
uart->port.iotype = UPIO_MEM;
uart->port.flags = UPF_BOOT_AUTOCONF;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
ret = -ENOENT;
goto out_error_free_peripherals;
}
uart->port.membase = ioremap(res->start,
res->end - res->start);
if (!uart->port.membase) {
dev_err(&pdev->dev, "Cannot map uart IO\n");
ret = -ENXIO;
goto out_error_free_peripherals;
}
uart->port.mapbase = res->start;
uart->port.irq = platform_get_irq(pdev, 0);
if (uart->port.irq < 0) {
dev_err(&pdev->dev, "No uart RX/TX IRQ specified\n");
ret = -ENOENT;
goto out_error_unmap;
}
uart->status_irq = platform_get_irq(pdev, 1);
if (uart->status_irq < 0) {
dev_err(&pdev->dev, "No uart status IRQ specified\n");
ret = -ENOENT;
goto out_error_unmap;
}
#ifdef CONFIG_SERIAL_BFIN_DMA
uart->tx_done = 1;
uart->tx_count = 0;
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (res == NULL) {
dev_err(&pdev->dev, "No uart TX DMA channel specified\n");
ret = -ENOENT;
goto out_error_unmap;
}
uart->tx_dma_channel = res->start;
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (res == NULL) {
dev_err(&pdev->dev, "No uart RX DMA channel specified\n");
ret = -ENOENT;
goto out_error_unmap;
}
uart->rx_dma_channel = res->start;
init_timer(&(uart->rx_dma_timer));
#endif
#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (res == NULL)
uart->cts_pin = -1;
else
uart->cts_pin = res->start;
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
if (res == NULL)
uart->rts_pin = -1;
else
uart->rts_pin = res->start;
# if defined(CONFIG_SERIAL_BFIN_CTSRTS)
if (uart->rts_pin >= 0)
gpio_request(uart->rts_pin, DRIVER_NAME);
# endif
#endif
}
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
if (!is_early_platform_device(pdev)) {
#endif
uart = bfin_serial_ports[pdev->id];
uart->port.dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, uart);
ret = uart_add_one_port(&bfin_serial_reg, &uart->port);
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
}
#endif
if (!ret)
return 0;
if (uart) {
out_error_unmap:
iounmap(uart->port.membase);
out_error_free_peripherals:
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
out_error_free_mem:
kfree(uart);
bfin_serial_ports[pdev->id] = NULL;
}
return ret;
}
static int __devexit bfin_serial_remove(struct platform_device *pdev)
{
struct bfin_serial_port *uart = platform_get_drvdata(pdev);
dev_set_drvdata(&pdev->dev, NULL);
if (uart) {
uart_remove_one_port(&bfin_serial_reg, &uart->port);
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
if (uart->rts_pin >= 0)
gpio_free(uart->rts_pin);
#endif
iounmap(uart->port.membase);
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
kfree(uart);
bfin_serial_ports[pdev->id] = NULL;
}
return 0;
}
static struct platform_driver bfin_serial_driver = {
.probe = bfin_serial_probe,
.remove = __devexit_p(bfin_serial_remove),
.suspend = bfin_serial_suspend,
.resume = bfin_serial_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
#if defined(CONFIG_SERIAL_BFIN_CONSOLE)
static __initdata struct early_platform_driver early_bfin_serial_driver = {
.class_str = CLASS_BFIN_CONSOLE,
.pdrv = &bfin_serial_driver,
.requested_id = EARLY_PLATFORM_ID_UNSET,
};
static int __init bfin_serial_rs_console_init(void)
{
early_platform_driver_register(&early_bfin_serial_driver, DRIVER_NAME);
early_platform_driver_probe(CLASS_BFIN_CONSOLE, BFIN_UART_NR_PORTS, 0);
register_console(&bfin_serial_console);
return 0;
}
console_initcall(bfin_serial_rs_console_init);
#endif
#ifdef CONFIG_EARLY_PRINTK
/*
* Memory can't be allocated dynamically during earlyprink init stage.
* So, do individual probe for earlyprink with a static uart port variable.
*/
static int bfin_earlyprintk_probe(struct platform_device *pdev)
{
struct resource *res;
int ret;
if (pdev->id < 0 || pdev->id >= BFIN_UART_NR_PORTS) {
dev_err(&pdev->dev, "Wrong earlyprintk platform device id.\n");
return -ENOENT;
}
ret = peripheral_request_list(
(unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev,
"fail to request bfin serial peripherals\n");
return ret;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
ret = -ENOENT;
goto out_error_free_peripherals;
}
bfin_earlyprintk_port.port.membase = ioremap(res->start,
res->end - res->start);
if (!bfin_earlyprintk_port.port.membase) {
dev_err(&pdev->dev, "Cannot map uart IO\n");
ret = -ENXIO;
goto out_error_free_peripherals;
}
bfin_earlyprintk_port.port.mapbase = res->start;
bfin_earlyprintk_port.port.line = pdev->id;
bfin_earlyprintk_port.port.uartclk = get_sclk();
bfin_earlyprintk_port.port.fifosize = BFIN_UART_TX_FIFO_SIZE;
spin_lock_init(&bfin_earlyprintk_port.port.lock);
return 0;
out_error_free_peripherals:
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
return ret;
}
static struct platform_driver bfin_earlyprintk_driver = {
.probe = bfin_earlyprintk_probe,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
static __initdata struct early_platform_driver early_bfin_earlyprintk_driver = {
.class_str = CLASS_BFIN_EARLYPRINTK,
.pdrv = &bfin_earlyprintk_driver,
.requested_id = EARLY_PLATFORM_ID_UNSET,
};
struct console __init *bfin_earlyserial_init(unsigned int port,
unsigned int cflag)
{
struct bfin_serial_port *uart;
struct ktermios t;
char port_name[20];
if (port < 0 || port >= BFIN_UART_NR_PORTS)
return NULL;
/*
* Only probe resource of the given port in earlyprintk boot arg.
* The expected port id should be indicated in port name string.
*/
snprintf(port_name, 20, DRIVER_NAME ".%d", port);
early_platform_driver_register(&early_bfin_earlyprintk_driver,
port_name);
early_platform_driver_probe(CLASS_BFIN_EARLYPRINTK, 1, 0);
if (!bfin_earlyprintk_port.port.membase)
return NULL;
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
/*
@ -1332,124 +1550,36 @@ struct console __init *bfin_earlyserial_init(unsigned int port,
bfin_serial_console.flags &= ~CON_PRINTBUFFER;
#endif
if (port == -1 || port >= nr_active_ports)
port = 0;
bfin_serial_init_ports();
bfin_early_serial_console.index = port;
uart = &bfin_serial_ports[port];
t.c_cflag = cflag;
t.c_iflag = 0;
t.c_oflag = 0;
t.c_lflag = ICANON;
t.c_line = port;
bfin_serial_set_termios(&uart->port, &t, &t);
bfin_serial_set_termios(&bfin_earlyprintk_port.port, &t, &t);
return &bfin_early_serial_console;
}
#endif /* CONFIG_EARLY_PRINTK */
static struct uart_driver bfin_serial_reg = {
.owner = THIS_MODULE,
.driver_name = "bfin-uart",
.dev_name = BFIN_SERIAL_NAME,
.major = BFIN_SERIAL_MAJOR,
.minor = BFIN_SERIAL_MINOR,
.nr = BFIN_UART_NR_PORTS,
.cons = BFIN_SERIAL_CONSOLE,
};
static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state)
{
int i;
for (i = 0; i < nr_active_ports; i++) {
if (bfin_serial_ports[i].port.dev != &dev->dev)
continue;
uart_suspend_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
}
return 0;
}
static int bfin_serial_resume(struct platform_device *dev)
{
int i;
for (i = 0; i < nr_active_ports; i++) {
if (bfin_serial_ports[i].port.dev != &dev->dev)
continue;
uart_resume_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
}
return 0;
}
static int bfin_serial_probe(struct platform_device *dev)
{
struct resource *res = dev->resource;
int i;
for (i = 0; i < dev->num_resources; i++, res++)
if (res->flags & IORESOURCE_MEM)
break;
if (i < dev->num_resources) {
for (i = 0; i < nr_active_ports; i++, res++) {
if (bfin_serial_ports[i].port.mapbase != res->start)
continue;
bfin_serial_ports[i].port.dev = &dev->dev;
uart_add_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
}
}
return 0;
}
static int bfin_serial_remove(struct platform_device *dev)
{
int i;
for (i = 0; i < nr_active_ports; i++) {
if (bfin_serial_ports[i].port.dev != &dev->dev)
continue;
uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
bfin_serial_ports[i].port.dev = NULL;
#if defined(CONFIG_SERIAL_BFIN_CTSRTS)
gpio_free(bfin_serial_ports[i].cts_pin);
gpio_free(bfin_serial_ports[i].rts_pin);
#endif
}
return 0;
}
static struct platform_driver bfin_serial_driver = {
.probe = bfin_serial_probe,
.remove = bfin_serial_remove,
.suspend = bfin_serial_suspend,
.resume = bfin_serial_resume,
.driver = {
.name = "bfin-uart",
.owner = THIS_MODULE,
},
};
static int __init bfin_serial_init(void)
{
int ret;
pr_info("Serial: Blackfin serial driver\n");
bfin_serial_init_ports();
pr_info("Blackfin serial driver\n");
ret = uart_register_driver(&bfin_serial_reg);
if (ret == 0) {
ret = platform_driver_register(&bfin_serial_driver);
if (ret) {
pr_debug("uart register failed\n");
uart_unregister_driver(&bfin_serial_reg);
}
if (ret) {
pr_err("failed to register %s:%d\n",
bfin_serial_reg.driver_name, ret);
}
ret = platform_driver_register(&bfin_serial_driver);
if (ret) {
pr_err("fail to register bfin uart\n");
uart_unregister_driver(&bfin_serial_reg);
}
return ret;
}
@ -1463,7 +1593,7 @@ static void __exit bfin_serial_exit(void)
module_init(bfin_serial_init);
module_exit(bfin_serial_exit);
MODULE_AUTHOR("Aubrey.Li <[email protected]>");
MODULE_AUTHOR("Sonic Zhang, Aubrey Li");
MODULE_DESCRIPTION("Blackfin generic serial port driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(BFIN_SERIAL_MAJOR);