2008-06-01 01:32:37 +04:00
/*
* arch / arm / mach - orion5x / ts78xx - setup . c
*
* Maintainer : Alexander Clouter < alex @ digriz . org . uk >
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
2012-05-12 18:17:00 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2008-06-01 01:32:37 +04:00
# include <linux/kernel.h>
# include <linux/init.h>
2009-02-07 01:16:55 +03:00
# include <linux/sysfs.h>
2008-06-01 01:32:37 +04:00
# include <linux/platform_device.h>
# include <linux/mv643xx_eth.h>
# include <linux/ata_platform.h>
# include <linux/m48t86.h>
2009-02-24 01:40:01 +03:00
# include <linux/mtd/nand.h>
# include <linux/mtd/partitions.h>
2009-05-03 23:57:48 +04:00
# include <linux/timeriomem-rng.h>
2008-06-01 01:32:37 +04:00
# include <asm/mach-types.h>
# include <asm/mach/arch.h>
# include <asm/mach/map.h>
2008-08-05 19:14:15 +04:00
# include <mach/orion5x.h>
2008-06-01 01:32:37 +04:00
# include "common.h"
# include "mpp.h"
2009-02-07 01:16:55 +03:00
# include "ts78xx-fpga.h"
2008-06-01 01:32:37 +04:00
/*****************************************************************************
* TS - 78 xx Info
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* FPGA - lives where the PCI bus would be at ORION5X_PCI_MEM_PHYS_BASE
*/
# define TS78XX_FPGA_REGS_PHYS_BASE 0xe8000000
2012-09-28 18:12:46 +04:00
# define TS78XX_FPGA_REGS_VIRT_BASE IOMEM(0xff900000)
2008-06-01 01:32:37 +04:00
# define TS78XX_FPGA_REGS_SIZE SZ_1M
2009-02-07 01:16:55 +03:00
static struct ts78xx_fpga_data ts78xx_fpga = {
. id = 0 ,
. state = 1 ,
/* .supports = ... - populated by ts78xx_fpga_supports() */
} ;
2008-06-01 01:32:37 +04:00
/*****************************************************************************
* I / O Address Mapping
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct map_desc ts78xx_io_desc [ ] __initdata = {
{
2012-09-28 18:12:46 +04:00
. virtual = ( unsigned long ) TS78XX_FPGA_REGS_VIRT_BASE ,
2008-06-01 01:32:37 +04:00
. pfn = __phys_to_pfn ( TS78XX_FPGA_REGS_PHYS_BASE ) ,
. length = TS78XX_FPGA_REGS_SIZE ,
. type = MT_DEVICE ,
} ,
} ;
void __init ts78xx_map_io ( void )
{
orion5x_map_io ( ) ;
iotable_init ( ts78xx_io_desc , ARRAY_SIZE ( ts78xx_io_desc ) ) ;
}
/*****************************************************************************
* Ethernet
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct mv643xx_eth_platform_data ts78xx_eth_data = {
2008-08-26 16:06:47 +04:00
. phy_addr = MV643XX_ETH_PHY_ADDR ( 0 ) ,
2008-06-01 01:32:37 +04:00
} ;
2009-02-07 01:16:55 +03:00
/*****************************************************************************
* SATA
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct mv_sata_platform_data ts78xx_sata_data = {
. n_ports = 2 ,
} ;
2008-06-01 01:32:37 +04:00
/*****************************************************************************
* RTC M48T86 - nicked ^ Wborrowed from arch / arm / mach - ep93xx / ts72xx . c
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-09-28 18:12:46 +04:00
# define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE + 0x808)
# define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE + 0x80c)
2009-02-07 01:16:55 +03:00
static unsigned char ts78xx_ts_rtc_readbyte ( unsigned long addr )
2008-06-01 01:32:37 +04:00
{
2009-02-07 01:16:55 +03:00
writeb ( addr , TS_RTC_CTRL ) ;
return readb ( TS_RTC_DATA ) ;
2008-06-01 01:32:37 +04:00
}
2009-02-07 01:16:55 +03:00
static void ts78xx_ts_rtc_writebyte ( unsigned char value , unsigned long addr )
2008-06-01 01:32:37 +04:00
{
2009-02-07 01:16:55 +03:00
writeb ( addr , TS_RTC_CTRL ) ;
writeb ( value , TS_RTC_DATA ) ;
2008-06-01 01:32:37 +04:00
}
2009-02-07 01:16:55 +03:00
static struct m48t86_ops ts78xx_ts_rtc_ops = {
. readbyte = ts78xx_ts_rtc_readbyte ,
. writebyte = ts78xx_ts_rtc_writebyte ,
2008-06-01 01:32:37 +04:00
} ;
2009-02-07 01:16:55 +03:00
static struct platform_device ts78xx_ts_rtc_device = {
2008-06-01 01:32:37 +04:00
. name = " rtc-m48t86 " ,
. id = - 1 ,
. dev = {
2009-02-07 01:16:55 +03:00
. platform_data = & ts78xx_ts_rtc_ops ,
2008-06-01 01:32:37 +04:00
} ,
. num_resources = 0 ,
} ;
/*
* TS uses some of the user storage space on the RTC chip so see if it is
* present ; as it ' s an optional feature at purchase time and not all boards
* will have it present
*
* I ' ve used the method TS use in their rtc7800 . c example for the detection
*
* TODO : track down a guinea pig without an RTC to see if we can work out a
2012-05-12 18:16:58 +04:00
* better RTC detection routine
2008-06-01 01:32:37 +04:00
*/
2009-02-07 01:16:55 +03:00
static int ts78xx_ts_rtc_load ( void )
2008-06-01 01:32:37 +04:00
{
2009-02-24 01:37:36 +03:00
int rc ;
2008-06-01 01:32:37 +04:00
unsigned char tmp_rtc0 , tmp_rtc1 ;
2009-02-07 01:16:55 +03:00
tmp_rtc0 = ts78xx_ts_rtc_readbyte ( 126 ) ;
tmp_rtc1 = ts78xx_ts_rtc_readbyte ( 127 ) ;
ts78xx_ts_rtc_writebyte ( 0x00 , 126 ) ;
ts78xx_ts_rtc_writebyte ( 0x55 , 127 ) ;
if ( ts78xx_ts_rtc_readbyte ( 127 ) = = 0x55 ) {
ts78xx_ts_rtc_writebyte ( 0xaa , 127 ) ;
if ( ts78xx_ts_rtc_readbyte ( 127 ) = = 0xaa
& & ts78xx_ts_rtc_readbyte ( 126 ) = = 0x00 ) {
ts78xx_ts_rtc_writebyte ( tmp_rtc0 , 126 ) ;
ts78xx_ts_rtc_writebyte ( tmp_rtc1 , 127 ) ;
2009-02-24 01:37:36 +03:00
2009-02-07 01:16:55 +03:00
if ( ts78xx_fpga . supports . ts_rtc . init = = 0 ) {
2009-02-24 01:37:36 +03:00
rc = platform_device_register ( & ts78xx_ts_rtc_device ) ;
if ( ! rc )
ts78xx_fpga . supports . ts_rtc . init = 1 ;
2009-02-07 01:16:55 +03:00
} else
2009-02-24 01:37:36 +03:00
rc = platform_device_add ( & ts78xx_ts_rtc_device ) ;
2012-05-12 18:17:00 +04:00
if ( rc )
pr_info ( " RTC could not be registered: %d \n " ,
rc ) ;
2009-02-24 01:37:36 +03:00
return rc ;
2008-06-01 01:32:37 +04:00
}
}
2012-05-12 18:17:00 +04:00
pr_info ( " RTC not found \n " ) ;
2009-02-07 01:16:55 +03:00
return - ENODEV ;
2008-06-01 01:32:37 +04:00
} ;
2009-02-07 01:16:55 +03:00
static void ts78xx_ts_rtc_unload ( void )
{
platform_device_del ( & ts78xx_ts_rtc_device ) ;
}
2008-06-01 01:32:37 +04:00
2009-02-24 01:40:01 +03:00
/*****************************************************************************
* NAND Flash
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-09-28 18:12:46 +04:00
# define TS_NAND_CTRL (TS78XX_FPGA_REGS_VIRT_BASE + 0x800) /* VIRT */
# define TS_NAND_DATA (TS78XX_FPGA_REGS_PHYS_BASE + 0x804) /* PHYS */
2009-02-24 01:40:01 +03:00
/*
* hardware specific access to control - lines
*
* ctrl :
* NAND_NCE : bit 0 - > bit 2
* NAND_CLE : bit 1 - > bit 1
* NAND_ALE : bit 2 - > bit 0
*/
static void ts78xx_ts_nand_cmd_ctrl ( struct mtd_info * mtd , int cmd ,
unsigned int ctrl )
{
struct nand_chip * this = mtd - > priv ;
if ( ctrl & NAND_CTRL_CHANGE ) {
unsigned char bits ;
bits = ( ctrl & NAND_NCE ) < < 2 ;
bits | = ctrl & NAND_CLE ;
bits | = ( ctrl & NAND_ALE ) > > 2 ;
writeb ( ( readb ( TS_NAND_CTRL ) & ~ 0x7 ) | bits , TS_NAND_CTRL ) ;
}
if ( cmd ! = NAND_CMD_NONE )
writeb ( cmd , this - > IO_ADDR_W ) ;
}
static int ts78xx_ts_nand_dev_ready ( struct mtd_info * mtd )
{
return readb ( TS_NAND_CTRL ) & 0x20 ;
}
2011-01-08 14:55:25 +03:00
static void ts78xx_ts_nand_write_buf ( struct mtd_info * mtd ,
const uint8_t * buf , int len )
{
struct nand_chip * chip = mtd - > priv ;
void __iomem * io_base = chip - > IO_ADDR_W ;
unsigned long off = ( ( unsigned long ) buf & 3 ) ;
int sz ;
if ( off ) {
2011-03-05 14:31:04 +03:00
sz = min_t ( int , 4 - off , len ) ;
2011-01-08 14:55:25 +03:00
writesb ( io_base , buf , sz ) ;
buf + = sz ;
len - = sz ;
}
sz = len > > 2 ;
if ( sz ) {
u32 * buf32 = ( u32 * ) buf ;
writesl ( io_base , buf32 , sz ) ;
buf + = sz < < 2 ;
len - = sz < < 2 ;
}
if ( len )
writesb ( io_base , buf , len ) ;
}
static void ts78xx_ts_nand_read_buf ( struct mtd_info * mtd ,
uint8_t * buf , int len )
{
struct nand_chip * chip = mtd - > priv ;
void __iomem * io_base = chip - > IO_ADDR_R ;
unsigned long off = ( ( unsigned long ) buf & 3 ) ;
int sz ;
if ( off ) {
2011-03-05 14:31:04 +03:00
sz = min_t ( int , 4 - off , len ) ;
2011-01-08 14:55:25 +03:00
readsb ( io_base , buf , sz ) ;
buf + = sz ;
len - = sz ;
}
sz = len > > 2 ;
if ( sz ) {
u32 * buf32 = ( u32 * ) buf ;
readsl ( io_base , buf32 , sz ) ;
buf + = sz < < 2 ;
len - = sz < < 2 ;
}
if ( len )
readsb ( io_base , buf , len ) ;
}
2009-02-24 01:40:01 +03:00
static struct mtd_partition ts78xx_ts_nand_parts [ ] = {
{
. name = " mbr " ,
. offset = 0 ,
. size = SZ_128K ,
. mask_flags = MTD_WRITEABLE ,
} , {
. name = " kernel " ,
. offset = MTDPART_OFS_APPEND ,
. size = SZ_4M ,
} , {
. name = " initrd " ,
. offset = MTDPART_OFS_APPEND ,
. size = SZ_4M ,
} , {
. name = " rootfs " ,
. offset = MTDPART_OFS_APPEND ,
. size = MTDPART_SIZ_FULL ,
}
} ;
static struct platform_nand_data ts78xx_ts_nand_data = {
. chip = {
2010-08-12 05:14:54 +04:00
. nr_chips = 1 ,
2009-02-24 01:40:01 +03:00
. partitions = ts78xx_ts_nand_parts ,
. nr_partitions = ARRAY_SIZE ( ts78xx_ts_nand_parts ) ,
. chip_delay = 15 ,
2011-06-01 03:31:23 +04:00
. bbt_options = NAND_BBT_USE_FLASH ,
2009-02-24 01:40:01 +03:00
} ,
. ctrl = {
/*
* The HW ECC offloading functions , used to give about a 9 %
* performance increase for ' dd if = / dev / mtdblockX ' and 5 % for
* nanddump . This all however was changed by git commit
* e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is
* no performance advantage to be had so we no longer bother
*/
. cmd_ctrl = ts78xx_ts_nand_cmd_ctrl ,
. dev_ready = ts78xx_ts_nand_dev_ready ,
2011-01-08 14:55:25 +03:00
. write_buf = ts78xx_ts_nand_write_buf ,
. read_buf = ts78xx_ts_nand_read_buf ,
2009-02-24 01:40:01 +03:00
} ,
} ;
2012-05-12 18:16:59 +04:00
static struct resource ts78xx_ts_nand_resources
= DEFINE_RES_MEM ( TS_NAND_DATA , 4 ) ;
2009-02-24 01:40:01 +03:00
static struct platform_device ts78xx_ts_nand_device = {
. name = " gen_nand " ,
. id = - 1 ,
. dev = {
. platform_data = & ts78xx_ts_nand_data ,
} ,
. resource = & ts78xx_ts_nand_resources ,
. num_resources = 1 ,
} ;
static int ts78xx_ts_nand_load ( void )
{
int rc ;
if ( ts78xx_fpga . supports . ts_nand . init = = 0 ) {
rc = platform_device_register ( & ts78xx_ts_nand_device ) ;
if ( ! rc )
ts78xx_fpga . supports . ts_nand . init = 1 ;
} else
rc = platform_device_add ( & ts78xx_ts_nand_device ) ;
2012-05-12 18:17:00 +04:00
if ( rc )
pr_info ( " NAND could not be registered: %d \n " , rc ) ;
2009-02-24 01:40:01 +03:00
return rc ;
} ;
static void ts78xx_ts_nand_unload ( void )
{
platform_device_del ( & ts78xx_ts_nand_device ) ;
}
2009-05-03 23:57:48 +04:00
/*****************************************************************************
* HW RNG
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define TS_RNG_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x044)
2012-05-12 18:16:59 +04:00
static struct resource ts78xx_ts_rng_resource
= DEFINE_RES_MEM ( TS_RNG_DATA , 4 ) ;
2009-05-03 23:57:48 +04:00
static struct timeriomem_rng_data ts78xx_ts_rng_data = {
. period = 1000000 , /* one second */
} ;
static struct platform_device ts78xx_ts_rng_device = {
. name = " timeriomem_rng " ,
. id = - 1 ,
. dev = {
. platform_data = & ts78xx_ts_rng_data ,
} ,
. resource = & ts78xx_ts_rng_resource ,
. num_resources = 1 ,
} ;
static int ts78xx_ts_rng_load ( void )
{
int rc ;
if ( ts78xx_fpga . supports . ts_rng . init = = 0 ) {
rc = platform_device_register ( & ts78xx_ts_rng_device ) ;
if ( ! rc )
ts78xx_fpga . supports . ts_rng . init = 1 ;
} else
rc = platform_device_add ( & ts78xx_ts_rng_device ) ;
2012-05-12 18:17:00 +04:00
if ( rc )
pr_info ( " RNG could not be registered: %d \n " , rc ) ;
2009-05-03 23:57:48 +04:00
return rc ;
} ;
static void ts78xx_ts_rng_unload ( void )
{
platform_device_del ( & ts78xx_ts_rng_device ) ;
}
2008-06-01 01:32:37 +04:00
/*****************************************************************************
2009-02-07 01:16:55 +03:00
* FPGA ' hotplug ' support code
2008-06-01 01:32:37 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-02-07 01:16:55 +03:00
static void ts78xx_fpga_devices_zero_init ( void )
{
ts78xx_fpga . supports . ts_rtc . init = 0 ;
2009-02-24 01:40:01 +03:00
ts78xx_fpga . supports . ts_nand . init = 0 ;
2009-05-03 23:57:48 +04:00
ts78xx_fpga . supports . ts_rng . init = 0 ;
2009-02-07 01:16:55 +03:00
}
static void ts78xx_fpga_supports ( void )
{
/* TODO: put this 'table' into ts78xx-fpga.h */
switch ( ts78xx_fpga . id ) {
2009-03-21 14:09:25 +03:00
case TS7800_REV_1 :
case TS7800_REV_2 :
case TS7800_REV_3 :
case TS7800_REV_4 :
case TS7800_REV_5 :
2011-02-17 01:29:39 +03:00
case TS7800_REV_6 :
case TS7800_REV_7 :
case TS7800_REV_8 :
case TS7800_REV_9 :
2009-02-07 01:16:55 +03:00
ts78xx_fpga . supports . ts_rtc . present = 1 ;
2009-02-24 01:40:01 +03:00
ts78xx_fpga . supports . ts_nand . present = 1 ;
2009-05-03 23:57:48 +04:00
ts78xx_fpga . supports . ts_rng . present = 1 ;
2009-02-07 01:16:55 +03:00
break ;
default :
2011-03-05 14:49:36 +03:00
/* enable devices if magic matches */
switch ( ( ts78xx_fpga . id > > 8 ) & 0xffffff ) {
case TS7800_FPGA_MAGIC :
2012-05-12 18:17:00 +04:00
pr_warning ( " unrecognised FPGA revision 0x%.2x \n " ,
2011-03-05 14:49:36 +03:00
ts78xx_fpga . id & 0xff ) ;
ts78xx_fpga . supports . ts_rtc . present = 1 ;
ts78xx_fpga . supports . ts_nand . present = 1 ;
ts78xx_fpga . supports . ts_rng . present = 1 ;
break ;
default :
ts78xx_fpga . supports . ts_rtc . present = 0 ;
ts78xx_fpga . supports . ts_nand . present = 0 ;
ts78xx_fpga . supports . ts_rng . present = 0 ;
}
2009-02-07 01:16:55 +03:00
}
}
static int ts78xx_fpga_load_devices ( void )
{
int tmp , ret = 0 ;
if ( ts78xx_fpga . supports . ts_rtc . present = = 1 ) {
tmp = ts78xx_ts_rtc_load ( ) ;
2012-05-12 18:17:00 +04:00
if ( tmp )
2009-02-24 01:37:36 +03:00
ts78xx_fpga . supports . ts_rtc . present = 0 ;
2009-02-07 01:16:55 +03:00
ret | = tmp ;
}
2009-02-24 01:40:01 +03:00
if ( ts78xx_fpga . supports . ts_nand . present = = 1 ) {
tmp = ts78xx_ts_nand_load ( ) ;
2012-05-12 18:17:00 +04:00
if ( tmp )
2009-02-24 01:40:01 +03:00
ts78xx_fpga . supports . ts_nand . present = 0 ;
ret | = tmp ;
}
2009-05-03 23:57:48 +04:00
if ( ts78xx_fpga . supports . ts_rng . present = = 1 ) {
tmp = ts78xx_ts_rng_load ( ) ;
2012-05-12 18:17:00 +04:00
if ( tmp )
2009-05-03 23:57:48 +04:00
ts78xx_fpga . supports . ts_rng . present = 0 ;
ret | = tmp ;
}
2009-02-07 01:16:55 +03:00
return ret ;
}
static int ts78xx_fpga_unload_devices ( void )
{
int ret = 0 ;
if ( ts78xx_fpga . supports . ts_rtc . present = = 1 )
ts78xx_ts_rtc_unload ( ) ;
2009-02-24 01:40:01 +03:00
if ( ts78xx_fpga . supports . ts_nand . present = = 1 )
ts78xx_ts_nand_unload ( ) ;
2009-05-03 23:57:48 +04:00
if ( ts78xx_fpga . supports . ts_rng . present = = 1 )
ts78xx_ts_rng_unload ( ) ;
2009-02-07 01:16:55 +03:00
return ret ;
}
static int ts78xx_fpga_load ( void )
{
ts78xx_fpga . id = readl ( TS78XX_FPGA_REGS_VIRT_BASE ) ;
2012-05-12 18:17:00 +04:00
pr_info ( " FPGA magic=0x%.6x, rev=0x%.2x \n " ,
2009-02-07 01:16:55 +03:00
( ts78xx_fpga . id > > 8 ) & 0xffffff ,
ts78xx_fpga . id & 0xff ) ;
ts78xx_fpga_supports ( ) ;
if ( ts78xx_fpga_load_devices ( ) ) {
ts78xx_fpga . state = - 1 ;
return - EBUSY ;
}
return 0 ;
2008-06-01 01:32:37 +04:00
} ;
2009-02-07 01:16:55 +03:00
static int ts78xx_fpga_unload ( void )
{
unsigned int fpga_id ;
fpga_id = readl ( TS78XX_FPGA_REGS_VIRT_BASE ) ;
/*
* There does not seem to be a feasible way to block access to the GPIO
* pins from userspace ( / dev / mem ) . This if clause should hopefully warn
* those foolish enough not to follow ' policy ' : )
*
* UrJTAG SVN since r1381 can be used to reprogram the FPGA
*/
if ( ts78xx_fpga . id ! = fpga_id ) {
2012-05-12 18:17:00 +04:00
pr_err ( " FPGA magic/rev mismatch \n "
2009-02-07 01:16:55 +03:00
" TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x \n " ,
( ts78xx_fpga . id > > 8 ) & 0xffffff , ts78xx_fpga . id & 0xff ,
( fpga_id > > 8 ) & 0xffffff , fpga_id & 0xff ) ;
ts78xx_fpga . state = - 1 ;
return - EBUSY ;
}
if ( ts78xx_fpga_unload_devices ( ) ) {
ts78xx_fpga . state = - 1 ;
return - EBUSY ;
}
return 0 ;
2008-06-01 01:32:37 +04:00
} ;
2009-02-07 01:16:55 +03:00
static ssize_t ts78xx_fpga_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
{
if ( ts78xx_fpga . state < 0 )
return sprintf ( buf , " borked \n " ) ;
return sprintf ( buf , " %s \n " , ( ts78xx_fpga . state ) ? " online " : " offline " ) ;
}
static ssize_t ts78xx_fpga_store ( struct kobject * kobj ,
struct kobj_attribute * attr , const char * buf , size_t n )
{
int value , ret ;
if ( ts78xx_fpga . state < 0 ) {
2012-05-12 18:17:00 +04:00
pr_err ( " FPGA borked, you must powercycle ASAP \n " ) ;
2009-02-07 01:16:55 +03:00
return - EBUSY ;
}
if ( strncmp ( buf , " online " , sizeof ( " online " ) - 1 ) = = 0 )
value = 1 ;
else if ( strncmp ( buf , " offline " , sizeof ( " offline " ) - 1 ) = = 0 )
value = 0 ;
2012-05-12 18:17:00 +04:00
else
2009-02-07 01:16:55 +03:00
return - EINVAL ;
if ( ts78xx_fpga . state = = value )
return n ;
ret = ( ts78xx_fpga . state = = 0 )
? ts78xx_fpga_load ( )
: ts78xx_fpga_unload ( ) ;
if ( ! ( ret < 0 ) )
ts78xx_fpga . state = value ;
return n ;
}
static struct kobj_attribute ts78xx_fpga_attr =
__ATTR ( ts78xx_fpga , 0644 , ts78xx_fpga_show , ts78xx_fpga_store ) ;
2008-06-01 01:32:37 +04:00
/*****************************************************************************
* General Setup
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-05-15 15:32:53 +04:00
static unsigned int ts78xx_mpp_modes [ ] __initdata = {
MPP0_UNUSED ,
MPP1_GPIO , /* JTAG Clock */
MPP2_GPIO , /* JTAG Data In */
MPP3_GPIO , /* Lat ECP2 256 FPGA - PB2B */
MPP4_GPIO , /* JTAG Data Out */
MPP5_GPIO , /* JTAG TMS */
MPP6_GPIO , /* Lat ECP2 256 FPGA - PB31A_CLK4+ */
MPP7_GPIO , /* Lat ECP2 256 FPGA - PB22B */
MPP8_UNUSED ,
MPP9_UNUSED ,
MPP10_UNUSED ,
MPP11_UNUSED ,
MPP12_UNUSED ,
MPP13_UNUSED ,
MPP14_UNUSED ,
MPP15_UNUSED ,
MPP16_UART ,
MPP17_UART ,
MPP18_UART ,
MPP19_UART ,
2009-02-07 00:59:15 +03:00
/*
* MPP [ 20 ] PCI Clock Out 1
* MPP [ 21 ] PCI Clock Out 0
* MPP [ 22 ] Unused
* MPP [ 23 ] Unused
* MPP [ 24 ] Unused
* MPP [ 25 ] Unused
*/
2011-05-15 15:32:53 +04:00
0 ,
2008-06-01 01:32:37 +04:00
} ;
static void __init ts78xx_init ( void )
{
2009-02-07 01:16:55 +03:00
int ret ;
2008-06-01 01:32:37 +04:00
/*
* Setup basic Orion functions . Need to be called early .
*/
orion5x_init ( ) ;
orion5x_mpp_conf ( ts78xx_mpp_modes ) ;
/*
* Configure peripherals .
*/
orion5x_ehci0_init ( ) ;
orion5x_ehci1_init ( ) ;
orion5x_eth_init ( & ts78xx_eth_data ) ;
orion5x_sata_init ( & ts78xx_sata_data ) ;
orion5x_uart0_init ( ) ;
orion5x_uart1_init ( ) ;
2008-06-17 14:25:12 +04:00
orion5x_xor_init ( ) ;
2008-06-01 01:32:37 +04:00
2009-02-07 01:16:55 +03:00
/* FPGA init */
ts78xx_fpga_devices_zero_init ( ) ;
ret = ts78xx_fpga_load ( ) ;
2012-05-12 18:17:01 +04:00
ret = sysfs_create_file ( firmware_kobj , & ts78xx_fpga_attr . attr ) ;
2009-02-07 01:16:55 +03:00
if ( ret )
2011-03-06 13:04:31 +03:00
pr_err ( " sysfs_create_file failed: %d \n " , ret ) ;
2008-06-01 01:32:37 +04:00
}
MACHINE_START ( TS78XX , " Technologic Systems TS-78xx SBC " )
/* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
2011-07-06 06:38:15 +04:00
. atag_offset = 0x100 ,
2008-06-01 01:32:37 +04:00
. init_machine = ts78xx_init ,
. map_io = ts78xx_map_io ,
2010-10-15 18:50:26 +04:00
. init_early = orion5x_init_early ,
2008-06-01 01:32:37 +04:00
. init_irq = orion5x_init_irq ,
2012-11-08 23:40:59 +04:00
. init_time = orion5x_timer_init ,
2011-11-05 14:13:41 +04:00
. restart = orion5x_restart ,
2008-06-01 01:32:37 +04:00
MACHINE_END