172a525cbSRafał Miłecki /* 272a525cbSRafał Miłecki * Sonics Silicon Backplane 372a525cbSRafał Miłecki * ChipCommon serial flash interface 472a525cbSRafał Miłecki * 572a525cbSRafał Miłecki * Licensed under the GNU/GPL. See COPYING for details. 672a525cbSRafał Miłecki */ 772a525cbSRafał Miłecki 872a525cbSRafał Miłecki #include "ssb_private.h" 972a525cbSRafał Miłecki 10*b8b6069cSMichael Büsch #include <linux/ssb/ssb.h> 11*b8b6069cSMichael Büsch 127b5d6043SRafał Miłecki static struct resource ssb_sflash_resource = { 137b5d6043SRafał Miłecki .name = "ssb_sflash", 147b5d6043SRafał Miłecki .start = SSB_FLASH2, 157b5d6043SRafał Miłecki .end = 0, 167b5d6043SRafał Miłecki .flags = IORESOURCE_MEM | IORESOURCE_READONLY, 177b5d6043SRafał Miłecki }; 187b5d6043SRafał Miłecki 197b5d6043SRafał Miłecki struct platform_device ssb_sflash_dev = { 207b5d6043SRafał Miłecki .name = "ssb_sflash", 217b5d6043SRafał Miłecki .resource = &ssb_sflash_resource, 227b5d6043SRafał Miłecki .num_resources = 1, 237b5d6043SRafał Miłecki }; 247b5d6043SRafał Miłecki 2559015278SRafał Miłecki struct ssb_sflash_tbl_e { 2659015278SRafał Miłecki char *name; 2759015278SRafał Miłecki u32 id; 2859015278SRafał Miłecki u32 blocksize; 2959015278SRafał Miłecki u16 numblocks; 3059015278SRafał Miłecki }; 3159015278SRafał Miłecki 3239cd206cSRafał Miłecki static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { 3359015278SRafał Miłecki { "M25P20", 0x11, 0x10000, 4, }, 3459015278SRafał Miłecki { "M25P40", 0x12, 0x10000, 8, }, 3559015278SRafał Miłecki 3659015278SRafał Miłecki { "M25P16", 0x14, 0x10000, 32, }, 3759015278SRafał Miłecki { "M25P32", 0x15, 0x10000, 64, }, 3859015278SRafał Miłecki { "M25P64", 0x16, 0x10000, 128, }, 3959015278SRafał Miłecki { "M25FL128", 0x17, 0x10000, 256, }, 40c9e4a3fbSHauke Mehrtens { NULL }, 4159015278SRafał Miłecki }; 4259015278SRafał Miłecki 4339cd206cSRafał Miłecki static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { 4459015278SRafał Miłecki { "SST25WF512", 1, 0x1000, 16, }, 4559015278SRafał Miłecki { "SST25VF512", 0x48, 0x1000, 16, }, 4659015278SRafał Miłecki { "SST25WF010", 2, 0x1000, 32, }, 4759015278SRafał Miłecki { "SST25VF010", 0x49, 0x1000, 32, }, 4859015278SRafał Miłecki { "SST25WF020", 3, 0x1000, 64, }, 4959015278SRafał Miłecki { "SST25VF020", 0x43, 0x1000, 64, }, 5059015278SRafał Miłecki { "SST25WF040", 4, 0x1000, 128, }, 5159015278SRafał Miłecki { "SST25VF040", 0x44, 0x1000, 128, }, 5259015278SRafał Miłecki { "SST25VF040B", 0x8d, 0x1000, 128, }, 5359015278SRafał Miłecki { "SST25WF080", 5, 0x1000, 256, }, 5459015278SRafał Miłecki { "SST25VF080B", 0x8e, 0x1000, 256, }, 5559015278SRafał Miłecki { "SST25VF016", 0x41, 0x1000, 512, }, 5659015278SRafał Miłecki { "SST25VF032", 0x4a, 0x1000, 1024, }, 5759015278SRafał Miłecki { "SST25VF064", 0x4b, 0x1000, 2048, }, 58c9e4a3fbSHauke Mehrtens { NULL }, 5959015278SRafał Miłecki }; 6059015278SRafał Miłecki 6139cd206cSRafał Miłecki static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { 6259015278SRafał Miłecki { "AT45DB011", 0xc, 256, 512, }, 6359015278SRafał Miłecki { "AT45DB021", 0x14, 256, 1024, }, 6459015278SRafał Miłecki { "AT45DB041", 0x1c, 256, 2048, }, 6559015278SRafał Miłecki { "AT45DB081", 0x24, 256, 4096, }, 6659015278SRafał Miłecki { "AT45DB161", 0x2c, 512, 4096, }, 6759015278SRafał Miłecki { "AT45DB321", 0x34, 512, 8192, }, 6859015278SRafał Miłecki { "AT45DB642", 0x3c, 1024, 8192, }, 69c9e4a3fbSHauke Mehrtens { NULL }, 7059015278SRafał Miłecki }; 7159015278SRafał Miłecki 7259015278SRafał Miłecki static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) 7359015278SRafał Miłecki { 7459015278SRafał Miłecki int i; 7559015278SRafał Miłecki chipco_write32(cc, SSB_CHIPCO_FLASHCTL, 7659015278SRafał Miłecki SSB_CHIPCO_FLASHCTL_START | opcode); 7759015278SRafał Miłecki for (i = 0; i < 1000; i++) { 7859015278SRafał Miłecki if (!(chipco_read32(cc, SSB_CHIPCO_FLASHCTL) & 7959015278SRafał Miłecki SSB_CHIPCO_FLASHCTL_BUSY)) 8059015278SRafał Miłecki return; 8159015278SRafał Miłecki cpu_relax(); 8259015278SRafał Miłecki } 83*b8b6069cSMichael Büsch dev_err(cc->dev->dev, "SFLASH control command failed (timeout)!\n"); 8459015278SRafał Miłecki } 8559015278SRafał Miłecki 8672a525cbSRafał Miłecki /* Initialize serial flash access */ 8772a525cbSRafał Miłecki int ssb_sflash_init(struct ssb_chipcommon *cc) 8872a525cbSRafał Miłecki { 89e570bd04SRafał Miłecki struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; 9039cd206cSRafał Miłecki const struct ssb_sflash_tbl_e *e; 9159015278SRafał Miłecki u32 id, id2; 9259015278SRafał Miłecki 9359015278SRafał Miłecki switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { 9459015278SRafał Miłecki case SSB_CHIPCO_FLASHT_STSER: 9559015278SRafał Miłecki ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP); 9659015278SRafał Miłecki 9759015278SRafał Miłecki chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0); 9859015278SRafał Miłecki ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); 9959015278SRafał Miłecki id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); 10059015278SRafał Miłecki 10159015278SRafał Miłecki chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1); 10259015278SRafał Miłecki ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); 10359015278SRafał Miłecki id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); 10459015278SRafał Miłecki 10559015278SRafał Miłecki switch (id) { 10659015278SRafał Miłecki case 0xbf: 10759015278SRafał Miłecki for (e = ssb_sflash_sst_tbl; e->name; e++) { 10859015278SRafał Miłecki if (e->id == id2) 10959015278SRafał Miłecki break; 11059015278SRafał Miłecki } 11159015278SRafał Miłecki break; 11259015278SRafał Miłecki case 0x13: 11359015278SRafał Miłecki return -ENOTSUPP; 11459015278SRafał Miłecki default: 11559015278SRafał Miłecki for (e = ssb_sflash_st_tbl; e->name; e++) { 11659015278SRafał Miłecki if (e->id == id) 11759015278SRafał Miłecki break; 11859015278SRafał Miłecki } 11959015278SRafał Miłecki break; 12059015278SRafał Miłecki } 12159015278SRafał Miłecki if (!e->name) { 12259015278SRafał Miłecki pr_err("Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", 12359015278SRafał Miłecki id, id2); 12459015278SRafał Miłecki return -ENOTSUPP; 12559015278SRafał Miłecki } 12659015278SRafał Miłecki 12759015278SRafał Miłecki break; 12859015278SRafał Miłecki case SSB_CHIPCO_FLASHT_ATSER: 12959015278SRafał Miłecki ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); 13059015278SRafał Miłecki id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c; 13159015278SRafał Miłecki 13259015278SRafał Miłecki for (e = ssb_sflash_at_tbl; e->name; e++) { 13359015278SRafał Miłecki if (e->id == id) 13459015278SRafał Miłecki break; 13559015278SRafał Miłecki } 13659015278SRafał Miłecki if (!e->name) { 13759015278SRafał Miłecki pr_err("Unsupported Atmel serial flash (id: 0x%X)\n", 13859015278SRafał Miłecki id); 13959015278SRafał Miłecki return -ENOTSUPP; 14059015278SRafał Miłecki } 14159015278SRafał Miłecki 14259015278SRafał Miłecki break; 14359015278SRafał Miłecki default: 14459015278SRafał Miłecki pr_err("Unsupported flash type\n"); 14559015278SRafał Miłecki return -ENOTSUPP; 14659015278SRafał Miłecki } 14759015278SRafał Miłecki 148e570bd04SRafał Miłecki sflash->window = SSB_FLASH2; 149e570bd04SRafał Miłecki sflash->blocksize = e->blocksize; 150e570bd04SRafał Miłecki sflash->numblocks = e->numblocks; 151e570bd04SRafał Miłecki sflash->size = sflash->blocksize * sflash->numblocks; 152e570bd04SRafał Miłecki sflash->present = true; 153e570bd04SRafał Miłecki 154092c4649SRafał Miłecki pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n", 155092c4649SRafał Miłecki e->name, sflash->size / 1024, e->blocksize, e->numblocks); 15659015278SRafał Miłecki 1577b5d6043SRafał Miłecki /* Prepare platform device, but don't register it yet. It's too early, 1587b5d6043SRafał Miłecki * malloc (required by device_private_init) is not available yet. */ 1597b5d6043SRafał Miłecki ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + 1607b5d6043SRafał Miłecki sflash->size; 1617b5d6043SRafał Miłecki ssb_sflash_dev.dev.platform_data = sflash; 1627b5d6043SRafał Miłecki 163092c4649SRafał Miłecki return 0; 16472a525cbSRafał Miłecki } 165