#include #include #include #include #include "spi_flash.h" extern void xspi_nor_enable_status_qe(struct spinor_info *sni); #define SPI_CTL_AHB_REQ (1<<8) #define SPI_STATUS_READY (1<<8) #define SPI_CTL_ADDR_MODE_MASK (1<<27) #define SPI_CTL_ADDR_MODE_2X4X (0<<27) #define SPI_CTL_ADDR_MODE_DUAL_QUAD (1<<27) static inline void spi_delay(void) { volatile int i = 100000; while (i--) ; } static inline void spi_setup_bus_width(struct spinor_info *sni, u8_t bus_width) { struct acts_spi_reg *spi= (struct acts_spi_reg *)sni->spi.base; spi->ctrl = (spi->ctrl & ~(0x3 << 10)) | (((bus_width & 0x7) / 2 + 1) << 10); spi_delay(); } __ramfunc static void _nor_set_spi_read_mode(struct spinor_info *sni) { struct spi_info *si = (struct spi_info *)&sni->spi; if(sni->spi.bus_width == 4) { printk("nor is 4 line mode\n"); xspi_nor_enable_status_qe(sni); /* enable 4x mode */ spi_setup_bus_width(sni, 4); } else if(sni->spi.bus_width == 2) { printk("nor is 2 line mode\n"); /* enable 2x mode */ spi_setup_bus_width(sni, 2); } else { sni->spi.bus_width = 1; printk("nor is 1 line mode\n"); /* enable 1x mode */ spi_setup_bus_width(sni, 1); } } #define COMPARE_BYTES (32) void _nor_read_mode_try(struct spinor_info *sni, unsigned char bus_width) { u8_t temp_data[COMPARE_BYTES], src_data[COMPARE_BYTES]; printk("_nor_read_mode_try:%d bit bus width\n", bus_width); sni->spi.bus_width = 1; sni->spi.flag &= ~SPI_FLAG_SPI_4XIO; memset(src_data, 0xff, COMPARE_BYTES); p_spinor_api->read(sni, 0, src_data, COMPARE_BYTES); /* try io mode */ sni->spi.bus_width = bus_width; sni->spi.flag |= SPI_FLAG_SPI_4XIO; if (sni->spi.bus_width == 4) { xspi_nor_enable_status_qe(sni); } memset(temp_data, 0x00, COMPARE_BYTES); p_spinor_api->read(sni, 0, temp_data, COMPARE_BYTES); if (memcmp(temp_data, src_data, COMPARE_BYTES) == 0) { return ; } /* try output mode */ sni->spi.flag &= ~SPI_FLAG_SPI_4XIO; memset(temp_data, 0x00, COMPARE_BYTES); p_spinor_api->read(sni, 0, temp_data, COMPARE_BYTES); if (memcmp(temp_data, src_data, COMPARE_BYTES) != 0) { sni->spi.bus_width = 1; } } void nor_dual_quad_read_mode_try(struct spinor_info *sni) { if(sni->spi.bus_width == 4) { _nor_read_mode_try(sni, 4); } else if(sni->spi.bus_width == 2) { _nor_read_mode_try(sni, 2); } _nor_set_spi_read_mode(sni); }