2011-12-24 01:17:10 +10:00
/*
* device . c - - common ColdFire SoC device support
*
* ( C ) Copyright 2011 , Greg Ungerer < gerg @ uclinux . org >
*
* 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/io.h>
2011-12-24 12:56:10 +10:00
# include <linux/spi/spi.h>
# include <linux/gpio.h>
2012-06-06 14:28:31 -07:00
# include <linux/fec.h>
2011-12-24 01:17:10 +10:00
# include <asm/traps.h>
# include <asm/coldfire.h>
# include <asm/mcfsim.h>
# include <asm/mcfuart.h>
2011-12-24 12:56:10 +10:00
# include <asm/mcfqspi.h>
2011-12-24 01:17:10 +10:00
2011-12-24 10:30:36 +10:00
/*
2012-06-06 14:28:31 -07:00
* All current ColdFire parts contain from 2 , 3 , 4 or 10 UARTS .
2011-12-24 10:30:36 +10:00
*/
2011-12-24 01:17:10 +10:00
static struct mcf_platform_uart mcf_uart_platform_data [ ] = {
{
. mapbase = MCFUART_BASE0 ,
. irq = MCF_IRQ_UART0 ,
} ,
{
. mapbase = MCFUART_BASE1 ,
. irq = MCF_IRQ_UART1 ,
} ,
# ifdef MCFUART_BASE2
{
. mapbase = MCFUART_BASE2 ,
. irq = MCF_IRQ_UART2 ,
} ,
# endif
# ifdef MCFUART_BASE3
{
. mapbase = MCFUART_BASE3 ,
. irq = MCF_IRQ_UART3 ,
} ,
2012-06-06 14:28:31 -07:00
# endif
# ifdef MCFUART_BASE4
{
. mapbase = MCFUART_BASE4 ,
. irq = MCF_IRQ_UART4 ,
} ,
# endif
# ifdef MCFUART_BASE5
{
. mapbase = MCFUART_BASE5 ,
. irq = MCF_IRQ_UART5 ,
} ,
# endif
# ifdef MCFUART_BASE6
{
. mapbase = MCFUART_BASE6 ,
. irq = MCF_IRQ_UART6 ,
} ,
# endif
# ifdef MCFUART_BASE7
{
. mapbase = MCFUART_BASE7 ,
. irq = MCF_IRQ_UART7 ,
} ,
# endif
# ifdef MCFUART_BASE8
{
. mapbase = MCFUART_BASE8 ,
. irq = MCF_IRQ_UART8 ,
} ,
# endif
# ifdef MCFUART_BASE9
{
. mapbase = MCFUART_BASE9 ,
. irq = MCF_IRQ_UART9 ,
} ,
2011-12-24 01:17:10 +10:00
# endif
{ } ,
} ;
static struct platform_device mcf_uart = {
. name = " mcfuart " ,
. id = 0 ,
. dev . platform_data = mcf_uart_platform_data ,
} ;
2016-01-11 10:07:49 +10:00
# if IS_ENABLED(CONFIG_FEC)
2012-06-06 14:28:31 -07:00
# ifdef CONFIG_M5441x
# define FEC_NAME "enet-fec"
static struct fec_platform_data fec_pdata = {
. phy = PHY_INTERFACE_MODE_RMII ,
} ;
# define FEC_PDATA (&fec_pdata)
# else
# define FEC_NAME "fec"
# define FEC_PDATA NULL
# endif
2011-12-24 10:30:36 +10:00
/*
* Some ColdFire cores contain the Fast Ethernet Controller ( FEC )
* block . It is Freescale ' s own hardware block . Some ColdFires
* have 2 of these .
*/
static struct resource mcf_fec0_resources [ ] = {
{
. start = MCFFEC_BASE0 ,
. end = MCFFEC_BASE0 + MCFFEC_SIZE0 - 1 ,
. flags = IORESOURCE_MEM ,
} ,
{
. start = MCF_IRQ_FECRX0 ,
. end = MCF_IRQ_FECRX0 ,
. flags = IORESOURCE_IRQ ,
} ,
{
. start = MCF_IRQ_FECTX0 ,
. end = MCF_IRQ_FECTX0 ,
. flags = IORESOURCE_IRQ ,
} ,
{
. start = MCF_IRQ_FECENTC0 ,
. end = MCF_IRQ_FECENTC0 ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct platform_device mcf_fec0 = {
2012-06-06 14:28:31 -07:00
. name = FEC_NAME ,
2011-12-24 10:30:36 +10:00
. id = 0 ,
. num_resources = ARRAY_SIZE ( mcf_fec0_resources ) ,
. resource = mcf_fec0_resources ,
2012-06-06 14:28:31 -07:00
. dev . platform_data = FEC_PDATA ,
2011-12-24 10:30:36 +10:00
} ;
# ifdef MCFFEC_BASE1
static struct resource mcf_fec1_resources [ ] = {
{
. start = MCFFEC_BASE1 ,
. end = MCFFEC_BASE1 + MCFFEC_SIZE1 - 1 ,
. flags = IORESOURCE_MEM ,
} ,
{
. start = MCF_IRQ_FECRX1 ,
. end = MCF_IRQ_FECRX1 ,
. flags = IORESOURCE_IRQ ,
} ,
{
. start = MCF_IRQ_FECTX1 ,
. end = MCF_IRQ_FECTX1 ,
. flags = IORESOURCE_IRQ ,
} ,
{
. start = MCF_IRQ_FECENTC1 ,
. end = MCF_IRQ_FECENTC1 ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct platform_device mcf_fec1 = {
2012-06-06 14:28:31 -07:00
. name = FEC_NAME ,
2012-04-17 16:58:35 +10:00
. id = 1 ,
2011-12-24 10:30:36 +10:00
. num_resources = ARRAY_SIZE ( mcf_fec1_resources ) ,
. resource = mcf_fec1_resources ,
2012-06-06 14:28:31 -07:00
. dev . platform_data = FEC_PDATA ,
2011-12-24 10:30:36 +10:00
} ;
# endif /* MCFFEC_BASE1 */
# endif /* CONFIG_FEC */
2012-05-06 12:22:53 -07:00
# if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
2011-12-24 12:56:10 +10:00
/*
* The ColdFire QSPI module is an SPI protocol hardware block used
* on a number of different ColdFire CPUs .
*/
static struct resource mcf_qspi_resources [ ] = {
{
. start = MCFQSPI_BASE ,
. end = MCFQSPI_BASE + MCFQSPI_SIZE - 1 ,
. flags = IORESOURCE_MEM ,
} ,
{
. start = MCF_IRQ_QSPI ,
. end = MCF_IRQ_QSPI ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static int mcf_cs_setup ( struct mcfqspi_cs_control * cs_control )
{
int status ;
status = gpio_request ( MCFQSPI_CS0 , " MCFQSPI_CS0 " ) ;
if ( status ) {
pr_debug ( " gpio_request for MCFQSPI_CS0 failed \n " ) ;
goto fail0 ;
}
status = gpio_direction_output ( MCFQSPI_CS0 , 1 ) ;
if ( status ) {
pr_debug ( " gpio_direction_output for MCFQSPI_CS0 failed \n " ) ;
goto fail1 ;
}
status = gpio_request ( MCFQSPI_CS1 , " MCFQSPI_CS1 " ) ;
if ( status ) {
pr_debug ( " gpio_request for MCFQSPI_CS1 failed \n " ) ;
goto fail1 ;
}
status = gpio_direction_output ( MCFQSPI_CS1 , 1 ) ;
if ( status ) {
pr_debug ( " gpio_direction_output for MCFQSPI_CS1 failed \n " ) ;
goto fail2 ;
}
status = gpio_request ( MCFQSPI_CS2 , " MCFQSPI_CS2 " ) ;
if ( status ) {
pr_debug ( " gpio_request for MCFQSPI_CS2 failed \n " ) ;
goto fail2 ;
}
status = gpio_direction_output ( MCFQSPI_CS2 , 1 ) ;
if ( status ) {
pr_debug ( " gpio_direction_output for MCFQSPI_CS2 failed \n " ) ;
goto fail3 ;
}
# ifdef MCFQSPI_CS3
status = gpio_request ( MCFQSPI_CS3 , " MCFQSPI_CS3 " ) ;
if ( status ) {
pr_debug ( " gpio_request for MCFQSPI_CS3 failed \n " ) ;
goto fail3 ;
}
status = gpio_direction_output ( MCFQSPI_CS3 , 1 ) ;
if ( status ) {
pr_debug ( " gpio_direction_output for MCFQSPI_CS3 failed \n " ) ;
gpio_free ( MCFQSPI_CS3 ) ;
goto fail3 ;
}
# endif
return 0 ;
fail3 :
gpio_free ( MCFQSPI_CS2 ) ;
fail2 :
gpio_free ( MCFQSPI_CS1 ) ;
fail1 :
gpio_free ( MCFQSPI_CS0 ) ;
fail0 :
return status ;
}
static void mcf_cs_teardown ( struct mcfqspi_cs_control * cs_control )
{
# ifdef MCFQSPI_CS3
gpio_free ( MCFQSPI_CS3 ) ;
# endif
gpio_free ( MCFQSPI_CS2 ) ;
gpio_free ( MCFQSPI_CS1 ) ;
gpio_free ( MCFQSPI_CS0 ) ;
}
static void mcf_cs_select ( struct mcfqspi_cs_control * cs_control ,
u8 chip_select , bool cs_high )
{
switch ( chip_select ) {
case 0 :
gpio_set_value ( MCFQSPI_CS0 , cs_high ) ;
break ;
case 1 :
gpio_set_value ( MCFQSPI_CS1 , cs_high ) ;
break ;
case 2 :
gpio_set_value ( MCFQSPI_CS2 , cs_high ) ;
break ;
# ifdef MCFQSPI_CS3
case 3 :
gpio_set_value ( MCFQSPI_CS3 , cs_high ) ;
break ;
# endif
}
}
static void mcf_cs_deselect ( struct mcfqspi_cs_control * cs_control ,
u8 chip_select , bool cs_high )
{
switch ( chip_select ) {
case 0 :
gpio_set_value ( MCFQSPI_CS0 , ! cs_high ) ;
break ;
case 1 :
gpio_set_value ( MCFQSPI_CS1 , ! cs_high ) ;
break ;
case 2 :
gpio_set_value ( MCFQSPI_CS2 , ! cs_high ) ;
break ;
# ifdef MCFQSPI_CS3
case 3 :
gpio_set_value ( MCFQSPI_CS3 , ! cs_high ) ;
break ;
# endif
}
}
static struct mcfqspi_cs_control mcf_cs_control = {
. setup = mcf_cs_setup ,
. teardown = mcf_cs_teardown ,
. select = mcf_cs_select ,
. deselect = mcf_cs_deselect ,
} ;
static struct mcfqspi_platform_data mcf_qspi_data = {
. bus_num = 0 ,
. num_chipselect = 4 ,
. cs_control = & mcf_cs_control ,
} ;
static struct platform_device mcf_qspi = {
. name = " mcfqspi " ,
. id = 0 ,
. num_resources = ARRAY_SIZE ( mcf_qspi_resources ) ,
. resource = mcf_qspi_resources ,
. dev . platform_data = & mcf_qspi_data ,
} ;
2012-05-06 12:22:53 -07:00
# endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
2011-12-24 12:56:10 +10:00
2011-12-24 01:17:10 +10:00
static struct platform_device * mcf_devices [ ] __initdata = {
& mcf_uart ,
2016-01-11 10:07:49 +10:00
# if IS_ENABLED(CONFIG_FEC)
2011-12-24 10:30:36 +10:00
& mcf_fec0 ,
# ifdef MCFFEC_BASE1
& mcf_fec1 ,
# endif
# endif
2012-05-06 12:22:53 -07:00
# if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
2011-12-24 12:56:10 +10:00
& mcf_qspi ,
# endif
2011-12-24 01:17:10 +10:00
} ;
2011-12-24 01:23:35 +10:00
/*
* Some ColdFire UARTs let you set the IRQ line to use .
*/
static void __init mcf_uart_set_irq ( void )
{
# ifdef MCFUART_UIVR
/* UART0 interrupt setup */
2012-08-17 16:48:16 +10:00
writeb ( MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1 , MCFSIM_UART1ICR ) ;
2011-12-24 01:23:35 +10:00
writeb ( MCF_IRQ_UART0 , MCFUART_BASE0 + MCFUART_UIVR ) ;
mcf_mapirq2imr ( MCF_IRQ_UART0 , MCFINTC_UART0 ) ;
/* UART1 interrupt setup */
2012-08-17 16:48:16 +10:00
writeb ( MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2 , MCFSIM_UART2ICR ) ;
2011-12-24 01:23:35 +10:00
writeb ( MCF_IRQ_UART1 , MCFUART_BASE1 + MCFUART_UIVR ) ;
mcf_mapirq2imr ( MCF_IRQ_UART1 , MCFINTC_UART1 ) ;
# endif
}
2011-12-24 01:17:10 +10:00
static int __init mcf_init_devices ( void )
{
2011-12-24 01:23:35 +10:00
mcf_uart_set_irq ( ) ;
2011-12-24 01:17:10 +10:00
platform_add_devices ( mcf_devices , ARRAY_SIZE ( mcf_devices ) ) ;
return 0 ;
}
arch_initcall ( mcf_init_devices ) ;