@ -32,14 +32,10 @@
# include "arm_pl180_mmci.h"
# include <malloc.h>
struct mmc_host {
struct sdi_registers * base ;
} ;
static int wait_for_command_end ( struct mmc * dev , struct mmc_cmd * cmd )
{
u32 hoststatus , statusmask ;
struct mmc_host * host = dev - > priv ;
struct pl180_mmc_host * host = dev - > priv ;
statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL ;
if ( ( cmd - > resp_type & MMC_RSP_PRESENT ) )
@ -53,8 +49,8 @@ static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
writel ( statusmask , & host - > base - > status_clear ) ;
if ( hoststatus & SDI_STA_CTIMEOUT ) {
printf ( " CMD%d time out \n " , cmd - > cmdidx ) ;
return - E TIMED OUT;
debug ( " CMD%d time out \n " , cmd - > cmdidx ) ;
return TIMEOUT ;
} else if ( ( hoststatus & SDI_STA_CCRCFAIL ) & &
( cmd - > flags & MMC_RSP_CRC ) ) {
printf ( " CMD%d CRC error \n " , cmd - > cmdidx ) ;
@ -80,7 +76,7 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd)
{
int result ;
u32 sdi_cmd = 0 ;
struct mmc_host * host = dev - > priv ;
struct pl180_ mmc_host * host = dev - > priv ;
sdi_cmd = ( ( cmd - > cmdidx & SDI_CMD_CMDINDEX_MASK ) | SDI_CMD_CPSMEN ) ;
@ -112,7 +108,7 @@ static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize)
{
u32 * tempbuff = dest ;
u64 xfercount = blkcount * blksize ;
struct mmc_host * host = dev - > priv ;
struct pl180_ mmc_host * host = dev - > priv ;
u32 status , status_err ;
debug ( " read_bytes: blkcount=%u blksize=%u \n " , blkcount , blksize ) ;
@ -168,7 +164,7 @@ static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize)
u32 * tempbuff = src ;
int i ;
u64 xfercount = blkcount * blksize ;
struct mmc_host * host = dev - > priv ;
struct pl180_ mmc_host * host = dev - > priv ;
u32 status , status_err ;
debug ( " write_bytes: blkcount=%u blksize=%u \n " , blkcount , blksize ) ;
@ -227,14 +223,19 @@ static int do_data_transfer(struct mmc *dev,
struct mmc_data * data )
{
int error = - ETIMEDOUT ;
struct mmc_host * host = dev - > priv ;
struct pl180_ mmc_host * host = dev - > priv ;
u32 blksz = 0 ;
u32 data_ctrl = 0 ;
u32 data_len = ( u32 ) ( data - > blocks * data - > blocksize ) ;
blksz = ( ffs ( data - > blocksize ) - 1 ) ;
data_ctrl | = ( ( blksz < < 4 ) & SDI_DCTRL_DBLKSIZE_MASK ) ;
data_ctrl | = SDI_DCTRL_DTEN ;
if ( ! host - > version2 ) {
blksz = ( ffs ( data - > blocksize ) - 1 ) ;
data_ctrl | = ( ( blksz < < 4 ) & SDI_DCTRL_DBLKSIZE_MASK ) ;
} else {
blksz = data - > blocksize ;
data_ctrl | = ( blksz < < SDI_DCTRL_DBLOCKSIZE_V2_SHIFT ) ;
}
data_ctrl | = SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE ;
writel ( SDI_DTIMER_DEFAULT , & host - > base - > datatimer ) ;
writel ( data_len , & host - > base - > datalength ) ;
@ -257,7 +258,7 @@ static int do_data_transfer(struct mmc *dev,
writel ( data_ctrl , & host - > base - > datactrl ) ;
error = write_bytes ( dev , ( u32 * ) data - > src , ( u32 ) data - > blocks ,
( u32 ) data - > blocksize ) ;
( u32 ) data - > blocksize ) ;
}
return error ;
@ -280,17 +281,16 @@ static int host_request(struct mmc *dev,
/* MMC uses open drain drivers in the enumeration phase */
static int mmc_host_reset ( struct mmc * dev )
{
struct mmc_host * host = dev - > priv ;
u32 sdi_u32 = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON ;
struct pl180_mmc_host * host = dev - > priv ;
writel ( sdi_u32 , & host - > base - > power ) ;
writel ( host - > pwr_init , & host - > base - > power ) ;
return 0 ;
}
static void host_set_ios ( struct mmc * dev )
{
struct mmc_host * host = dev - > priv ;
struct pl180_ mmc_host * host = dev - > priv ;
u32 sdi_clkcr ;
sdi_clkcr = readl ( & host - > base - > clock ) ;
@ -298,15 +298,26 @@ static void host_set_ios(struct mmc *dev)
/* Ramp up the clock rate */
if ( dev - > clock ) {
u32 clkdiv = 0 ;
u32 tmp_clock ;
if ( dev - > clock > = dev - > f_max )
if ( dev - > clock > = dev - > f_max ) {
clkdiv = 0 ;
dev - > clock = dev - > f_max ;
} else {
clkdiv = ( host - > clock_in / dev - > clock ) - 2 ;
}
clkdiv = ( ( ARM_MCLK / dev - > clock ) / 2 ) - 1 ;
tmp_clock = host - > clock_in / ( clkdiv + 2 ) ;
while ( tmp_clock > dev - > clock ) {
clkdiv + + ;
tmp_clock = host - > clock_in / ( clkdiv + 2 ) ;
}
if ( clkdiv > SDI_CLKCR_CLKDIV_MASK )
clkdiv = SDI_CLKCR_CLKDIV_MASK ;
tmp_clock = host - > clock_in / ( clkdiv + 2 ) ;
dev - > clock = tmp_clock ;
sdi_clkcr & = ~ ( SDI_CLKCR_CLKDIV_MASK ) ;
sdi_clkcr | = clkdiv ;
}
@ -322,8 +333,11 @@ static void host_set_ios(struct mmc *dev)
case 4 :
buswidth | = SDI_CLKCR_WIDBUS_4 ;
break ;
case 8 :
buswidth | = SDI_CLKCR_WIDBUS_8 ;
break ;
default :
printf ( " Invalid bus width \n " ) ;
printf ( " Invalid bus width: %d \n " , dev - > bus_width ) ;
break ;
}
sdi_clkcr & = ~ ( SDI_CLKCR_WIDBUS_MASK ) ;
@ -334,83 +348,40 @@ static void host_set_ios(struct mmc *dev)
udelay ( CLK_CHANGE_DELAY ) ;
}
struct mmc * alloc_mmc_struct ( void )
{
struct mmc_host * host = NULL ;
struct mmc * mmc_device = NULL ;
host = malloc ( sizeof ( struct mmc_host ) ) ;
if ( ! host )
return NULL ;
mmc_device = malloc ( sizeof ( struct mmc ) ) ;
if ( ! mmc_device )
goto err ;
mmc_device - > priv = host ;
return mmc_device ;
err :
free ( host ) ;
return NULL ;
}
/*
* mmc_host_init - initialize the mmc controller .
* Set initial clock and power for mmc slot .
* Initialize mmc struct and register with mmc framework .
*/
static int arm_pl180_mmci_host _init ( struct mmc * dev )
int arm_pl180_mmci_init ( struct pl180_mmc_host * host )
{
struct mmc_host * host = dev - > pri v ;
struct mmc * dev ;
u32 sdi_u32 ;
host - > base = ( struct sdi_registers * ) CONFIG_ARM_PL180_MMCI_BASE ;
dev = malloc ( sizeof ( struct mmc ) ) ;
if ( ! dev )
return - ENOMEM ;
/* Initially set power-on, full voltage & MMCI read */
sdi_u32 = INIT_PWR ;
writel ( sdi_u32 , & host - > base - > power ) ;
memset ( dev , 0 , sizeof ( struct mmc ) ) ;
dev - > priv = host ;
/* setting clk freq 505KHz */
sdi_u32 = SDI_CLKCR_CLKDIV_INIT | SDI_CLKCR_CLKEN ;
writel ( sdi_u32 , & host - > base - > clock ) ;
writel ( host - > pwr_init , & host - > base - > power ) ;
writel ( host - > clkdiv_init , & host - > base - > clock ) ;
udelay ( CLK_CHANGE_DELAY ) ;
/* Disable mmc interrupts */
sdi_u32 = readl ( & host - > base - > mask0 ) & ~ SDI_MASK0_MASK ;
writel ( sdi_u32 , & host - > base - > mask0 ) ;
sprintf ( dev - > name , " MMC " ) ;
dev - > clock = ARM_MCLK / ( 2 * ( SDI_CLKCR_CLKDIV_INIT + 1 ) ) ;
strncpy ( dev - > name , host - > name , sizeof ( dev - > name ) ) ;
dev - > send_cmd = host_request ;
dev - > set_ios = host_set_ios ;
dev - > init = mmc_host_reset ;
dev - > getcd = NULL ;
dev - > host_caps = 0 ;
dev - > voltages = VOLTAGE_WINDOW_MMC ;
dev - > f_min = dev - > clock ;
dev - > f_max = CONFIG_ARM_PL180_MMCI_CLOCK_FREQ ;
return 0 ;
}
int arm_pl180_mmci_init ( void )
{
int error ;
struct mmc * dev ;
dev = alloc_mmc_struct ( ) ;
if ( ! dev )
return - 1 ;
error = arm_pl180_mmci_host_init ( dev ) ;
if ( error ) {
printf ( " mmci_host_init error - %d \n " , error ) ;
return - 1 ;
}
dev - > b_max = 0 ;
dev - > host_caps = host - > caps ;
dev - > voltages = host - > voltages ;
dev - > f_min = host - > clock_min ;
dev - > f_max = host - > clock_max ;
dev - > b_max = host - > b_max ;
mmc_register ( dev ) ;
debug ( " registered mmc interface number is:%d \n " , dev - > block_dev . dev ) ;