在使用spi flash时,执行reboot命令,有时会无法重启,这里追查下原因
原因
是使用了32M flash,在重启的时候,没有退出4-byte地址模式导致。(因为板子上没有PMU,没有对flash进行复位)
在 m25p_shutdown 函数中退出4-byte地址模式即可。
static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
const struct flash_info *info)
{
/* Do some manufacturer fixups first */
switch (JEDEC_MFR(info)) {
case SNOR_MFR_SPANSION:
/* No small sector erase for 4-byte command set */
nor->erase_opcode = SPINOR_OP_SE;
nor->mtd.erasesize = info->sector_size;
break;
default:
break;
}
nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode);
nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
}
/* Enable/disable 4-byte addressing mode. */
static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
int enable)
{
int status;
bool need_wren = false;
u8 cmd;
switch (JEDEC_MFR(info)) {
case SNOR_MFR_MICRON:
/* Some Micron need WREN command; all will accept it */
need_wren = true;
case SNOR_MFR_MACRONIX:
case SNOR_MFR_WINBOND:
if (need_wren)
write_enable(nor); //nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
status = nor->write_reg(nor, cmd, NULL, 0);
if (need_wren)
write_disable(nor);
return status;
default:
/* Spansion style */
nor->cmd_buf[0] = enable << 7;
return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1);
}
}
struct m25p {
struct spi_device *spi;
struct spi_nor spi_nor;
u8 command[MAX_CMD_SIZE];
};
static int m25p_remove(struct spi_device *spi)
{
struct m25p *flash = spi_get_drvdata(spi);
//add to exit 4-byte address mode
/* Clean up MTD stuff. */
return mtd_device_unregister(&flash->spi_nor.mtd);
}
新增关机接口
static void m25p_shutdown(struct spi_device *spi)
{
struct m25p *flash = spi_get_drvdata(spi);
struct spi_nor nor = flash->spi_nor;
int status;
//add to exit 4-byte address mode
nor.write_reg(&nor, SPINOR_OP_WREN, NULL, 0);
status = nor.write_reg(&nor, SPINOR_OP_EX4B, NULL, 0);
printk("remove spi flash!\n");
/* Clean up MTD stuff. */
mtd_device_unregister(&flash->spi_nor.mtd);
return;
}
static struct spi_driver m25p80_driver = {
.driver = {
.name = "m25p80",
.of_match_table = m25p_of_table,
},
.id_table = m25p_ids,
.probe = m25p_probe,
.remove = m25p_remove,
.shutdown = m25p_shutdown,
/* REVISIT: many of these chips have deep power-down modes, which
* should clearly be entered on suspend() to minimize power use.
* And also when they're otherwise idle...
*/
};
CONFIG_SPI_FLASH_BAR
参考资料
http://www.wowotech.net/linux_kenrel/reboot.html