2005-11-10 14:26:51 +00:00
/*
2006-10-03 23:01:26 +02:00
* arch / arm / mach - omap2 / serial . c
2005-11-10 14:26:51 +00:00
*
* OMAP2 serial support .
*
2008-10-06 15:49:15 +03:00
* Copyright ( C ) 2005 - 2008 Nokia Corporation
2005-11-10 14:26:51 +00:00
* Author : Paul Mundt < paul . mundt @ nokia . com >
*
* Based off of arch / arm / mach - omap / omap1 / serial . c
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/serial_8250.h>
# include <linux/serial_reg.h>
2006-01-07 16:15:52 +00:00
# include <linux/clk.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2005-11-10 14:26:51 +00:00
2008-08-05 16:14:15 +01:00
# include <mach/common.h>
# include <mach/board.h>
2005-11-10 14:26:51 +00:00
2008-10-06 15:49:15 +03:00
static struct clk * uart_ick [ OMAP_MAX_NR_PORTS ] ;
static struct clk * uart_fck [ OMAP_MAX_NR_PORTS ] ;
2005-11-10 14:26:51 +00:00
static struct plat_serial8250_port serial_platform_data [ ] = {
{
2008-09-01 22:07:37 +01:00
. membase = IO_ADDRESS ( OMAP_UART1_BASE ) ,
. mapbase = OMAP_UART1_BASE ,
2005-11-10 14:26:51 +00:00
. irq = 72 ,
. flags = UPF_BOOT_AUTOCONF ,
. iotype = UPIO_MEM ,
. regshift = 2 ,
2008-10-06 15:49:15 +03:00
. uartclk = OMAP24XX_BASE_BAUD * 16 ,
2005-11-10 14:26:51 +00:00
} , {
2008-09-01 22:07:37 +01:00
. membase = IO_ADDRESS ( OMAP_UART2_BASE ) ,
. mapbase = OMAP_UART2_BASE ,
2005-11-10 14:26:51 +00:00
. irq = 73 ,
. flags = UPF_BOOT_AUTOCONF ,
. iotype = UPIO_MEM ,
. regshift = 2 ,
2008-10-06 15:49:15 +03:00
. uartclk = OMAP24XX_BASE_BAUD * 16 ,
2005-11-10 14:26:51 +00:00
} , {
2008-09-01 22:07:37 +01:00
. membase = IO_ADDRESS ( OMAP_UART3_BASE ) ,
. mapbase = OMAP_UART3_BASE ,
2005-11-10 14:26:51 +00:00
. irq = 74 ,
. flags = UPF_BOOT_AUTOCONF ,
. iotype = UPIO_MEM ,
. regshift = 2 ,
2008-10-06 15:49:15 +03:00
. uartclk = OMAP24XX_BASE_BAUD * 16 ,
2005-11-10 14:26:51 +00:00
} , {
. flags = 0
}
} ;
static inline unsigned int serial_read_reg ( struct plat_serial8250_port * up ,
int offset )
{
offset < < = up - > regshift ;
return ( unsigned int ) __raw_readb ( up - > membase + offset ) ;
}
static inline void serial_write_reg ( struct plat_serial8250_port * p , int offset ,
int value )
{
offset < < = p - > regshift ;
2008-09-01 22:07:37 +01:00
__raw_writeb ( value , p - > membase + offset ) ;
2005-11-10 14:26:51 +00:00
}
/*
* Internal UARTs need to be initialized for the 8250 autoconfig to work
* properly . Note that the TX watermark initialization may not be needed
* once the 8250. c watermark handling code is merged .
*/
static inline void __init omap_serial_reset ( struct plat_serial8250_port * p )
{
serial_write_reg ( p , UART_OMAP_MDR1 , 0x07 ) ;
serial_write_reg ( p , UART_OMAP_SCR , 0x08 ) ;
serial_write_reg ( p , UART_OMAP_MDR1 , 0x00 ) ;
2006-12-06 17:13:49 -08:00
serial_write_reg ( p , UART_OMAP_SYSC , ( 0x02 < < 3 ) | ( 1 < < 2 ) | ( 1 < < 0 ) ) ;
2005-11-10 14:26:51 +00:00
}
2008-10-06 15:49:15 +03:00
void omap_serial_enable_clocks ( int enable )
{
int i ;
for ( i = 0 ; i < OMAP_MAX_NR_PORTS ; i + + ) {
if ( uart_ick [ i ] & & uart_fck [ i ] ) {
if ( enable ) {
clk_enable ( uart_ick [ i ] ) ;
clk_enable ( uart_fck [ i ] ) ;
} else {
clk_disable ( uart_ick [ i ] ) ;
clk_disable ( uart_fck [ i ] ) ;
}
}
}
}
void __init omap_serial_init ( void )
2005-11-10 14:26:51 +00:00
{
int i ;
const struct omap_uart_config * info ;
2008-10-06 15:49:15 +03:00
char name [ 16 ] ;
2005-11-10 14:26:51 +00:00
/*
* Make sure the serial ports are muxed on at this point .
* You have to mux them off in device drivers later on
* if not needed .
*/
2008-10-06 15:49:15 +03:00
info = omap_get_config ( OMAP_TAG_UART , struct omap_uart_config ) ;
2005-11-10 14:26:51 +00:00
if ( info = = NULL )
return ;
for ( i = 0 ; i < OMAP_MAX_NR_PORTS ; i + + ) {
struct plat_serial8250_port * p = serial_platform_data + i ;
if ( ! ( info - > enabled_uarts & ( 1 < < i ) ) ) {
2008-09-05 15:10:27 +01:00
p - > membase = NULL ;
2005-11-10 14:26:51 +00:00
p - > mapbase = 0 ;
continue ;
}
2008-10-06 15:49:15 +03:00
sprintf ( name , " uart%d_ick " , i + 1 ) ;
uart_ick [ i ] = clk_get ( NULL , name ) ;
if ( IS_ERR ( uart_ick [ i ] ) ) {
printk ( KERN_ERR " Could not get uart%d_ick \n " , i + 1 ) ;
uart_ick [ i ] = NULL ;
} else
clk_enable ( uart_ick [ i ] ) ;
sprintf ( name , " uart%d_fck " , i + 1 ) ;
uart_fck [ i ] = clk_get ( NULL , name ) ;
if ( IS_ERR ( uart_fck [ i ] ) ) {
printk ( KERN_ERR " Could not get uart%d_fck \n " , i + 1 ) ;
uart_fck [ i ] = NULL ;
} else
clk_enable ( uart_fck [ i ] ) ;
2005-11-10 14:26:51 +00:00
omap_serial_reset ( p ) ;
}
}
static struct platform_device serial_device = {
. name = " serial8250 " ,
2006-03-23 12:59:08 +00:00
. id = PLAT8250_DEV_PLATFORM ,
2005-11-10 14:26:51 +00:00
. dev = {
. platform_data = serial_platform_data ,
} ,
} ;
static int __init omap_init ( void )
{
return platform_device_register ( & serial_device ) ;
}
arch_initcall ( omap_init ) ;