2005-04-17 02:20:36 +04:00
/*
* linux / drivers / serial / cpm_uart_cpm2 . c
*
* Driver for CPM ( SCC / SMC ) serial ports ; CPM2 definitions
*
2005-11-14 03:06:30 +03:00
* Maintainer : Kumar Gala ( galak @ kernel . crashing . org ) ( CPM2 )
2005-04-17 02:20:36 +04:00
* Pantelis Antoniou ( panto @ intracom . gr ) ( CPM1 )
2008-06-12 16:53:48 +04:00
*
2005-04-17 02:20:36 +04:00
* Copyright ( C ) 2004 Freescale Semiconductor , Inc .
* ( C ) 2004 Intracom , S . A .
2006-04-29 23:06:00 +04:00
* ( C ) 2006 MontaVista Software , Inc .
2008-06-12 16:53:48 +04:00
* Vitaly Bordug < vbordug @ ru . mvista . com >
2005-04-17 02:20:36 +04:00
*
* 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 . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <linux/module.h>
# include <linux/tty.h>
# include <linux/ioport.h>
# include <linux/init.h>
# include <linux/serial.h>
# include <linux/console.h>
# include <linux/sysrq.h>
# include <linux/device.h>
# include <linux/bootmem.h>
# include <linux/dma-mapping.h>
# include <asm/io.h>
# include <asm/irq.h>
2006-09-21 17:27:15 +04:00
# include <asm/fs_pd.h>
2008-04-10 19:01:27 +04:00
# include <asm/prom.h>
2005-04-17 02:20:36 +04:00
# include <linux/serial_core.h>
# include <linux/kernel.h>
# include "cpm_uart.h"
/**************************************************************/
2007-07-18 02:59:06 +04:00
void cpm_line_cr_cmd ( struct uart_cpm_port * port , int cmd )
{
2007-11-26 20:03:40 +03:00
cpm_command ( port - > command , cmd ) ;
2007-07-18 02:59:06 +04:00
}
2008-04-10 19:01:27 +04:00
void __iomem * cpm_uart_map_pram ( struct uart_cpm_port * port ,
struct device_node * np )
{
void __iomem * pram ;
unsigned long offset ;
struct resource res ;
unsigned long len ;
/* Don't remap parameter RAM if it has already been initialized
* during console setup .
*/
if ( IS_SMC ( port ) & & port - > smcup )
return port - > smcup ;
else if ( ! IS_SMC ( port ) & & port - > sccup )
return port - > sccup ;
if ( of_address_to_resource ( np , 1 , & res ) )
return NULL ;
len = 1 + res . end - res . start ;
pram = ioremap ( res . start , len ) ;
if ( ! pram )
return NULL ;
if ( ! IS_SMC ( port ) )
return pram ;
if ( len ! = 2 ) {
printk ( KERN_WARNING " cpm_uart[%d]: device tree references "
" SMC pram, using boot loader/wrapper pram mapping. "
" Please fix your device tree to reference the pram "
" base register instead. \n " ,
port - > port . line ) ;
return pram ;
}
offset = cpm_dpalloc ( PROFF_SMC_SIZE , 64 ) ;
out_be16 ( pram , offset ) ;
iounmap ( pram ) ;
return cpm_muram_addr ( offset ) ;
}
void cpm_uart_unmap_pram ( struct uart_cpm_port * port , void __iomem * pram )
{
if ( ! IS_SMC ( port ) )
iounmap ( pram ) ;
}
2005-04-17 02:20:36 +04:00
/*
2008-06-12 16:53:48 +04:00
* Allocate DP - Ram and memory buffers . We need to allocate a transmit and
2005-04-17 02:20:36 +04:00
* receive buffer descriptors from dual port ram , and a character
* buffer area from host mem . If we are allocating for the console we need
* to do it from bootmem
*/
int cpm_uart_allocbuf ( struct uart_cpm_port * pinfo , unsigned int is_con )
{
int dpmemsz , memsz ;
2007-09-28 23:06:16 +04:00
u8 __iomem * dp_mem ;
2007-05-08 23:46:36 +04:00
unsigned long dp_offset ;
2005-04-17 02:20:36 +04:00
u8 * mem_addr ;
dma_addr_t dma_addr = 0 ;
pr_debug ( " CPM uart[%d]:allocbuf \n " , pinfo - > port . line ) ;
dpmemsz = sizeof ( cbd_t ) * ( pinfo - > rx_nrfifos + pinfo - > tx_nrfifos ) ;
dp_offset = cpm_dpalloc ( dpmemsz , 8 ) ;
2007-05-08 23:46:36 +04:00
if ( IS_ERR_VALUE ( dp_offset ) ) {
2005-04-17 02:20:36 +04:00
printk ( KERN_ERR
" cpm_uart_cpm.c: could not allocate buffer descriptors \n " ) ;
return - ENOMEM ;
}
dp_mem = cpm_dpram_addr ( dp_offset ) ;
memsz = L1_CACHE_ALIGN ( pinfo - > rx_nrfifos * pinfo - > rx_fifosize ) +
L1_CACHE_ALIGN ( pinfo - > tx_nrfifos * pinfo - > tx_fifosize ) ;
2006-04-25 20:26:46 +04:00
if ( is_con ) {
2009-07-20 15:51:03 +04:00
mem_addr = kzalloc ( memsz , GFP_NOWAIT ) ;
2006-05-24 21:40:18 +04:00
dma_addr = virt_to_bus ( mem_addr ) ;
2006-04-25 20:26:46 +04:00
}
2005-04-17 02:20:36 +04:00
else
2008-09-12 19:42:56 +04:00
mem_addr = dma_alloc_coherent ( pinfo - > port . dev , memsz , & dma_addr ,
2005-04-17 02:20:36 +04:00
GFP_KERNEL ) ;
if ( mem_addr = = NULL ) {
cpm_dpfree ( dp_offset ) ;
printk ( KERN_ERR
" cpm_uart_cpm.c: could not allocate coherent memory \n " ) ;
return - ENOMEM ;
}
pinfo - > dp_addr = dp_offset ;
pinfo - > mem_addr = mem_addr ;
pinfo - > dma_addr = dma_addr ;
2006-04-25 20:26:46 +04:00
pinfo - > mem_size = memsz ;
2005-04-17 02:20:36 +04:00
pinfo - > rx_buf = mem_addr ;
pinfo - > tx_buf = pinfo - > rx_buf + L1_CACHE_ALIGN ( pinfo - > rx_nrfifos
* pinfo - > rx_fifosize ) ;
2007-09-28 23:06:16 +04:00
pinfo - > rx_bd_base = ( cbd_t __iomem * ) dp_mem ;
2005-04-17 02:20:36 +04:00
pinfo - > tx_bd_base = pinfo - > rx_bd_base + pinfo - > rx_nrfifos ;
return 0 ;
}
void cpm_uart_freebuf ( struct uart_cpm_port * pinfo )
{
2008-09-12 19:42:56 +04:00
dma_free_coherent ( pinfo - > port . dev , L1_CACHE_ALIGN ( pinfo - > rx_nrfifos *
pinfo - > rx_fifosize ) +
2005-04-17 02:20:36 +04:00
L1_CACHE_ALIGN ( pinfo - > tx_nrfifos *
2007-07-25 00:53:07 +04:00
pinfo - > tx_fifosize ) , ( void __force * ) pinfo - > mem_addr ,
2005-04-17 02:20:36 +04:00
pinfo - > dma_addr ) ;
cpm_dpfree ( pinfo - > dp_addr ) ;
}