X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fat91sam7.c;h=7b9fb659955001fe303941c96d2925cb936caf3f;hp=59ed2aa08a9afa6bf46c7048430b80beb38c3b78;hb=972ca49d3a5e285492e4c1680289f819f26eaec3;hpb=82d2633b5f550115e9e7c7d0520babb6680aa38f diff --git a/src/flash/at91sam7.c b/src/flash/at91sam7.c index 59ed2aa08a..7b9fb65995 100644 --- a/src/flash/at91sam7.c +++ b/src/flash/at91sam7.c @@ -63,7 +63,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size); u32 at91sam7_get_flash_status(flash_bank_t *bank); void at91sam7_set_flash_mode(flash_bank_t *bank,int mode); -u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout); +u32 at91sam7_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout); int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); flash_driver_t at91sam7_flash = @@ -133,9 +133,9 @@ u32 at91sam7_get_flash_status(flash_bank_t *bank) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; target_t *target = at91sam7_info->target; - long fsr; + u32 fsr; - target->type->read_memory(target, MC_FSR, 4, 1, (u8 *)&fsr); + target_read_u32(target, MC_FSR, &fsr); return fsr; } @@ -145,19 +145,15 @@ void at91sam7_read_clock_info(flash_bank_t *bank) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; target_t *target = at91sam7_info->target; - unsigned long mckr, mcfr, pllr, tmp, status, mainfreq; - unsigned int css, pres, mul, div; + u32 mckr, mcfr, pllr; + unsigned long tmp = 0, mainfreq; /* Read main clock freqency register */ - target->type->read_memory(target, CKGR_MCFR, 4, 1, (u8 *)&mcfr); + target_read_u32(target, CKGR_MCFR, &mcfr); /* Read master clock register */ - target->type->read_memory(target, PMC_MCKR, 4, 1, (u8 *)&mckr); + target_read_u32(target, PMC_MCKR, &mckr); /* Read Clock Generator PLL Register */ - target->type->read_memory(target, CKGR_PLLR, 4, 1, (u8 *)&pllr); - - pres = (mckr>>2)&0x7; - mul = (pllr>>16)&0x7FF; - div = pllr&0xFF; + target_read_u32(target, CKGR_PLLR, &pllr); at91sam7_info->mck_valid = 0; switch (mckr & PMC_MCKR_CSS) { @@ -179,10 +175,9 @@ void at91sam7_read_clock_info(flash_bank_t *bank) case 3: /* PLL Clock */ if (mcfr & CKGR_MCFR_MAINRDY) { - target->type->read_memory(target, CKGR_PLLR, 4, 1, - (u8 *)&pllr); + target_read_u32(target, CKGR_PLLR, &pllr); if (!(pllr & CKGR_PLLR_DIV)) - break; /* 0 Hz */ + break; /* 0 Hz */ at91sam7_info->mck_valid = 1; mainfreq = RC_FREQ / 16ul * (mcfr & 0xffff); /* Integer arithmetic should have sufficient precision @@ -200,41 +195,56 @@ void at91sam7_read_clock_info(flash_bank_t *bank) at91sam7_info->mck_freq = tmp >> ((mckr & PMC_MCKR_PRES) >> 2); /* Forget old flash timing */ - at91sam7_set_flash_mode(bank,0); + at91sam7_set_flash_mode(bank,FMR_TIMING_NONE); } /* Setup the timimg registers for nvbits or normal flash */ void at91sam7_set_flash_mode(flash_bank_t *bank,int mode) { - u32 fmcn, fmr; + u32 fmr, fmcn = 0, fws = 0; at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; target_t *target = at91sam7_info->target; - if (mode && (mode != at91sam7_info->flashmode)) { + if (mode && (mode != at91sam7_info->flashmode)) + { /* Always round up (ceil) */ - if (mode==1) - /* main clocks in 1uS */ - fmcn = (at91sam7_info->mck_freq/1000000ul)+1; - else if (mode==2) + if (mode==FMR_TIMING_NVBITS) + { + if (at91sam7_info->cidr_arch == 0x60) + { + /* AT91SAM7A3 uses master clocks in 100 ns */ + fmcn = (at91sam7_info->mck_freq/10000000ul)+1; + } + else + { + /* master clocks in 1uS for ARCH 0x7 types */ + fmcn = (at91sam7_info->mck_freq/1000000ul)+1; + } + } + else if (mode==FMR_TIMING_FLASH) /* main clocks in 1.5uS */ fmcn = (at91sam7_info->mck_freq/666666ul)+1; - /* Only allow fmcn=0 if clock period is > 30 us. */ - if (at91sam7_info->mck_freq <= 33333) + /* Only allow fmcn=0 if clock period is > 30 us = 33kHz. */ + if (at91sam7_info->mck_freq <= 33333ul) fmcn = 0; + /* Only allow fws=0 if clock frequency is < 30 MHz. */ + if (at91sam7_info->mck_freq > 30000000ul) + fws = 1; DEBUG("fmcn: %i", fmcn); - fmr = fmcn<<16; - target->type->write_memory(target, MC_FSR, 4, 1, (u8 *)&fmr); + fmr = fmcn << 16 | fws << 8; + target_write_u32(target, MC_FMR, fmr); } + at91sam7_info->flashmode = mode; } -u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout) +u32 at91sam7_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout) { u32 status; - while ((!((status = at91sam7_get_flash_status(bank)) & 0x01)) && (timeout-- > 0)) + while ((!((status = at91sam7_get_flash_status(bank)) & waitbits)) && (timeout-- > 0)) { DEBUG("status: 0x%x", status); usleep(1000); @@ -242,7 +252,7 @@ u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout) DEBUG("status: 0x%x", status); - if (status&0x0C) + if (status & 0x0C) { ERROR("status register: 0x%x", status); if (status & 0x4) @@ -256,6 +266,7 @@ u8 at91sam7_wait_status_busy(flash_bank_t *bank, int timeout) return status; } + /* Send one command to the AT91SAM flash controller */ int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) { @@ -264,11 +275,21 @@ int at91sam7_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) target_t *target = at91sam7_info->target; fcr = (0x5A<<24) | (pagen<<8) | cmd; - target->type->write_memory(target, MC_FCR, 4, 1, (u8 *)&fcr); - DEBUG("Flash command: 0x%x, pagenumber:", fcr, pagen); + target_write_u32(target, MC_FCR, fcr); + DEBUG("Flash command: 0x%x, pagenumber:%u", fcr, pagen); - if (at91sam7_wait_status_busy(bank, 10)&0x0C) + if ((at91sam7_info->cidr_arch == 0x60)&&((cmd==SLB)|(cmd==CLB))) { + /* Lock bit manipulation on AT91SAM7A3 waits for FC_FSR bit 1, EOL */ + if (at91sam7_wait_status_busy(bank, MC_FSR_EOL, 10)&0x0C) + { + return ERROR_FLASH_OPERATION_FAILED; + } + return ERROR_OK; + } + + if (at91sam7_wait_status_busy(bank, MC_FSR_FRDY, 10)&0x0C) + { return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; @@ -279,7 +300,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; target_t *target = at91sam7_info->target; - unsigned long cidr, mcfr, status; + u32 cidr, status; if (at91sam7_info->target->state != TARGET_HALTED) { @@ -287,7 +308,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) } /* Read and parse chip identification register */ - target->type->read_memory(target, DBGU_CIDR, 4, 1, (u8 *)&cidr); + target_read_u32(target, DBGU_CIDR, &cidr); if (cidr == 0) { @@ -307,7 +328,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) bank->size = NVPSIZ[at91sam7_info->cidr_nvpsiz]; at91sam7_info->target_name = "Unknown"; - DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch ); + DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch ); /* Read main and master clock freqency register */ at91sam7_read_clock_info(bank); @@ -360,8 +381,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) if (at91sam7_info->cidr_arch == 0x71 ) { - at91sam7_info->num_nvmbits = 2; - at91sam7_info->nvmbits = (status>>8)&0x03; + at91sam7_info->num_nvmbits = 3; + at91sam7_info->nvmbits = (status>>8)&0x07; bank->base = 0x100000; bank->bus_width = 4; if (bank->size==0x40000) /* AT91SAM7XC256 */ @@ -384,6 +405,40 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) return ERROR_OK; } + if (at91sam7_info->cidr_arch == 0x72 ) + { + at91sam7_info->num_nvmbits = 2; + at91sam7_info->nvmbits = (status>>8)&0x03; + bank->base = 0x100000; + bank->bus_width = 4; + if (bank->size==0x80000) /* AT91SAM7SE512 */ + { + at91sam7_info->target_name = "AT91SAM7SE512"; + at91sam7_info->num_lockbits = 32; + at91sam7_info->pagesize = 256; + at91sam7_info->pages_in_lockregion = 64; + at91sam7_info->num_pages = 32*64; + } + if (bank->size==0x40000) + { + at91sam7_info->target_name = "AT91SAM7SE256"; + at91sam7_info->num_lockbits = 16; + at91sam7_info->pagesize = 256; + at91sam7_info->pages_in_lockregion = 64; + at91sam7_info->num_pages = 16*64; + } + if (bank->size==0x08000) + { + at91sam7_info->target_name = "AT91SAM7SE32"; + at91sam7_info->num_lockbits = 8; + at91sam7_info->pagesize = 128; + at91sam7_info->pages_in_lockregion = 32; + at91sam7_info->num_pages = 8*32; + } + + return ERROR_OK; + } + if (at91sam7_info->cidr_arch == 0x75 ) { at91sam7_info->num_nvmbits = 3; @@ -422,7 +477,7 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) at91sam7_info->target_name = "AT91SAM7A3"; at91sam7_info->num_lockbits = 16; at91sam7_info->pagesize = 256; - at91sam7_info->pages_in_lockregion = 64; + at91sam7_info->pages_in_lockregion = 16; at91sam7_info->num_pages = 16*64; } return ERROR_OK; @@ -436,8 +491,6 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) int at91sam7_erase_check(struct flash_bank_s *bank) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; - int i; if (!at91sam7_info->working_area_size) { @@ -454,7 +507,6 @@ int at91sam7_protect_check(struct flash_bank_s *bank) u32 status; at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; if (at91sam7_info->cidr == 0) { @@ -468,7 +520,7 @@ int at91sam7_protect_check(struct flash_bank_s *bank) } status = at91sam7_get_flash_status(bank); - at91sam7_info->lockbits = status>>16; + at91sam7_info->lockbits = status >> 16; return ERROR_OK; } @@ -489,11 +541,10 @@ int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, ch at91sam7_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); if (!at91sam7_info->target) { - ERROR("no target '%i' configured", args[5]); + ERROR("no target '%s' configured", args[5]); exit(-1); } - /* part wasn't probed for info yet */ at91sam7_info->cidr = 0; @@ -527,12 +578,12 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last) /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); - at91sam7_set_flash_mode(bank,2); + at91sam7_set_flash_mode(bank,FMR_TIMING_FLASH); - if ((first == 0) && (last == (at91sam7_info->num_lockbits-1))) - { - return at91sam7_flash_command(bank, EA, 0); - } + if ((first == 0) && (last == (at91sam7_info->num_lockbits-1))) + { + return at91sam7_flash_command(bank, EA, 0); + } WARNING("Can only erase the whole flash area, pages are autoerased on write"); return ERROR_FLASH_OPERATION_FAILED; @@ -544,7 +595,6 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last) int lockregion; at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - target_t *target = at91sam7_info->target; if (at91sam7_info->target->state != TARGET_HALTED) { @@ -569,7 +619,7 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last) /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); - at91sam7_set_flash_mode(bank,1); + at91sam7_set_flash_mode(bank,FMR_TIMING_NVBITS); for (lockregion=first;lockregion<=last;lockregion++) { @@ -597,7 +647,6 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) target_t *target = at91sam7_info->target; u32 dst_min_alignment, wcount, bytes_remaining = count; u32 first_page, last_page, pagen, buffer_pos; - u32 fcr; if (at91sam7_info->target->state != TARGET_HALTED) { @@ -639,7 +688,7 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); - at91sam7_set_flash_mode(bank,2); + at91sam7_set_flash_mode(bank,FMR_TIMING_FLASH); for (pagen=first_page; pagentarget_name); buf += printed; buf_size -= printed; @@ -800,7 +850,7 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); - at91sam7_set_flash_mode(bank,1); + at91sam7_set_flash_mode(bank,FMR_TIMING_NVBITS); if (at91sam7_flash_command(bank, flashcmd, (u16)(bit)) != ERROR_OK) {