SMI interface hides the real SPI bus between SPEAr and
external flash.
Added comments to highlight the SPI operation, to help a
future rework in SPI generic and SPEAr specific drivers.
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+/* SPEAr Serial Memory Interface (SMI) controller is a SPI bus controller
+ * specifically designed for SPI memories.
+ * Only SPI "mode 3" (CPOL=1 and CPHA=1) is supported.
+ * Two working modes are available:
+ * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
+ * on the bus.
+ * - HW mode: the SPI but is under SMI control. Memory content is directly
+ * accessible in CPU memory space. CPU can read, write and execute memory
+ * content. */
+
/* ATTENTION:
* To have flash memory mapped in CPU memory space, the SMI controller
* have to be in "HW mode". This requires following constraints:
/* ATTENTION:
* To have flash memory mapped in CPU memory space, the SMI controller
* have to be in "HW mode". This requires following constraints:
.size_in_bytes = size \
}
.size_in_bytes = size \
}
+/* List below is taken from Linux driver. It is not exhaustive of all the
+ * possible SPI memories, nor exclusive for SMI. Could be shared with
+ * other SPI drivers. */
static struct flash_device flash_devices[] = {
/* name, erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
FLASH_ID("st m25p05", 0xd8, 0x00102020, 0x80, 0x8000, 0x10000),
static struct flash_device flash_devices[] = {
/* name, erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
FLASH_ID("st m25p05", 0xd8, 0x00102020, 0x80, 0x8000, 0x10000),
return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_FLASH_OPERATION_FAILED;
}
+/* Read the status register of the external SPI flash chip.
+ * The operation is triggered by setting SMI_RSR bit.
+ * SMI sends the proper SPI command (0x05) and returns value in SMI_SR */
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
{
struct target *target = bank->target;
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
{
struct target *target = bank->target;
/* clear transmit finished flag */
SMI_CLEAR_TFF();
/* clear transmit finished flag */
SMI_CLEAR_TFF();
- /* Check write enabled */
*status = SMI_READ_REG(SMI_SR) & 0x0000ffff;
/* clean-up SMI_CR2 */
*status = SMI_READ_REG(SMI_SR) & 0x0000ffff;
/* clean-up SMI_CR2 */
+/* Send "write enable" command to SPI flash chip.
+ * The operation is triggered by setting SMI_WE bit, and SMI sends
+ * the proper SPI command (0x06) */
static int smi_write_enable(struct flash_bank *bank)
{
struct target *target = bank->target;
static int smi_write_enable(struct flash_bank *bank)
{
struct target *target = bank->target;
/* clear transmit finished flag */
SMI_CLEAR_TFF();
/* clear transmit finished flag */
SMI_CLEAR_TFF();
- /* send erase command */
+ /* send SPI command "block erase" */
cmd = erase_command(spearsmi_info, bank->sectors[sector].offset);
SMI_WRITE_REG(SMI_TR, cmd);
SMI_WRITE_REG(SMI_CR2, spearsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4);
cmd = erase_command(spearsmi_info, bank->sectors[sector].offset);
SMI_WRITE_REG(SMI_TR, cmd);
SMI_WRITE_REG(SMI_CR2, spearsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4);
/* clear transmit finished flag */
SMI_CLEAR_TFF();
/* clear transmit finished flag */
SMI_CLEAR_TFF();
- /* Require read flash ID */
+ /* Send SPI command "read ID" */
SMI_WRITE_REG(SMI_TR, SMI_READ_ID);
SMI_WRITE_REG(SMI_CR2,
spearsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1);
SMI_WRITE_REG(SMI_TR, SMI_READ_ID);
SMI_WRITE_REG(SMI_CR2,
spearsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1);
/* clear transmit finished flag */
SMI_CLEAR_TFF();
/* clear transmit finished flag */
SMI_CLEAR_TFF();
+ /* read ID from Receive Register */
*id = SMI_READ_REG(SMI_RR) & 0x00ffffff;
return ERROR_OK;
}
*id = SMI_READ_REG(SMI_RR) & 0x00ffffff;
return ERROR_OK;
}
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)