/* * I observed a typical wait time of 16 iterations for a UMA transfer to * finish, so this should be a safe limit.
*/ #define UMA_WAIT_ITERATIONS 100
/* The memory-mapped view of flash is 16 MiB long */ #define MAX_MEMORY_SIZE_PER_CS (16 << 20) #define MAX_MEMORY_SIZE_TOTAL (4 * MAX_MEMORY_SIZE_PER_CS)
/* * 4-byte addressing. * * Flash view: [ C A A A A D D D D] * bytes: 13 aa bb cc dd -> 5a a5 f0 0f * FIU's view: [ C A A A][ C D D D D] * FIU mode: [ read/write][ read ]
*/ staticbool wpcm_fiu_4ba_match(conststruct spi_mem_op *op)
{ return op->addr.nbytes == 4 && op->dummy.nbytes == 0 && op->data.nbytes <= 4;
}
if (op->data.dir == SPI_MEM_DATA_IN)
wpcm_fiu_get_data(fiu, op->data.buf.in, op->data.nbytes);
return 0;
}
/* * RDID (Read Identification) needs special handling because Linux expects to * be able to read 6 ID bytes and FIU can only read up to 4 at once. * * We're lucky in this case, because executing the RDID instruction twice will * result in the same result. * * What we do is as follows (C: write command/opcode byte, D: read data byte, * A: write address byte): * * 1. C D D D * 2. C A A A D D D
*/ staticbool wpcm_fiu_rdid_match(conststruct spi_mem_op *op)
{ return op->cmd.opcode == 0x9f && op->addr.nbytes == 0 &&
op->dummy.nbytes == 0 && op->data.nbytes == 6 &&
op->data.dir == SPI_MEM_DATA_IN;
}
/* First transfer */
wpcm_fiu_set_opcode(fiu, op->cmd.opcode);
wpcm_fiu_set_addr(fiu, 0);
wpcm_fiu_do_uma(fiu, cs, false, false, 3);
wpcm_fiu_get_data(fiu, op->data.buf.in, 3);
/* Second transfer */
wpcm_fiu_set_opcode(fiu, op->cmd.opcode);
wpcm_fiu_set_addr(fiu, 0);
wpcm_fiu_do_uma(fiu, cs, true, false, 3);
wpcm_fiu_get_data(fiu, op->data.buf.in + 3, 3);
return 0;
}
/* * With some dummy bytes. * * C A A A X* X D D D D * [C A A A D*][C D D D D]
*/ staticbool wpcm_fiu_dummy_match(conststruct spi_mem_op *op)
{ // Opcode 0x0b (FAST READ) is treated differently in hardware if (op->cmd.opcode == 0x0b) returnfalse;
/* * In order to ensure the integrity of SPI transfers performed via UMA, * temporarily disable (stall) memory accesses coming from the host CPU.
*/ staticvoid wpcm_fiu_stall_host(struct wpcm_fiu_spi *fiu, bool stall)
{ if (fiu->shm_regmap) { int res = regmap_update_bits(fiu->shm_regmap, SHM_FLASH_SIZE,
SHM_FLASH_SIZE_STALL_HOST,
stall ? SHM_FLASH_SIZE_STALL_HOST : 0); if (res)
dev_warn(fiu->dev, "Failed to (un)stall host memory accesses: %d\n", res);
}
}
if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN) return -EOPNOTSUPP;
/* * Unfortunately, FIU only supports a 16 MiB direct mapping window (per * attached flash chip), but the SPI MEM core doesn't support partial * direct mappings. This means that we can't support direct mapping on * flashes that are bigger than 16 MiB.
*/ if (desc->info.offset + desc->info.length > MAX_MEMORY_SIZE_PER_CS) return -EINVAL;
/* Don't read past the memory window */ if (cs * MAX_MEMORY_SIZE_PER_CS + desc->info.offset + desc->info.length > fiu->memory_size) return -EINVAL;
/* * The FIU doesn't include a clock divider, the clock is entirely * determined by the AHB3 bus clock.
*/
ctrl->min_speed_hz = clk_get_rate(fiu->clk);
ctrl->max_speed_hz = clk_get_rate(fiu->clk);
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.