X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnand%2Fat91sam9.c;h=47c0505630713f523fa142dbe072cab8d1c2abc0;hb=46f077aa003449f95781170fc2d0cf674272ad3e;hp=5cfbb0a38611b9fc20ead51711c3e384f61ad0d8;hpb=b72bfabf0dc697e6445c4ed3dba632b164a006e1;p=openocd.git diff --git a/src/flash/nand/at91sam9.c b/src/flash/nand/at91sam9.c index 5cfbb0a386..47c0505630 100644 --- a/src/flash/nand/at91sam9.c +++ b/src/flash/nand/at91sam9.c @@ -13,10 +13,9 @@ * 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. + * along with this program. If not, see . */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -26,21 +25,18 @@ #include "imp.h" #include "arm_io.h" -#define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */ -#define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */ -#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */ -#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */ -#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */ -#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */ -#define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */ +#define AT91C_PIOx_SODR (0x30) /**< Offset to PIO SODR. */ +#define AT91C_PIOx_CODR (0x34) /**< Offset to PIO CODR. */ +#define AT91C_PIOx_PDSR (0x3C) /**< Offset to PIO PDSR. */ +#define AT91C_ECCx_CR (0x00) /**< Offset to ECC CR. */ +#define AT91C_ECCx_SR (0x08) /**< Offset to ECC SR. */ +#define AT91C_ECCx_PR (0x0C) /**< Offset to ECC PR. */ +#define AT91C_ECCx_NPR (0x10) /**< Offset to ECC NPR. */ /** * Representation of a pin on an AT91SAM9 chip. */ struct at91sam9_pin { - /** Target this pin is on. */ - struct target *target; - /** Address of the PIO controller. */ uint32_t pioc; @@ -52,9 +48,6 @@ struct at91sam9_pin { * Private data for the controller that is stored in the NAND device structure. */ struct at91sam9_nand { - /** Target the NAND is attached to. */ - struct target *target; - /** Address of the ECC controller for NAND. */ uint32_t ecc; @@ -101,12 +94,10 @@ static int at91sam9_halted(struct target *target, const char *label) */ static int at91sam9_init(struct nand_device *nand) { - struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; - if (!at91sam9_halted(target, "init")) { + if (!at91sam9_halted(target, "init")) return ERROR_NAND_OPERATION_FAILED; - } return ERROR_OK; } @@ -117,9 +108,10 @@ static int at91sam9_init(struct nand_device *nand) * @param info NAND controller information for controlling NAND device. * @return Success or failure of the enabling. */ -static int at91sam9_enable(struct at91sam9_nand *info) +static int at91sam9_enable(struct nand_device *nand) { - struct target *target = info->target; + struct at91sam9_nand *info = nand->controller_priv; + struct target *target = nand->target; return target_write_u32(target, info->ce.pioc + AT91C_PIOx_CODR, 1 << info->ce.num); } @@ -130,9 +122,10 @@ static int at91sam9_enable(struct at91sam9_nand *info) * @param info NAND controller information for controlling NAND device. * @return Success or failure of the disabling. */ -static int at91sam9_disable(struct at91sam9_nand *info) +static int at91sam9_disable(struct nand_device *nand) { - struct target *target = info->target; + struct at91sam9_nand *info = nand->controller_priv; + struct target *target = nand->target; return target_write_u32(target, info->ce.pioc + AT91C_PIOx_SODR, 1 << info->ce.num); } @@ -147,13 +140,12 @@ static int at91sam9_disable(struct at91sam9_nand *info) static int at91sam9_command(struct nand_device *nand, uint8_t command) { struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; - if (!at91sam9_halted(target, "command")) { + if (!at91sam9_halted(target, "command")) return ERROR_NAND_OPERATION_FAILED; - } - at91sam9_enable(info); + at91sam9_enable(nand); return target_write_u8(target, info->cmd, command); } @@ -166,13 +158,10 @@ static int at91sam9_command(struct nand_device *nand, uint8_t command) */ static int at91sam9_reset(struct nand_device *nand) { - struct at91sam9_nand *info = nand->controller_priv; - - if (!at91sam9_halted(info->target, "reset")) { + if (!at91sam9_halted(nand->target, "reset")) return ERROR_NAND_OPERATION_FAILED; - } - return at91sam9_disable(info); + return at91sam9_disable(nand); } /** @@ -185,11 +174,10 @@ static int at91sam9_reset(struct nand_device *nand) static int at91sam9_address(struct nand_device *nand, uint8_t address) { struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; - if (!at91sam9_halted(info->target, "address")) { + if (!at91sam9_halted(nand->target, "address")) return ERROR_NAND_OPERATION_FAILED; - } return target_write_u8(target, info->addr, address); } @@ -205,11 +193,10 @@ static int at91sam9_address(struct nand_device *nand, uint8_t address) static int at91sam9_read_data(struct nand_device *nand, void *data) { struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; - if (!at91sam9_halted(info->target, "read data")) { + if (!at91sam9_halted(nand->target, "read data")) return ERROR_NAND_OPERATION_FAILED; - } return target_read_u8(target, info->data, data); } @@ -225,11 +212,10 @@ static int at91sam9_read_data(struct nand_device *nand, void *data) static int at91sam9_write_data(struct nand_device *nand, uint16_t data) { struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; - if (!at91sam9_halted(target, "write data")) { + if (!at91sam9_halted(target, "write data")) return ERROR_NAND_OPERATION_FAILED; - } return target_write_u8(target, info->data, data); } @@ -244,19 +230,17 @@ static int at91sam9_write_data(struct nand_device *nand, uint16_t data) static int at91sam9_nand_ready(struct nand_device *nand, int timeout) { struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; uint32_t status; - if (!at91sam9_halted(target, "nand ready")) { + if (!at91sam9_halted(target, "nand ready")) return 0; - } do { target_read_u32(target, info->busy.pioc + AT91C_PIOx_PDSR, &status); - if (status & (1 << info->busy.num)) { + if (status & (1 << info->busy.num)) return 1; - } alive_sleep(1); } while (timeout-- > 0); @@ -279,9 +263,8 @@ static int at91sam9_read_block_data(struct nand_device *nand, uint8_t *data, int struct arm_nand_data *io = &info->io; int status; - if (!at91sam9_halted(info->target, "read block")) { + if (!at91sam9_halted(nand->target, "read block")) return ERROR_NAND_OPERATION_FAILED; - } io->chunk_size = nand->page_size; status = arm_nandread(io, data, size); @@ -304,9 +287,8 @@ static int at91sam9_write_block_data(struct nand_device *nand, uint8_t *data, in struct arm_nand_data *io = &info->io; int status; - if (!at91sam9_halted(info->target, "write block")) { + if (!at91sam9_halted(nand->target, "write block")) return ERROR_NAND_OPERATION_FAILED; - } io->chunk_size = nand->page_size; status = arm_nandwrite(io, data, size); @@ -328,7 +310,7 @@ static int at91sam9_ecc_init(struct target *target, struct at91sam9_nand *info) return ERROR_NAND_OPERATION_FAILED; } - // reset ECC parity registers + /* reset ECC parity registers */ return target_write_u32(target, info->ecc + AT91C_ECCx_CR, 1); } @@ -342,19 +324,19 @@ static int at91sam9_ecc_init(struct target *target, struct at91sam9_nand *info) * @param size Size of the OOB. * @return Pointer to an area to store OOB data. */ -static uint8_t * at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size) +static uint8_t *at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint32_t *size) { if (!oob) { - // user doesn't want OOB, allocate it - if (nand->page_size == 512) { + /* user doesn't want OOB, allocate it */ + if (nand->page_size == 512) *size = 16; - } else if (nand->page_size == 2048) { + else if (nand->page_size == 2048) *size = 64; - } oob = malloc(*size); if (!oob) { LOG_ERROR("Unable to allocate space for OOB"); + return NULL; } memset(oob, 0xFF, *size); @@ -377,29 +359,26 @@ static uint8_t * at91sam9_oob_init(struct nand_device *nand, uint8_t *oob, uint3 * @return Success or failure of reading the NAND page. */ static int at91sam9_read_page(struct nand_device *nand, uint32_t page, - uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) + uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { int retval; struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; uint8_t *oob_data; uint32_t status; retval = at91sam9_ecc_init(target, info); - if (ERROR_OK != retval) { + if (ERROR_OK != retval) return retval; - } retval = nand_page_command(nand, page, NAND_CMD_READ0, !data); - if (ERROR_OK != retval) { + if (ERROR_OK != retval) return retval; - } if (data) { retval = nand_read_data_page(nand, data, data_size); - if (ERROR_OK != retval) { + if (ERROR_OK != retval) return retval; - } } oob_data = at91sam9_oob_init(nand, oob, &oob_size); @@ -408,33 +387,33 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page, target_read_u32(target, info->ecc + AT91C_ECCx_SR, &status); if (status & 1) { LOG_ERROR("Error detected!"); - if (status & 4) { + if (status & 4) LOG_ERROR("Multiple errors encountered; unrecoverable!"); - } else { - // attempt recovery + else { + /* attempt recovery */ uint32_t parity; target_read_u32(target, - info->ecc + AT91C_ECCx_PR, - &parity); + info->ecc + AT91C_ECCx_PR, + &parity); uint32_t word = (parity & 0x0000FFF0) >> 4; uint32_t bit = parity & 0x0F; data[word] ^= (0x1) << bit; LOG_INFO("Data word %d, bit %d corrected.", - (unsigned) word, - (unsigned) bit); + (unsigned) word, + (unsigned) bit); } } if (status & 2) { - // we could write back correct ECC data + /* we could write back correct ECC data */ LOG_ERROR("Error in ECC bytes detected"); } } if (!oob) { - // if it wasn't asked for, free it + /* if it wasn't asked for, free it */ free(oob_data); } @@ -455,23 +434,21 @@ static int at91sam9_read_page(struct nand_device *nand, uint32_t page, * @return Success or failure of the page write. */ static int at91sam9_write_page(struct nand_device *nand, uint32_t page, - uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) + uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { struct at91sam9_nand *info = nand->controller_priv; - struct target *target = info->target; + struct target *target = nand->target; int retval; uint8_t *oob_data = oob; uint32_t parity, nparity; retval = at91sam9_ecc_init(target, info); - if (ERROR_OK != retval) { + if (ERROR_OK != retval) return retval; - } retval = nand_page_command(nand, page, NAND_CMD_SEQIN, !data); - if (ERROR_OK != retval) { + if (ERROR_OK != retval) return retval; - } if (data) { retval = nand_write_data_page(nand, data, data_size); @@ -484,7 +461,7 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page, oob_data = at91sam9_oob_init(nand, oob, &oob_size); if (!oob) { - // no OOB given, so read in the ECC parity from the ECC controller + /* no OOB given, so read in the ECC parity from the ECC controller */ target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity); target_read_u32(target, info->ecc + AT91C_ECCx_NPR, &nparity); @@ -496,9 +473,8 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page, retval = nand_write_data_page(nand, oob_data, oob_size); - if (!oob) { + if (!oob) free(oob_data); - } if (ERROR_OK != retval) { LOG_ERROR("Unable to write OOB data to NAND"); @@ -517,23 +493,16 @@ static int at91sam9_write_page(struct nand_device *nand, uint32_t page, */ NAND_DEVICE_COMMAND_HANDLER(at91sam9_nand_device_command) { - struct target *target = NULL; unsigned long chip = 0, ecc = 0; struct at91sam9_nand *info = NULL; - LOG_DEBUG("AT91SAM9 NAND Device Command\n"); + LOG_DEBUG("AT91SAM9 NAND Device Command"); if (CMD_ARGC < 3 || CMD_ARGC > 4) { LOG_ERROR("parameters: %s target chip_addr", CMD_ARGV[0]); return ERROR_NAND_OPERATION_FAILED; } - target = get_target(CMD_ARGV[1]); - if (!target) { - LOG_ERROR("invalid target: %s", CMD_ARGV[1]); - return ERROR_NAND_OPERATION_FAILED; - } - COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], chip); if (chip == 0) { LOG_ERROR("invalid NAND chip address: %s", CMD_ARGV[2]); @@ -554,14 +523,13 @@ NAND_DEVICE_COMMAND_HANDLER(at91sam9_nand_device_command) return ERROR_NAND_OPERATION_FAILED; } - info->target = target; info->data = chip; info->cmd = chip | (1 << 22); info->addr = chip | (1 << 21); info->ecc = ecc; nand->controller_priv = info; - info->io.target = target; + info->io.target = nand->target; info->io.data = info->data; info->io.op = ARM_NAND_NONE; @@ -579,14 +547,14 @@ COMMAND_HANDLER(handle_at91sam9_cle_command) unsigned num, address_line; if (CMD_ARGC != 2) { - command_print(CMD_CTX, "incorrect number of arguments for 'at91sam9 cle' command"); + command_print(CMD, "incorrect number of arguments for 'at91sam9 cle' command"); return ERROR_OK; } COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { - command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); + command_print(CMD, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_OK; } @@ -608,14 +576,13 @@ COMMAND_HANDLER(handle_at91sam9_ale_command) struct at91sam9_nand *info = NULL; unsigned num, address_line; - if (CMD_ARGC != 2) { + if (CMD_ARGC != 2) return ERROR_COMMAND_SYNTAX_ERROR; - } COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { - command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); + command_print(CMD, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -637,14 +604,13 @@ COMMAND_HANDLER(handle_at91sam9_rdy_busy_command) struct at91sam9_nand *info = NULL; unsigned num, base_pioc, pin_num; - if (CMD_ARGC != 3) { + if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; - } COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { - command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); + command_print(CMD, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -669,14 +635,13 @@ COMMAND_HANDLER(handle_at91sam9_ce_command) struct at91sam9_nand *info = NULL; unsigned num, base_pioc, pin_num; - if (CMD_ARGC != 3) { + if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; - } COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); nand = get_nand_device_by_num(num); if (!nand) { - command_print(CMD_CTX, "invalid nand device number: %s", CMD_ARGV[0]); + command_print(CMD, "invalid nand device number: %s", CMD_ARGV[0]); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -697,28 +662,30 @@ static const struct command_registration at91sam9_sub_command_handlers[] = { .handler = handle_at91sam9_cle_command, .mode = COMMAND_CONFIG, .help = "set command latch enable address line (default is 22)", - .usage = " ", + .usage = "bank_id address_line", }, { .name = "ale", .handler = handle_at91sam9_ale_command, .mode = COMMAND_CONFIG, .help = "set address latch enable address line (default is 21)", - .usage = " ", + .usage = "bank_id address_line", }, { .name = "rdy_busy", .handler = handle_at91sam9_rdy_busy_command, .mode = COMMAND_CONFIG, - .help = "set the input pin connected to RDY/~BUSY signal (no default)", - .usage = " ", + .help = "set the GPIO input pin connected to " + "the RDY/~BUSY signal (no default)", + .usage = "bank_id pio_base_addr pin_num", }, { .name = "ce", .handler = handle_at91sam9_ce_command, .mode = COMMAND_CONFIG, - .help = "set the output pin connected to chip enable signal (no default)", - .usage = " ", + .help = "set the GPIO output pin connected to " + "the chip enable signal (no default)", + .usage = "bank_id pio_base_addr pin_num", }, COMMAND_REGISTRATION_DONE }; @@ -728,6 +695,7 @@ static const struct command_registration at91sam9_command_handler[] = { .name = "at91sam9", .mode = COMMAND_ANY, .help = "AT91SAM9 NAND flash controller commands", + .usage = "", .chain = at91sam9_sub_command_handlers, }, COMMAND_REGISTRATION_DONE