2010-10-12 14:18:31 +04:00
/*
* Freescale SPI / eSPI controller driver library .
*
* Maintainer : Kumar Gala
*
* Copyright ( C ) 2006 Polycom , Inc .
*
* CPM SPI and QE buffer descriptors mode support :
* Copyright ( c ) 2009 MontaVista Software , Inc .
* Author : Anton Vorontsov < avorontsov @ ru . mvista . com >
*
* Copyright 2010 Freescale Semiconductor , Inc .
*
* 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 .
*/
# include <linux/dma-mapping.h>
2014-09-29 06:57:06 +04:00
# include <linux/fsl_devices.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
2010-10-12 14:18:31 +04:00
# include <linux/mm.h>
2015-01-06 16:07:34 +03:00
# include <linux/module.h>
2010-10-12 14:18:31 +04:00
# include <linux/of_platform.h>
2012-04-08 00:16:53 +04:00
# include <linux/spi/spi.h>
2013-02-15 19:52:21 +04:00
# ifdef CONFIG_FSL_SOC
2010-10-12 14:18:31 +04:00
# include <sysdev/fsl_soc.h>
2013-02-15 19:52:21 +04:00
# endif
2010-10-12 14:18:31 +04:00
2011-06-06 11:16:30 +04:00
# include "spi-fsl-lib.h"
2010-10-12 14:18:31 +04:00
# define MPC8XXX_SPI_RX_BUF(type) \
void mpc8xxx_spi_rx_buf_ # # type ( u32 data , struct mpc8xxx_spi * mpc8xxx_spi ) \
{ \
type * rx = mpc8xxx_spi - > rx ; \
* rx + + = ( type ) ( data > > mpc8xxx_spi - > rx_shift ) ; \
mpc8xxx_spi - > rx = rx ; \
2015-01-06 16:07:34 +03:00
} \
EXPORT_SYMBOL_GPL ( mpc8xxx_spi_rx_buf_ # # type ) ;
2010-10-12 14:18:31 +04:00
# define MPC8XXX_SPI_TX_BUF(type) \
u32 mpc8xxx_spi_tx_buf_ # # type ( struct mpc8xxx_spi * mpc8xxx_spi ) \
{ \
u32 data ; \
const type * tx = mpc8xxx_spi - > tx ; \
if ( ! tx ) \
return 0 ; \
data = * tx + + < < mpc8xxx_spi - > tx_shift ; \
mpc8xxx_spi - > tx = tx ; \
return data ; \
2015-01-06 16:07:34 +03:00
} \
EXPORT_SYMBOL_GPL ( mpc8xxx_spi_tx_buf_ # # type ) ;
2010-10-12 14:18:31 +04:00
MPC8XXX_SPI_RX_BUF ( u8 )
MPC8XXX_SPI_RX_BUF ( u16 )
MPC8XXX_SPI_RX_BUF ( u32 )
MPC8XXX_SPI_TX_BUF ( u8 )
MPC8XXX_SPI_TX_BUF ( u16 )
MPC8XXX_SPI_TX_BUF ( u32 )
struct mpc8xxx_spi_probe_info * to_of_pinfo ( struct fsl_spi_platform_data * pdata )
{
return container_of ( pdata , struct mpc8xxx_spi_probe_info , pdata ) ;
}
2015-01-06 16:07:34 +03:00
EXPORT_SYMBOL_GPL ( to_of_pinfo ) ;
2010-10-12 14:18:31 +04:00
const char * mpc8xxx_spi_strmode ( unsigned int flags )
{
if ( flags & SPI_QE_CPU_MODE ) {
return " QE CPU " ;
} else if ( flags & SPI_CPM_MODE ) {
if ( flags & SPI_QE )
return " QE " ;
else if ( flags & SPI_CPM2 )
return " CPM2 " ;
else
return " CPM1 " ;
}
return " CPU " ;
}
2015-01-06 16:07:34 +03:00
EXPORT_SYMBOL_GPL ( mpc8xxx_spi_strmode ) ;
2010-10-12 14:18:31 +04:00
2014-12-03 09:56:17 +03:00
void mpc8xxx_spi_probe ( struct device * dev , struct resource * mem ,
2010-10-12 14:18:31 +04:00
unsigned int irq )
{
2013-07-30 11:58:59 +04:00
struct fsl_spi_platform_data * pdata = dev_get_platdata ( dev ) ;
2010-10-12 14:18:31 +04:00
struct spi_master * master ;
struct mpc8xxx_spi * mpc8xxx_spi ;
master = dev_get_drvdata ( dev ) ;
/* the spi->mode bits understood by this driver: */
master - > mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
| SPI_LSB_FIRST | SPI_LOOP ;
master - > dev . of_node = dev - > of_node ;
mpc8xxx_spi = spi_master_get_devdata ( master ) ;
mpc8xxx_spi - > dev = dev ;
mpc8xxx_spi - > get_rx = mpc8xxx_spi_rx_buf_u8 ;
mpc8xxx_spi - > get_tx = mpc8xxx_spi_tx_buf_u8 ;
mpc8xxx_spi - > flags = pdata - > flags ;
mpc8xxx_spi - > spibrg = pdata - > sysclk ;
mpc8xxx_spi - > irq = irq ;
mpc8xxx_spi - > rx_shift = 0 ;
mpc8xxx_spi - > tx_shift = 0 ;
master - > bus_num = pdata - > bus_num ;
master - > num_chipselect = pdata - > max_chipselect ;
init_completion ( & mpc8xxx_spi - > done ) ;
}
2015-01-06 16:07:34 +03:00
EXPORT_SYMBOL_GPL ( mpc8xxx_spi_probe ) ;
2010-10-12 14:18:31 +04:00
2012-12-07 20:57:14 +04:00
int of_mpc8xxx_spi_probe ( struct platform_device * ofdev )
2010-10-12 14:18:31 +04:00
{
struct device * dev = & ofdev - > dev ;
struct device_node * np = ofdev - > dev . of_node ;
struct mpc8xxx_spi_probe_info * pinfo ;
struct fsl_spi_platform_data * pdata ;
const void * prop ;
int ret = - ENOMEM ;
2014-03-20 13:20:17 +04:00
pinfo = devm_kzalloc ( & ofdev - > dev , sizeof ( * pinfo ) , GFP_KERNEL ) ;
2010-10-12 14:18:31 +04:00
if ( ! pinfo )
2014-06-26 07:26:43 +04:00
return ret ;
2010-10-12 14:18:31 +04:00
pdata = & pinfo - > pdata ;
dev - > platform_data = pdata ;
/* Allocate bus num dynamically. */
pdata - > bus_num = - 1 ;
2013-02-15 19:52:21 +04:00
# ifdef CONFIG_FSL_SOC
2010-10-12 14:18:31 +04:00
/* SPI controller is either clocked from QE or SoC clock. */
pdata - > sysclk = get_brgfreq ( ) ;
if ( pdata - > sysclk = = - 1 ) {
pdata - > sysclk = fsl_get_sys_freq ( ) ;
2014-03-20 13:20:17 +04:00
if ( pdata - > sysclk = = - 1 )
return - ENODEV ;
2010-10-12 14:18:31 +04:00
}
2013-02-15 19:52:21 +04:00
# else
ret = of_property_read_u32 ( np , " clock-frequency " , & pdata - > sysclk ) ;
if ( ret )
2014-03-20 13:20:17 +04:00
return ret ;
2013-02-15 19:52:21 +04:00
# endif
2010-10-12 14:18:31 +04:00
prop = of_get_property ( np , " mode " , NULL ) ;
if ( prop & & ! strcmp ( prop , " cpu-qe " ) )
pdata - > flags = SPI_QE_CPU_MODE ;
else if ( prop & & ! strcmp ( prop , " qe " ) )
pdata - > flags = SPI_CPM_MODE | SPI_QE ;
else if ( of_device_is_compatible ( np , " fsl,cpm2-spi " ) )
pdata - > flags = SPI_CPM_MODE | SPI_CPM2 ;
else if ( of_device_is_compatible ( np , " fsl,cpm1-spi " ) )
pdata - > flags = SPI_CPM_MODE | SPI_CPM1 ;
return 0 ;
}
2015-01-06 16:07:34 +03:00
EXPORT_SYMBOL_GPL ( of_mpc8xxx_spi_probe ) ;
MODULE_LICENSE ( " GPL " ) ;