2007-04-30 19:37:19 +01: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 12:10:45 +01:00
# include <linux/io.h>
2007-04-30 19:37:19 +01:00
# include <asm/irq.h>
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
# include <mach/serial.h>
# include <mach/irqs.h>
2009-04-14 08:04:26 -05:00
# include <mach/cputype.h>
2009-03-18 12:36:08 -05:00
# include <mach/common.h>
2009-04-14 08:04:26 -05:00
# include "clock.h"
2007-04-30 19:37:19 +01:00
2009-04-14 08:04:26 -05:00
static inline unsigned int serial_read_reg ( struct plat_serial8250_port * up ,
int offset )
2007-04-30 19:37:19 +01:00
{
offset < < = up - > regshift ;
2009-04-14 08:04:26 -05:00
return ( unsigned int ) __raw_readl ( IO_ADDRESS ( up - > mapbase ) + offset ) ;
2007-04-30 19:37:19 +01:00
}
2009-04-14 08:04:26 -05:00
static inline void serial_write_reg ( struct plat_serial8250_port * p , int offset ,
int value )
2007-04-30 19:37:19 +01:00
{
offset < < = p - > regshift ;
2009-04-14 08:04:26 -05:00
__raw_writel ( value , IO_ADDRESS ( p - > mapbase ) + offset ) ;
2007-04-30 19:37:19 +01:00
}
static void __init davinci_serial_reset ( struct plat_serial8250_port * p )
{
unsigned int pwremu = 0 ;
2009-04-14 08:04:26 -05:00
serial_write_reg ( p , UART_IER , 0 ) ; /* disable all interrupts */
2007-04-30 19:37:19 +01:00
2009-04-14 08:04:26 -05:00
/* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
serial_write_reg ( p , UART_DAVINCI_PWREMU , pwremu ) ;
2007-04-30 19:37:19 +01:00
mdelay ( 10 ) ;
pwremu | = ( 0x3 < < 13 ) ;
pwremu | = 0x1 ;
2009-04-14 08:04:26 -05: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 12:36:08 -05:00
int __init davinci_serial_init ( struct davinci_uart_config * info )
2009-04-14 08:04:26 -05:00
{
int i ;
char name [ 16 ] ;
struct clk * uart_clk ;
2009-03-18 12:36:08 -05: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 08:04:26 -05:00
/*
* Make sure the serial ports are muxed on at this point .
2009-03-18 12:36:08 -05:00
* You have to mux them off in device drivers later on if not needed .
2009-04-14 08:04:26 -05:00
*/
2009-03-18 12:36:08 -05:00
for ( i = 0 ; i < DAVINCI_MAX_NR_UARTS ; i + + , p + + ) {
if ( ! ( info - > enabled_uarts & ( 1 < < i ) ) )
2009-04-14 08:04:26 -05:00
continue ;
sprintf ( name , " uart%d " , i ) ;
uart_clk = clk_get ( dev , name ) ;
if ( IS_ERR ( uart_clk ) )
printk ( KERN_ERR " %s:%d: failed to get UART%d clock \n " ,
__func__ , __LINE__ , i ) ;
else {
clk_enable ( uart_clk ) ;
p - > uartclk = clk_get_rate ( uart_clk ) ;
davinci_serial_reset ( p ) ;
}
}
2007-04-30 19:37:19 +01:00
2009-03-18 12:36:08 -05:00
return platform_device_register ( soc_info - > serial_dev ) ;
2007-04-30 19:37:19 +01:00
}