/*_____________________________________________________________________________ ** function name: SPI_cfg ** descriptions: ** Set the SPI controller to the more buffer mode, and choose the SLIC device by id ** parameters: ** id: The identification number of SLIC device ** global: ** SPI_SEM: The semaphore exported from the kernel and protecting atomic SPI Controller ** return: ** S_OK: Configure successfully ** S_EROR: Configure incorrectly ** call: ** down(): Check the SPI_SEM semaphore ** spi_regread32(): Read SPI Controller register by the offset reg ** spi_regwrite32(): Write SPI Controller register by the offset reg ** up(): Release the SPI_SEM semaphore ** revision: ** 1.1 2008/09/26 14:30 Ian **____________________________________________________________________________ */ int SPI_cfg(int id) { down(&SPI_SEM); do { reg = spi_regread32(SPI_FLASH_CTL); } while (reg & SPI_CTL_BUSY); //Turn on the more buffer mode and select device reg0x28 = spi_regread32(SPI_FLASH_MM); orig_reg0x28 = reg0x28; //printk("SPI_reg0x28 -- 0x%08lx \n",reg0x28); reg0x2c = spi_regread32(SPI_FLASH_MBC); reg0x28 |= 0x4;//Set bit [2] to 1 to enter more buffer mode reg0x28 &= ~(0x7 << 29);//Set bits [31:29] to 0 /*add the margin between SPI CLK and CS*/ reg0x28 |= (0x1 << 8);//Set bits [31:29] to 0 reg0x28 |= (id + 1) << 29;//Set bits [31:29] to select SPI device #ifdef SLIC_SILICON reg0x28 |= (1 << 4); /*Rodney_test*/ reg0x28 |= (1 << 5); /*Rodney_test*/ #endif #if 1 /*set cpol and cpoa to 1*/ //reg0x28 |= 0x3 <<4; // Set bits [5:4] to 0x3; /*lower the SPI clock = HCLK/64*/ reg0x28 &= ~(0xfff << 16);//Set bits [27:16] to 0 reg0x28 |= 0x3E << 16; #endif //printk("after SPI_reg0x28 -- 0x%08lx \n",reg0x28); spi_regwrite32(SPI_FLASH_MM, reg0x28); //Check the initialized value #if 0 /*Rodney_20091121*/ if(reg0x28 == spi_regread32(SPI_FLASH_MM)){ //printk("after read :SPI_reg0x28 -- 0x%08lx \n",reg0x28); up(&SPI_SEM); return S_OK; } else{ up(&SPI_SEM); return S_ERROR; } #endif spi_regwrite32(SPI_FLASH_MM, orig_reg0x28); up(&SPI_SEM); return S_OK; }
int SPI_bytes_read(int id, unsigned char cmd, unsigned char *data_ptr, unsigned char cmdLen) #endif { unsigned char i; __u32 data; down(&SPI_SEM); //Prepare register for sending MPI command reg0x28 &= ~(0x7 << 29);//Set bits [31:29] to 0 reg0x28 |= (id + 1) << 29;//Set bits [31:29] to select SPI device reg0x2c &= ~0x1ff;//Set bits [8:0] to 0 (Transmitted data bit counts) reg0x2c &= ~(0x1ff << 12);//Set bits [20:12] to 0 (Received data bit counts) reg0x2c &= ~(0x3f << 24);//Set bits[29:24] to 0 (command bit counts) reg0x2c |= (1 * 8) << 24;//Set bits [29:24] to 8 (Command bit counts) spi_regwrite32(SPI_FLASH_MM, reg0x28); spi_regwrite32(SPI_FLASH_MBC, reg0x2c); #ifdef SLIC_SILICON spi_regwrite32(SPI_FLASH_OPCODE, ctrl); reg |= SPI_CTL_START; spi_regwrite32(SPI_FLASH_CTL, reg); udelay(delaytime); do { reg = spi_regread32(SPI_FLASH_CTL); udelay(delaytime); } while (reg & SPI_CTL_BUSY); #endif //Send command for reading MPI spi_regwrite32(SPI_FLASH_OPCODE, cmd); //printk("R: cmd %d \n",cmd); reg |= SPI_CTL_START; spi_regwrite32(SPI_FLASH_CTL, reg); udelay(delaytime); do { reg = spi_regread32(SPI_FLASH_CTL); udelay(delaytime); } while (reg & SPI_CTL_BUSY); //Prepare register for reading MPI reg0x2c &= ~0x1ff;//Set bits [8:0] to 0 (Transmitted data bit counts) reg0x2c &= ~(0x1ff << 12);//Set bits [20:12] to 0 (Received data bit counts) reg0x2c &= ~(0x3f << 24);//Set bits[29:24] to 0 (command bit counts) reg0x2c |= (1 * 8) << 12;//Set bits [20:12] to 8 (Received data bit counts) //printk("reg0x2c: 0x%08lx \n",reg0x2c); spi_regwrite32(SPI_FLASH_MBC, reg0x2c); spi_regwrite32(SPI_FLASH_DATA, 0); for(i = 0; i < cmdLen; i++){ //Read the ith byte reg |= SPI_CTL_START; spi_regwrite32(SPI_FLASH_CTL, reg); //printk("R: reg %d \n",reg); udelay(delaytime); do { reg = spi_regread32(SPI_FLASH_CTL); udelay(delaytime); } while (reg & SPI_CTL_BUSY); reg0x08 = (__u32) spi_regread32(SPI_FLASH_DATA); data = reg0x08; udelay(delaytime); #ifdef SLIC_SILICON //*(data_ptr + i) = ((reg0x08 >> 7) & 0x000000ff); #ifdef TC3262_PCM //software workaround for msb shift problem, jrchen modify 20100409 __u32 tmp = ((reg0x08 << 1) & 0xfe); tmp |= ((reg0x08 >> 15) & 0x1); *(data_ptr + i) = tmp; // printk("reg0x08 = %08x\n", reg0x08); // printk("work around tmp = %08x\n", tmp); // *(data_ptr + i) = reg0x08; // printk("read workaround\n"); #else *(data_ptr + i) = reg0x08; #endif #else *(data_ptr + i) = reg0x08; #endif } //printk("[%s] id=%d ctrl=%X, cmd=%X, data=%02X\n",__FUNCTION__,id,ctrl,cmd,data); up(&SPI_SEM); return S_OK; }
int SPI_bytes_write(int id, unsigned char cmd, unsigned char *data_ptr, unsigned char cmdLen) #endif { unsigned char i; down(&SPI_SEM); //printk("[%s] id=%d ctrl=%X, cmd=%X data=%02X\n",__FUNCTION__,id,ctrl,cmd,*(data_ptr + 0)); do { reg = spi_regread32(SPI_FLASH_CTL); } while (reg & SPI_CTL_BUSY); //Prepare register for sending MPI command reg0x28 &= ~(0x7 << 29);//Set bits [31:29] to 0 reg0x28 |= (id + 1) << 29;//Set bits [31:29] to select SPI device reg0x2c &= ~0x1ff;//Set bits [8:0] to 0 (Transmitted data bit counts) reg0x2c &= ~(0x1ff << 12);//Set bits [20:12] to 0 (Received data bit counts) reg0x2c &= ~(0x3f << 24);//Set bits[29:24] to 0 (command bit counts) reg0x2c |= (1 * 8) << 24;//Set bits [29:24] to 8 (Command bit counts) spi_regwrite32(SPI_FLASH_MM, reg0x28); spi_regwrite32(SPI_FLASH_MBC, reg0x2c); #ifdef SLIC_SILICON spi_regwrite32(SPI_FLASH_OPCODE, ctrl); reg |= SPI_CTL_START; spi_regwrite32(SPI_FLASH_CTL, reg); udelay(delaytime); do { reg = spi_regread32(SPI_FLASH_CTL); udelay(delaytime); } while (reg & SPI_CTL_BUSY); #endif //Send command for writing MPI spi_regwrite32(SPI_FLASH_OPCODE, cmd); reg |= SPI_CTL_START; spi_regwrite32(SPI_FLASH_CTL, reg); udelay(delaytime); do { reg = spi_regread32(SPI_FLASH_CTL); udelay(delaytime); } while (reg & SPI_CTL_BUSY); for(i = 0; i < cmdLen; i++){ //Write the ith byte reg0x04 = (__u32) spi_regread32(SPI_FLASH_OPCODE); //printk("read opcode: %d \n",reg0x04); reg0x04 &= ~0xFF;//Set bits[7:0] to 0 (Opcode) reg0x04 |= *(data_ptr + i);//Set bits[7:0] to the content of the ith byte of *data_ptr (Opcode) //printk("write opcode: %d \n",reg0x04); spi_regwrite32(SPI_FLASH_OPCODE, reg0x04); reg |= SPI_CTL_START; spi_regwrite32(SPI_FLASH_CTL, reg); //printk("write CTL: %d \n",reg); udelay(delaytime); do { reg = spi_regread32(SPI_FLASH_CTL); udelay(delaytime); } while (reg & SPI_CTL_BUSY); } up(&SPI_SEM); return S_OK; }