Files
android_kernel_motorola_sm6225/drivers/misc/cypress/ProgrammingSteps.c
T
Ryan Lattrel 0ee3f8162a cyttsp_sar_mmi: fix flashing issues
The maximum frequency to bit-bang at is 7 MHz. This
puts us right on the edge.  Slow down writes by
changing writel_relaxed_no_log to writel_relaxed.

Additionally, DeviceAcquire is given a single retry.
It sometimes fails the first time, but I have not
seen it fail twice.  The hssp protocol for the
cypress chip is a little iffy so this gives us a better
shot at being successful everytime.

Also includes various other fixes.

Change-Id: I94cc3496b74174ca14680299a5bd7020d5d88336
Signed-off-by: Ryan Lattrel <ryanl@motorola.com>
Reviewed-on: https://gerrit.mot.com/1119584
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Kenneth Kessler <kennykessler@motorola.com>
Submit-Approved: Jira Key
2018-01-19 15:23:03 -06:00

1407 lines
45 KiB
C

/******************************************************************************
* File Name: ProgrammingSteps.c
* Version 1.0
*
* Description:
* This file provides the source code for the high level Programming functions
* used by the main code to program target PSoC 4
*
* Owner:
* Tushar Rastogi, Application Engineer (tusr@cypress.com)
*
* Related Document:
* AN84858 - PSoC 4 Programming using an External Microcontroller (HSSP)
*
* Hardware Dependency:
* PSoC 5LP Development Kit - CY8CKIT-050
*
* Code Tested With:
* PSoC Creator 2.2
* ARM GCC 4.4.1
* CY8CKIT-050
*
*******************************************************************************
* Copyright (2013), Cypress Semiconductor Corporation.
*******************************************************************************
* This software is owned by Cypress Semiconductor Corporation (Cypress) and is
* protected by and subject to worldwide patent protection (United States and
* foreign), United States copyright laws and international treaty provisions.
* Cypress hereby grants to licensee a personal, non-exclusive, non-transferable
* license to copy, use, modify, create derivative works of, and compile the
* Cypress Source Code and derivative works for the sole purpose of creating
* custom software in support of licensee product to be used only in conjunction
* with a Cypress integrated circuit as specified in the applicable agreement.
* Any reproduction, modification, translation, compilation, or representation
* of this software except as specified above is prohibited without the express
* written permission of Cypress.
*
* Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH
* REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* Cypress reserves the right to make changes without further notice to the
* materials described herein. Cypress does not assume any liability arising out
* of the application or use of any product or circuit described herein. Cypress
* does not authorize its products for use as critical components in life-support
* systems where a malfunction or failure may reasonably be expected to result in
* significant injury to the user. The inclusion of Cypress' product in a life-
* support systems application implies that the manufacturer assumes all risk of
* such use and in doing so indemnifies Cypress against all charges. Use may be
* limited by and subject to the applicable Cypress software license agreement.
******************************************************************************/
/******************************************************************************
* Header file Inclusion
******************************************************************************/
#include "ProgrammingSteps.h"
#include "SWD_PhysicalLayer.h"
#include "SWD_UpperPacketLayer.h"
#include "SWD_PacketLayer.h"
#include "DataFetch.h"
#include "Timeout.h"
/******************************************************************************
* Global Variable definitions
******************************************************************************/
unsigned long checksum_Privileged;
unsigned long statusCode;
unsigned char result;
unsigned char chipProtectionData_Chip;
enum Transition_mode { OPEN_XXX, VIRGIN_OPEN, PROT_XXX, WRONG_TRANSITION } flow;
/******************************************************************************
* Function Definitions
******************************************************************************/
/******************************************************************************
* Function Name: PollSromStatus
*******************************************************************************
* Summary:
* Polls the SROM_SYSREQ_BIT and SROM_PRIVILEGED_BIT in the CPUSS_SYSREQ
* register till it is reset or a timeout condition occurred, whichever is
* earlier. For a SROM polling timeout error, the timeout error status bit is
* set in swd_PacketAck variable and CPUSS_SYSARG register is read to get the
* error status code. If timeout does not happen, the CPUSS_SYSARG register is
* read to determine if the task executed successfully.
*
* Parameters:
* None.
*
* Return:
* SUCCESS - SROM executed the task successfully
* FAILURE - SROM task is not executed successfully and a timeout error occured.
* The failure code is stored in the statusCode global variable.
*
* Note:
* This function is called after non volatile memory operations like Read,
* Write of Flash, to check if SROM task has been executed which is indicated
* by SUCCESS. The status is read from the CPUSS_SYSARG register.
*
******************************************************************************/
unsigned char PollSromStatus(void)
{
unsigned long time_elapsed = 0;
do {
/* Read CPUSS_SYSREQ register and check if SROM_SYSREQ_BIT and
SROM_PRIVILEGED_BIT are reset to 0 */
Read_IO(CPUSS_SYSREQ, &statusCode);
statusCode &= (SROM_SYSREQ_BIT | SROM_PRIVILEGED_BIT);
time_elapsed++;
} while ((statusCode != 0) && (time_elapsed <= SROM_POLLING_TIMEOUT));
/* If time exceeds the timeout value, set the SROM_TIMEOUT_ERROR bit in
swd_PacketAck */
if (time_elapsed > SROM_POLLING_TIMEOUT) {
swd_PacketAck = swd_PacketAck | SROM_TIMEOUT_ERROR;
Read_IO(CPUSS_SYSARG, &statusCode);
return FAILURE;
}
/* Read CPUSS_SYSARG register to check if the SROM command executed
successfully else set SROM_TIMEOUT_ERROR in swd_PacketAck */
Read_IO(CPUSS_SYSARG, &statusCode);
if ((statusCode & SROM_STATUS_SUCCESS_MASK) != SROM_STATUS_SUCCEEDED) {
swd_PacketAck = swd_PacketAck | SROM_TIMEOUT_ERROR;
return FAILURE;
}
return SUCCESS;
}
#if defined CY8C40xx_FAMILY
/******************************************************************************
* Function Name: SetIMO48MHz
*******************************************************************************
* Summary:
* Set IMO to 48 MHz
*
* Parameters:
* None.
*
* Return:
* None
*
* Note:
* This function is required to be called before any flash operation.
* This function sets the IMO to 48 MHz before flash write/erase operations
* and is part of the device acquire routine.
*
******************************************************************************/
void SetIMO48MHz(void)
{
unsigned long parameter1 = 0;
/* Load the Parameter1 with the SROM command to read silicon ID */
parameter1 = (unsigned long)(((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)SROM_CMD_SET_IMO_48MHZ) <<
8));
/* Write the command to CPUSS_SYSARG register */
Write_IO(CPUSS_SYSARG, parameter1);
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_SET_IMO_48MHZ);
}
#endif
/******************************************************************************
* Function Name: ReadSromStatus
*******************************************************************************
*
* Summary:
* It reads the StatusCode global variable and returns LSB of this long variable
* to main.c.
*
* Parameters:
* None.
*
* Return:
* LSB of statusCode - LSB of statusCode global variable contains the error code
*
* Note:
* This function is called from main.c when SROM_TIMEOUT_ERROR bit is set in the
* swd_PacketAck.
*
******************************************************************************/
unsigned char ReadSromStatus(void)
{
return (unsigned char)statusCode;
}
/******************************************************************************
* Function Name: GetChipProtectionVal
*******************************************************************************
* Summary:
* This sub-routine is used to read the Chip Protection Setting by using SROM
* System Calls. System call to read Silicon Id returns Chip protection settings
* in the CPUSS_SYSREQ register. The location of the data is bit [15:12] in the
* 32-bit register.
*
* Parameters:
* None.
*
* Return:
* chipProtectionData_Chip - 1 byte chip protection setting read from the chip
*
* Note:
* This function is called in the "Step 3. Erase All Flash" to read the chip
* protection settings to take decision whether to move the protection state
* to open and then erase the flash or directly erase the flash.
*
******************************************************************************/
unsigned char GetChipProtectionVal(struct hssp_data *d)
{
unsigned long parameter1 = 0;
unsigned long chipProtData = 0;
/* Load the Parameter1 with the SROM command to read silicon ID */
parameter1 = (unsigned long)(((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)SROM_CMD_GET_SILICON_ID)
<< 8));
/* Write the command to CPUSS_SYSARG register */
Write_IO(CPUSS_SYSARG, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request system call by writing to CPUSS_SYSREQ register */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_GET_SILICON_ID);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
/* Read CPUSS_SYSREQ register to get the current protection setting of
the chip */
Read_IO(CPUSS_SYSREQ, &chipProtData);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
chipProtectionData_Chip = (unsigned char)(chipProtData >> 12);
return SUCCESS;
}
/******************************************************************************
* Function Name: GetTransitionMode
*******************************************************************************
*
* Summary:
* It reads the chipProtectionData_Chip global variable which contains the Chip
* protection setting stored in the Chip and chipProtectionData_Hex from the
* hex file which contains the Chip protection setting stored in the HEX file.
* The function then validates if the two settings correspond to a valid
* transition.
*
* Parameters:
* None.
*
* Return:
* SUCCESS - Returns SUCCESS if the transition is valid.
* FAILURE - Returns Failure if the transition is invalid.
* Stores the transition in the global enum flow.
*
* Note:
* This function is called in "Step 3. Erase All Flash" to take decision on
* basis of the global enum flow.
*
******************************************************************************/
unsigned char GetTransitionMode(struct hssp_data *d)
{
unsigned char chipProtectionData_Hex;
/* Get the chip protection setting in the HEX file */
HEX_ReadChipProtectionData(&d->inf, &chipProtectionData_Hex);
/* enum variable flow stores the transition (current protection
setting to setting in hex file) of the chip */
flow = WRONG_TRANSITION;
switch (chipProtectionData_Chip) {
/* virgin to open protection setting is the only
allowed transition */
case CHIP_PROT_VIRGIN:
if (chipProtectionData_Hex == CHIP_PROT_OPEN)
flow = VIRGIN_OPEN;
else
flow = WRONG_TRANSITION;
break;
/* All transitions from Open are allowed other than
transition to virgin mode */
case CHIP_PROT_OPEN:
if (chipProtectionData_Hex == CHIP_PROT_VIRGIN)
flow = WRONG_TRANSITION;
else
flow = OPEN_XXX;
break;
/* Protected to Protected and Protected to Open are
the allowed transitions */
case CHIP_PROT_PROTECTED:
if ((chipProtectionData_Hex == CHIP_PROT_OPEN) ||
(chipProtectionData_Hex == CHIP_PROT_PROTECTED))
flow = PROT_XXX;
else
flow = WRONG_TRANSITION;
break;
default:
flow = WRONG_TRANSITION;
break;
}
/* Set TRANSITION_ERROR bit high in Swd_PacketAck to show wrong
transition error */
if (flow == WRONG_TRANSITION) {
swd_PacketAck = swd_PacketAck | TRANSITION_ERROR;
return FAILURE;
}
return SUCCESS;
}
/******************************************************************************
* Function Name: LoadLatch
*******************************************************************************
*
* Summary:
* This function loads the page latch buffer with data to be programmed in to a
* row of flash. Data is loaded into the page latch buffer starting at the
* location specified by the SRAM_PARAMS_BASE input parameter. Data loaded into
* the page latch buffer will remain until a program operation is performed,
* which clears the page latch contents.
*
* Parameters:
* arrayID - Array Number of the flash
* rowData - Array containing 128 bytes of programming data
*
* Return:
* SUCCESS - Returns SUCCESS if Data is successfully latched
* FAILURE - Returns Failure if Data is not latched successfully
*
* Note:
* This function is called in "Step 5. Program Flash" and
* "Step 7. Program Protection Settings" to latch the programming data in SRAM.
*
******************************************************************************/
unsigned char LoadLatch(struct hssp_data *d, unsigned char arrayID,
unsigned char *rowData)
{
unsigned long parameter1 = 0;
unsigned long parameter2 = 0;
unsigned char i = 0;
/* Load parameter1 with the SROM command to load the page latch buffer
with programming data */
parameter1 = ((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)SROM_CMD_LOAD_LATCH) << 8) +
(0x00 << 16) + ((unsigned long)arrayID << 24);
/* Number of Bytes to load minus 1 */
parameter2 = (FLASH_ROW_BYTE_SIZE_HEX_FILE - 1);
/* Write parameter1 in SRAM */
Write_IO(SRAM_PARAMS_BASE + 0x00, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Write parameter2 in SRAM */
Write_IO(SRAM_PARAMS_BASE + 0x04, parameter2);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Put row data into SRAM buffer */
for (i = 0; i < FLASH_ROW_BYTE_SIZE_HEX_FILE; i += 4) {
parameter1 = (rowData[i] << 0) + (rowData[i + 1] << 8) +
(rowData[i + 2] << 16) + (rowData[i + 3] << 24);
/* Write parameter1 in SRAM */
Write_IO(SRAM_PARAMS_BASE + 0x08 + i, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
}
/* Call "Load Latch" SROM API */
/* Set location of parameters */
Write_IO(CPUSS_SYSARG, SRAM_PARAMS_BASE);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request SROM operation */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_LOAD_LATCH);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
return SUCCESS;
}
/******************************************************************************
* Function Name: ChecksumAPI
*******************************************************************************
*
* Summary:
* This function reads either the whole flash memory or a row of flash. When
* performing a checksum on the whole flash, the user code and the supervisory
* flash regions are included. When performing a checksum only on one row of
* flash, the flash row number is passed as a parameter. For computing Checksum
* of entire flash, ChecksumRow input parameter is loaded as macro
* CHECKSUM_ENTIRE_FLASH (0x8000).
*
* Parameters:
* checksumRow: Row number of flash for which checksum has to be calculated.
* To compute checksum of entire flash,
* this variable is set to
* CHECKSUM_ENTIRE_FLASH (0x8000).
*
* checksum: This variable is loaded with the checksum after the execution of
* the function.
*
* Return:
* SUCCESS - Returns SUCCESS if Checksum System call is successfully executed.
* FAILURE - Returns Failure if Checksum system call fails to execute.
*
* Note:
* This function is called in "Step 4. Checksum Privileged Calculation" and
* "Step 9. Verify Checksum" to calculate the checksum of flash privileged rows
* and entire flash, respectively.
*
******************************************************************************/
unsigned char ChecksumAPI(struct hssp_data *d, unsigned short checksumRow,
unsigned long *checksum)
{
unsigned long parameter1 = 0;
unsigned long checksum_chip = 0;
/* Load parameter1 with the SROM command to compute checksum of whole
flash */
parameter1 = ((unsigned long)SROM_KEY1 << 00) +
(((unsigned long)SROM_KEY2 +
(unsigned long)SROM_CMD_CHECKSUM) << 8) +
(((unsigned long)checksumRow & 0x000000FF) << 16) +
(((unsigned long)checksumRow & 0x0000FF00) << 16);
/* Load CPUSS_SYSARG register with parameter1 command */
Write_IO(CPUSS_SYSARG, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request SROM operation */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_CHECKSUM);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
/* Read CPUSS_SYSARG register to get the checksum value */
Read_IO(CPUSS_SYSARG, &checksum_chip);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* 28-bit checksum */
*checksum = (checksum_chip & 0x0FFFFFFF);
return SUCCESS;
}
/******************************************************************************
*Function Name: DeviceAcquire
*******************************************************************************
*
* Summary:
* Acquire device with a alternate method which don't require >1.5Mhz SWD clock rate
*
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if the device is successfully acquired.
* FAILURE - Returns Failure if the function fails in any of the intermediate
* step.
*
* Note:
* This function has very strict timing requirements. The device must be
* acquired as per the timing requirements given in PSoC 4 Device Programming
* Specification Document.
*
******************************************************************************/
#define DEVICE_ACQUIRE_TIMEOUT_ALTERNATE_METHOD 400
unsigned char DeviceAcquire(void)
{
unsigned long chip_DAP_Id = 0;
unsigned short total_packet_count = 0;
unsigned long status = 0;
unsigned long reset_address = 0;
unsigned long psr_reg_val = 0;
unsigned long params = 0;
int i = 1;
SetXresCmosOutput();
SetXresHigh();
SetSwdckCmosOutput();
SetSwdckLow();
SetSwdioCmosOutput();
SetSwdioLow();
SetXresLow();
DelayHundredUs();
SetXresHigh();
/* Execute SWD connect sequence.
100 ms time out below is worst case time out value */
do {
Swd_LineReset();
Read_DAP(DPACC_DP_IDCODE_READ, &chip_DAP_Id);
total_packet_count++;
} while ((swd_PacketAck != SWD_OK_ACK) &&
(total_packet_count < DEVICE_ACQUIRE_TIMEOUT_ALTERNATE_METHOD));
/* Set PORT_ACQUIRE_TIMEOUT_ERROR bit in swd_PacketAck if time
exceeds 100 ms */
if (total_packet_count == DEVICE_ACQUIRE_TIMEOUT_ALTERNATE_METHOD) {
swd_PacketAck = swd_PacketAck | PORT_ACQUIRE_TIMEOUT_ERROR;
return FAILURE;
}
/* Set VERIFICATION_ERROR bit in swd_PacketAck if the DAP_ID read
from chip does not match with the ARM CM0_DAP_ID (MACRO defined in
ProgrammingSteps.h file - 0x0BB11477) */
if ((chip_DAP_Id != CM0_DAP_ID) && (chip_DAP_Id != CM0PLUS_DAP_ID)) {
swd_PacketAck = swd_PacketAck | VERIFICATION_ERROR;
return FAILURE;
}
/* Clear WDATAERR if any previous firmware upgrade operation was aborted in the mddle
and WDATAERR bit is set. This write is to the AP_ABORT register in Debug Port
(APnDP bit - 0, Address is 2'b00, Access -W for the AP ABORT register */
Write_DAP(DPACC_DP_ABORT_WRITE, 0x00000008);
/* Set the CSYSPWRUPEQ(System power up request), CDBGPRWUPREQ(debug power up request),
CDBGRSTREQ(Debug reset request) bits in the DP_CTRLSTAT regsiter) */
Write_DAP(DPACC_DP_CTRLSTAT_WRITE, 0x54000000);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Set the AP register bank selection */
Write_DAP(DPACC_DP_SELECT_WRITE, 0x00000000);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* set the register access as word 4-byte access
For device with CM0+ CPU, the HPROT[1] bit also needs to be set along with few other bits field */
if (chip_DAP_Id == CM0PLUS_DAP_ID) {
Write_DAP(DPACC_AP_CSW_WRITE, 0x03000042);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
}
/* Enable debug, and halt the CPU */
Write_IO(0xE000EDF0, 0xA05F0003);
/* Verify the debug enable, cpu halt bits are set */
Read_IO(0xE000EDF0, &status);
if ((status & 0x00000003) != 0x00000003)
return FAILURE;
/* Enable Breakpoint unit */
Write_IO(0xE0002000, 0x00000003);
/* Get address at reset vector */
Read_IO(0x00000004, &reset_address);
/* Map the address bits to the breakpoint compare register bit map,
Set the enable breakpoint bit, and the match bits */
reset_address = (reset_address & 0x1FFFFFFC) | 0xC0000001;
/* Update the breakpoint compare register */
Write_IO(0xE0002008, reset_address);
/* Issue software reset */
Write_IO(0xE000ED0C, 0x05FA0004);
/* Sufficient delay after reset for boot process, 5ms */
while (i <= 50) {
DelayHundredUs();
i++;
}
/* Repeat a portion of the acquire sequence again */
do {
Swd_LineReset();
Read_DAP(DPACC_DP_IDCODE_READ, &chip_DAP_Id);
total_packet_count++;
} while ((swd_PacketAck != SWD_OK_ACK) &&
(total_packet_count < DEVICE_ACQUIRE_TIMEOUT_ALTERNATE_METHOD));
/* Set PORT_ACQUIRE_TIMEOUT_ERROR bit in swd_PacketAck if time
exceeds 100 ms */
if (total_packet_count == DEVICE_ACQUIRE_TIMEOUT_ALTERNATE_METHOD) {
swd_PacketAck = swd_PacketAck | PORT_ACQUIRE_TIMEOUT_ERROR;
return FAILURE;
}
/* Set VERIFICATION_ERROR bit in swd_PacketAck if the DAP_ID read
from chip does not match with the ARM CM0_DAP_ID (MACRO defined in
ProgrammingSteps.h file - 0x0BB11477) */
if ((chip_DAP_Id != CM0_DAP_ID) && (chip_DAP_Id != CM0PLUS_DAP_ID)) {
swd_PacketAck = swd_PacketAck | VERIFICATION_ERROR;
return FAILURE;
}
/* Set the CSYSPWRUPEQ(System power up request), CDBGPRWUPREQ(debug power up request),
CDBGRSTREQ(Debug reset request) bits in the DP_CTRLSTAT regsiter) */
Write_DAP(DPACC_DP_CTRLSTAT_WRITE, 0x54000000);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Set the AP register bank selection */
Write_DAP(DPACC_DP_SELECT_WRITE, 0x00000000);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* set the register access as word 4-byte access
For device with CM0+ CPU, the HPROT[1] bit also needs to be set along with few other bits field */
if (chip_DAP_Id == CM0PLUS_DAP_ID) {
Write_DAP(DPACC_AP_CSW_WRITE, 0x03000042);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
}
/* Verify the debug enable, cpu halt bits are set */
Read_IO(0xE000EDF0, &status);
if ((status & 0x00000003) != 0x00000003)
return FAILURE;
/* Load infinite for loop code in SRAM address 0x20000300 */
Write_IO(0x20000300, 0xE7FEE7FE);
/* Load PC with address of infinite for loop SRAM address with thumb it(bit 0) set */
Write_IO(0xE000EDF8, 0x20000301);
Write_IO(0xE000EDF4, 0x0001000F);
/* Load SP with top of the SRAM address - set for mimimum SRAM size device(2KB size) */
Write_IO(0xE000EDF8, 0x20000800);
Write_IO(0xE000EDF4, 0x00010011);
/* Read xPSR regsiter, set the thumb bit, and store modified value to xPSR regsiter */
Write_IO(0xE000EDF4, 0x00000010);
Read_IO(0xE000EDF8, &psr_reg_val);
psr_reg_val = psr_reg_val | 0x01000000;
Write_IO(0xE000EDF8, psr_reg_val);
Write_IO(0xE000EDF4, 0x00010010);
/* Disable breakpoint unit */
Write_IO(0xE0002000, 0x00000002);
/* Unhalt CPU */
Write_IO(0xE000EDF0, 0xA05F0001);
/* The following SROM call to set IMO to 48MHZ must be skipped for PSOC 4100M, 4200M devices
Set "IMO=48MHZ" to enable Erase/Program/Write Flash operations. */
params = ((unsigned long)SROM_KEY1 << 0) + (((unsigned long)SROM_KEY2 + (unsigned long)SROM_CMD_SET_IMO_48MHZ) << 8);
/* Write Params in CPUSS_SYSARG */
Write_IO(CPUSS_SYSARG, params);
/* Request SROM call */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_SET_IMO_48MHZ);
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
return SUCCESS;
}
/******************************************************************************
* Function Name: VerifySiliconId
*******************************************************************************
*
* Summary:
* This is Step 2 of the programming sequence. In this Step, Silicon Id of the
* PSoC 4 device is read and matched with the silicon id stored in the Hex File
* to verify that the correct device is being programmed.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if Silicon Id read from chip matches the Id in the
* HEX File.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char VerifySiliconId(struct hssp_data *d)
{
unsigned char i;
unsigned long deviceSiliconID;
unsigned long hexSiliconId = 0;
unsigned long parameter1 = 0;
unsigned long siliconIdData1 = 0;
unsigned long siliconIdData2 = 0;
/* Read and store Silicon ID from HEX file to hexSiliconId array */
HEX_ReadSiliconId(&d->inf, &hexSiliconId);
/* Load Parameter1 with the SROM command to read silicon ID from
PSoC 4 chip */
parameter1 = (unsigned long)(((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)SROM_CMD_GET_SILICON_ID)
<< 8));
/* Load CPUSS_SYSARG register with parameter1 */
Write_IO(CPUSS_SYSARG, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request SROM operation */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_GET_SILICON_ID);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
/* Read CPUSS_SYSARG and CPUSS_SYSREQ to read 4 bytes of silicon ID */
Read_IO(CPUSS_SYSARG, &siliconIdData1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
Read_IO(CPUSS_SYSREQ, &siliconIdData2);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/*
SiliconIdData2 (0th byte) = 4th byte of Device Silicon ID (MSB)
SiliconIdData1 (3rd byte) = 3rd byte of Device Silicon ID
SiliconIdData1 (1st byte) = 2nd byte of Device Silicon ID
SiliconIdData1 (2nd byte) = 1st byte of Device Silicon ID (LSB)
*/
deviceSiliconID = (((siliconIdData2 << 24) & 0xFF000000) +
(siliconIdData1 & 0x00FF0000) +
((siliconIdData1 << 8) & 0x0000FF00) +
((siliconIdData1 >> 8) & 0x000000FF));
/* Match the Silicon ID read from HEX file and PSoC 4 chip */
for (i = 0; i < SILICON_ID_BYTE_LENGTH; i++) {
if ((deviceSiliconID & 0xFF00FFFF) !=
(hexSiliconId & 0xFF00FFFF)) {
/* Set the VERIFICATION_ERROR bit in swd_PacketAck */
swd_PacketAck = swd_PacketAck | VERIFICATION_ERROR;
return FAILURE;
}
}
return SUCCESS;
}
/******************************************************************************
* Function Name: EraseAllFlash
*******************************************************************************
*
* Summary:
* This is Step 3 of the programming sequence. In this Step, the whole user
* flash is erased. This function uses GetChipProtectionVal() and
* GetTransitionMode() API's to take the decision on the method to follow to
* erase the device.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully erases complete user
* flash region.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char EraseAllFlash(struct hssp_data *d)
{
unsigned long parameter1 = 0;
/* Get current chip protection setting */
GetChipProtectionVal(d);
/* Check if the Chip protection setting transition is valid */
result = GetTransitionMode(d);
if (result != SUCCESS)
return FAILURE;
/* If the transition is from open to any protection setting or from
virgin to open, call ERASE_ALL SROM command */
if ((flow == OPEN_XXX) || (flow == VIRGIN_OPEN)) {
parameter1 = (unsigned long)(((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)
SROM_CMD_ERASE_ALL) << 8));
/* Load ERASE_ALL SROM command in parameter1 to SRAM */
Write_IO(SRAM_PARAMS_BASE + 0x00, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Set location of parameters */
Write_IO(CPUSS_SYSARG, SRAM_PARAMS_BASE);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request SROM call */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_ERASE_ALL);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
} else if (flow == PROT_XXX) {
/* If the transition is from protected mode to open mode or
protected mode to protected mode only,
call ERASE_ALL SROM command */
/* Move chip to open state: 0x01 corresponds to open state,
0x00 to macro 1 */
parameter1 = ((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)SROM_CMD_WRITE_PROTECTION) << 8) +
(0x01 << 16) + (0x00 << 24);
/* Load the write protection command to SRAM */
Write_IO(CPUSS_SYSARG, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request SROM call */
Write_IO(CPUSS_SYSREQ,
SROM_SYSREQ_BIT | SROM_CMD_WRITE_PROTECTION);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
/* Re-acquire chip in OPEN mode */
result = DeviceAcquire();
if (result != SUCCESS)
return FAILURE;
}
return SUCCESS;
}
/******************************************************************************
* Function Name: ChecksumPrivileged
*******************************************************************************
*
* Summary:
* This is Step 4 of the programming sequence. In this Step, checksum of the
* privileged rows is calulated using system call to determine checksum. This
* step uses ChecksumAPI() API to store the checksum of privileged rows in a
* Checksum_Privileged global variable. This variable is used in step 9 to
* calculate the checksum of user rows.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully calculated the checksum
* of privileged rows.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char ChecksumPrivileged(struct hssp_data *d)
{
result = ChecksumAPI(d, CHECKSUM_ENTIRE_FLASH, &checksum_Privileged);
if (result != SUCCESS)
return FAILURE;
return SUCCESS;
}
/******************************************************************************
* Function Name: ProgramFlash
*******************************************************************************
*
* Summary:
* This is Step 5 of the programming sequence. In this Step, the whole user
* flash is re-programmed with the programming data in the HEX File. This
* function uses LoadLatch() API to latch the row data in SRAM page latch buffer
* which is then programmed to the specific row using system calls to program
* row.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully programs entire flash
* region.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char ProgramFlash(struct hssp_data *d)
{
unsigned char arrayID = 0;
unsigned char rowData[FLASH_ROW_BYTE_SIZE_HEX_FILE];
unsigned short numOfFlashRows = 0;
unsigned short rowCount = 0;
unsigned long parameter1 = 0;
/* Get the total number of flash rows in the Target PSoC 4 device */
numOfFlashRows = GetFlashRowCount();
/* Program all flash rows */
for (rowCount = 0; rowCount < numOfFlashRows; rowCount++) {
HEX_ReadRowData(&d->inf, rowCount, &rowData[0]);
arrayID = rowCount / ROWS_PER_ARRAY;
result = LoadLatch(d, arrayID, &rowData[0]);
if (result != SUCCESS)
return FAILURE;
/* Load parameter1 with Program Row - SROM command */
parameter1 = (unsigned long)(((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)
SROM_CMD_PROGRAM_ROW) << 8) +
(((unsigned long)rowCount &
0x000000FF) << 16) +
(((unsigned long)rowCount &
0x0000FF00) << 16));
/* Write parameters in SRAM */
Write_IO(SRAM_PARAMS_BASE + 0x00, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Set location of parameters */
Write_IO(CPUSS_SYSARG, SRAM_PARAMS_BASE);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request SROM operation */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_PROGRAM_ROW);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
}
return SUCCESS;
}
/******************************************************************************
* Function Name: VerifySwRevision
*******************************************************************************
*
* Summary:
* This is a way to check Sw revision stored in flash at SW_REVISION_OFFSET.
* This is a preliminary step to avoid reflashing with the same SW revision.
* The checksum verification may not work because the checksun is changed is
* a configuration is stored in the flash. In this Step, flash region is
* directly read using Read_IO API defined in SWD_UpperPacketLayer.h and
* compared with the HEX File.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully verifies the software
* revision with the HEX File.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char VerifySwRevision(struct hssp_data *d)
{
unsigned long flashData = 0;
unsigned short row;
unsigned short offset;
unsigned short HexSwRev;
unsigned short ChipSwRev;
unsigned char rowData[FLASH_ROW_BYTE_SIZE_HEX_FILE];
/* Get the Sw rev row in the Target PSoC 4 device */
row = SW_REVISION_OFFSET / FLASH_ROW_BYTE_SIZE_HEX_FILE;
offset = SW_REVISION_OFFSET % FLASH_ROW_BYTE_SIZE_HEX_FILE;
/* Extract row from the hex-file */
HEX_ReadRowData(&d->inf, row, &rowData[0]);
HexSwRev = (rowData[offset + 1]<<8) | rowData[offset];
/* Read flash via AHB-interface */
Read_IO(SW_REVISION_OFFSET, &flashData);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
ChipSwRev = ((flashData >> (offset % 4)*8)) & 0x00FF;
ChipSwRev |= ((flashData >> (offset % 4 + 1) * 8) << 8) & 0xFF00;
d->sw_rev = HexSwRev;
pr_info("cycapsense_hssp: File SW rev 0x%x, Flash SW rev 0x%x\n",
HexSwRev, ChipSwRev);
if (HexSwRev != ChipSwRev) {
swd_PacketAck = swd_PacketAck|VERIFICATION_ERROR;
return FAILURE;
}
return SUCCESS;
}
/******************************************************************************
* Function Name: VerifyFlash
*******************************************************************************
*
* Summary:
* This is Step 6 of the programming sequence. This is an optional step as we
* verify the checksum explicitly. In this Step, flash region is directly read
* using Read_IO API defined in SWD_UpperPacketLayer.h and compared with the
* HEX File.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully verifies the entire flash
* with the HEX File.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char VerifyFlash(struct hssp_data *d)
{
unsigned long flashData = 0;
unsigned short numOfFlashRows = 0;
unsigned short rowAddress = 0;
unsigned short rowCount;
unsigned char i;
unsigned char rowData[FLASH_ROW_BYTE_SIZE_HEX_FILE];
unsigned char chipData[FLASH_ROW_BYTE_SIZE_HEX_FILE];
/* Get the total number of flash rows in the Target PSoC 4 device */
numOfFlashRows = GetFlashRowCount();
/* Read and Verify Flash rows */
for (rowCount = 0; rowCount < numOfFlashRows; rowCount++) {
/* Read row from hex file */
/* linear address of row in flash */
rowAddress = FLASH_ROW_BYTE_SIZE_HEX_FILE * rowCount;
/* Extract 128-byte row from the hex-file from address:
"rowCount" into buffer - "rowData". */
HEX_ReadRowData(&d->inf, rowCount, &rowData[0]);
/* Read row from chip */
for (i = 0; i < FLASH_ROW_BYTE_SIZE_HEX_FILE; i += 4) {
/* Read flash via AHB-interface */
Read_IO(rowAddress + i, &flashData);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
chipData[i + 0] = (flashData >> 0) & 0xFF;
chipData[i + 1] = (flashData >> 8) & 0xFF;
chipData[i + 2] = (flashData >> 16) & 0xFF;
chipData[i + 3] = (flashData >> 24) & 0xFF;
}
/* Compare the row data of HEX file with chip data */
for (i = 0; i < FLASH_ROW_BYTE_SIZE_HEX_FILE; i++) {
if (chipData[i] != rowData[i]) {
swd_PacketAck = swd_PacketAck |
VERIFICATION_ERROR;
return FAILURE;
}
}
}
return SUCCESS;
}
/******************************************************************************
* Function Name: ProgramProtectionSettings
*******************************************************************************
*
* Summary:
* This is Step 7 of the programming sequence. In this step, Chip protection
* settings and Row Protection settings are read from the HEX file and
* programmed to the specific loctions in the flash.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully writes the protection
* settings.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char ProgramProtectionSettings(struct hssp_data *d)
{
unsigned char arrayID = 0;
unsigned char rowProtectionByteSize = 0;
unsigned char rowProtectionData[MAXIMUM_ROW_PROTECTION_BYTE_LENGTH];
unsigned char chipProtectionData_Hex;
unsigned short numOfFlashRows = 0;
unsigned long parameter1 = 0;
/* Get total number of flash rows to determine the size of
row protection data and arrayID */
numOfFlashRows = GetFlashRowCount();
rowProtectionByteSize = numOfFlashRows / 8;
arrayID = numOfFlashRows / ROWS_PER_ARRAY;
HEX_ReadChipProtectionData(&d->inf, &chipProtectionData_Hex);
HEX_ReadRowProtectionData(&d->inf, rowProtectionByteSize,
&rowProtectionData[0]);
/* Load protection setting of current macro into volatile latch using
LoadLatch API */
result = LoadLatch(d, arrayID, &rowProtectionData[0]);
if (result != SUCCESS)
return FAILURE;
/* Program protection setting into supervisory row */
parameter1 = (unsigned long)(((unsigned long)SROM_KEY1 << 0) +
(((unsigned long)SROM_KEY2 +
(unsigned long)SROM_CMD_WRITE_PROTECTION)
<< 8) +
((unsigned long)chipProtectionData_Hex <<
16));
/* Load parameter1 in CPUSS_SYSARG register */
Write_IO(CPUSS_SYSARG, parameter1);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Request SROM call */
Write_IO(CPUSS_SYSREQ, SROM_SYSREQ_BIT | SROM_CMD_WRITE_PROTECTION);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
/* Read status of the operation */
result = PollSromStatus();
if (result != SUCCESS)
return FAILURE;
return SUCCESS;
}
/******************************************************************************
* Function Name: VerifyProtectionSettings
*******************************************************************************
*
* Summary:
* This is Step 8 of the programming sequence. In this step, Chip protection
* settings and Row Protection settings are read from the HEX file and verified
* with the protection settings programmed in flash.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully verifies the protection
* settings.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char VerifyProtectionSettings(struct hssp_data *d)
{
unsigned long protectionData = 0;
unsigned long flashProtectionAddress = 0;
unsigned short numOfFlashRows = 0;
unsigned char chipProtectionData_Hex = 0;
unsigned char rowProtectionByteSize = 0;
unsigned char i;
unsigned char rowProtectionData[MAXIMUM_ROW_PROTECTION_BYTE_LENGTH];
unsigned char
rowProtectionFlashData[MAXIMUM_ROW_PROTECTION_BYTE_LENGTH];
numOfFlashRows = GetFlashRowCount();
rowProtectionByteSize = numOfFlashRows / 8;
flashProtectionAddress = SFLASH_MACRO;
/* Read Protection settings from hex-file */
HEX_ReadRowProtectionData(&d->inf, rowProtectionByteSize,
&rowProtectionData[0]);
/* Read Protection settings from silicon */
for (i = 0; i < rowProtectionByteSize; i += 4) {
Read_IO(flashProtectionAddress + i, &protectionData);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
rowProtectionFlashData[i + 0] = (protectionData >> 0) & 0xFF;
rowProtectionFlashData[i + 1] = (protectionData >> 8) & 0xFF;
rowProtectionFlashData[i + 2] = (protectionData >> 16) & 0xFF;
rowProtectionFlashData[i + 3] = (protectionData >> 24) & 0xFF;
}
/* Compare hex and silicon's data */
for (i = 0; i < rowProtectionByteSize; i++) {
if (rowProtectionData[i] != rowProtectionFlashData[i]) {
/* Set the verification error bit for Flash
protection data mismatch and return failure */
swd_PacketAck = swd_PacketAck | VERIFICATION_ERROR;
return FAILURE;
}
}
/* Read Chip Level Protection from hex-file */
HEX_ReadChipProtectionData(&d->inf, &chipProtectionData_Hex);
/* Read Chip Level Protection from the silicon */
Read_IO(SFLASH_CPUSS_PROTECTION, &protectionData);
if (swd_PacketAck != SWD_OK_ACK)
return FAILURE;
chipProtectionData_Chip = (protectionData >> 24) & 0x0F;
if (chipProtectionData_Chip == CHIP_PROT_VIRGIN)
chipProtectionData_Chip = CHIP_PROT_OPEN;
else if (chipProtectionData_Chip == CHIP_PROT_OPEN)
chipProtectionData_Chip = CHIP_PROT_VIRGIN;
/* Compare hex's and silicon's chip protection data */
if (chipProtectionData_Chip != chipProtectionData_Hex) {
/* Set the verification error bit for Flash protection data
mismatch and return failure */
swd_PacketAck = swd_PacketAck | VERIFICATION_ERROR;
return FAILURE;
}
return SUCCESS;
}
/******************************************************************************
* Function Name: VerifyChecksum
*******************************************************************************
*
* Summary:
* This is Step 9 of the programming sequence. In this step, Checksum of user
* data in flash is verified with the Checksum stored in the HEX File. This step
* uses the Checksum of privileged rows calculated in Step 4 get the checksum
* of user data in flash.
*
* Parameters:
* None
*
* Return:
* SUCCESS - Returns SUCCESS if function successfully verifies the checksum.
* FAILURE - Returns Failure if any of the intermediate step returns a fail
* message.
*
* Note:
*
******************************************************************************/
unsigned char VerifyChecksum(struct hssp_data *d)
{
unsigned long checksum_All = 0;
unsigned short chip_Checksum = 0;
unsigned short checksumData = 0;
/* Read the checksum of entire flash */
result = ChecksumAPI(d, CHECKSUM_ENTIRE_FLASH, &checksum_All);
if (result != SUCCESS)
return FAILURE;
/* Calculate checksum of user flash */
chip_Checksum = (unsigned short)checksum_All -
(unsigned short)checksum_Privileged;
d->chip_cs = chip_Checksum;
/* Read checksum from hex file */
HEX_ReadChecksumData(&d->inf, &checksumData);
/* Compare the checksum data of silicon and hex file */
if (chip_Checksum != checksumData) {
swd_PacketAck = swd_PacketAck | VERIFICATION_ERROR;
return FAILURE;
}
return SUCCESS;
}
/******************************************************************************
* Function Name: ReadHsspErrorStatus
*******************************************************************************
*
* Summary:
* Returns the HSSP Error status in case of FAILURE return in any one of the
* programming steps.
*
* Parameters:
* None.
*
* Return:
* swd_PacketAck - Each bit of this 8-bit return value has a specific meaning.
*
* Note:
* Refer to the application note pdf for details on the Error status bit
* definitions
******************************************************************************/
unsigned char ReadHsspErrorStatus(void)
{
return swd_PacketAck;
}
/******************************************************************************
* Function Name: ExitProgrammingMode
*******************************************************************************
*
* Summary:
* Releases the target PSoC 4 device from Programming mode.
*
* Parameters:
* None.
*
* Return:
* None.
*
* Note:
*
******************************************************************************/
void ExitProgrammingMode(void)
{
/* Drive the SWDIO, SWDCK outputs low */
SetSwdckLow();
SetSwdioLow();
/* Make SWDIO, SWDCK High-Z after completing Programming */
SetSwdioHizInput();
SetSwdckHizInput();
/* Generate active low rest pulse for 100 uS */
SetXresCmosOutput();
SetXresLow();
DelayHundredUs();
SetXresHigh();
}
/* [] END OF FILE */