2019-05-20 09:19:02 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2007-04-30 19:37:19 +01: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 12:10:45 +01:00
# include <linux/io.h>
2007-04-30 19:37:19 +01:00
2008-08-05 16:14:15 +01:00
# include <mach/serial.h>
2009-04-14 08:04:26 -05:00
# include <mach/cputype.h>
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 ;
2010-05-02 14:28:13 -04:00
WARN_ONCE ( ! p - > membase , " unmapped write: uart[%d] \n " , offset ) ;
__raw_writel ( value , p - > membase + 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 ) ;
}
2013-06-19 14:45:42 +05:30
int __init davinci_serial_init ( struct platform_device * serial_dev )
2012-08-29 22:48:52 +05:30
{
2013-06-19 14:45:38 +05:30
int i , ret = 0 ;
struct device * dev ;
struct plat_serial8250_port * p ;
2013-06-19 14:45:42 +05:30
struct clk * clk ;
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
*/
2013-06-19 14:45:42 +05:30
for ( i = 0 ; serial_dev [ i ] . dev . platform_data ! = NULL ; i + + ) {
dev = & serial_dev [ i ] . dev ;
2013-06-19 14:45:38 +05:30
p = dev - > platform_data ;
2009-04-14 08:04:26 -05:00
2013-06-19 14:45:42 +05:30
ret = platform_device_register ( & serial_dev [ i ] ) ;
2013-06-19 14:45:38 +05:30
if ( ret )
continue ;
2013-06-19 14:45:42 +05:30
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 14:28:13 -04:00
continue ;
2013-06-19 14:45:42 +05:30
}
clk_prepare_enable ( clk ) ;
p - > uartclk = clk_get_rate ( clk ) ;
2010-05-02 14: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 14:28:14 -04:00
if ( p - > membase & & p - > type ! = PORT_AR7 )
2010-05-02 14:28:13 -04:00
davinci_serial_reset ( p ) ;
2009-04-14 08:04:26 -05:00
}
2013-06-19 14:45:38 +05:30
return ret ;
2007-04-30 19:37:19 +01:00
}