2005-04-17 02:20:36 +04:00
/*
* linux / drivers / serial / cpm_uart . c
*
* Driver for CPM ( SCC / SMC ) serial ports ; CPM1 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 )
2005-08-09 21:08:00 +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>
2007-01-24 22:40:49 +03:00
# include <asm/fs_pd.h>
2005-04-17 02:20:36 +04:00
# include <linux/serial_core.h>
# include <linux/kernel.h>
2008-04-10 19:01:27 +04:00
# include <linux/of.h>
2005-04-17 02:20:36 +04:00
# 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 )
{
return of_iomap ( np , 1 ) ;
}
void cpm_uart_unmap_pram ( struct uart_cpm_port * port , void __iomem * pram )
{
iounmap ( pram ) ;
}
2005-04-17 02:20:36 +04:00
/*
2005-08-09 21:08:00 +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 ;
u8 * 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_cpm1.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 ) ;
if ( is_con ) {
2005-08-09 21:08:00 +04:00
/* was hostalloc but changed cause it blows away the */
/* large tlb mapping when pinning the kernel area */
2005-07-27 22:46:01 +04:00
mem_addr = ( u8 * ) cpm_dpram_addr ( cpm_dpalloc ( memsz , 8 ) ) ;
2007-01-24 22:40:49 +03:00
dma_addr = ( u32 ) cpm_dpram_phys ( mem_addr ) ;
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_cpm1.c: could not allocate coherent memory \n " ) ;
return - ENOMEM ;
}
pinfo - > dp_addr = dp_offset ;
2006-04-25 20:26:46 +04:00
pinfo - > mem_addr = mem_addr ; /* virtual address*/
pinfo - > dma_addr = dma_addr ; /* physical address*/
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-07-25 00:53:07 +04:00
pinfo - > rx_bd_base = ( cbd_t __iomem __force * ) 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 *
pinfo - > tx_fifosize ) , pinfo - > mem_addr ,
pinfo - > dma_addr ) ;
cpm_dpfree ( pinfo - > dp_addr ) ;
}