* Date: 2011.06.18\r
*/\r
\r
-#ifndef CONFIG_SERIAL_RK_CONSOLE\r
-#if defined(CONFIG_SERIAL_RK29_CONSOLE)\r
-#define CONFIG_SERIAL_RK_CONSOLE\r
-#endif\r
-#endif\r
-\r
-#if defined(CONFIG_SERIAL_RK_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)\r
+#if defined(CONFIG_SERIAL_ROCKCHIP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)\r
#define SUPPORT_SYSRQ\r
#endif\r
\r
#include <linux/timer.h>\r
#include <linux/workqueue.h>\r
#include <linux/dma-mapping.h>\r
-\r
#include <asm/io.h>\r
#include <asm/irq.h>\r
\r
+#ifdef CONFIG_OF\r
+#include <linux/of.h>\r
+#endif\r
+\r
+\r
/*\r
* Driver Version Note\r
*\r
* 1.fix bug dma buffer free error\r
*v1.5 : 2013-10-17\r
* 1.in some case, set uart rx as gpio interrupt to wake up arm, when arm suspends \r
+*v1.6 : 2013-11-29\r
+ migrate to kernel3.10,and fit device tree \r
*/\r
-#define VERSION_AND_TIME "rk_serial.c v1.5 2013-10-17"\r
+#define VERSION_AND_TIME "rk_serial.c v1.5 2013-11-29"\r
\r
#define PORT_RK 90\r
#define UART_USR 0x1F /* UART Status Register */\r
\r
//#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)\r
\r
-#define UART_NR 4 //uart port number\r
+#define UART_NR 5 //uart port number\r
\r
\r
/* configurate whether the port transmit-receive by DMA in menuconfig*/\r
#define UART3_USE_WAKEUP 0\r
#endif\r
\r
-\r
-\r
#define USE_TIMER 1 // use timer for dma transport\r
#define POWER_MANEGEMENT 1\r
#define RX_TIMEOUT (3000*3) //uint ms\r
#define DMA_TX_TRRIGE_LEVEL 128\r
#define SERIAL_CIRC_CNT_TO_END(xmit) CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)\r
\r
+#ifdef CONFIG_OF\r
+#define USE_DMA 0\r
+#else\r
+#define USE_DMA (UART0_USE_DMA | UART1_USE_DMA | UART2_USE_DMA | UART3_USE_DMA)\r
+#endif\r
\r
-#define USE_DMA (UART0_USE_DMA | UART1_USE_DMA | UART2_USE_DMA | UART3_USE_DMA)\r
#define USE_WAKEUP (UART0_USE_WAKEUP | UART1_USE_WAKEUP | UART2_USE_WAKEUP | UART3_USE_WAKEUP)\r
\r
#if USE_DMA\r
#endif\r
\r
\r
+//#define CONFIG_CLOCK_CTRL\r
+\r
#if USE_DMA\r
/* added by hhb@rock-chips.com for uart dma transfer */\r
\r
};\r
#endif\r
\r
+#ifdef CONFIG_OF\r
+struct of_rk_serial {\r
+ unsigned int id;\r
+ unsigned int use_dma; \r
+ unsigned int uartclk;\r
+};\r
+#endif\r
+\r
+\r
struct uart_rk_port {\r
struct uart_port port;\r
struct platform_device *pdev;\r
up->port.icount.rx += count;\r
flip = tty_insert_flip_string(up->port.state->port.tty, uart_dma->rx_buffer\r
+ uart_dma->rb_tail, count);\r
- tty_flip_buffer_push(up->port.state->port.tty);\r
+ tty_flip_buffer_push(&up->port.state->port);\r
uart_dma->rb_tail = (uart_dma->rb_tail + count) & (uart_dma->rb_size - 1);\r
up->port_activity = jiffies;\r
}\r
if(up->port.state->port.tty && up->dma->use_timer != 1 && up->fifo_size > 0){\r
\r
tty_insert_flip_string(up->port.state->port.tty, up->fifo, up->fifo_size);\r
- tty_flip_buffer_push(up->port.state->port.tty);\r
+ tty_flip_buffer_push(&up->port.state->port);\r
up->port.icount.rx += up->fifo_size;\r
up->ier |= UART_IER_RDI;\r
serial_out(up, UART_IER, up->ier);\r
lsr = serial_in(up, UART_LSR);\r
} while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));\r
spin_unlock(&up->port.lock);\r
- tty_flip_buffer_push(tty);\r
+ tty_flip_buffer_push(tty->port);\r
spin_lock(&up->port.lock);\r
*status = lsr;\r
}\r
dev_dbg(port->dev, "-%s lcr: 0x%02x\n", __func__, up->lcr);\r
}\r
\r
-#if defined(CONFIG_SERIAL_RK_CONSOLE) || defined(CONFIG_CONSOLE_POLL)\r
+#if defined(CONFIG_SERIAL_ROCKCHIP_CONSOLE) || defined(CONFIG_CONSOLE_POLL)\r
/*\r
* Wait for transmitter & holding register to empty\r
*/\r
return retval;\r
\r
up->mcr = 0;\r
-\r
+#ifdef CONFIG_CLOCK_CTRL\r
clk_enable(up->pclk);\r
clk_enable(up->clk); // enable the config uart clock\r
-\r
+#endif\r
/*\r
* Clear the FIFO buffers and disable them.\r
* (they will be reenabled in set_termios())\r
up->port.state->xmit.buf = NULL;\r
#endif\r
free_irq(up->port.irq, up);\r
+#ifdef CONFIG_CLOCK_CTRL\r
clk_disable(up->clk);\r
clk_disable(up->pclk);\r
+#endif\r
}\r
\r
static void\r
\r
dev_dbg(port->dev, "%s: %s\n", __func__, state ? "disable" : "enable");\r
if (state) {\r
+#ifdef CONFIG_CLOCK_CTRL\r
clk_disable(up->clk);\r
clk_disable(up->pclk);\r
+#endif\r
} else {\r
+#ifdef CONFIG_CLOCK_CTRL\r
clk_enable(up->pclk);\r
clk_enable(up->clk);\r
+#endif\r
}\r
}\r
\r
#endif\r
};\r
\r
-#ifdef CONFIG_SERIAL_RK_CONSOLE\r
+#ifdef CONFIG_SERIAL_ROCKCHIP_CONSOLE\r
\r
static struct uart_rk_port *serial_rk_console_ports[UART_NR];\r
\r
\r
static struct uart_driver serial_rk_reg = {\r
.owner = THIS_MODULE,\r
- .driver_name = "rk29_serial",\r
+ .driver_name = "rk_serial",\r
.dev_name = "ttyS",\r
.major = TTY_MAJOR,\r
.minor = 64,\r
}\r
#endif\r
\r
+#ifdef CONFIG_OF\r
+static int of_rk_serial_parse_dt(const struct device_node *np, struct of_rk_serial *rks) {\r
+ unsigned int val = 0;\r
+ if(!of_property_read_u32(np, "id", &val))\r
+ rks->id = val;\r
+ if(!of_property_read_u32(np, "clock-frequency", &val))\r
+ rks->uartclk = val;\r
+#if USE_DMA\r
+ rks->use_dma = 0; \r
+ if(of_find_property(np, "use-dma-rx", &val))\r
+ rks->use_dma |= RX_DMA;\r
+ if(of_find_property(np, "use-dma-tx", &val))\r
+ rks->use_dma |= TX_DMA;\r
+#endif\r
+ return 0;\r
+}\r
+#endif\r
\r
\r
-static int __devinit serial_rk_probe(struct platform_device *pdev)\r
+static int serial_rk_probe(struct platform_device *pdev)\r
{\r
struct uart_rk_port *up;\r
struct resource *mem;\r
int irq;\r
int ret = -ENOSPC;\r
- \r
+ struct of_rk_serial rks; \r
+\r
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
if (!mem) {\r
dev_err(&pdev->dev, "no mem resource?\n");\r
return irq;\r
}\r
\r
+#ifdef CONFIG_OF\r
+ of_rk_serial_parse_dt(pdev->dev.of_node, &rks);\r
+ pdev->id = rks.id;\r
+#endif\r
if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,\r
pdev->dev.driver->name)) {\r
dev_err(&pdev->dev, "memory region already claimed\n");\r
return -EBUSY;\r
}\r
-\r
+ \r
up = kzalloc(sizeof(*up), GFP_KERNEL);\r
if (up == NULL) {\r
ret = -ENOMEM;\r
goto do_release_region;\r
}\r
-\r
+ \r
sprintf(up->name, "rk29_serial.%d", pdev->id);\r
up->pdev = pdev;\r
+#ifdef CONFIG_CLOCK_CTRL\r
up->pclk = clk_get(&pdev->dev, "pclk_uart");\r
up->clk = clk_get(&pdev->dev, "uart");\r
if (unlikely(IS_ERR(up->clk))) {\r
ret = PTR_ERR(up->clk);\r
+ printk("%s:%d\n", __func__, __LINE__);\r
goto do_free;\r
+ \r
}\r
+#endif\r
up->tx_loadsz = 30;\r
#if USE_DMA\r
up->dma = &rk29_uart_ports_dma[pdev->id];\r
+ up->dma->use_dma = rks.use_dma;\r
#endif\r
#if USE_WAKEUP\r
up->wakeup = &rk29_uart_ports_wakeup[pdev->id];\r
up->port.dev = &pdev->dev;\r
up->port.type = PORT_RK;\r
up->port.irq = irq;\r
- up->port.iotype = UPIO_DWAPB;\r
-\r
+ up->port.iotype = UPIO_MEM;\r
+ \r
up->port.regshift = 2;\r
//fifo size default is 32, but it will be updated later when start_up\r
up->port.fifosize = 32;\r
}\r
up->port.mapbase = mem->start;\r
up->port.irqflags = IRQF_DISABLED;\r
+#if defined(CONFIG_CLOCK_CTRL)\r
up->port.uartclk = clk_get_rate(up->clk);\r
-\r
+#elif defined(CONFIG_OF)\r
+ up->port.uartclk = rks.uartclk;\r
+#else\r
+ up->port.uartclk = 24000000;\r
+#endif\r
#if USE_DMA\r
/* set dma config */\r
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);\r
ret = uart_add_one_port(&serial_rk_reg, &up->port);\r
if (ret != 0)\r
goto do_iounmap;\r
-\r
platform_set_drvdata(pdev, up);\r
dev_info(&pdev->dev, "membase 0x%08x\n", (unsigned) up->port.membase);\r
#if USE_WAKEUP\r
iounmap(up->port.membase);\r
up->port.membase = NULL;\r
do_put_clk:\r
+#ifdef CONFIG_CLOCK_CTRL\r
clk_put(up->clk);\r
clk_put(up->pclk);\r
do_free:\r
+#endif\r
kfree(up);\r
do_release_region:\r
release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
return ret;\r
}\r
\r
-static int __devexit serial_rk_remove(struct platform_device *pdev)\r
+static int serial_rk_remove(struct platform_device *pdev)\r
{\r
struct uart_rk_port *up = platform_get_drvdata(pdev);\r
\r
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
iounmap(up->port.membase);\r
up->port.membase = NULL;\r
+#ifdef CONFIG_CLOCK_CTRL\r
clk_put(up->clk);\r
clk_put(up->pclk);\r
+#endif\r
kfree(up);\r
release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
}\r
}\r
return 0;\r
}\r
-\r
+#ifdef CONFIG_OF\r
+static const struct of_device_id of_rk_serial_match[] = {\r
+ { .compatible = "rockchip,serial" },\r
+ { /* Sentinel */ }\r
+};\r
+#endif\r
static struct platform_driver serial_rk_driver = {\r
.probe = serial_rk_probe,\r
- .remove = __devexit_p(serial_rk_remove),\r
+ .remove = serial_rk_remove,\r
.suspend = serial_rk_suspend,\r
.resume = serial_rk_resume,\r
.driver = {\r
-#if defined(CONFIG_ARCH_RK29)\r
- .name = "rk29_serial",\r
-#elif defined(CONFIG_SERIAL_RK2818)\r
- .name = "rk2818_serial",\r
-#else\r
- .name = "rk_serial",\r
+ .name = "serial",\r
+#ifdef CONFIG_OF\r
+ .of_match_table = of_rk_serial_match,\r
#endif\r
.owner = THIS_MODULE,\r
},\r
int ret;\r
//hhb@rock-chips.com\r
printk("%s\n", VERSION_AND_TIME);\r
-\r
ret = uart_register_driver(&serial_rk_reg);\r
if (ret)\r
return ret;\r
-\r
ret = platform_driver_register(&serial_rk_driver);\r
if (ret != 0)\r
uart_unregister_driver(&serial_rk_reg);\r
-\r
return ret;\r
}\r
\r