2011-05-17 21:41:21 -05:00
/***************************************************************************
* Copyright ( C ) 2011 by Rodrigo L . Rosa *
* rodrigorosa . LG @ gmail . com *
* *
* Based on a file written by : *
2011-06-10 14:23:34 -05:00
* Kevin McGuire *
2011-05-17 21:41:21 -05:00
* Marcel Wijlaars *
* Michael Ashton *
* *
* 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 . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-06-10 14:24:27 -05:00
/**
* @ file dsp5680xx_flash . c
* @ author Rodrigo L . Rosa < rodrigorosa . LG @ gmail . com >
* @ date Thu Jun 9 18 : 21 : 58 2011
*
* @ brief This file implements the basic functions to run flashing commands
* from the TCL interface .
* It allows the user to flash the Freescale 5680 xx DSP .
*
*
*/
2011-05-17 21:41:21 -05:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifndef DSP5680XX_FLASH_H
# define DSP5680XX_FLASH_H
# include "imp.h"
# include <helper/binarybuffer.h>
# include <helper/time_support.h>
# include <target/algorithm.h>
# include <target/dsp5680xx.h>
struct dsp5680xx_flash_bank {
struct working_area * write_algorithm ;
} ;
static int dsp5680xx_build_sector_list ( struct flash_bank * bank ) {
2011-06-10 14:19:58 -05:00
uint32_t offset = HFM_FLASH_BASE_ADDR ;
2011-05-17 21:41:21 -05:00
bank - > sectors = malloc ( sizeof ( struct flash_sector ) * bank - > num_sectors ) ;
int i ;
for ( i = 0 ; i < bank - > num_sectors ; + + i ) {
2011-06-10 14:19:58 -05:00
bank - > sectors [ i ] . offset = i * HFM_SECTOR_SIZE ;
2011-05-17 21:41:21 -05:00
bank - > sectors [ i ] . size = HFM_SECTOR_SIZE ;
2011-06-10 14:19:58 -05:00
offset + = bank - > sectors [ i ] . size ;
2011-05-17 21:41:21 -05:00
bank - > sectors [ i ] . is_erased = - 1 ;
bank - > sectors [ i ] . is_protected = - 1 ;
}
LOG_USER ( " %s not tested yet. " , __FUNCTION__ ) ;
return ERROR_OK ;
}
// flash bank dsp5680xx 0 0 0 0 <target#>
FLASH_BANK_COMMAND_HANDLER ( dsp5680xx_flash_bank_command ) {
struct dsp5680xx_flash_bank * nbank ;
nbank = malloc ( sizeof ( struct dsp5680xx_flash_bank ) ) ;
bank - > base = HFM_FLASH_BASE_ADDR ;
2011-06-10 14:19:58 -05:00
bank - > size = HFM_SIZE_BYTES ; // top 4k not accessible
2011-05-17 21:41:21 -05:00
bank - > driver_priv = nbank ;
2011-06-10 14:19:58 -05:00
bank - > num_sectors = HFM_SECTOR_COUNT ;
2011-05-17 21:41:21 -05:00
dsp5680xx_build_sector_list ( bank ) ;
return ERROR_OK ;
}
2011-06-10 14:24:27 -05:00
/**
* A memory mapped register ( PROT ) holds information regarding sector protection .
* Protection refers to undesired core access .
* The value in this register is loaded from flash upon reset .
*
* @ param bank
*
* @ return
*/
2011-05-17 21:41:21 -05:00
static int dsp5680xx_flash_protect_check ( struct flash_bank * bank ) {
int retval = ERROR_OK ;
2011-06-10 14:19:58 -05:00
uint16_t protected = 0 ;
2011-05-17 21:41:21 -05:00
retval = dsp5680xx_f_protect_check ( bank - > target , & protected ) ;
2011-06-10 14:19:58 -05:00
if ( retval ! = ERROR_OK ) {
for ( int i = 0 ; i < HFM_SECTOR_COUNT ; i + + )
bank - > sectors [ i ] . is_protected = - 1 ;
return ERROR_OK ;
}
for ( int i = 0 ; i < HFM_SECTOR_COUNT / 2 ; i + + ) {
if ( protected & 1 ) {
bank - > sectors [ 2 * i ] . is_protected = 1 ;
bank - > sectors [ 2 * i + 1 ] . is_protected = 1 ;
} else {
bank - > sectors [ 2 * i ] . is_protected = 0 ;
bank - > sectors [ 2 * i + 1 ] . is_protected = 0 ;
}
protected = ( protected > > 1 ) ;
2011-05-17 21:41:21 -05:00
}
return retval ;
}
2011-06-10 14:24:27 -05:00
/**
* Protection funcionality is not implemented .
* The current implementation applies / removes security on the chip .
* The chip is effectively secured / unsecured after the first reset following the execution of this function .
*
* @ param bank
* @ param set Apply or remove security on the chip .
* @ param first This parameter is ignored .
* @ param last This parameter is ignored .
*
* @ return
*/
2011-05-17 21:41:21 -05:00
static int dsp5680xx_flash_protect ( struct flash_bank * bank , int set , int first , int last ) {
2011-06-10 14:19:58 -05:00
// This applies security to flash module after next reset, it does not actually apply protection (protection refers to undesired access from the core)
2011-05-17 21:41:21 -05:00
int retval ;
2011-06-10 14:23:52 -05:00
if ( set )
2011-05-17 21:41:21 -05:00
retval = dsp5680xx_f_lock ( bank - > target ) ;
2011-11-19 17:39:20 -06:00
else {
retval = dsp5680xx_f_unlock ( bank - > target ) ;
if ( retval = = ERROR_OK ) {
/* mark all as erased */
for ( int i = 0 ; i < = ( HFM_SECTOR_COUNT - 1 ) ; i + + )
/* FM does not recognize it as erased if erased via JTAG. */
bank - > sectors [ i ] . is_erased = 1 ;
}
}
2011-05-17 21:41:21 -05:00
return retval ;
}
2011-06-10 14:24:27 -05:00
/**
* The dsp5680xx use word addressing . The " /2 " that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing .
*
* @ param bank
* @ param buffer Data to write to flash .
* @ param offset
* @ param count In bytes ( 2 bytes per address ) .
*
* @ return
*/
2011-05-17 21:41:21 -05:00
static int dsp5680xx_flash_write ( struct flash_bank * bank , uint8_t * buffer , uint32_t offset , uint32_t count ) {
int retval ;
if ( ( offset + count / 2 ) > bank - > size ) {
LOG_ERROR ( " %s: Flash bank cannot fit data. " , __FUNCTION__ ) ;
return ERROR_FAIL ;
}
if ( offset % 2 ) {
LOG_ERROR ( " %s: Writing to odd addresses not supported. This chip uses word addressing, Openocd only supports byte addressing. The workaround results in disabling writing to odd byte addresses. " , __FUNCTION__ ) ;
return ERROR_FAIL ;
}
2011-08-30 16:19:09 -05:00
retval = dsp5680xx_f_wr ( bank - > target , buffer , bank - > base + offset / 2 , count , 0 ) ;
2011-06-10 14:23:52 -05:00
uint32_t addr_word ;
for ( addr_word = bank - > base + offset / 2 ; addr_word < count / 2 ; addr_word + = ( HFM_SECTOR_SIZE / 2 ) ) {
if ( retval = = ERROR_OK )
bank - > sectors [ addr_word / ( HFM_SECTOR_SIZE / 2 ) ] . is_erased = 0 ;
else
bank - > sectors [ addr_word / ( HFM_SECTOR_SIZE / 2 ) ] . is_erased = - 1 ;
}
2011-05-17 21:41:21 -05:00
return retval ;
}
static int dsp5680xx_probe ( struct flash_bank * bank ) {
2011-05-18 22:11:04 -05:00
LOG_DEBUG ( " %s not implemented " , __FUNCTION__ ) ;
return ERROR_OK ;
2011-05-17 21:41:21 -05:00
}
static int dsp5680xx_flash_info ( struct flash_bank * bank , char * buf , int buf_size ) {
snprintf ( buf , buf_size , " \n dsp5680xx flash driver info: \n - Currently only full erase/lock/unlock are implemented. \n - Call with bank==0 and sector 0 to 0. \n - Protect requires arp_init-reset to complete. \n - Before removing protection the master tap must be selected, and arp_init-reset is required to complete unlocking. " ) ;
return ERROR_OK ;
}
2011-06-10 14:24:27 -05:00
/**
* The flash module ( FM ) on the dsp5680xx supports both individual sector and mass erase of the flash memory .
* If this function is called with @ first = = @ last = = 0 or if @ first is the first sector ( # 0 ) and @ last is the last sector then the mass erase command is executed ( much faster than erasing each sector individually ) .
*
* @ param bank
* @ param first
* @ param last
*
* @ return
*/
2011-05-17 21:41:21 -05:00
static int dsp5680xx_flash_erase ( struct flash_bank * bank , int first , int last ) {
int retval ;
retval = dsp5680xx_f_erase ( bank - > target , ( uint32_t ) first , ( uint32_t ) last ) ;
2011-11-21 12:34:24 -06:00
if ( ( ! ( first | last ) ) | | ( ( first = = 0 ) & & ( last = = ( HFM_SECTOR_COUNT - 1 ) ) ) )
last = HFM_SECTOR_COUNT - 1 ;
2011-05-17 21:41:21 -05:00
if ( retval = = ERROR_OK )
2011-06-10 14:19:58 -05:00
for ( int i = first ; i < = last ; i + + )
bank - > sectors [ i ] . is_erased = 1 ;
2011-05-17 21:41:21 -05:00
else
2011-06-10 14:19:58 -05:00
// If an error occurred unknown status is set even though some sector could have been correctly erased.
for ( int i = first ; i < = last ; i + + )
bank - > sectors [ i ] . is_erased = - 1 ;
2011-05-17 21:41:21 -05:00
return retval ;
}
2011-06-10 14:24:27 -05:00
/**
* The flash module ( FM ) on the dsp5680xx support a blank check function .
* This function executes the FM ' s blank check functionality on each and every sector .
*
* @ param bank
*
* @ return
*/
2011-05-17 21:41:21 -05:00
static int dsp5680xx_flash_erase_check ( struct flash_bank * bank ) {
int retval = ERROR_OK ;
uint8_t erased = 0 ;
2011-06-10 14:19:58 -05:00
uint32_t i ;
for ( i = 0 ; i < HFM_SECTOR_COUNT ; i + + ) {
if ( bank - > sectors [ i ] . is_erased = = - 1 ) {
retval = dsp5680xx_f_erase_check ( bank - > target , & erased , i ) ;
2011-05-17 21:41:21 -05:00
if ( retval ! = ERROR_OK ) {
2011-06-10 14:19:58 -05:00
bank - > sectors [ i ] . is_erased = - 1 ;
2011-05-17 21:41:21 -05:00
} else {
if ( erased )
2011-06-10 14:19:58 -05:00
bank - > sectors [ i ] . is_erased = 1 ;
2011-05-17 21:41:21 -05:00
else
2011-06-10 14:19:58 -05:00
bank - > sectors [ i ] . is_erased = 0 ;
}
2011-05-17 21:41:21 -05:00
}
}
return retval ;
}
struct flash_driver dsp5680xx_flash = {
. name = " dsp5680xx_flash " ,
. flash_bank_command = dsp5680xx_flash_bank_command ,
. erase = dsp5680xx_flash_erase ,
. protect = dsp5680xx_flash_protect ,
. write = dsp5680xx_flash_write ,
//.read = default_flash_read,
2011-05-18 22:11:04 -05:00
. probe = dsp5680xx_probe ,
2011-05-17 21:41:21 -05:00
. auto_probe = dsp5680xx_probe ,
. erase_check = dsp5680xx_flash_erase_check ,
. protect_check = dsp5680xx_flash_protect_check ,
. info = dsp5680xx_flash_info
} ;
# endif // dsp5680xx_flash.h