예제 #1
0
파일: alt_nand.c 프로젝트: Syanna/firmware
ALT_STATUS_CODE alt_nand_int_enable(const uint32_t mask)
{
    uint32_t bank = alt_nand_bank_get();
    uint32_t reg  = alt_nand_get_interrupt_enable_register_addr(bank);
    alt_setbits_word(reg, mask);
    return ALT_E_SUCCESS;
}
예제 #2
0
uint8_t init_i2c(uint32_t i2c_dev){

	void *virtual_base;
	volatile uint32_t *i2c_ic_con = NULL;
	volatile uint32_t *i2c_en = NULL;
	int fd;
	uint32_t daten_register;

	//Oeffnen der Datei des Speichers mit Fehlerabrage
	if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
		printf( "ERROR: could not open \"/dev/mem\"...\n" );
		return 1;
	}

	//Erstellen einer Virtuellen Adresse
	virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE );

	//Fehlerabrage der Virtuellen Adresse
	if( virtual_base == MAP_FAILED ) {
		printf( "ERROR: mmap() failed...\n" );
		close( fd );
		return 2;
	}

	//Erstellen einen Pointers auf das ic_con Register im Speicher
	i2c_ic_con = virtual_base + ( (uint32_t)( i2c_dev + ic_con ) & (uint32_t)( HW_REGS_MASK ) );
	//Erstellen einen Pointers auf das ic_enable Register im Speicher
	i2c_en = virtual_base + ( (uint32_t)( i2c_dev + ic_enable ) & (uint32_t)( HW_REGS_MASK ) );

	//Auschalten des I2C Moduls
	alt_clrbits_word(i2c_en, 0x1);
	//Auf 100kHz stellen
	alt_write_word(i2c_ic_con, ( (alt_read_word(i2c_ic_con) & 0xFFFFFFF9) | 0x00000002) );
	//Einschalten des I2C Moduls
	alt_setbits_word(i2c_en, 0x1);

	//Lesen des Registers
	daten_register = alt_read_word(i2c_ic_con);

	//Pruefen des Registerinhalts auf 0x73 oder 0x63
	if(daten_register != 0x73){
		if( daten_register != 0x63){
			close( fd );
			return 3;
		}
	}

	//Memorryunmapping aufheben mti Fehlerabfrage
	if( munmap( virtual_base, HW_REGS_SPAN ) != 0 ) {
		printf( "ERROR: munmap() failed...\n" );
		close( fd );
		return( 4 );
	}

	//Datei schliesen
	close( fd );

	return 0;

}
예제 #3
0
파일: alt_ecc.c 프로젝트: Syanna/firmware
ALT_STATUS_CODE alt_ecc_start(const ALT_ECC_RAM_ENUM_t ram_block)
{
    void *   ecc_addr;
    uint32_t ecc_bits;

    switch (ram_block)
    {
    case ALT_ECC_RAM_L2_DATA:
        return alt_cache_l2_ecc_start(block, sizeof(block));

    case ALT_ECC_RAM_OCRAM:
        return alt_ocram_ecc_start(block, sizeof(block));

    case ALT_ECC_RAM_USB0:
        ecc_addr = ALT_SYSMGR_ECC_USB0_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_USB0_EN_SET_MSK;
        break;
    case ALT_ECC_RAM_USB1:
        ecc_addr = ALT_SYSMGR_ECC_USB1_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_USB1_EN_SET_MSK;
        break;
    case ALT_ECC_RAM_EMAC0:
        ecc_addr = ALT_SYSMGR_ECC_EMAC0_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_EMAC0_EN_SET_MSK;
        break;
    case ALT_ECC_RAM_EMAC1:
        ecc_addr = ALT_SYSMGR_ECC_EMAC1_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_EMAC1_EN_SET_MSK;
        break;
    case ALT_ECC_RAM_DMA:
        return alt_dma_ecc_start(block, sizeof(block));

    case ALT_ECC_RAM_CAN0:
        ecc_addr = ALT_SYSMGR_ECC_CAN0_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_CAN0_EN_SET_MSK;
        break;
    case ALT_ECC_RAM_CAN1:
        ecc_addr = ALT_SYSMGR_ECC_CAN1_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_CAN1_EN_SET_MSK;
        break;
    case ALT_ECC_RAM_NAND:
        ecc_addr = ALT_SYSMGR_ECC_NAND_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_NAND_EN_SET_MSK;
        break;
    case ALT_ECC_RAM_QSPI:
        return alt_qspi_ecc_start(block, sizeof(block));

    case ALT_ECC_RAM_SDMMC:
        ecc_addr = ALT_SYSMGR_ECC_SDMMC_ADDR;
        ecc_bits = ALT_SYSMGR_ECC_SDMMC_EN_SET_MSK;
        break;
    default:
        return ALT_E_ERROR;
    }

    alt_setbits_word(ecc_addr, ecc_bits);

    return ALT_E_SUCCESS;
}
예제 #4
0
파일: alt_ecc.c 프로젝트: Syanna/firmware
static ALT_STATUS_CODE alt_ocram_ecc_start(void * block, size_t size)
{
    const uint32_t ocram_size = ((uint32_t)ALT_OCRAM_UB_ADDR - (uint32_t)ALT_OCRAM_LB_ADDR) + 1;
    dprintf("DEBUG[ECC][OCRAM]: OCRAM Size = 0x%lx.\n", ocram_size);

    // Verify buffer is large enough to contain the entire contents of OCRAM.
    if (size < ocram_size)
    {
        return ALT_E_ERROR;
    }

    // Verify buffer is word aligned.
    if ((uintptr_t)block & (sizeof(uint32_t) - 1))
    {
        return ALT_E_ERROR;
    }

    // Read the contents of OCRAM into the provided buffer

    uint32_t * block_iter = block;
    uint32_t * ocram_iter = ALT_OCRAM_ADDR;
    uint32_t   size_counter = ocram_size;

    while (size_counter)
    {
        *block_iter = alt_read_word(ocram_iter);
        ++block_iter;
        ++ocram_iter;
        size_counter -= sizeof(*ocram_iter);
    }

    // Enable ECC

    alt_setbits_word(ALT_SYSMGR_ECC_OCRAM_ADDR, ALT_SYSMGR_ECC_OCRAM_EN_SET_MSK);

    // Write back contents of OCRAM from buffer to OCRAM

    block_iter   = block;
    ocram_iter   = ALT_OCRAM_ADDR;
    size_counter = ocram_size;

    while (size_counter)
    {
        alt_write_word(ocram_iter, *block_iter);
        ++block_iter;
        ++ocram_iter;
        size_counter -= sizeof(*ocram_iter);
    }

    // Clear any pending spurious interrupts

    alt_write_word(ALT_SYSMGR_ECC_OCRAM_ADDR,
                     ALT_SYSMGR_ECC_OCRAM_EN_SET_MSK
                   | ALT_SYSMGR_ECC_OCRAM_SERR_SET_MSK
                   | ALT_SYSMGR_ECC_OCRAM_DERR_SET_MSK);

    return ALT_E_SUCCESS;
}
예제 #5
0
파일: alt_nand.c 프로젝트: Syanna/firmware
void alt_nand_reset_bank(uint32_t bank)
{
    ALT_NAND_CFG_raw_t * cfg = (ALT_NAND_CFG_raw_t *)(nand->cfg);

    uint32_t  interrup_status_register = alt_nand_get_interrupt_status_register_addr(bank);
    uint32_t  device_reset_bank        = alt_nand_get_device_reset_register_bank(bank);


    // Write on clear of all interrupt status
    alt_write_word(interrup_status_register, ALT_HHP_UINT32_MASK);

    // Controller sends a RESET command to device
    alt_setbits_word(&cfg->device_reset, device_reset_bank);

    alt_nand_poll_for_interrupt_status_register(interrup_status_register, ALT_NAND_STAT_INTR_STAT0_RST_COMP_SET_MSK);

    // Write on clear of all interrupt status
    alt_write_word(interrup_status_register, ALT_HHP_UINT32_MASK);
}
예제 #6
0
int main() {

	void *virtual_base;
	int fd;
	int loop_count;
	int led_direction;
	uint8_t led_state;

	// map the address space for the LED registers into user space so we can interact with them.
	// we'll actually map in the entire CSR span of the HPS since we want to access various registers within that span

	if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
		printf( "ERROR: could not open \"/dev/mem\"...\n" );
		return( 1 );
	}

	virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE );

	if( virtual_base == MAP_FAILED ) {
		printf( "ERROR: mmap() failed...\n" );
		close( fd );
		return( 1 );
	}

	// initialize the LEDs

	// set the direction of the HPS GPIO1 bits attached to LEDs to output
	alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DDR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x0F000000 );
	// set the value of the HPS GPIO1 bits attached to LEDs to ONE, turn OFF the LEDs
	alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x0F000000 );
	// set the value of the FPGA PIO bits attached to LEDs to ONE, turn OFF the LEDs
	alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_LWFPGASLVS_OFST + LED_PIO_BASE ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x0000000F );

	// toggle the LEDs a bit

	loop_count = 0;
	led_state = 0x01;
	led_direction = 0;
	while( loop_count < 60 ) {

		// turn off all LEDs
		alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x0F000000 );
		alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_LWFPGASLVS_OFST + LED_PIO_BASE ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x0000000F );

		// turn on the one led that we need
		switch( led_state ) {
		case( 0x01 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_LWFPGASLVS_OFST + LED_PIO_BASE ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x00000001 );
			break;
		case( 0x02 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_LWFPGASLVS_OFST + LED_PIO_BASE ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x00000002 );
			break;
		case( 0x04 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_LWFPGASLVS_OFST + LED_PIO_BASE ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x00000004 );
			break;
		case( 0x08 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_LWFPGASLVS_OFST + LED_PIO_BASE ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x00000008 );
			break;
		case( 0x10 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x01000000 );
			break;
		case( 0x20 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x02000000 );
			break;
		case( 0x40 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x04000000 );
			break;
		case( 0x80 ) :
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), 0x08000000 );
			break;
		default :
			break;
		}

	usleep( 1000000 / 16 );

	// calculate the next LED value
	if( led_state == 0x80 ) {

		led_direction = 0;
		led_state >>= 1;

	} else if( led_state == 0x01 ) {
예제 #7
0
ALT_STATUS_CODE alt_fpga_interface_enable(ALT_FPGA_INTERFACE_t intfc)
{
    switch (intfc)
    {
    case ALT_FPGA_INTERFACE_GLOBAL:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_GBL_ADDR,
                                ALT_SYSMGR_FPGAINTF_GBL_INTF_SET_MSK);

    case ALT_FPGA_INTERFACE_RESET_REQ:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                ALT_SYSMGR_FPGAINTF_INDIV_RSTREQINTF_SET_MSK);

    case ALT_FPGA_INTERFACE_JTAG_ENABLE:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                ALT_SYSMGR_FPGAINTF_INDIV_JTAGENINTF_SET_MSK);

    case ALT_FPGA_INTERFACE_CONFIG_IO:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                ALT_SYSMGR_FPGAINTF_INDIV_CFGIOINTF_SET_MSK);

    case ALT_FPGA_INTERFACE_BSCAN:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                ALT_SYSMGR_FPGAINTF_INDIV_BSCANINTF_SET_MSK);

    case ALT_FPGA_INTERFACE_TRACE:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                ALT_SYSMGR_FPGAINTF_INDIV_TRACEINTF_SET_MSK);

    case ALT_FPGA_INTERFACE_DBG_APB:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                1 << 5);

    case ALT_FPGA_INTERFACE_STM:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                ALT_SYSMGR_FPGAINTF_INDIV_STMEVENTINTF_SET_MSK);

    case ALT_FPGA_INTERFACE_CTI:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_INDIV_ADDR,
                                ALT_SYSMGR_FPGAINTF_INDIV_CROSSTRIGINTF_SET_MSK);

    case ALT_FPGA_INTERFACE_EMAC0:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_MODULE_ADDR,
                                ALT_SYSMGR_FPGAINTF_MODULE_EMAC_0_SET_MSK);

    case ALT_FPGA_INTERFACE_EMAC1:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_MODULE_ADDR,
                                ALT_SYSMGR_FPGAINTF_MODULE_EMAC_1_SET_MSK);

    case ALT_FPGA_INTERFACE_SPIM0:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_MODULE_ADDR,
                                1 << 0);

    case ALT_FPGA_INTERFACE_SPIM1:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_MODULE_ADDR,
                                1 << 1);

    case ALT_FPGA_INTERFACE_NAND:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_MODULE_ADDR,
                                1 << 4);

    case ALT_FPGA_INTERFACE_SDMMC:
        return alt_setbits_word(ALT_SYSMGR_FPGAINTF_MODULE_ADDR,
                                1 << 5);

    default:
        return ALT_E_BAD_ARG;
    }
}
예제 #8
0
int main(int argc, char **argv) {
	void *virtual_base;
	int fd;
	char *data;
	char ledstatus[5]="";

	// map the address space for the LED registers into user space so we can interact with them.
	// we'll actually map in the entire CSR span of the HPS since we want to access various registers within that span
	if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
		printf( "ERROR: could not open \"/dev/mem\"...\n" );
		return( 1 );
	}

	virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE );
	
	if( virtual_base == MAP_FAILED ) {
		printf( "ERROR: mmap() failed...\n" );
		close( fd );
		return( 1 );
	}
	// initialize the pio controller
	// led: set the direction of the HPS GPIO1 bits attached to LEDs to output
	alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DDR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), USER_IO_DIR );

	printf("%s%c%c\n","Content-Type:text/html;charset=iso-8859-1",13,10);
	printf("<html>");
	printf("<header>");
	printf("<TITLE>CGI</TITLE>\n");
	printf("</header>");

	printf("<body>");
	printf("<H1>Hello, World!</H1>\n");
	printf("<h2>About this Server</h2>\n");
	printf("Server Name: %s <BR>\n",getenv("SERVER_NAME"));
	printf("Server Name: CGI test with DE0-Nano-SoC <BR>\n");
	printf("Running on Port: %s <BR>\n",getenv("SERVER_PORT"));
	printf("Server Software: %s <BR>\n",getenv("SERVER_SOFTWARE"));
	printf("Server Protocol: %s <BR>\n",getenv("SERVER_PROTOCOL"));
	printf("CGI Revision: %s <BR>\n",getenv("GATEWAY_INTERFACE"));
	
	printf("<H2>Test CGI</H2>\n");
	printf("<form action='/cgi-bin/hps.cgi' method='GET'><br>"); // add target='_blank' >> open new tab
	printf("<input type='submit' name='led' value='on'>");
	printf("<input type='submit' name='led' value='off'><br>");
	printf("</form>");

	data = getenv("QUERY_STRING");
	if(data == NULL)
  	printf("<h3> LED status is </h3>");
	else {
		sscanf(data,"led=%s",&ledstatus);
		if(strcmp(ledstatus,"on")) {
			alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );
		}
		else {
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );
		}
		printf("<h3> LED status is %s</h3>",ledstatus);
	}
	printf("</body>");
	printf("</html>");

	return 0;
}
예제 #9
0
파일: alt_nand.c 프로젝트: Syanna/firmware
void alt_nand_rb_pin_mode_set(uint32_t mask)
{
    ALT_NAND_CFG_raw_t * cfg = (ALT_NAND_CFG_raw_t *)(nand->cfg);
    alt_setbits_word(&cfg->rb_pin_enabled, mask);
}
예제 #10
0
파일: alt_nand.c 프로젝트: Syanna/firmware
ALT_STATUS_CODE alt_nand_flash_ecc_enable(const ALT_NAND_ECC_CORRECTION_t ecc_correction)
{
    ALT_NAND_CFG_raw_t * cfg = (ALT_NAND_CFG_raw_t *)(nand->cfg);
    alt_setbits_word(&cfg->ecc_enable, ALT_NAND_CFG_ECC_EN_FLAG_SET_MSK); 
    return ALT_E_SUCCESS;
}
예제 #11
0
파일: alt_nand.c 프로젝트: Syanna/firmware
ALT_STATUS_CODE alt_nand_flash_init(const bool load_block0_page0,
                                    const bool page_size_512,
                                    alt_nand_flash_custom_init_t custom_init,
                                    void *user_arg)
{
    ALT_NAND_CFG_raw_t * cfg = (ALT_NAND_CFG_raw_t *)(nand->cfg);
    ALT_NAND_PARAM_raw_t * param = (ALT_NAND_PARAM_raw_t *)(nand->param);
    ALT_STATUS_CODE ret = ALT_E_SUCCESS;
    uint32_t x;

    alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_NAND_SET_MSK);
    alt_nand_set_sysmgr_bootstrap_value( ALT_NAND_BOOTSTRAP_INHIBIT_INIT_DISABLE,
                                         load_block0_page0,  
                                         page_size_512,
                                         ALT_NAND_BOOTSTRAP_TWO_ROW_ADDR_CYCLES_DISABLE
                                       );
    alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_NAND_SET_MSK);
                             
    g_nand_interrup_status_register_poll_counter_limit = (uint32_t)(-1);

    ret = (*custom_init)(user_arg);
    if (ret == ALT_E_RESERVED)    // no custom initialization being done
    {
        alt_nand_reset_bank(0);
    }

    // Read flash device characterization 
    flash->manufacturer_id = alt_read_word(&param->manufacturer_id);
    flash->device_id = alt_read_word(&param->device_id);
    flash->device_param_0 = alt_read_word(&param->device_param_0);
    flash->device_param_1 = alt_read_word(&param->device_param_1);
    flash->device_param_2 = alt_read_word(&param->device_param_2);
    flash->page_size = alt_read_word(&cfg->device_main_area_size);
    flash->spare_size = alt_read_word(&cfg->device_spare_area_size);
    flash->revision = alt_read_word(&param->revision);
    flash->onfi_device_features = alt_read_word(&param->onfi_device_features);
    flash->onfi_optional_commands = alt_read_word(&param->onfi_optional_commands);
    flash->onfi_timing_mode = alt_read_word(&param->onfi_timing_mode);
    flash->onfi_pgm_cache_timing_mode = alt_read_word(&param->onfi_pgm_cache_timing_mode);
    flash->onfi_compliant = alt_read_word(&param->onfi_device_no_of_luns) >> 8;
    flash->onfi_device_no_of_luns = alt_read_word(&param->onfi_device_no_of_luns) & 0xff;
    x = alt_read_word(&param->onfi_device_no_of_blocks_per_lun_l);
    flash->onfi_device_no_of_blocks_per_lun = (alt_read_word(&param->onfi_device_no_of_blocks_per_lun_u) << 16) + x;
    flash->features = alt_read_word(&param->features);
    x = alt_read_word(&cfg->number_of_planes);
    switch (x)
    {
        case 0:
             flash->number_of_planes = 1;
             break;
        case 1: 
             flash->number_of_planes = 2;
             break;
        case 3: 
             flash->number_of_planes = 4;
             break;
        case 7: 
             flash->number_of_planes = 4;
             break;
        default: 
             flash->number_of_planes = 1;
             break;
    }
    flash->pages_per_block = alt_read_word(&cfg->pages_per_block);

    // Device Width register content should automatically update SystemManager:NandGrp:BootStrap:page512 or page512x16 bit
    flash->device_width = alt_read_word(&cfg->device_width);

    // Set the skip bytes and then read back the result.
    alt_write_word(&cfg->spare_area_skip_bytes, flash->spare_area_skip_bytes);
    flash->spare_area_skip_bytes = alt_read_word(&cfg->spare_area_skip_bytes);
    flash->block_size = flash->pages_per_block * flash->page_size;

    flash->first_block_of_next_plane = alt_read_word(&cfg->first_block_of_next_plane);
    // Set flash config based on read config
    flash->page_size_32 = flash->page_size / sizeof(uint32_t);

    flash->page_shift = ffs32(flash->page_size);
    flash->block_shift = ffs32(flash->pages_per_block);
  
    alt_nand_rb_pin_mode_clear(ALT_NAND_CFG_RB_PIN_END_BANK0_SET_MSK);
    alt_nand_flash_ecc_disable();
    alt_write_word(&cfg->first_block_of_next_plane,alt_nand_number_blocks_of_plane_get());
    flash->first_block_of_next_plane  = alt_read_word(&cfg->first_block_of_next_plane);

    return ALT_E_SUCCESS;
}