2007-04-30 22:37:19 +04:00
/*
* TI DaVinci serial driver
*
* Copyright ( C ) 2006 Texas Instruments .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/serial_8250.h>
# include <linux/serial_reg.h>
# include <linux/platform_device.h>
# include <linux/delay.h>
# include <linux/clk.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2007-04-30 22:37:19 +04:00
2008-08-05 19:14:15 +04:00
# include <mach/serial.h>
2009-04-14 17:04:26 +04:00
# include <mach/cputype.h>
2007-04-30 22:37:19 +04:00
2009-04-14 17:04:26 +04:00
static inline unsigned int serial_read_reg ( struct plat_serial8250_port * up ,
int offset )
2007-04-30 22:37:19 +04:00
{
offset < < = up - > regshift ;
2010-05-02 22:28:13 +04:00
WARN_ONCE ( ! up - > membase , " unmapped read: uart[%d] \n " , offset ) ;
return ( unsigned int ) __raw_readl ( up - > membase + offset ) ;
2007-04-30 22:37:19 +04:00
}
2009-04-14 17:04:26 +04:00
static inline void serial_write_reg ( struct plat_serial8250_port * p , int offset ,
int value )
2007-04-30 22:37:19 +04:00
{
offset < < = p - > regshift ;
2010-05-02 22:28:13 +04:00
WARN_ONCE ( ! p - > membase , " unmapped write: uart[%d] \n " , offset ) ;
__raw_writel ( value , p - > membase + offset ) ;
2007-04-30 22:37:19 +04:00
}
static void __init davinci_serial_reset ( struct plat_serial8250_port * p )
{
unsigned int pwremu = 0 ;
2009-04-14 17:04:26 +04:00
serial_write_reg ( p , UART_IER , 0 ) ; /* disable all interrupts */
2007-04-30 22:37:19 +04:00
2009-04-14 17:04:26 +04:00
/* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
serial_write_reg ( p , UART_DAVINCI_PWREMU , pwremu ) ;
2007-04-30 22:37:19 +04:00
mdelay ( 10 ) ;
pwremu | = ( 0x3 < < 13 ) ;
pwremu | = 0x1 ;
2009-04-14 17:04:26 +04:00
serial_write_reg ( p , UART_DAVINCI_PWREMU , pwremu ) ;
if ( cpu_is_davinci_dm646x ( ) )
serial_write_reg ( p , UART_DM646X_SCR ,
UART_DM646X_SCR_TX_WATERMARK ) ;
}
2009-03-18 20:36:08 +03:00
int __init davinci_serial_init ( struct davinci_uart_config * info )
2009-04-14 17:04:26 +04:00
{
int i ;
char name [ 16 ] ;
struct clk * uart_clk ;
2009-03-18 20:36:08 +03:00
struct davinci_soc_info * soc_info = & davinci_soc_info ;
struct device * dev = & soc_info - > serial_dev - > dev ;
struct plat_serial8250_port * p = dev - > platform_data ;
2009-04-14 17:04:26 +04:00
/*
* Make sure the serial ports are muxed on at this point .
2009-03-18 20:36:08 +03:00
* You have to mux them off in device drivers later on if not needed .
2009-04-14 17:04:26 +04:00
*/
2010-05-02 22:28:12 +04:00
for ( i = 0 ; p - > flags ; i + + , p + + ) {
2009-03-18 20:36:08 +03:00
if ( ! ( info - > enabled_uarts & ( 1 < < i ) ) )
2009-04-14 17:04:26 +04:00
continue ;
sprintf ( name , " uart%d " , i ) ;
uart_clk = clk_get ( dev , name ) ;
2010-05-02 22:28:13 +04:00
if ( IS_ERR ( uart_clk ) ) {
2009-04-14 17:04:26 +04:00
printk ( KERN_ERR " %s:%d: failed to get UART%d clock \n " ,
__func__ , __LINE__ , i ) ;
2010-05-02 22:28:13 +04:00
continue ;
2009-04-14 17:04:26 +04:00
}
2010-05-02 22:28:13 +04:00
clk_enable ( uart_clk ) ;
p - > uartclk = clk_get_rate ( uart_clk ) ;
if ( ! p - > membase & & p - > mapbase ) {
p - > membase = ioremap ( p - > mapbase , SZ_4K ) ;
if ( p - > membase )
p - > flags & = ~ UPF_IOREMAP ;
else
pr_err ( " uart regs ioremap failed \n " ) ;
}
2010-05-02 22:28:14 +04:00
if ( p - > membase & & p - > type ! = PORT_AR7 )
2010-05-02 22:28:13 +04:00
davinci_serial_reset ( p ) ;
2009-04-14 17:04:26 +04:00
}
2007-04-30 22:37:19 +04:00
2009-03-18 20:36:08 +03:00
return platform_device_register ( soc_info - > serial_dev ) ;
2007-04-30 22:37:19 +04:00
}