static int eeprom_len(unsigned offset, unsigned end) { unsigned len = end - offset; /* * For a FRAM device there is no limit on the number of the * bytes that can be ccessed with the single read or write * operation. */ #if !defined(CONFIG_SYS_I2C_FRAM) unsigned blk_off = offset & 0xff; unsigned maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off); if (maxlen > I2C_RXTX_LEN) maxlen = I2C_RXTX_LEN; if (len > maxlen) len = maxlen; #endif return len; }
int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt) { unsigned end = offset + cnt; unsigned blk_off; int rcode = 0; #if defined(CONFIG_SYS_EEPROM_X40430) uchar contr_r_addr[2]; uchar addr_void[2]; uchar contr_reg[2]; uchar ctrl_reg_v; int i; #endif #if defined(CONFIG_SYS_EEPROM_WREN) eeprom_write_enable (dev_addr,1); #endif /* Write data until done or would cross a write page boundary. * We must write the address again when changing pages * because the address counter only increments within a page. */ while (offset < end) { unsigned alen, len; #if !defined(CONFIG_SYS_I2C_FRAM) unsigned maxlen; #endif #if CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X) uchar addr[2]; blk_off = offset & 0xFF; /* block offset */ addr[0] = offset >> 8; /* block number */ addr[1] = blk_off; /* block offset */ alen = 2; #else uchar addr[3]; blk_off = offset & 0xFF; /* block offset */ addr[0] = offset >> 16; /* block number */ addr[1] = offset >> 8; /* upper address octet */ addr[2] = blk_off; /* lower address octet */ alen = 3; #endif /* CONFIG_SYS_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */ addr[0] |= dev_addr; /* insert device address */ len = end - offset; /* * For a FRAM device there is no limit on the number of the * bytes that can be accessed with the single read or write * operation. */ #if !defined(CONFIG_SYS_I2C_FRAM) #if defined(CONFIG_SYS_EEPROM_PAGE_WRITE_BITS) #define EEPROM_PAGE_SIZE (1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS) #define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1)) maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off); #else maxlen = 0x100 - blk_off; #endif if (maxlen > I2C_RXTX_LEN) maxlen = I2C_RXTX_LEN; if (len > maxlen) len = maxlen; #endif #if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) spi_write (addr, alen, buffer, len); #else #if defined(CONFIG_SYS_EEPROM_X40430) /* Get the value of the control register. * Set current address (internal pointer in the x40430) * to 0x1ff. */ contr_r_addr[0] = 9; contr_r_addr[1] = 0xff; addr_void[0] = 0; addr_void[1] = addr[1]; #ifdef CONFIG_SYS_I2C_EEPROM_ADDR contr_r_addr[0] |= CONFIG_SYS_I2C_EEPROM_ADDR; addr_void[0] |= CONFIG_SYS_I2C_EEPROM_ADDR; #endif contr_reg[0] = 0xff; if (i2c_read (contr_r_addr[0], contr_r_addr[1], 1, contr_reg, 1) != 0) { rcode = 1; } ctrl_reg_v = contr_reg[0]; /* Are any of the eeprom blocks write protected? */ if (ctrl_reg_v & 0x18) { ctrl_reg_v &= ~0x18; /* reset block protect bits */ ctrl_reg_v |= 0x02; /* set write enable latch */ ctrl_reg_v &= ~0x04; /* clear RWEL */ /* Set write enable latch. */ contr_reg[0] = 0x02; if (i2c_write (contr_r_addr[0], 0xff, 1, contr_reg, 1) != 0) { rcode = 1; } /* Set register write enable latch. */ contr_reg[0] = 0x06; if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) { rcode = 1; } /* Modify ctrl register. */ contr_reg[0] = ctrl_reg_v; if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) { rcode = 1; } /* The write (above) is an operation on NV memory. * These can take some time (~5ms), and the device * will not respond to further I2C messages till * it's completed the write. * So poll device for an I2C acknowledge. * When we get one we know we can continue with other * operations. */ contr_reg[0] = 0; for (i = 0; i < MAX_ACKNOWLEDGE_POLLS; i++) { if (i2c_read (addr_void[0], addr_void[1], 1, contr_reg, 1) == 0) break; /* got ack */ #if defined(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS) udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000); #endif } if (i == MAX_ACKNOWLEDGE_POLLS) { puts ("EEPROM poll acknowledge failed\n"); rcode = 1; } } /* Is the write enable latch on?. */ else if (!(ctrl_reg_v & 0x02)) { /* Set write enable latch. */ contr_reg[0] = 0x02; if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) { rcode = 1; } } /* Write is enabled ... now write eeprom value. */ #endif if (i2c_write(addr[0], offset, alen - 1, buffer, len)) rcode = 1; #endif buffer += len; offset += len; #if defined(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS) udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000); #endif } #if defined(CONFIG_SYS_EEPROM_WREN) eeprom_write_enable (dev_addr,0); #endif return rcode; }
/*********************************************************************//** * @brief Write data to EEPROM at specific address * @param[in] address EEPROM address that start to write data, it must be * in range 0..0x1000 * mode Write mode, should be: * - MODE_8_BIT : write 8 bit mode * - MODE_16_BIT : write 16 bit mode * - MODE_32_BIT : write 32 bit mode * data buffer that contain data that will be written to buffer * count number written data * @return None * @note This function actually write data into EEPROM memory and automatically * write into next page if current page is overflowed **********************************************************************/ void EEPROM_Write(uint16_t page_offset, uint16_t page_address, void* data, EEPROM_Mode_Type mode, uint32_t count) { uint32_t i; #ifdef __IAR_SYSTEMS_ICC__ #if (mode == MODE_8_BIT) uint8_t *tmp = (uint8_t *)data; #elif (mode == MODE_16_BIT) uint16_t *tmp = (uint16_t *)data; #else uint32_t *tmp = (uint32_t *)data; #endif #endif LPC_EEPROM->INT_CLR_STATUS = ((1 << EEPROM_ENDOF_RW)|(1 << EEPROM_ENDOF_PROG)); //check page_offset if(mode == MODE_16_BIT){ if((page_offset & 0x01)!=0) while(1); } else if(mode == MODE_32_BIT){ if((page_offset & 0x03)!=0) while(1); } LPC_EEPROM->ADDR = EEPROM_PAGE_OFFSET(page_offset); LPC_EEPROM->INT_CLR_STATUS = (1 << EEPROM_ENDOF_RW); for(i=0;i<count;i++) { //update data to page register if(mode == MODE_8_BIT){ LPC_EEPROM->CMD = EEPROM_CMD_8_BIT_WRITE; #ifdef __IAR_SYSTEMS_ICC__ LPC_EEPROM -> WDATA = *tmp; tmp++; #else LPC_EEPROM->WDATA = *((uint8_t *)data); data++; #endif page_offset +=1; } else if(mode == MODE_16_BIT){ LPC_EEPROM->CMD = EEPROM_CMD_16_BIT_WRITE; #ifdef __IAR_SYSTEMS_ICC__ LPC_EEPROM -> WDATA = *tmp; tmp++; #else LPC_EEPROM -> WDATA = *((uint16_t *)data); data++; #endif page_offset +=2; } else{ LPC_EEPROM->CMD = EEPROM_CMD_32_BIT_WRITE; #ifdef __IAR_SYSTEMS_ICC__ LPC_EEPROM -> WDATA = *tmp; tmp++; #else LPC_EEPROM -> WDATA = *((uint32_t *)data); data++; #endif page_offset +=4; } if((page_offset >= EEPROM_PAGE_NUM)|(i==count-1)){ //update to EEPROM memory LPC_EEPROM->INT_CLR_STATUS = (0x1 << EEPROM_ENDOF_PROG); LPC_EEPROM->ADDR = EEPROM_PAGE_ADRESS(page_address); LPC_EEPROM->CMD = EEPROM_CMD_ERASE_PRG_PAGE; while(!((LPC_EEPROM->INT_STATUS >> 28)&0x01)); } if(page_offset >= EEPROM_PAGE_NUM) { page_offset = 0; page_address +=1; LPC_EEPROM->ADDR =0; if(page_address > EEPROM_PAGE_NUM - 1) page_address = 0; } }