/* We may be in 23-bit addressing mode, which uses the id as the *toptwoaddressbits.So,ifwe'rereferencingadifferentID, *useabsoluteaddresses.
*/ if (((last_addr >> 21) & 0x3) != id) returnfalse;
/* remove the top two bits from any 23-bit addressing */
last_addr &= (1 << 21) - 1;
/* We know that the addresses are limited to 21 bits, so this won't
* overflow the signed rel_addr */
rel_addr = addr - last_addr; if (rel_addr > 255 || rel_addr < -256) returnfalse;
/* we have 21 bits of address max */
addr &= ((1 << 21) - 1);
/* cmd opcodes are variable length - SAME_AR is only two bits */
opcode_bits = 3;
if (check_same_address(master, id, addr)) { /* we still address the byte offset within the word */
addr_bits = 2;
opcode_bits = 2;
opcode = FSI_CMD_SAME_AR;
trace_fsi_master_acf_cmd_same_addr(master);
/* Ring doorbell if any */ if (master->cvic)
iowrite32(0x2, master->cvic + CVIC_TRIG_REG);
/* Wait for status to indicate completion (or error) */ do { if (timeout-- == 0) {
dev_warn(master->dev, "Timeout waiting for coprocessor completion\n"); return -ETIMEDOUT;
}
stat = ioread8(master->sram + CMD_STAT_REG);
} while(stat < STAT_COMPLETE || stat == 0xff);
if (stat == STAT_COMPLETE) return0; switch(stat) { case STAT_ERR_INVAL_CMD: return -EINVAL; case STAT_ERR_INVAL_IRQ: return -EIO; case STAT_ERR_MTOE: return -ESHUTDOWN;
} return -ENXIO;
}
staticint clock_zeros(struct fsi_master_acf *master, int count)
{ while (count) { int rc, lcnt = min(count, 255);
for (i = 0; i < 512; i++) {
uint8_t v; if ((i % 16) == 0)
p = trbuf;
v = ioread8(master->sram + TRACEBUF + i);
p += sprintf(p, "%02x ", v); if (((i % 16) == 15) || v == TR_END)
dev_dbg(master->dev, "%s\n", trbuf); if (v == TR_END) break;
}
}
/* Setup segment 0 to our memory region */
regmap_write(master->scu, SCU_2500_COPRO_SEG0, master->cf_mem_addr |
SCU_2500_COPRO_SEG_SWAP);
/* Segments 2 and 3 to sysregs with byteswap (for SRAM) */
regmap_write(master->scu, SCU_2500_COPRO_SEG2, SYSREG_BASE |
SCU_2500_COPRO_SEG_SWAP);
regmap_write(master->scu, SCU_2500_COPRO_SEG3, SYSREG_BASE | 0x100000 |
SCU_2500_COPRO_SEG_SWAP);
/* And segment 6 and 7 to sysregs no byteswap */
regmap_write(master->scu, SCU_2500_COPRO_SEG6, SYSREG_BASE);
regmap_write(master->scu, SCU_2500_COPRO_SEG7, SYSREG_BASE | 0x100000);
/* Memory cachable, regs and SRAM not cachable */
regmap_write(master->scu, SCU_2500_COPRO_CACHE_CTL,
SCU_2500_COPRO_SEG0_CACHE_EN | SCU_2500_COPRO_CACHE_EN);
}
staticvoid setup_ast2400_cf_maps(struct fsi_master_acf *master)
{ /* Setup segment 0 to our memory region */
regmap_write(master->scu, SCU_2400_COPRO_SEG0, master->cf_mem_addr |
SCU_2400_COPRO_SEG_SWAP);
/* Segments 2 to sysregs with byteswap (for SRAM) */
regmap_write(master->scu, SCU_2400_COPRO_SEG2, SYSREG_BASE |
SCU_2400_COPRO_SEG_SWAP);
/* And segment 6 to sysregs no byteswap */
regmap_write(master->scu, SCU_2400_COPRO_SEG6, SYSREG_BASE);
/* Memory cachable, regs and SRAM not cachable */
regmap_write(master->scu, SCU_2400_COPRO_CACHE_CTL,
SCU_2400_COPRO_SEG0_CACHE_EN | SCU_2400_COPRO_CACHE_EN);
}
staticvoid setup_common_fw_config(struct fsi_master_acf *master, void __iomem *base)
{
iowrite16be(master->gpio_clk_vreg, base + HDR_CLOCK_GPIO_VADDR);
iowrite16be(master->gpio_clk_dreg, base + HDR_CLOCK_GPIO_DADDR);
iowrite16be(master->gpio_dat_vreg, base + HDR_DATA_GPIO_VADDR);
iowrite16be(master->gpio_dat_dreg, base + HDR_DATA_GPIO_DADDR);
iowrite16be(master->gpio_tra_vreg, base + HDR_TRANS_GPIO_VADDR);
iowrite16be(master->gpio_tra_dreg, base + HDR_TRANS_GPIO_DADDR);
iowrite8(master->gpio_clk_bit, base + HDR_CLOCK_GPIO_BIT);
iowrite8(master->gpio_dat_bit, base + HDR_DATA_GPIO_BIT);
iowrite8(master->gpio_tra_bit, base + HDR_TRANS_GPIO_BIT);
}
/* This aren't under ColdFire control, just set them up appropriately */
gpiod_direction_output(master->gpio_mux, 1);
gpiod_direction_output(master->gpio_enable, 1);
/* Those are under ColdFire control, let it configure them */
rc = aspeed_gpio_copro_grab_gpio(master->gpio_clk, &master->gpio_clk_vreg,
&master->gpio_clk_dreg, &master->gpio_clk_bit); if (rc) {
dev_err(master->dev, "failed to assign clock gpio to coprocessor\n"); return rc;
}
rc = aspeed_gpio_copro_grab_gpio(master->gpio_data, &master->gpio_dat_vreg,
&master->gpio_dat_dreg, &master->gpio_dat_bit); if (rc) {
dev_err(master->dev, "failed to assign data gpio to coprocessor\n");
aspeed_gpio_copro_release_gpio(master->gpio_clk); return rc;
}
rc = aspeed_gpio_copro_grab_gpio(master->gpio_trans, &master->gpio_tra_vreg,
&master->gpio_tra_dreg, &master->gpio_tra_bit); if (rc) {
dev_err(master->dev, "failed to assign trans gpio to coprocessor\n");
aspeed_gpio_copro_release_gpio(master->gpio_clk);
aspeed_gpio_copro_release_gpio(master->gpio_data); return rc;
} return0;
}
/* Get the binary */
rc = request_firmware(&fw, FW_FILE_NAME, master->dev); if (rc) {
dev_err(
master->dev, "Error %d to load firmware '%s' !\n",
rc, FW_FILE_NAME); return rc;
}
/* Which image do we want ? (shared vs. split clock/data GPIOs) */ if (master->gpio_clk_vreg == master->gpio_dat_vreg)
wanted_sig = SYS_SIG_SHARED; else
wanted_sig = SYS_SIG_SPLIT;
dev_dbg(master->dev, "Looking for image sig %04x\n", wanted_sig);
/* Try to find it */ for (data = fw->data; data < (fw->data + fw->size);) {
sig = be16_to_cpup((__be16 *)(data + HDR_OFFSET + HDR_SYS_SIG));
size = be32_to_cpup((__be32 *)(data + HDR_OFFSET + HDR_FW_SIZE)); if (sig == wanted_sig) break;
data += size;
} if (sig != wanted_sig) {
dev_err(master->dev, "Failed to locate image sig %04x in FW blob\n",
wanted_sig);
rc = -ENODEV; goto release_fw;
} if (size > master->cf_mem_size) {
dev_err(master->dev, "FW size (%zd) bigger than memory reserve (%zd)\n",
fw->size, master->cf_mem_size);
rc = -ENOMEM;
} else {
memcpy_toio(master->cf_mem, data, size);
}
/* Enable SW interrupt to copro if any */ if (master->cvic) {
rc = copro_enable_sw_irq(master); if (rc) goto err;
} return0;
err: /* An error occurred, don't leave the coprocessor running */
reset_cf(master);
/* Release the GPIOs */
release_copro_gpios(master);
/* We mark the copro not-started */
iowrite32(0, master->sram + CF_STARTED);
/* We mark the ARB register as having given up arbitration to *dealwithapotentialracewiththearbitrationrequest
*/
iowrite8(ARB_ARM_ACK, master->sram + ARB_REG);
local_irq_restore(flags);
/* Return the GPIOs to the ARM */
release_copro_gpios(master);
}
/* AST2400 vs. AST2500 */
master->is_ast2500 = of_device_is_compatible(mnode, "aspeed,ast2500-cf-fsi-master");
/* Grab the SCU, we'll need to access it to configure the coprocessor */ if (master->is_ast2500)
master->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2500-scu"); else
master->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2400-scu"); if (IS_ERR(master->scu)) {
dev_err(&pdev->dev, "failed to find SCU regmap\n");
rc = PTR_ERR(master->scu); goto err_free;
}
/* Grab all the GPIOs we need */
gpio = devm_gpiod_get(&pdev->dev, "clock", 0); if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get clock gpio\n");
rc = PTR_ERR(gpio); goto err_free;
}
master->gpio_clk = gpio;
gpio = devm_gpiod_get(&pdev->dev, "data", 0); if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get data gpio\n");
rc = PTR_ERR(gpio); goto err_free;
}
master->gpio_data = gpio;
/* Optional GPIOs */
gpio = devm_gpiod_get_optional(&pdev->dev, "trans", 0); if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get trans gpio\n");
rc = PTR_ERR(gpio); goto err_free;
}
master->gpio_trans = gpio;
gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 0); if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get enable gpio\n");
rc = PTR_ERR(gpio); goto err_free;
}
master->gpio_enable = gpio;
gpio = devm_gpiod_get_optional(&pdev->dev, "mux", 0); if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get mux gpio\n");
rc = PTR_ERR(gpio); goto err_free;
}
master->gpio_mux = gpio;
/* Grab the reserved memory region (use DMA API instead ?) */
rc = of_reserved_mem_region_to_resource(mnode, 0, &res); if (rc) {
dev_err(&pdev->dev, "Couldn't address to resource for reserved memory\n");
rc = -ENOMEM; goto err_free;
}
master->cf_mem_size = resource_size(&res);
master->cf_mem_addr = (uint32_t)res.start;
cf_mem_align = master->is_ast2500 ? 0x00100000 : 0x00200000; if (master->cf_mem_addr & (cf_mem_align - 1)) {
dev_err(&pdev->dev, "Reserved memory has insufficient alignment\n");
rc = -ENOMEM; goto err_free;
}
master->cf_mem = devm_ioremap_resource(&pdev->dev, &res); if (IS_ERR(master->cf_mem)) {
rc = PTR_ERR(master->cf_mem); goto err_free;
}
dev_dbg(&pdev->dev, "DRAM allocation @%x\n", master->cf_mem_addr);
/* AST2500 has a SW interrupt to the coprocessor */ if (master->is_ast2500) { /* Grab the CVIC (ColdFire interrupts controller) */
np = of_parse_phandle(mnode, "aspeed,cvic", 0); if (!np) {
dev_err(&pdev->dev, "Didn't find CVIC\n");
rc = -EINVAL; goto err_free;
}
master->cvic = devm_of_iomap(&pdev->dev, np, 0, NULL); if (IS_ERR(master->cvic)) {
of_node_put(np);
rc = PTR_ERR(master->cvic);
dev_err(&pdev->dev, "Error %d mapping CVIC\n", rc); goto err_free;
}
rc = of_property_read_u32(np, "copro-sw-interrupts",
&master->cvic_sw_irq);
of_node_put(np); if (rc) {
dev_err(&pdev->dev, "Can't find coprocessor SW interrupt\n"); goto err_free;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.