2019-05-20 10:19:02 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2007-04-30 22:37:19 +04:00
/*
* TI DaVinci serial driver
*
* Copyright ( C ) 2006 Texas Instruments .
*/
# 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 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 ) ;
}
2013-06-19 13:15:42 +04:00
int __init davinci_serial_init ( struct platform_device * serial_dev )
2012-08-29 21:18:52 +04:00
{
2013-06-19 13:15:38 +04:00
int i , ret = 0 ;
struct device * dev ;
struct plat_serial8250_port * p ;
2013-06-19 13:15:42 +04:00
struct clk * clk ;
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
*/
2013-06-19 13:15:42 +04:00
for ( i = 0 ; serial_dev [ i ] . dev . platform_data ! = NULL ; i + + ) {
dev = & serial_dev [ i ] . dev ;
2013-06-19 13:15:38 +04:00
p = dev - > platform_data ;
2009-04-14 17:04:26 +04:00
2013-06-19 13:15:42 +04:00
ret = platform_device_register ( & serial_dev [ i ] ) ;
2013-06-19 13:15:38 +04:00
if ( ret )
continue ;
2013-06-19 13:15:42 +04:00
clk = clk_get ( dev , NULL ) ;
if ( IS_ERR ( clk ) ) {
pr_err ( " %s:%d: failed to get UART%d clock \n " ,
__func__ , __LINE__ , i ) ;
2010-05-02 22:28:13 +04:00
continue ;
2013-06-19 13:15:42 +04:00
}
clk_prepare_enable ( clk ) ;
p - > uartclk = clk_get_rate ( clk ) ;
2010-05-02 22:28:13 +04:00
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
}
2013-06-19 13:15:38 +04:00
return ret ;
2007-04-30 22:37:19 +04:00
}