static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc, u32 offset, u32 mask, u32 set) { u32 value; chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset); chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); value &= mask; value |= set; chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value); chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); }
static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id) { struct ssb_bus *bus = dev_id; struct ssb_chipcommon *chipco = &bus->chipco; u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN); u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ); u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL); unsigned long irqs = (val ^ pol) & mask; int gpio; if (!irqs) return IRQ_NONE; for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio)); ssb_chipco_gpio_polarity(chipco, irqs, val & irqs); return IRQ_HANDLED; }
static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) { int i; chipco_write32(cc, SSB_CHIPCO_FLASHCTL, SSB_CHIPCO_FLASHCTL_START | opcode); for (i = 0; i < 1000; i++) { if (!(chipco_read32(cc, SSB_CHIPCO_FLASHCTL) & SSB_CHIPCO_FLASHCTL_BUSY)) return; cpu_relax(); } pr_err("SFLASH control command failed (timeout)!\n"); }
static u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset) { chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); return chipco_read32(cc, SSB_CHIPCO_PLLCTL_DATA); }
/* Initialize serial flash access */ int ssb_sflash_init(struct ssb_chipcommon *cc) { struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; const struct ssb_sflash_tbl_e *e; u32 id, id2; switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { case SSB_CHIPCO_FLASHT_STSER: ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP); chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0); ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1); ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES); id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA); switch (id) { case 0xbf: for (e = ssb_sflash_sst_tbl; e->name; e++) { if (e->id == id2) break; } break; case 0x13: return -ENOTSUPP; default: for (e = ssb_sflash_st_tbl; e->name; e++) { if (e->id == id) break; } break; } if (!e->name) { pr_err("Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2); return -ENOTSUPP; } break; case SSB_CHIPCO_FLASHT_ATSER: ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS); id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c; for (e = ssb_sflash_at_tbl; e->name; e++) { if (e->id == id) break; } if (!e->name) { pr_err("Unsupported Atmel serial flash (id: 0x%X)\n", id); return -ENOTSUPP; } break; default: pr_err("Unsupported flash type\n"); return -ENOTSUPP; } sflash->window = SSB_FLASH2; sflash->blocksize = e->blocksize; sflash->numblocks = e->numblocks; sflash->size = sflash->blocksize * sflash->numblocks; sflash->present = true; pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n", e->name, sflash->size / 1024, e->blocksize, e->numblocks); /* Prepare platform device, but don't register it yet. It's too early, * malloc (required by device_private_init) is not available yet. */ ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + sflash->size; ssb_sflash_dev.dev.platform_data = sflash; return 0; }