1d90db4a0SLee Jones /* 2d90db4a0SLee Jones * st_spi_fsm.c - ST Fast Sequence Mode (FSM) Serial Flash Controller 3d90db4a0SLee Jones * 4d90db4a0SLee Jones * Author: Angus Clark <angus.clark@st.com> 5d90db4a0SLee Jones * 6d90db4a0SLee Jones * Copyright (C) 2010-2014 STicroelectronics Limited 7d90db4a0SLee Jones * 8d90db4a0SLee Jones * JEDEC probe based on drivers/mtd/devices/m25p80.c 9d90db4a0SLee Jones * 10d90db4a0SLee Jones * This code is free software; you can redistribute it and/or modify 11d90db4a0SLee Jones * it under the terms of the GNU General Public License version 2 as 12d90db4a0SLee Jones * published by the Free Software Foundation. 13d90db4a0SLee Jones * 14d90db4a0SLee Jones */ 15d90db4a0SLee Jones #include <linux/kernel.h> 16d90db4a0SLee Jones #include <linux/module.h> 17a63984c1SLee Jones #include <linux/regmap.h> 18d90db4a0SLee Jones #include <linux/platform_device.h> 19a63984c1SLee Jones #include <linux/mfd/syscon.h> 20d90db4a0SLee Jones #include <linux/mtd/mtd.h> 21*221cff13SLee Jones #include <linux/mtd/partitions.h> 22d90db4a0SLee Jones #include <linux/sched.h> 23d90db4a0SLee Jones #include <linux/delay.h> 24d90db4a0SLee Jones #include <linux/io.h> 25d90db4a0SLee Jones #include <linux/of.h> 26d90db4a0SLee Jones 275549fbd5SLee Jones #include "serial_flash_cmds.h" 285549fbd5SLee Jones 29bc09fb57SLee Jones /* 30bc09fb57SLee Jones * FSM SPI Controller Registers 31bc09fb57SLee Jones */ 32bc09fb57SLee Jones #define SPI_CLOCKDIV 0x0010 33bc09fb57SLee Jones #define SPI_MODESELECT 0x0018 34bc09fb57SLee Jones #define SPI_CONFIGDATA 0x0020 35bc09fb57SLee Jones #define SPI_STA_MODE_CHANGE 0x0028 36bc09fb57SLee Jones #define SPI_FAST_SEQ_TRANSFER_SIZE 0x0100 37bc09fb57SLee Jones #define SPI_FAST_SEQ_ADD1 0x0104 38bc09fb57SLee Jones #define SPI_FAST_SEQ_ADD2 0x0108 39bc09fb57SLee Jones #define SPI_FAST_SEQ_ADD_CFG 0x010c 40bc09fb57SLee Jones #define SPI_FAST_SEQ_OPC1 0x0110 41bc09fb57SLee Jones #define SPI_FAST_SEQ_OPC2 0x0114 42bc09fb57SLee Jones #define SPI_FAST_SEQ_OPC3 0x0118 43bc09fb57SLee Jones #define SPI_FAST_SEQ_OPC4 0x011c 44bc09fb57SLee Jones #define SPI_FAST_SEQ_OPC5 0x0120 45bc09fb57SLee Jones #define SPI_MODE_BITS 0x0124 46bc09fb57SLee Jones #define SPI_DUMMY_BITS 0x0128 47bc09fb57SLee Jones #define SPI_FAST_SEQ_FLASH_STA_DATA 0x012c 48bc09fb57SLee Jones #define SPI_FAST_SEQ_1 0x0130 49bc09fb57SLee Jones #define SPI_FAST_SEQ_2 0x0134 50bc09fb57SLee Jones #define SPI_FAST_SEQ_3 0x0138 51bc09fb57SLee Jones #define SPI_FAST_SEQ_4 0x013c 52bc09fb57SLee Jones #define SPI_FAST_SEQ_CFG 0x0140 53bc09fb57SLee Jones #define SPI_FAST_SEQ_STA 0x0144 54bc09fb57SLee Jones #define SPI_QUAD_BOOT_SEQ_INIT_1 0x0148 55bc09fb57SLee Jones #define SPI_QUAD_BOOT_SEQ_INIT_2 0x014c 56bc09fb57SLee Jones #define SPI_QUAD_BOOT_READ_SEQ_1 0x0150 57bc09fb57SLee Jones #define SPI_QUAD_BOOT_READ_SEQ_2 0x0154 58bc09fb57SLee Jones #define SPI_PROGRAM_ERASE_TIME 0x0158 59bc09fb57SLee Jones #define SPI_MULT_PAGE_REPEAT_SEQ_1 0x015c 60bc09fb57SLee Jones #define SPI_MULT_PAGE_REPEAT_SEQ_2 0x0160 61bc09fb57SLee Jones #define SPI_STATUS_WR_TIME_REG 0x0164 62bc09fb57SLee Jones #define SPI_FAST_SEQ_DATA_REG 0x0300 63bc09fb57SLee Jones 64bc09fb57SLee Jones /* 65bc09fb57SLee Jones * Register: SPI_MODESELECT 66bc09fb57SLee Jones */ 67bc09fb57SLee Jones #define SPI_MODESELECT_CONTIG 0x01 68bc09fb57SLee Jones #define SPI_MODESELECT_FASTREAD 0x02 69bc09fb57SLee Jones #define SPI_MODESELECT_DUALIO 0x04 70bc09fb57SLee Jones #define SPI_MODESELECT_FSM 0x08 71bc09fb57SLee Jones #define SPI_MODESELECT_QUADBOOT 0x10 72bc09fb57SLee Jones 73bc09fb57SLee Jones /* 74bc09fb57SLee Jones * Register: SPI_CONFIGDATA 75bc09fb57SLee Jones */ 76bc09fb57SLee Jones #define SPI_CFG_DEVICE_ST 0x1 77bc09fb57SLee Jones #define SPI_CFG_DEVICE_ATMEL 0x4 78bc09fb57SLee Jones #define SPI_CFG_MIN_CS_HIGH(x) (((x) & 0xfff) << 4) 79bc09fb57SLee Jones #define SPI_CFG_CS_SETUPHOLD(x) (((x) & 0xff) << 16) 80bc09fb57SLee Jones #define SPI_CFG_DATA_HOLD(x) (((x) & 0xff) << 24) 81bc09fb57SLee Jones 8286f309fdSLee Jones #define SPI_CFG_DEFAULT_MIN_CS_HIGH SPI_CFG_MIN_CS_HIGH(0x0AA) 8386f309fdSLee Jones #define SPI_CFG_DEFAULT_CS_SETUPHOLD SPI_CFG_CS_SETUPHOLD(0xA0) 8486f309fdSLee Jones #define SPI_CFG_DEFAULT_DATA_HOLD SPI_CFG_DATA_HOLD(0x00) 8586f309fdSLee Jones 86bc09fb57SLee Jones /* 87bc09fb57SLee Jones * Register: SPI_FAST_SEQ_TRANSFER_SIZE 88bc09fb57SLee Jones */ 89bc09fb57SLee Jones #define TRANSFER_SIZE(x) ((x) * 8) 90bc09fb57SLee Jones 91bc09fb57SLee Jones /* 92bc09fb57SLee Jones * Register: SPI_FAST_SEQ_ADD_CFG 93bc09fb57SLee Jones */ 94bc09fb57SLee Jones #define ADR_CFG_CYCLES_ADD1(x) ((x) << 0) 95bc09fb57SLee Jones #define ADR_CFG_PADS_1_ADD1 (0x0 << 6) 96bc09fb57SLee Jones #define ADR_CFG_PADS_2_ADD1 (0x1 << 6) 97bc09fb57SLee Jones #define ADR_CFG_PADS_4_ADD1 (0x3 << 6) 98bc09fb57SLee Jones #define ADR_CFG_CSDEASSERT_ADD1 (1 << 8) 99bc09fb57SLee Jones #define ADR_CFG_CYCLES_ADD2(x) ((x) << (0+16)) 100bc09fb57SLee Jones #define ADR_CFG_PADS_1_ADD2 (0x0 << (6+16)) 101bc09fb57SLee Jones #define ADR_CFG_PADS_2_ADD2 (0x1 << (6+16)) 102bc09fb57SLee Jones #define ADR_CFG_PADS_4_ADD2 (0x3 << (6+16)) 103bc09fb57SLee Jones #define ADR_CFG_CSDEASSERT_ADD2 (1 << (8+16)) 104bc09fb57SLee Jones 105bc09fb57SLee Jones /* 106bc09fb57SLee Jones * Register: SPI_FAST_SEQ_n 107bc09fb57SLee Jones */ 108bc09fb57SLee Jones #define SEQ_OPC_OPCODE(x) ((x) << 0) 109bc09fb57SLee Jones #define SEQ_OPC_CYCLES(x) ((x) << 8) 110bc09fb57SLee Jones #define SEQ_OPC_PADS_1 (0x0 << 14) 111bc09fb57SLee Jones #define SEQ_OPC_PADS_2 (0x1 << 14) 112bc09fb57SLee Jones #define SEQ_OPC_PADS_4 (0x3 << 14) 113bc09fb57SLee Jones #define SEQ_OPC_CSDEASSERT (1 << 16) 114bc09fb57SLee Jones 115bc09fb57SLee Jones /* 116bc09fb57SLee Jones * Register: SPI_FAST_SEQ_CFG 117bc09fb57SLee Jones */ 118bc09fb57SLee Jones #define SEQ_CFG_STARTSEQ (1 << 0) 119bc09fb57SLee Jones #define SEQ_CFG_SWRESET (1 << 5) 120bc09fb57SLee Jones #define SEQ_CFG_CSDEASSERT (1 << 6) 121bc09fb57SLee Jones #define SEQ_CFG_READNOTWRITE (1 << 7) 122bc09fb57SLee Jones #define SEQ_CFG_ERASE (1 << 8) 123bc09fb57SLee Jones #define SEQ_CFG_PADS_1 (0x0 << 16) 124bc09fb57SLee Jones #define SEQ_CFG_PADS_2 (0x1 << 16) 125bc09fb57SLee Jones #define SEQ_CFG_PADS_4 (0x3 << 16) 126bc09fb57SLee Jones 127bc09fb57SLee Jones /* 128bc09fb57SLee Jones * Register: SPI_MODE_BITS 129bc09fb57SLee Jones */ 130bc09fb57SLee Jones #define MODE_DATA(x) (x & 0xff) 131bc09fb57SLee Jones #define MODE_CYCLES(x) ((x & 0x3f) << 16) 132bc09fb57SLee Jones #define MODE_PADS_1 (0x0 << 22) 133bc09fb57SLee Jones #define MODE_PADS_2 (0x1 << 22) 134bc09fb57SLee Jones #define MODE_PADS_4 (0x3 << 22) 135bc09fb57SLee Jones #define DUMMY_CSDEASSERT (1 << 24) 136bc09fb57SLee Jones 137bc09fb57SLee Jones /* 138bc09fb57SLee Jones * Register: SPI_DUMMY_BITS 139bc09fb57SLee Jones */ 140bc09fb57SLee Jones #define DUMMY_CYCLES(x) ((x & 0x3f) << 16) 141bc09fb57SLee Jones #define DUMMY_PADS_1 (0x0 << 22) 142bc09fb57SLee Jones #define DUMMY_PADS_2 (0x1 << 22) 143bc09fb57SLee Jones #define DUMMY_PADS_4 (0x3 << 22) 144bc09fb57SLee Jones #define DUMMY_CSDEASSERT (1 << 24) 145bc09fb57SLee Jones 146bc09fb57SLee Jones /* 147bc09fb57SLee Jones * Register: SPI_FAST_SEQ_FLASH_STA_DATA 148bc09fb57SLee Jones */ 149bc09fb57SLee Jones #define STA_DATA_BYTE1(x) ((x & 0xff) << 0) 150bc09fb57SLee Jones #define STA_DATA_BYTE2(x) ((x & 0xff) << 8) 151bc09fb57SLee Jones #define STA_PADS_1 (0x0 << 16) 152bc09fb57SLee Jones #define STA_PADS_2 (0x1 << 16) 153bc09fb57SLee Jones #define STA_PADS_4 (0x3 << 16) 154bc09fb57SLee Jones #define STA_CSDEASSERT (0x1 << 20) 155bc09fb57SLee Jones #define STA_RDNOTWR (0x1 << 21) 156bc09fb57SLee Jones 157bc09fb57SLee Jones /* 158bc09fb57SLee Jones * FSM SPI Instruction Opcodes 159bc09fb57SLee Jones */ 160bc09fb57SLee Jones #define STFSM_OPC_CMD 0x1 161bc09fb57SLee Jones #define STFSM_OPC_ADD 0x2 162bc09fb57SLee Jones #define STFSM_OPC_STA 0x3 163bc09fb57SLee Jones #define STFSM_OPC_MODE 0x4 164bc09fb57SLee Jones #define STFSM_OPC_DUMMY 0x5 165bc09fb57SLee Jones #define STFSM_OPC_DATA 0x6 166bc09fb57SLee Jones #define STFSM_OPC_WAIT 0x7 167bc09fb57SLee Jones #define STFSM_OPC_JUMP 0x8 168bc09fb57SLee Jones #define STFSM_OPC_GOTO 0x9 169bc09fb57SLee Jones #define STFSM_OPC_STOP 0xF 170bc09fb57SLee Jones 171bc09fb57SLee Jones /* 172bc09fb57SLee Jones * FSM SPI Instructions (== opcode + operand). 173bc09fb57SLee Jones */ 174bc09fb57SLee Jones #define STFSM_INSTR(cmd, op) ((cmd) | ((op) << 4)) 175bc09fb57SLee Jones 176bc09fb57SLee Jones #define STFSM_INST_CMD1 STFSM_INSTR(STFSM_OPC_CMD, 1) 177bc09fb57SLee Jones #define STFSM_INST_CMD2 STFSM_INSTR(STFSM_OPC_CMD, 2) 178bc09fb57SLee Jones #define STFSM_INST_CMD3 STFSM_INSTR(STFSM_OPC_CMD, 3) 179bc09fb57SLee Jones #define STFSM_INST_CMD4 STFSM_INSTR(STFSM_OPC_CMD, 4) 180bc09fb57SLee Jones #define STFSM_INST_CMD5 STFSM_INSTR(STFSM_OPC_CMD, 5) 181bc09fb57SLee Jones #define STFSM_INST_ADD1 STFSM_INSTR(STFSM_OPC_ADD, 1) 182bc09fb57SLee Jones #define STFSM_INST_ADD2 STFSM_INSTR(STFSM_OPC_ADD, 2) 183bc09fb57SLee Jones 184bc09fb57SLee Jones #define STFSM_INST_DATA_WRITE STFSM_INSTR(STFSM_OPC_DATA, 1) 185bc09fb57SLee Jones #define STFSM_INST_DATA_READ STFSM_INSTR(STFSM_OPC_DATA, 2) 186bc09fb57SLee Jones 187bc09fb57SLee Jones #define STFSM_INST_STA_RD1 STFSM_INSTR(STFSM_OPC_STA, 0x1) 188bc09fb57SLee Jones #define STFSM_INST_STA_WR1 STFSM_INSTR(STFSM_OPC_STA, 0x1) 189bc09fb57SLee Jones #define STFSM_INST_STA_RD2 STFSM_INSTR(STFSM_OPC_STA, 0x2) 190bc09fb57SLee Jones #define STFSM_INST_STA_WR1_2 STFSM_INSTR(STFSM_OPC_STA, 0x3) 191bc09fb57SLee Jones 192bc09fb57SLee Jones #define STFSM_INST_MODE STFSM_INSTR(STFSM_OPC_MODE, 0) 193bc09fb57SLee Jones #define STFSM_INST_DUMMY STFSM_INSTR(STFSM_OPC_DUMMY, 0) 194bc09fb57SLee Jones #define STFSM_INST_WAIT STFSM_INSTR(STFSM_OPC_WAIT, 0) 195bc09fb57SLee Jones #define STFSM_INST_STOP STFSM_INSTR(STFSM_OPC_STOP, 0) 196bc09fb57SLee Jones 19786f309fdSLee Jones #define STFSM_DEFAULT_EMI_FREQ 100000000UL /* 100 MHz */ 19886f309fdSLee Jones #define STFSM_DEFAULT_WR_TIME (STFSM_DEFAULT_EMI_FREQ * (15/1000)) /* 15ms */ 19986f309fdSLee Jones 20086f309fdSLee Jones #define STFSM_FLASH_SAFE_FREQ 10000000UL /* 10 MHz */ 20186f309fdSLee Jones 2023c8b85b3SLee Jones #define STFSM_MAX_WAIT_SEQ_MS 1000 /* FSM execution time */ 2033c8b85b3SLee Jones 204e85a6196SLee Jones /* Flash Commands */ 205e85a6196SLee Jones #define FLASH_CMD_WREN 0x06 206e85a6196SLee Jones #define FLASH_CMD_WRDI 0x04 207e85a6196SLee Jones #define FLASH_CMD_RDID 0x9f 208e85a6196SLee Jones #define FLASH_CMD_RDSR 0x05 209e85a6196SLee Jones #define FLASH_CMD_RDSR2 0x35 210e85a6196SLee Jones #define FLASH_CMD_WRSR 0x01 211e85a6196SLee Jones #define FLASH_CMD_SE_4K 0x20 212e85a6196SLee Jones #define FLASH_CMD_SE_32K 0x52 213e85a6196SLee Jones #define FLASH_CMD_SE 0xd8 214e85a6196SLee Jones #define FLASH_CMD_CHIPERASE 0xc7 215e85a6196SLee Jones #define FLASH_CMD_WRVCR 0x81 216e85a6196SLee Jones #define FLASH_CMD_RDVCR 0x85 217e85a6196SLee Jones 218e85a6196SLee Jones #define FLASH_CMD_READ 0x03 /* READ */ 219e85a6196SLee Jones #define FLASH_CMD_READ_FAST 0x0b /* FAST READ */ 220e85a6196SLee Jones #define FLASH_CMD_READ_1_1_2 0x3b /* DUAL OUTPUT READ */ 221e85a6196SLee Jones #define FLASH_CMD_READ_1_2_2 0xbb /* DUAL I/O READ */ 222e85a6196SLee Jones #define FLASH_CMD_READ_1_1_4 0x6b /* QUAD OUTPUT READ */ 223e85a6196SLee Jones #define FLASH_CMD_READ_1_4_4 0xeb /* QUAD I/O READ */ 224e85a6196SLee Jones 225e85a6196SLee Jones #define FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */ 226e85a6196SLee Jones #define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */ 227e85a6196SLee Jones #define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */ 228e85a6196SLee Jones #define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */ 229e85a6196SLee Jones #define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */ 230e85a6196SLee Jones 231e85a6196SLee Jones #define FLASH_CMD_EN4B_ADDR 0xb7 /* Enter 4-byte address mode */ 232e85a6196SLee Jones #define FLASH_CMD_EX4B_ADDR 0xe9 /* Exit 4-byte address mode */ 233e85a6196SLee Jones 234e85a6196SLee Jones /* READ commands with 32-bit addressing (N25Q256 and S25FLxxxS) */ 235e85a6196SLee Jones #define FLASH_CMD_READ4 0x13 236e85a6196SLee Jones #define FLASH_CMD_READ4_FAST 0x0c 237e85a6196SLee Jones #define FLASH_CMD_READ4_1_1_2 0x3c 238e85a6196SLee Jones #define FLASH_CMD_READ4_1_2_2 0xbc 239e85a6196SLee Jones #define FLASH_CMD_READ4_1_1_4 0x6c 240e85a6196SLee Jones #define FLASH_CMD_READ4_1_4_4 0xec 241e85a6196SLee Jones 2425343a123SLee Jones /* S25FLxxxS commands */ 2435343a123SLee Jones #define S25FL_CMD_WRITE4_1_1_4 0x34 2445343a123SLee Jones #define S25FL_CMD_SE4 0xdc 2455343a123SLee Jones #define S25FL_CMD_CLSR 0x30 2465343a123SLee Jones #define S25FL_CMD_DYBWR 0xe1 2475343a123SLee Jones #define S25FL_CMD_DYBRD 0xe0 2485343a123SLee Jones #define S25FL_CMD_WRITE4 0x12 /* Note, opcode clashes with 2495343a123SLee Jones * 'FLASH_CMD_WRITE_1_4_4' 2505343a123SLee Jones * as found on N25Qxxx devices! */ 2515343a123SLee Jones 252176b4377SLee Jones /* Status register */ 253176b4377SLee Jones #define FLASH_STATUS_BUSY 0x01 254176b4377SLee Jones #define FLASH_STATUS_WEL 0x02 255176b4377SLee Jones #define FLASH_STATUS_BP0 0x04 256176b4377SLee Jones #define FLASH_STATUS_BP1 0x08 257176b4377SLee Jones #define FLASH_STATUS_BP2 0x10 258176b4377SLee Jones #define FLASH_STATUS_SRWP0 0x80 259176b4377SLee Jones #define FLASH_STATUS_TIMEOUT 0xff 2605343a123SLee Jones /* S25FL Error Flags */ 2615343a123SLee Jones #define S25FL_STATUS_E_ERR 0x20 2625343a123SLee Jones #define S25FL_STATUS_P_ERR 0x40 263176b4377SLee Jones 264e514f105SLee Jones #define FLASH_PAGESIZE 256 /* In Bytes */ 265e514f105SLee Jones #define FLASH_PAGESIZE_32 (FLASH_PAGESIZE / 4) /* In uint32_t */ 266176b4377SLee Jones #define FLASH_MAX_BUSY_WAIT (300 * HZ) /* Maximum 'CHIPERASE' time */ 267e514f105SLee Jones 268e85a6196SLee Jones /* 269e85a6196SLee Jones * Flags to tweak operation of default read/write/erase routines 270e85a6196SLee Jones */ 271e85a6196SLee Jones #define CFG_READ_TOGGLE_32BIT_ADDR 0x00000001 272e85a6196SLee Jones #define CFG_WRITE_TOGGLE_32BIT_ADDR 0x00000002 273e85a6196SLee Jones #define CFG_WRITE_EX_32BIT_ADDR_DELAY 0x00000004 274e85a6196SLee Jones #define CFG_ERASESEC_TOGGLE_32BIT_ADDR 0x00000008 275e85a6196SLee Jones #define CFG_S25FL_CHECK_ERROR_FLAGS 0x00000010 276e85a6196SLee Jones 277e6b1bb4eSLee Jones struct stfsm_seq { 278e6b1bb4eSLee Jones uint32_t data_size; 279e6b1bb4eSLee Jones uint32_t addr1; 280e6b1bb4eSLee Jones uint32_t addr2; 281e6b1bb4eSLee Jones uint32_t addr_cfg; 282e6b1bb4eSLee Jones uint32_t seq_opc[5]; 283e6b1bb4eSLee Jones uint32_t mode; 284e6b1bb4eSLee Jones uint32_t dummy; 285e6b1bb4eSLee Jones uint32_t status; 286e6b1bb4eSLee Jones uint8_t seq[16]; 287e6b1bb4eSLee Jones uint32_t seq_cfg; 288e6b1bb4eSLee Jones } __packed __aligned(4); 289e6b1bb4eSLee Jones 290d90db4a0SLee Jones struct stfsm { 291d90db4a0SLee Jones struct device *dev; 292d90db4a0SLee Jones void __iomem *base; 293d90db4a0SLee Jones struct resource *region; 294d90db4a0SLee Jones struct mtd_info mtd; 295d90db4a0SLee Jones struct mutex lock; 29624fec651SLee Jones struct flash_info *info; 29786f309fdSLee Jones 298e85a6196SLee Jones uint32_t configuration; 29986f309fdSLee Jones uint32_t fifo_dir_delay; 300a63984c1SLee Jones bool booted_from_spi; 3010ea7d706SLee Jones bool reset_signal; 3020ea7d706SLee Jones bool reset_por; 303d90db4a0SLee Jones 304e6b1bb4eSLee Jones struct stfsm_seq stfsm_seq_read; 305e6b1bb4eSLee Jones struct stfsm_seq stfsm_seq_write; 306e6b1bb4eSLee Jones struct stfsm_seq stfsm_seq_en_32bit_addr; 307e6b1bb4eSLee Jones }; 3083c8b85b3SLee Jones 30908981274SLee Jones /* Parameters to configure a READ or WRITE FSM sequence */ 31008981274SLee Jones struct seq_rw_config { 31108981274SLee Jones uint32_t flags; /* flags to support config */ 31208981274SLee Jones uint8_t cmd; /* FLASH command */ 31308981274SLee Jones int write; /* Write Sequence */ 31408981274SLee Jones uint8_t addr_pads; /* No. of addr pads (MODE & DUMMY) */ 31508981274SLee Jones uint8_t data_pads; /* No. of data pads */ 31608981274SLee Jones uint8_t mode_data; /* MODE data */ 31708981274SLee Jones uint8_t mode_cycles; /* No. of MODE cycles */ 31808981274SLee Jones uint8_t dummy_cycles; /* No. of DUMMY cycles */ 31908981274SLee Jones }; 32008981274SLee Jones 32111d7f826SLee Jones /* SPI Flash Device Table */ 32211d7f826SLee Jones struct flash_info { 32311d7f826SLee Jones char *name; 32411d7f826SLee Jones /* 32511d7f826SLee Jones * JEDEC id zero means "no ID" (most older chips); otherwise it has 32611d7f826SLee Jones * a high byte of zero plus three data bytes: the manufacturer id, 32711d7f826SLee Jones * then a two byte device id. 32811d7f826SLee Jones */ 32911d7f826SLee Jones u32 jedec_id; 33011d7f826SLee Jones u16 ext_id; 33111d7f826SLee Jones /* 33211d7f826SLee Jones * The size listed here is what works with FLASH_CMD_SE, which isn't 33311d7f826SLee Jones * necessarily called a "sector" by the vendor. 33411d7f826SLee Jones */ 33511d7f826SLee Jones unsigned sector_size; 33611d7f826SLee Jones u16 n_sectors; 33711d7f826SLee Jones u32 flags; 33811d7f826SLee Jones /* 33911d7f826SLee Jones * Note, where FAST_READ is supported, freq_max specifies the 34011d7f826SLee Jones * FAST_READ frequency, not the READ frequency. 34111d7f826SLee Jones */ 34211d7f826SLee Jones u32 max_freq; 34311d7f826SLee Jones int (*config)(struct stfsm *); 34411d7f826SLee Jones }; 34511d7f826SLee Jones 346218b870fSLee Jones static int stfsm_n25q_config(struct stfsm *fsm); 34789818066SLee Jones static int stfsm_mx25_config(struct stfsm *fsm); 3485343a123SLee Jones static int stfsm_s25fl_config(struct stfsm *fsm); 349cd7cac9eSLee Jones static int stfsm_w25q_config(struct stfsm *fsm); 350218b870fSLee Jones 35111d7f826SLee Jones static struct flash_info flash_types[] = { 35211d7f826SLee Jones /* 35311d7f826SLee Jones * ST Microelectronics/Numonyx -- 35411d7f826SLee Jones * (newer production versions may have feature updates 35511d7f826SLee Jones * (eg faster operating frequency) 35611d7f826SLee Jones */ 35711d7f826SLee Jones #define M25P_FLAG (FLASH_FLAG_READ_WRITE | FLASH_FLAG_READ_FAST) 35811d7f826SLee Jones { "m25p40", 0x202013, 0, 64 * 1024, 8, M25P_FLAG, 25, NULL }, 35911d7f826SLee Jones { "m25p80", 0x202014, 0, 64 * 1024, 16, M25P_FLAG, 25, NULL }, 36011d7f826SLee Jones { "m25p16", 0x202015, 0, 64 * 1024, 32, M25P_FLAG, 25, NULL }, 36111d7f826SLee Jones { "m25p32", 0x202016, 0, 64 * 1024, 64, M25P_FLAG, 50, NULL }, 36211d7f826SLee Jones { "m25p64", 0x202017, 0, 64 * 1024, 128, M25P_FLAG, 50, NULL }, 36311d7f826SLee Jones { "m25p128", 0x202018, 0, 256 * 1024, 64, M25P_FLAG, 50, NULL }, 36411d7f826SLee Jones 36511d7f826SLee Jones #define M25PX_FLAG (FLASH_FLAG_READ_WRITE | \ 36611d7f826SLee Jones FLASH_FLAG_READ_FAST | \ 36711d7f826SLee Jones FLASH_FLAG_READ_1_1_2 | \ 36811d7f826SLee Jones FLASH_FLAG_WRITE_1_1_2) 36911d7f826SLee Jones { "m25px32", 0x207116, 0, 64 * 1024, 64, M25PX_FLAG, 75, NULL }, 37011d7f826SLee Jones { "m25px64", 0x207117, 0, 64 * 1024, 128, M25PX_FLAG, 75, NULL }, 37111d7f826SLee Jones 37211d7f826SLee Jones #define MX25_FLAG (FLASH_FLAG_READ_WRITE | \ 37311d7f826SLee Jones FLASH_FLAG_READ_FAST | \ 37411d7f826SLee Jones FLASH_FLAG_READ_1_1_2 | \ 37511d7f826SLee Jones FLASH_FLAG_READ_1_2_2 | \ 37611d7f826SLee Jones FLASH_FLAG_READ_1_1_4 | \ 37711d7f826SLee Jones FLASH_FLAG_READ_1_4_4 | \ 37811d7f826SLee Jones FLASH_FLAG_SE_4K | \ 37911d7f826SLee Jones FLASH_FLAG_SE_32K) 38011d7f826SLee Jones { "mx25l25635e", 0xc22019, 0, 64*1024, 512, 38189818066SLee Jones (MX25_FLAG | FLASH_FLAG_32BIT_ADDR | FLASH_FLAG_RESET), 70, 38289818066SLee Jones stfsm_mx25_config }, 38311d7f826SLee Jones 38411d7f826SLee Jones #define N25Q_FLAG (FLASH_FLAG_READ_WRITE | \ 38511d7f826SLee Jones FLASH_FLAG_READ_FAST | \ 38611d7f826SLee Jones FLASH_FLAG_READ_1_1_2 | \ 38711d7f826SLee Jones FLASH_FLAG_READ_1_2_2 | \ 38811d7f826SLee Jones FLASH_FLAG_READ_1_1_4 | \ 38911d7f826SLee Jones FLASH_FLAG_READ_1_4_4 | \ 39011d7f826SLee Jones FLASH_FLAG_WRITE_1_1_2 | \ 39111d7f826SLee Jones FLASH_FLAG_WRITE_1_2_2 | \ 39211d7f826SLee Jones FLASH_FLAG_WRITE_1_1_4 | \ 39311d7f826SLee Jones FLASH_FLAG_WRITE_1_4_4) 394218b870fSLee Jones { "n25q128", 0x20ba18, 0, 64 * 1024, 256, N25Q_FLAG, 108, 395218b870fSLee Jones stfsm_n25q_config }, 39611d7f826SLee Jones { "n25q256", 0x20ba19, 0, 64 * 1024, 512, 397218b870fSLee Jones N25Q_FLAG | FLASH_FLAG_32BIT_ADDR, 108, stfsm_n25q_config }, 39811d7f826SLee Jones 39911d7f826SLee Jones /* 40011d7f826SLee Jones * Spansion S25FLxxxP 40111d7f826SLee Jones * - 256KiB and 64KiB sector variants (identified by ext. JEDEC) 40211d7f826SLee Jones */ 40311d7f826SLee Jones #define S25FLXXXP_FLAG (FLASH_FLAG_READ_WRITE | \ 40411d7f826SLee Jones FLASH_FLAG_READ_1_1_2 | \ 40511d7f826SLee Jones FLASH_FLAG_READ_1_2_2 | \ 40611d7f826SLee Jones FLASH_FLAG_READ_1_1_4 | \ 40711d7f826SLee Jones FLASH_FLAG_READ_1_4_4 | \ 40811d7f826SLee Jones FLASH_FLAG_WRITE_1_1_4 | \ 40911d7f826SLee Jones FLASH_FLAG_READ_FAST) 41011d7f826SLee Jones { "s25fl129p0", 0x012018, 0x4d00, 256 * 1024, 64, S25FLXXXP_FLAG, 80, 4115343a123SLee Jones stfsm_s25fl_config }, 41211d7f826SLee Jones { "s25fl129p1", 0x012018, 0x4d01, 64 * 1024, 256, S25FLXXXP_FLAG, 80, 4135343a123SLee Jones stfsm_s25fl_config }, 41411d7f826SLee Jones 41511d7f826SLee Jones /* 41611d7f826SLee Jones * Spansion S25FLxxxS 41711d7f826SLee Jones * - 256KiB and 64KiB sector variants (identified by ext. JEDEC) 41811d7f826SLee Jones * - RESET# signal supported by die but not bristled out on all 41911d7f826SLee Jones * package types. The package type is a function of board design, 42011d7f826SLee Jones * so this information is captured in the board's flags. 42111d7f826SLee Jones * - Supports 'DYB' sector protection. Depending on variant, sectors 42211d7f826SLee Jones * may default to locked state on power-on. 42311d7f826SLee Jones */ 42411d7f826SLee Jones #define S25FLXXXS_FLAG (S25FLXXXP_FLAG | \ 42511d7f826SLee Jones FLASH_FLAG_RESET | \ 42611d7f826SLee Jones FLASH_FLAG_DYB_LOCKING) 42711d7f826SLee Jones { "s25fl128s0", 0x012018, 0x0300, 256 * 1024, 64, S25FLXXXS_FLAG, 80, 4285343a123SLee Jones stfsm_s25fl_config }, 42911d7f826SLee Jones { "s25fl128s1", 0x012018, 0x0301, 64 * 1024, 256, S25FLXXXS_FLAG, 80, 4305343a123SLee Jones stfsm_s25fl_config }, 43111d7f826SLee Jones { "s25fl256s0", 0x010219, 0x4d00, 256 * 1024, 128, 4325343a123SLee Jones S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, stfsm_s25fl_config }, 43311d7f826SLee Jones { "s25fl256s1", 0x010219, 0x4d01, 64 * 1024, 512, 4345343a123SLee Jones S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, stfsm_s25fl_config }, 43511d7f826SLee Jones 43611d7f826SLee Jones /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ 43711d7f826SLee Jones #define W25X_FLAG (FLASH_FLAG_READ_WRITE | \ 43811d7f826SLee Jones FLASH_FLAG_READ_FAST | \ 43911d7f826SLee Jones FLASH_FLAG_READ_1_1_2 | \ 44011d7f826SLee Jones FLASH_FLAG_WRITE_1_1_2) 44111d7f826SLee Jones { "w25x40", 0xef3013, 0, 64 * 1024, 8, W25X_FLAG, 75, NULL }, 44211d7f826SLee Jones { "w25x80", 0xef3014, 0, 64 * 1024, 16, W25X_FLAG, 75, NULL }, 44311d7f826SLee Jones { "w25x16", 0xef3015, 0, 64 * 1024, 32, W25X_FLAG, 75, NULL }, 44411d7f826SLee Jones { "w25x32", 0xef3016, 0, 64 * 1024, 64, W25X_FLAG, 75, NULL }, 44511d7f826SLee Jones { "w25x64", 0xef3017, 0, 64 * 1024, 128, W25X_FLAG, 75, NULL }, 44611d7f826SLee Jones 44711d7f826SLee Jones /* Winbond -- w25q "blocks" are 64K, "sectors" are 4KiB */ 44811d7f826SLee Jones #define W25Q_FLAG (FLASH_FLAG_READ_WRITE | \ 44911d7f826SLee Jones FLASH_FLAG_READ_FAST | \ 45011d7f826SLee Jones FLASH_FLAG_READ_1_1_2 | \ 45111d7f826SLee Jones FLASH_FLAG_READ_1_2_2 | \ 45211d7f826SLee Jones FLASH_FLAG_READ_1_1_4 | \ 45311d7f826SLee Jones FLASH_FLAG_READ_1_4_4 | \ 45411d7f826SLee Jones FLASH_FLAG_WRITE_1_1_4) 455cd7cac9eSLee Jones { "w25q80", 0xef4014, 0, 64 * 1024, 16, W25Q_FLAG, 80, 456cd7cac9eSLee Jones stfsm_w25q_config }, 457cd7cac9eSLee Jones { "w25q16", 0xef4015, 0, 64 * 1024, 32, W25Q_FLAG, 80, 458cd7cac9eSLee Jones stfsm_w25q_config }, 459cd7cac9eSLee Jones { "w25q32", 0xef4016, 0, 64 * 1024, 64, W25Q_FLAG, 80, 460cd7cac9eSLee Jones stfsm_w25q_config }, 461cd7cac9eSLee Jones { "w25q64", 0xef4017, 0, 64 * 1024, 128, W25Q_FLAG, 80, 462cd7cac9eSLee Jones stfsm_w25q_config }, 46311d7f826SLee Jones 46411d7f826SLee Jones /* Sentinel */ 46511d7f826SLee Jones { NULL, 0x000000, 0, 0, 0, 0, 0, NULL }, 46611d7f826SLee Jones }; 46711d7f826SLee Jones 468a37b2f5aSLee Jones /* 469a37b2f5aSLee Jones * FSM message sequence configurations: 470a37b2f5aSLee Jones * 471a37b2f5aSLee Jones * All configs are presented in order of preference 472a37b2f5aSLee Jones */ 473a37b2f5aSLee Jones 474a37b2f5aSLee Jones /* Default READ configurations, in order of preference */ 475a37b2f5aSLee Jones static struct seq_rw_config default_read_configs[] = { 476a37b2f5aSLee Jones {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ_1_4_4, 0, 4, 4, 0x00, 2, 4}, 477a37b2f5aSLee Jones {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ_1_1_4, 0, 1, 4, 0x00, 4, 0}, 478a37b2f5aSLee Jones {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ_1_2_2, 0, 2, 2, 0x00, 4, 0}, 479a37b2f5aSLee Jones {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ_1_1_2, 0, 1, 2, 0x00, 0, 8}, 480a37b2f5aSLee Jones {FLASH_FLAG_READ_FAST, FLASH_CMD_READ_FAST, 0, 1, 1, 0x00, 0, 8}, 481a37b2f5aSLee Jones {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ, 0, 1, 1, 0x00, 0, 0}, 482a37b2f5aSLee Jones {0x00, 0, 0, 0, 0, 0x00, 0, 0}, 483a37b2f5aSLee Jones }; 484a37b2f5aSLee Jones 485a37b2f5aSLee Jones /* Default WRITE configurations */ 486a37b2f5aSLee Jones static struct seq_rw_config default_write_configs[] = { 487a37b2f5aSLee Jones {FLASH_FLAG_WRITE_1_4_4, FLASH_CMD_WRITE_1_4_4, 1, 4, 4, 0x00, 0, 0}, 488a37b2f5aSLee Jones {FLASH_FLAG_WRITE_1_1_4, FLASH_CMD_WRITE_1_1_4, 1, 1, 4, 0x00, 0, 0}, 489a37b2f5aSLee Jones {FLASH_FLAG_WRITE_1_2_2, FLASH_CMD_WRITE_1_2_2, 1, 2, 2, 0x00, 0, 0}, 490a37b2f5aSLee Jones {FLASH_FLAG_WRITE_1_1_2, FLASH_CMD_WRITE_1_1_2, 1, 1, 2, 0x00, 0, 0}, 491a37b2f5aSLee Jones {FLASH_FLAG_READ_WRITE, FLASH_CMD_WRITE, 1, 1, 1, 0x00, 0, 0}, 492a37b2f5aSLee Jones {0x00, 0, 0, 0, 0, 0x00, 0, 0}, 493a37b2f5aSLee Jones }; 494a37b2f5aSLee Jones 495e85a6196SLee Jones /* 496e85a6196SLee Jones * [N25Qxxx] Configuration 497e85a6196SLee Jones */ 498e85a6196SLee Jones #define N25Q_VCR_DUMMY_CYCLES(x) (((x) & 0xf) << 4) 499e85a6196SLee Jones #define N25Q_VCR_XIP_DISABLED ((uint8_t)0x1 << 3) 500e85a6196SLee Jones #define N25Q_VCR_WRAP_CONT 0x3 501e85a6196SLee Jones 502e85a6196SLee Jones /* N25Q 3-byte Address READ configurations 503e85a6196SLee Jones * - 'FAST' variants configured for 8 dummy cycles. 504e85a6196SLee Jones * 505e85a6196SLee Jones * Note, the number of dummy cycles used for 'FAST' READ operations is 506e85a6196SLee Jones * configurable and would normally be tuned according to the READ command and 507e85a6196SLee Jones * operating frequency. However, this applies universally to all 'FAST' READ 508e85a6196SLee Jones * commands, including those used by the SPIBoot controller, and remains in 509e85a6196SLee Jones * force until the device is power-cycled. Since the SPIBoot controller is 510e85a6196SLee Jones * hard-wired to use 8 dummy cycles, we must configure the device to also use 8 511e85a6196SLee Jones * cycles. 512e85a6196SLee Jones */ 513e85a6196SLee Jones static struct seq_rw_config n25q_read3_configs[] = { 514e85a6196SLee Jones {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ_1_4_4, 0, 4, 4, 0x00, 0, 8}, 515e85a6196SLee Jones {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ_1_1_4, 0, 1, 4, 0x00, 0, 8}, 516e85a6196SLee Jones {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ_1_2_2, 0, 2, 2, 0x00, 0, 8}, 517e85a6196SLee Jones {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ_1_1_2, 0, 1, 2, 0x00, 0, 8}, 518e85a6196SLee Jones {FLASH_FLAG_READ_FAST, FLASH_CMD_READ_FAST, 0, 1, 1, 0x00, 0, 8}, 519e85a6196SLee Jones {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ, 0, 1, 1, 0x00, 0, 0}, 520e85a6196SLee Jones {0x00, 0, 0, 0, 0, 0x00, 0, 0}, 521e85a6196SLee Jones }; 522e85a6196SLee Jones 523e85a6196SLee Jones /* N25Q 4-byte Address READ configurations 524e85a6196SLee Jones * - use special 4-byte address READ commands (reduces overheads, and 525e85a6196SLee Jones * reduces risk of hitting watchdog reset issues). 526e85a6196SLee Jones * - 'FAST' variants configured for 8 dummy cycles (see note above.) 527e85a6196SLee Jones */ 528e85a6196SLee Jones static struct seq_rw_config n25q_read4_configs[] = { 529e85a6196SLee Jones {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ4_1_4_4, 0, 4, 4, 0x00, 0, 8}, 530e85a6196SLee Jones {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8}, 531e85a6196SLee Jones {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ4_1_2_2, 0, 2, 2, 0x00, 0, 8}, 532e85a6196SLee Jones {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8}, 533e85a6196SLee Jones {FLASH_FLAG_READ_FAST, FLASH_CMD_READ4_FAST, 0, 1, 1, 0x00, 0, 8}, 534e85a6196SLee Jones {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ4, 0, 1, 1, 0x00, 0, 0}, 535e85a6196SLee Jones {0x00, 0, 0, 0, 0, 0x00, 0, 0}, 536e85a6196SLee Jones }; 537e85a6196SLee Jones 53889818066SLee Jones /* 53989818066SLee Jones * [MX25xxx] Configuration 54089818066SLee Jones */ 54189818066SLee Jones #define MX25_STATUS_QE (0x1 << 6) 54289818066SLee Jones 54389818066SLee Jones static int stfsm_mx25_en_32bit_addr_seq(struct stfsm_seq *seq) 54489818066SLee Jones { 54589818066SLee Jones seq->seq_opc[0] = (SEQ_OPC_PADS_1 | 54689818066SLee Jones SEQ_OPC_CYCLES(8) | 54789818066SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_EN4B_ADDR) | 54889818066SLee Jones SEQ_OPC_CSDEASSERT); 54989818066SLee Jones 55089818066SLee Jones seq->seq[0] = STFSM_INST_CMD1; 55189818066SLee Jones seq->seq[1] = STFSM_INST_WAIT; 55289818066SLee Jones seq->seq[2] = STFSM_INST_STOP; 55389818066SLee Jones 55489818066SLee Jones seq->seq_cfg = (SEQ_CFG_PADS_1 | 55589818066SLee Jones SEQ_CFG_ERASE | 55689818066SLee Jones SEQ_CFG_READNOTWRITE | 55789818066SLee Jones SEQ_CFG_CSDEASSERT | 55889818066SLee Jones SEQ_CFG_STARTSEQ); 55989818066SLee Jones 56089818066SLee Jones return 0; 56189818066SLee Jones } 56289818066SLee Jones 5635343a123SLee Jones /* 5645343a123SLee Jones * [S25FLxxx] Configuration 5655343a123SLee Jones */ 5665343a123SLee Jones #define STFSM_S25FL_CONFIG_QE (0x1 << 1) 5675343a123SLee Jones 5685343a123SLee Jones /* 5695343a123SLee Jones * S25FLxxxS devices provide three ways of supporting 32-bit addressing: Bank 5705343a123SLee Jones * Register, Extended Address Modes, and a 32-bit address command set. The 5715343a123SLee Jones * 32-bit address command set is used here, since it avoids any problems with 5725343a123SLee Jones * entering a state that is incompatible with the SPIBoot Controller. 5735343a123SLee Jones */ 5745343a123SLee Jones static struct seq_rw_config stfsm_s25fl_read4_configs[] = { 5755343a123SLee Jones {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ4_1_4_4, 0, 4, 4, 0x00, 2, 4}, 5765343a123SLee Jones {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8}, 5775343a123SLee Jones {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ4_1_2_2, 0, 2, 2, 0x00, 4, 0}, 5785343a123SLee Jones {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8}, 5795343a123SLee Jones {FLASH_FLAG_READ_FAST, FLASH_CMD_READ4_FAST, 0, 1, 1, 0x00, 0, 8}, 5805343a123SLee Jones {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ4, 0, 1, 1, 0x00, 0, 0}, 5815343a123SLee Jones {0x00, 0, 0, 0, 0, 0x00, 0, 0}, 5825343a123SLee Jones }; 5835343a123SLee Jones 5845343a123SLee Jones static struct seq_rw_config stfsm_s25fl_write4_configs[] = { 5855343a123SLee Jones {FLASH_FLAG_WRITE_1_1_4, S25FL_CMD_WRITE4_1_1_4, 1, 1, 4, 0x00, 0, 0}, 5865343a123SLee Jones {FLASH_FLAG_READ_WRITE, S25FL_CMD_WRITE4, 1, 1, 1, 0x00, 0, 0}, 5875343a123SLee Jones {0x00, 0, 0, 0, 0, 0x00, 0, 0}, 5885343a123SLee Jones }; 5895343a123SLee Jones 590cd7cac9eSLee Jones /* 591cd7cac9eSLee Jones * [W25Qxxx] Configuration 592cd7cac9eSLee Jones */ 593cd7cac9eSLee Jones #define W25Q_STATUS_QE (0x1 << 9) 594cd7cac9eSLee Jones 5951bd512b5SLee Jones static struct stfsm_seq stfsm_seq_read_jedec = { 5961bd512b5SLee Jones .data_size = TRANSFER_SIZE(8), 5971bd512b5SLee Jones .seq_opc[0] = (SEQ_OPC_PADS_1 | 5981bd512b5SLee Jones SEQ_OPC_CYCLES(8) | 5991bd512b5SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_RDID)), 6001bd512b5SLee Jones .seq = { 6011bd512b5SLee Jones STFSM_INST_CMD1, 6021bd512b5SLee Jones STFSM_INST_DATA_READ, 6031bd512b5SLee Jones STFSM_INST_STOP, 6041bd512b5SLee Jones }, 6051bd512b5SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 6061bd512b5SLee Jones SEQ_CFG_READNOTWRITE | 6071bd512b5SLee Jones SEQ_CFG_CSDEASSERT | 6081bd512b5SLee Jones SEQ_CFG_STARTSEQ), 6091bd512b5SLee Jones }; 6101bd512b5SLee Jones 611176b4377SLee Jones static struct stfsm_seq stfsm_seq_read_status_fifo = { 612176b4377SLee Jones .data_size = TRANSFER_SIZE(4), 613176b4377SLee Jones .seq_opc[0] = (SEQ_OPC_PADS_1 | 614176b4377SLee Jones SEQ_OPC_CYCLES(8) | 615176b4377SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_RDSR)), 616176b4377SLee Jones .seq = { 617176b4377SLee Jones STFSM_INST_CMD1, 618176b4377SLee Jones STFSM_INST_DATA_READ, 619176b4377SLee Jones STFSM_INST_STOP, 620176b4377SLee Jones }, 621176b4377SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 622176b4377SLee Jones SEQ_CFG_READNOTWRITE | 623176b4377SLee Jones SEQ_CFG_CSDEASSERT | 624176b4377SLee Jones SEQ_CFG_STARTSEQ), 625176b4377SLee Jones }; 626176b4377SLee Jones 627fa5ba3afSLee Jones static struct stfsm_seq stfsm_seq_erase_sector = { 628fa5ba3afSLee Jones /* 'addr_cfg' configured during initialisation */ 629fa5ba3afSLee Jones .seq_opc = { 630fa5ba3afSLee Jones (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 631fa5ba3afSLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), 632fa5ba3afSLee Jones 633fa5ba3afSLee Jones (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 634fa5ba3afSLee Jones SEQ_OPC_OPCODE(FLASH_CMD_SE)), 635fa5ba3afSLee Jones }, 636fa5ba3afSLee Jones .seq = { 637fa5ba3afSLee Jones STFSM_INST_CMD1, 638fa5ba3afSLee Jones STFSM_INST_CMD2, 639fa5ba3afSLee Jones STFSM_INST_ADD1, 640fa5ba3afSLee Jones STFSM_INST_ADD2, 641fa5ba3afSLee Jones STFSM_INST_STOP, 642fa5ba3afSLee Jones }, 643fa5ba3afSLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 644fa5ba3afSLee Jones SEQ_CFG_READNOTWRITE | 645fa5ba3afSLee Jones SEQ_CFG_CSDEASSERT | 646fa5ba3afSLee Jones SEQ_CFG_STARTSEQ), 647fa5ba3afSLee Jones }; 648fa5ba3afSLee Jones 6494a341fe7SLee Jones static struct stfsm_seq stfsm_seq_erase_chip = { 6504a341fe7SLee Jones .seq_opc = { 6514a341fe7SLee Jones (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 6524a341fe7SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), 6534a341fe7SLee Jones 6544a341fe7SLee Jones (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 6554a341fe7SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_CHIPERASE) | SEQ_OPC_CSDEASSERT), 6564a341fe7SLee Jones }, 6574a341fe7SLee Jones .seq = { 6584a341fe7SLee Jones STFSM_INST_CMD1, 6594a341fe7SLee Jones STFSM_INST_CMD2, 6604a341fe7SLee Jones STFSM_INST_WAIT, 6614a341fe7SLee Jones STFSM_INST_STOP, 6624a341fe7SLee Jones }, 6634a341fe7SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 6644a341fe7SLee Jones SEQ_CFG_ERASE | 6654a341fe7SLee Jones SEQ_CFG_READNOTWRITE | 6664a341fe7SLee Jones SEQ_CFG_CSDEASSERT | 6674a341fe7SLee Jones SEQ_CFG_STARTSEQ), 6684a341fe7SLee Jones }; 6694a341fe7SLee Jones 670150571b7SLee Jones static struct stfsm_seq stfsm_seq_write_status = { 671150571b7SLee Jones .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 672150571b7SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), 673150571b7SLee Jones .seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 674150571b7SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WRSR)), 675150571b7SLee Jones .seq = { 676150571b7SLee Jones STFSM_INST_CMD1, 677150571b7SLee Jones STFSM_INST_CMD2, 678150571b7SLee Jones STFSM_INST_STA_WR1, 679150571b7SLee Jones STFSM_INST_STOP, 680150571b7SLee Jones }, 681150571b7SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 682150571b7SLee Jones SEQ_CFG_READNOTWRITE | 683150571b7SLee Jones SEQ_CFG_CSDEASSERT | 684150571b7SLee Jones SEQ_CFG_STARTSEQ), 685150571b7SLee Jones }; 686150571b7SLee Jones 687249516c9SLee Jones static struct stfsm_seq stfsm_seq_wrvcr = { 688249516c9SLee Jones .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 689249516c9SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WREN) | SEQ_OPC_CSDEASSERT), 690249516c9SLee Jones .seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 691249516c9SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WRVCR)), 692249516c9SLee Jones .seq = { 693249516c9SLee Jones STFSM_INST_CMD1, 694249516c9SLee Jones STFSM_INST_CMD2, 695249516c9SLee Jones STFSM_INST_STA_WR1, 696249516c9SLee Jones STFSM_INST_STOP, 697249516c9SLee Jones }, 698249516c9SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 699249516c9SLee Jones SEQ_CFG_READNOTWRITE | 700249516c9SLee Jones SEQ_CFG_CSDEASSERT | 701249516c9SLee Jones SEQ_CFG_STARTSEQ), 702249516c9SLee Jones }; 703249516c9SLee Jones 7046bd29600SLee Jones static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq) 7056bd29600SLee Jones { 7066bd29600SLee Jones seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 7076bd29600SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_EN4B_ADDR)); 7086bd29600SLee Jones seq->seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 7096bd29600SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WREN) | 7106bd29600SLee Jones SEQ_OPC_CSDEASSERT); 7116bd29600SLee Jones 7126bd29600SLee Jones seq->seq[0] = STFSM_INST_CMD2; 7136bd29600SLee Jones seq->seq[1] = STFSM_INST_CMD1; 7146bd29600SLee Jones seq->seq[2] = STFSM_INST_WAIT; 7156bd29600SLee Jones seq->seq[3] = STFSM_INST_STOP; 7166bd29600SLee Jones 7176bd29600SLee Jones seq->seq_cfg = (SEQ_CFG_PADS_1 | 7186bd29600SLee Jones SEQ_CFG_ERASE | 7196bd29600SLee Jones SEQ_CFG_READNOTWRITE | 7206bd29600SLee Jones SEQ_CFG_CSDEASSERT | 7216bd29600SLee Jones SEQ_CFG_STARTSEQ); 7226bd29600SLee Jones 7236bd29600SLee Jones return 0; 7246bd29600SLee Jones } 7256bd29600SLee Jones 7263c8b85b3SLee Jones static inline int stfsm_is_idle(struct stfsm *fsm) 7273c8b85b3SLee Jones { 7283c8b85b3SLee Jones return readl(fsm->base + SPI_FAST_SEQ_STA) & 0x10; 7293c8b85b3SLee Jones } 7303c8b85b3SLee Jones 73186f309fdSLee Jones static inline uint32_t stfsm_fifo_available(struct stfsm *fsm) 73286f309fdSLee Jones { 73386f309fdSLee Jones return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; 73486f309fdSLee Jones } 73586f309fdSLee Jones 73686f309fdSLee Jones static void stfsm_clear_fifo(struct stfsm *fsm) 73786f309fdSLee Jones { 73886f309fdSLee Jones uint32_t avail; 73986f309fdSLee Jones 74086f309fdSLee Jones for (;;) { 74186f309fdSLee Jones avail = stfsm_fifo_available(fsm); 74286f309fdSLee Jones if (!avail) 74386f309fdSLee Jones break; 74486f309fdSLee Jones 74586f309fdSLee Jones while (avail) { 74686f309fdSLee Jones readl(fsm->base + SPI_FAST_SEQ_DATA_REG); 74786f309fdSLee Jones avail--; 74886f309fdSLee Jones } 74986f309fdSLee Jones } 75086f309fdSLee Jones } 75186f309fdSLee Jones 7523c8b85b3SLee Jones static inline void stfsm_load_seq(struct stfsm *fsm, 7533c8b85b3SLee Jones const struct stfsm_seq *seq) 7543c8b85b3SLee Jones { 7553c8b85b3SLee Jones void __iomem *dst = fsm->base + SPI_FAST_SEQ_TRANSFER_SIZE; 7563c8b85b3SLee Jones const uint32_t *src = (const uint32_t *)seq; 7573c8b85b3SLee Jones int words = sizeof(*seq) / sizeof(*src); 7583c8b85b3SLee Jones 7593c8b85b3SLee Jones BUG_ON(!stfsm_is_idle(fsm)); 7603c8b85b3SLee Jones 7613c8b85b3SLee Jones while (words--) { 7623c8b85b3SLee Jones writel(*src, dst); 7633c8b85b3SLee Jones src++; 7643c8b85b3SLee Jones dst += 4; 7653c8b85b3SLee Jones } 7663c8b85b3SLee Jones } 7673c8b85b3SLee Jones 7683c8b85b3SLee Jones static void stfsm_wait_seq(struct stfsm *fsm) 7693c8b85b3SLee Jones { 7703c8b85b3SLee Jones unsigned long deadline; 7713c8b85b3SLee Jones int timeout = 0; 7723c8b85b3SLee Jones 7733c8b85b3SLee Jones deadline = jiffies + msecs_to_jiffies(STFSM_MAX_WAIT_SEQ_MS); 7743c8b85b3SLee Jones 7753c8b85b3SLee Jones while (!timeout) { 7763c8b85b3SLee Jones if (time_after_eq(jiffies, deadline)) 7773c8b85b3SLee Jones timeout = 1; 7783c8b85b3SLee Jones 7793c8b85b3SLee Jones if (stfsm_is_idle(fsm)) 7803c8b85b3SLee Jones return; 7813c8b85b3SLee Jones 7823c8b85b3SLee Jones cond_resched(); 7833c8b85b3SLee Jones } 7843c8b85b3SLee Jones 7853c8b85b3SLee Jones dev_err(fsm->dev, "timeout on sequence completion\n"); 7863c8b85b3SLee Jones } 7873c8b85b3SLee Jones 788030e82dcSLee Jones static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf, 789030e82dcSLee Jones const uint32_t size) 790030e82dcSLee Jones { 791030e82dcSLee Jones uint32_t remaining = size >> 2; 792030e82dcSLee Jones uint32_t avail; 793030e82dcSLee Jones uint32_t words; 794030e82dcSLee Jones 795030e82dcSLee Jones dev_dbg(fsm->dev, "Reading %d bytes from FIFO\n", size); 796030e82dcSLee Jones 797030e82dcSLee Jones BUG_ON((((uint32_t)buf) & 0x3) || (size & 0x3)); 798030e82dcSLee Jones 799030e82dcSLee Jones while (remaining) { 800030e82dcSLee Jones for (;;) { 801030e82dcSLee Jones avail = stfsm_fifo_available(fsm); 802030e82dcSLee Jones if (avail) 803030e82dcSLee Jones break; 804030e82dcSLee Jones udelay(1); 805030e82dcSLee Jones } 806030e82dcSLee Jones words = min(avail, remaining); 807030e82dcSLee Jones remaining -= words; 808030e82dcSLee Jones 809030e82dcSLee Jones readsl(fsm->base + SPI_FAST_SEQ_DATA_REG, buf, words); 810030e82dcSLee Jones buf += words; 811030e82dcSLee Jones } 812030e82dcSLee Jones } 813030e82dcSLee Jones 81430ca64f9SLee Jones static int stfsm_write_fifo(struct stfsm *fsm, 81530ca64f9SLee Jones const uint32_t *buf, const uint32_t size) 81630ca64f9SLee Jones { 81730ca64f9SLee Jones uint32_t words = size >> 2; 81830ca64f9SLee Jones 81930ca64f9SLee Jones dev_dbg(fsm->dev, "writing %d bytes to FIFO\n", size); 82030ca64f9SLee Jones 82130ca64f9SLee Jones BUG_ON((((uint32_t)buf) & 0x3) || (size & 0x3)); 82230ca64f9SLee Jones 82330ca64f9SLee Jones writesl(fsm->base + SPI_FAST_SEQ_DATA_REG, buf, words); 82430ca64f9SLee Jones 82530ca64f9SLee Jones return size; 82630ca64f9SLee Jones } 82730ca64f9SLee Jones 8280de08e43SLee Jones static int stfsm_enter_32bit_addr(struct stfsm *fsm, int enter) 8290de08e43SLee Jones { 830e6b1bb4eSLee Jones struct stfsm_seq *seq = &fsm->stfsm_seq_en_32bit_addr; 8310de08e43SLee Jones uint32_t cmd = enter ? FLASH_CMD_EN4B_ADDR : FLASH_CMD_EX4B_ADDR; 8320de08e43SLee Jones 8330de08e43SLee Jones seq->seq_opc[0] = (SEQ_OPC_PADS_1 | 8340de08e43SLee Jones SEQ_OPC_CYCLES(8) | 8350de08e43SLee Jones SEQ_OPC_OPCODE(cmd) | 8360de08e43SLee Jones SEQ_OPC_CSDEASSERT); 8370de08e43SLee Jones 8380de08e43SLee Jones stfsm_load_seq(fsm, seq); 8390de08e43SLee Jones 8400de08e43SLee Jones stfsm_wait_seq(fsm); 8410de08e43SLee Jones 8420de08e43SLee Jones return 0; 8430de08e43SLee Jones } 8440de08e43SLee Jones 845176b4377SLee Jones static uint8_t stfsm_wait_busy(struct stfsm *fsm) 846176b4377SLee Jones { 847176b4377SLee Jones struct stfsm_seq *seq = &stfsm_seq_read_status_fifo; 848176b4377SLee Jones unsigned long deadline; 849176b4377SLee Jones uint32_t status; 850176b4377SLee Jones int timeout = 0; 851176b4377SLee Jones 852176b4377SLee Jones /* Use RDRS1 */ 853176b4377SLee Jones seq->seq_opc[0] = (SEQ_OPC_PADS_1 | 854176b4377SLee Jones SEQ_OPC_CYCLES(8) | 855176b4377SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_RDSR)); 856176b4377SLee Jones 857176b4377SLee Jones /* Load read_status sequence */ 858176b4377SLee Jones stfsm_load_seq(fsm, seq); 859176b4377SLee Jones 860176b4377SLee Jones /* 861176b4377SLee Jones * Repeat until busy bit is deasserted, or timeout, or error (S25FLxxxS) 862176b4377SLee Jones */ 863176b4377SLee Jones deadline = jiffies + FLASH_MAX_BUSY_WAIT; 864176b4377SLee Jones while (!timeout) { 865176b4377SLee Jones cond_resched(); 866176b4377SLee Jones 867176b4377SLee Jones if (time_after_eq(jiffies, deadline)) 868176b4377SLee Jones timeout = 1; 869176b4377SLee Jones 870176b4377SLee Jones stfsm_wait_seq(fsm); 871176b4377SLee Jones 872176b4377SLee Jones stfsm_read_fifo(fsm, &status, 4); 873176b4377SLee Jones 874176b4377SLee Jones if ((status & FLASH_STATUS_BUSY) == 0) 875176b4377SLee Jones return 0; 876176b4377SLee Jones 877176b4377SLee Jones if ((fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS) && 878176b4377SLee Jones ((status & S25FL_STATUS_P_ERR) || 879176b4377SLee Jones (status & S25FL_STATUS_E_ERR))) 880176b4377SLee Jones return (uint8_t)(status & 0xff); 881176b4377SLee Jones 882176b4377SLee Jones if (!timeout) 883176b4377SLee Jones /* Restart */ 884176b4377SLee Jones writel(seq->seq_cfg, fsm->base + SPI_FAST_SEQ_CFG); 885176b4377SLee Jones } 886176b4377SLee Jones 887176b4377SLee Jones dev_err(fsm->dev, "timeout on wait_busy\n"); 888176b4377SLee Jones 889176b4377SLee Jones return FLASH_STATUS_TIMEOUT; 890176b4377SLee Jones } 891176b4377SLee Jones 892ac94dbcbSLee Jones static int stfsm_read_status(struct stfsm *fsm, uint8_t cmd, 893ac94dbcbSLee Jones uint8_t *status) 894ac94dbcbSLee Jones { 895ac94dbcbSLee Jones struct stfsm_seq *seq = &stfsm_seq_read_status_fifo; 896ac94dbcbSLee Jones uint32_t tmp; 897ac94dbcbSLee Jones 898ac94dbcbSLee Jones dev_dbg(fsm->dev, "reading STA[%s]\n", 899ac94dbcbSLee Jones (cmd == FLASH_CMD_RDSR) ? "1" : "2"); 900ac94dbcbSLee Jones 901ac94dbcbSLee Jones seq->seq_opc[0] = (SEQ_OPC_PADS_1 | 902ac94dbcbSLee Jones SEQ_OPC_CYCLES(8) | 903ac94dbcbSLee Jones SEQ_OPC_OPCODE(cmd)), 904ac94dbcbSLee Jones 905ac94dbcbSLee Jones stfsm_load_seq(fsm, seq); 906ac94dbcbSLee Jones 907ac94dbcbSLee Jones stfsm_read_fifo(fsm, &tmp, 4); 908ac94dbcbSLee Jones 909ac94dbcbSLee Jones *status = (uint8_t)(tmp >> 24); 910ac94dbcbSLee Jones 911ac94dbcbSLee Jones stfsm_wait_seq(fsm); 912ac94dbcbSLee Jones 913ac94dbcbSLee Jones return 0; 914ac94dbcbSLee Jones } 915ac94dbcbSLee Jones 916150571b7SLee Jones static int stfsm_write_status(struct stfsm *fsm, uint16_t status, 917150571b7SLee Jones int sta_bytes) 918150571b7SLee Jones { 919150571b7SLee Jones struct stfsm_seq *seq = &stfsm_seq_write_status; 920150571b7SLee Jones 921150571b7SLee Jones dev_dbg(fsm->dev, "writing STA[%s] 0x%04x\n", 922150571b7SLee Jones (sta_bytes == 1) ? "1" : "1+2", status); 923150571b7SLee Jones 924150571b7SLee Jones seq->status = (uint32_t)status | STA_PADS_1 | STA_CSDEASSERT; 925150571b7SLee Jones seq->seq[2] = (sta_bytes == 1) ? 926150571b7SLee Jones STFSM_INST_STA_WR1 : STFSM_INST_STA_WR1_2; 927150571b7SLee Jones 928150571b7SLee Jones stfsm_load_seq(fsm, seq); 929150571b7SLee Jones 930150571b7SLee Jones stfsm_wait_seq(fsm); 931150571b7SLee Jones 932150571b7SLee Jones return 0; 933150571b7SLee Jones }; 934150571b7SLee Jones 935249516c9SLee Jones static int stfsm_wrvcr(struct stfsm *fsm, uint8_t data) 936249516c9SLee Jones { 937249516c9SLee Jones struct stfsm_seq *seq = &stfsm_seq_wrvcr; 938249516c9SLee Jones 939249516c9SLee Jones dev_dbg(fsm->dev, "writing VCR 0x%02x\n", data); 940249516c9SLee Jones 941249516c9SLee Jones seq->status = (STA_DATA_BYTE1(data) | STA_PADS_1 | STA_CSDEASSERT); 942249516c9SLee Jones 943249516c9SLee Jones stfsm_load_seq(fsm, seq); 944249516c9SLee Jones 945249516c9SLee Jones stfsm_wait_seq(fsm); 946249516c9SLee Jones 947249516c9SLee Jones return 0; 948249516c9SLee Jones } 949249516c9SLee Jones 9500ea7d706SLee Jones /* 9510ea7d706SLee Jones * SoC reset on 'boot-from-spi' systems 9520ea7d706SLee Jones * 9530ea7d706SLee Jones * Certain modes of operation cause the Flash device to enter a particular state 9540ea7d706SLee Jones * for a period of time (e.g. 'Erase Sector', 'Quad Enable', and 'Enter 32-bit 9550ea7d706SLee Jones * Addr' commands). On boot-from-spi systems, it is important to consider what 9560ea7d706SLee Jones * happens if a warm reset occurs during this period. The SPIBoot controller 9570ea7d706SLee Jones * assumes that Flash device is in its default reset state, 24-bit address mode, 9580ea7d706SLee Jones * and ready to accept commands. This can be achieved using some form of 9590ea7d706SLee Jones * on-board logic/controller to force a device POR in response to a SoC-level 9600ea7d706SLee Jones * reset or by making use of the device reset signal if available (limited 9610ea7d706SLee Jones * number of devices only). 9620ea7d706SLee Jones * 9630ea7d706SLee Jones * Failure to take such precautions can cause problems following a warm reset. 9640ea7d706SLee Jones * For some operations (e.g. ERASE), there is little that can be done. For 9650ea7d706SLee Jones * other modes of operation (e.g. 32-bit addressing), options are often 9660ea7d706SLee Jones * available that can help minimise the window in which a reset could cause a 9670ea7d706SLee Jones * problem. 9680ea7d706SLee Jones * 9690ea7d706SLee Jones */ 9700ea7d706SLee Jones static bool stfsm_can_handle_soc_reset(struct stfsm *fsm) 9710ea7d706SLee Jones { 9720ea7d706SLee Jones /* Reset signal is available on the board and supported by the device */ 9730ea7d706SLee Jones if (fsm->reset_signal && fsm->info->flags & FLASH_FLAG_RESET) 9740ea7d706SLee Jones return true; 9750ea7d706SLee Jones 9760ea7d706SLee Jones /* Board-level logic forces a power-on-reset */ 9770ea7d706SLee Jones if (fsm->reset_por) 9780ea7d706SLee Jones return true; 9790ea7d706SLee Jones 9800ea7d706SLee Jones /* Reset is not properly handled and may result in failure to reboot */ 9810ea7d706SLee Jones return false; 9820ea7d706SLee Jones } 9830ea7d706SLee Jones 984fa5ba3afSLee Jones /* Configure 'addr_cfg' according to addressing mode */ 985fa5ba3afSLee Jones static void stfsm_prepare_erasesec_seq(struct stfsm *fsm, 986fa5ba3afSLee Jones struct stfsm_seq *seq) 987fa5ba3afSLee Jones { 988fa5ba3afSLee Jones int addr1_cycles = fsm->info->flags & FLASH_FLAG_32BIT_ADDR ? 16 : 8; 989fa5ba3afSLee Jones 990fa5ba3afSLee Jones seq->addr_cfg = (ADR_CFG_CYCLES_ADD1(addr1_cycles) | 991fa5ba3afSLee Jones ADR_CFG_PADS_1_ADD1 | 992fa5ba3afSLee Jones ADR_CFG_CYCLES_ADD2(16) | 993fa5ba3afSLee Jones ADR_CFG_PADS_1_ADD2 | 994fa5ba3afSLee Jones ADR_CFG_CSDEASSERT_ADD2); 995fa5ba3afSLee Jones } 996fa5ba3afSLee Jones 99708981274SLee Jones /* Search for preferred configuration based on available flags */ 99808981274SLee Jones static struct seq_rw_config * 99908981274SLee Jones stfsm_search_seq_rw_configs(struct stfsm *fsm, 100008981274SLee Jones struct seq_rw_config cfgs[]) 100108981274SLee Jones { 100208981274SLee Jones struct seq_rw_config *config; 100308981274SLee Jones int flags = fsm->info->flags; 100408981274SLee Jones 100508981274SLee Jones for (config = cfgs; config->cmd != 0; config++) 100608981274SLee Jones if ((config->flags & flags) == config->flags) 100708981274SLee Jones return config; 100808981274SLee Jones 100908981274SLee Jones return NULL; 101008981274SLee Jones } 101108981274SLee Jones 101297ccf2d2SLee Jones /* Prepare a READ/WRITE sequence according to configuration parameters */ 101397ccf2d2SLee Jones static void stfsm_prepare_rw_seq(struct stfsm *fsm, 101497ccf2d2SLee Jones struct stfsm_seq *seq, 101597ccf2d2SLee Jones struct seq_rw_config *cfg) 101697ccf2d2SLee Jones { 101797ccf2d2SLee Jones int addr1_cycles, addr2_cycles; 101897ccf2d2SLee Jones int i = 0; 101997ccf2d2SLee Jones 102097ccf2d2SLee Jones memset(seq, 0, sizeof(*seq)); 102197ccf2d2SLee Jones 102297ccf2d2SLee Jones /* Add READ/WRITE OPC */ 102397ccf2d2SLee Jones seq->seq_opc[i++] = (SEQ_OPC_PADS_1 | 102497ccf2d2SLee Jones SEQ_OPC_CYCLES(8) | 102597ccf2d2SLee Jones SEQ_OPC_OPCODE(cfg->cmd)); 102697ccf2d2SLee Jones 102797ccf2d2SLee Jones /* Add WREN OPC for a WRITE sequence */ 102897ccf2d2SLee Jones if (cfg->write) 102997ccf2d2SLee Jones seq->seq_opc[i++] = (SEQ_OPC_PADS_1 | 103097ccf2d2SLee Jones SEQ_OPC_CYCLES(8) | 103197ccf2d2SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WREN) | 103297ccf2d2SLee Jones SEQ_OPC_CSDEASSERT); 103397ccf2d2SLee Jones 103497ccf2d2SLee Jones /* Address configuration (24 or 32-bit addresses) */ 103597ccf2d2SLee Jones addr1_cycles = (fsm->info->flags & FLASH_FLAG_32BIT_ADDR) ? 16 : 8; 103697ccf2d2SLee Jones addr1_cycles /= cfg->addr_pads; 103797ccf2d2SLee Jones addr2_cycles = 16 / cfg->addr_pads; 103897ccf2d2SLee Jones seq->addr_cfg = ((addr1_cycles & 0x3f) << 0 | /* ADD1 cycles */ 103997ccf2d2SLee Jones (cfg->addr_pads - 1) << 6 | /* ADD1 pads */ 104097ccf2d2SLee Jones (addr2_cycles & 0x3f) << 16 | /* ADD2 cycles */ 104197ccf2d2SLee Jones ((cfg->addr_pads - 1) << 22)); /* ADD2 pads */ 104297ccf2d2SLee Jones 104397ccf2d2SLee Jones /* Data/Sequence configuration */ 104497ccf2d2SLee Jones seq->seq_cfg = ((cfg->data_pads - 1) << 16 | 104597ccf2d2SLee Jones SEQ_CFG_STARTSEQ | 104697ccf2d2SLee Jones SEQ_CFG_CSDEASSERT); 104797ccf2d2SLee Jones if (!cfg->write) 104897ccf2d2SLee Jones seq->seq_cfg |= SEQ_CFG_READNOTWRITE; 104997ccf2d2SLee Jones 105097ccf2d2SLee Jones /* Mode configuration (no. of pads taken from addr cfg) */ 105197ccf2d2SLee Jones seq->mode = ((cfg->mode_data & 0xff) << 0 | /* data */ 105297ccf2d2SLee Jones (cfg->mode_cycles & 0x3f) << 16 | /* cycles */ 105397ccf2d2SLee Jones (cfg->addr_pads - 1) << 22); /* pads */ 105497ccf2d2SLee Jones 105597ccf2d2SLee Jones /* Dummy configuration (no. of pads taken from addr cfg) */ 105697ccf2d2SLee Jones seq->dummy = ((cfg->dummy_cycles & 0x3f) << 16 | /* cycles */ 105797ccf2d2SLee Jones (cfg->addr_pads - 1) << 22); /* pads */ 105897ccf2d2SLee Jones 105997ccf2d2SLee Jones 106097ccf2d2SLee Jones /* Instruction sequence */ 106197ccf2d2SLee Jones i = 0; 106297ccf2d2SLee Jones if (cfg->write) 106397ccf2d2SLee Jones seq->seq[i++] = STFSM_INST_CMD2; 106497ccf2d2SLee Jones 106597ccf2d2SLee Jones seq->seq[i++] = STFSM_INST_CMD1; 106697ccf2d2SLee Jones 106797ccf2d2SLee Jones seq->seq[i++] = STFSM_INST_ADD1; 106897ccf2d2SLee Jones seq->seq[i++] = STFSM_INST_ADD2; 106997ccf2d2SLee Jones 107097ccf2d2SLee Jones if (cfg->mode_cycles) 107197ccf2d2SLee Jones seq->seq[i++] = STFSM_INST_MODE; 107297ccf2d2SLee Jones 107397ccf2d2SLee Jones if (cfg->dummy_cycles) 107497ccf2d2SLee Jones seq->seq[i++] = STFSM_INST_DUMMY; 107597ccf2d2SLee Jones 107697ccf2d2SLee Jones seq->seq[i++] = 107797ccf2d2SLee Jones cfg->write ? STFSM_INST_DATA_WRITE : STFSM_INST_DATA_READ; 107897ccf2d2SLee Jones seq->seq[i++] = STFSM_INST_STOP; 107997ccf2d2SLee Jones } 108097ccf2d2SLee Jones 108188cccb89SLee Jones static int stfsm_search_prepare_rw_seq(struct stfsm *fsm, 108288cccb89SLee Jones struct stfsm_seq *seq, 108388cccb89SLee Jones struct seq_rw_config *cfgs) 108488cccb89SLee Jones { 108588cccb89SLee Jones struct seq_rw_config *config; 108688cccb89SLee Jones 108788cccb89SLee Jones config = stfsm_search_seq_rw_configs(fsm, cfgs); 108888cccb89SLee Jones if (!config) { 108988cccb89SLee Jones dev_err(fsm->dev, "failed to find suitable config\n"); 109088cccb89SLee Jones return -EINVAL; 109188cccb89SLee Jones } 109288cccb89SLee Jones 109388cccb89SLee Jones stfsm_prepare_rw_seq(fsm, seq, config); 109488cccb89SLee Jones 109588cccb89SLee Jones return 0; 109688cccb89SLee Jones } 109788cccb89SLee Jones 10984eb3f0d8SLee Jones /* Prepare a READ/WRITE/ERASE 'default' sequences */ 10994eb3f0d8SLee Jones static int stfsm_prepare_rwe_seqs_default(struct stfsm *fsm) 11004eb3f0d8SLee Jones { 11014eb3f0d8SLee Jones uint32_t flags = fsm->info->flags; 11024eb3f0d8SLee Jones int ret; 11034eb3f0d8SLee Jones 11044eb3f0d8SLee Jones /* Configure 'READ' sequence */ 1105e6b1bb4eSLee Jones ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, 11064eb3f0d8SLee Jones default_read_configs); 11074eb3f0d8SLee Jones if (ret) { 11084eb3f0d8SLee Jones dev_err(fsm->dev, 11094eb3f0d8SLee Jones "failed to prep READ sequence with flags [0x%08x]\n", 11104eb3f0d8SLee Jones flags); 11114eb3f0d8SLee Jones return ret; 11124eb3f0d8SLee Jones } 11134eb3f0d8SLee Jones 11144eb3f0d8SLee Jones /* Configure 'WRITE' sequence */ 1115e6b1bb4eSLee Jones ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_write, 11164eb3f0d8SLee Jones default_write_configs); 11174eb3f0d8SLee Jones if (ret) { 11184eb3f0d8SLee Jones dev_err(fsm->dev, 11194eb3f0d8SLee Jones "failed to prep WRITE sequence with flags [0x%08x]\n", 11204eb3f0d8SLee Jones flags); 11214eb3f0d8SLee Jones return ret; 11224eb3f0d8SLee Jones } 11234eb3f0d8SLee Jones 11244eb3f0d8SLee Jones /* Configure 'ERASE_SECTOR' sequence */ 11254eb3f0d8SLee Jones stfsm_prepare_erasesec_seq(fsm, &stfsm_seq_erase_sector); 11264eb3f0d8SLee Jones 11274eb3f0d8SLee Jones return 0; 11284eb3f0d8SLee Jones } 11294eb3f0d8SLee Jones 113089818066SLee Jones static int stfsm_mx25_config(struct stfsm *fsm) 113189818066SLee Jones { 113289818066SLee Jones uint32_t flags = fsm->info->flags; 113389818066SLee Jones uint32_t data_pads; 113489818066SLee Jones uint8_t sta; 113589818066SLee Jones int ret; 113689818066SLee Jones bool soc_reset; 113789818066SLee Jones 113889818066SLee Jones /* 113989818066SLee Jones * Use default READ/WRITE sequences 114089818066SLee Jones */ 114189818066SLee Jones ret = stfsm_prepare_rwe_seqs_default(fsm); 114289818066SLee Jones if (ret) 114389818066SLee Jones return ret; 114489818066SLee Jones 114589818066SLee Jones /* 114689818066SLee Jones * Configure 32-bit Address Support 114789818066SLee Jones */ 114889818066SLee Jones if (flags & FLASH_FLAG_32BIT_ADDR) { 114989818066SLee Jones /* Configure 'enter_32bitaddr' FSM sequence */ 1150e6b1bb4eSLee Jones stfsm_mx25_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr); 115189818066SLee Jones 115289818066SLee Jones soc_reset = stfsm_can_handle_soc_reset(fsm); 115389818066SLee Jones if (soc_reset || !fsm->booted_from_spi) { 115489818066SLee Jones /* If we can handle SoC resets, we enable 32-bit address 115589818066SLee Jones * mode pervasively */ 115689818066SLee Jones stfsm_enter_32bit_addr(fsm, 1); 115789818066SLee Jones 115889818066SLee Jones } else { 115989818066SLee Jones /* Else, enable/disable 32-bit addressing before/after 116089818066SLee Jones * each operation */ 116189818066SLee Jones fsm->configuration = (CFG_READ_TOGGLE_32BIT_ADDR | 116289818066SLee Jones CFG_WRITE_TOGGLE_32BIT_ADDR | 116389818066SLee Jones CFG_ERASESEC_TOGGLE_32BIT_ADDR); 116489818066SLee Jones /* It seems a small delay is required after exiting 116589818066SLee Jones * 32-bit mode following a write operation. The issue 116689818066SLee Jones * is under investigation. 116789818066SLee Jones */ 116889818066SLee Jones fsm->configuration |= CFG_WRITE_EX_32BIT_ADDR_DELAY; 116989818066SLee Jones } 117089818066SLee Jones } 117189818066SLee Jones 117289818066SLee Jones /* For QUAD mode, set 'QE' STATUS bit */ 1173e6b1bb4eSLee Jones data_pads = ((fsm->stfsm_seq_read.seq_cfg >> 16) & 0x3) + 1; 117489818066SLee Jones if (data_pads == 4) { 117589818066SLee Jones stfsm_read_status(fsm, FLASH_CMD_RDSR, &sta); 117689818066SLee Jones sta |= MX25_STATUS_QE; 117789818066SLee Jones stfsm_write_status(fsm, sta, 1); 117889818066SLee Jones } 117989818066SLee Jones 118089818066SLee Jones return 0; 118189818066SLee Jones } 118289818066SLee Jones 1183218b870fSLee Jones static int stfsm_n25q_config(struct stfsm *fsm) 1184218b870fSLee Jones { 1185218b870fSLee Jones uint32_t flags = fsm->info->flags; 1186218b870fSLee Jones uint8_t vcr; 1187218b870fSLee Jones int ret = 0; 1188218b870fSLee Jones bool soc_reset; 1189218b870fSLee Jones 1190218b870fSLee Jones /* Configure 'READ' sequence */ 1191218b870fSLee Jones if (flags & FLASH_FLAG_32BIT_ADDR) 1192e6b1bb4eSLee Jones ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, 1193218b870fSLee Jones n25q_read4_configs); 1194218b870fSLee Jones else 1195e6b1bb4eSLee Jones ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, 1196218b870fSLee Jones n25q_read3_configs); 1197218b870fSLee Jones if (ret) { 1198218b870fSLee Jones dev_err(fsm->dev, 1199218b870fSLee Jones "failed to prepare READ sequence with flags [0x%08x]\n", 1200218b870fSLee Jones flags); 1201218b870fSLee Jones return ret; 1202218b870fSLee Jones } 1203218b870fSLee Jones 1204218b870fSLee Jones /* Configure 'WRITE' sequence (default configs) */ 1205e6b1bb4eSLee Jones ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_write, 1206218b870fSLee Jones default_write_configs); 1207218b870fSLee Jones if (ret) { 1208218b870fSLee Jones dev_err(fsm->dev, 1209218b870fSLee Jones "preparing WRITE sequence using flags [0x%08x] failed\n", 1210218b870fSLee Jones flags); 1211218b870fSLee Jones return ret; 1212218b870fSLee Jones } 1213218b870fSLee Jones 1214218b870fSLee Jones /* * Configure 'ERASE_SECTOR' sequence */ 1215218b870fSLee Jones stfsm_prepare_erasesec_seq(fsm, &stfsm_seq_erase_sector); 1216218b870fSLee Jones 1217218b870fSLee Jones /* Configure 32-bit address support */ 1218218b870fSLee Jones if (flags & FLASH_FLAG_32BIT_ADDR) { 1219e6b1bb4eSLee Jones stfsm_n25q_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr); 1220218b870fSLee Jones 1221218b870fSLee Jones soc_reset = stfsm_can_handle_soc_reset(fsm); 1222218b870fSLee Jones if (soc_reset || !fsm->booted_from_spi) { 1223218b870fSLee Jones /* 1224218b870fSLee Jones * If we can handle SoC resets, we enable 32-bit 1225218b870fSLee Jones * address mode pervasively 1226218b870fSLee Jones */ 1227218b870fSLee Jones stfsm_enter_32bit_addr(fsm, 1); 1228218b870fSLee Jones } else { 1229218b870fSLee Jones /* 1230218b870fSLee Jones * If not, enable/disable for WRITE and ERASE 1231218b870fSLee Jones * operations (READ uses special commands) 1232218b870fSLee Jones */ 1233218b870fSLee Jones fsm->configuration = (CFG_WRITE_TOGGLE_32BIT_ADDR | 1234218b870fSLee Jones CFG_ERASESEC_TOGGLE_32BIT_ADDR); 1235218b870fSLee Jones } 1236218b870fSLee Jones } 1237218b870fSLee Jones 1238218b870fSLee Jones /* 1239218b870fSLee Jones * Configure device to use 8 dummy cycles 1240218b870fSLee Jones */ 1241218b870fSLee Jones vcr = (N25Q_VCR_DUMMY_CYCLES(8) | N25Q_VCR_XIP_DISABLED | 1242218b870fSLee Jones N25Q_VCR_WRAP_CONT); 1243218b870fSLee Jones stfsm_wrvcr(fsm, vcr); 1244218b870fSLee Jones 1245218b870fSLee Jones return 0; 1246218b870fSLee Jones } 1247218b870fSLee Jones 12485343a123SLee Jones static void stfsm_s25fl_prepare_erasesec_seq_32(struct stfsm_seq *seq) 12495343a123SLee Jones { 12505343a123SLee Jones seq->seq_opc[1] = (SEQ_OPC_PADS_1 | 12515343a123SLee Jones SEQ_OPC_CYCLES(8) | 12525343a123SLee Jones SEQ_OPC_OPCODE(S25FL_CMD_SE4)); 12535343a123SLee Jones 12545343a123SLee Jones seq->addr_cfg = (ADR_CFG_CYCLES_ADD1(16) | 12555343a123SLee Jones ADR_CFG_PADS_1_ADD1 | 12565343a123SLee Jones ADR_CFG_CYCLES_ADD2(16) | 12575343a123SLee Jones ADR_CFG_PADS_1_ADD2 | 12585343a123SLee Jones ADR_CFG_CSDEASSERT_ADD2); 12595343a123SLee Jones } 12605343a123SLee Jones 12615343a123SLee Jones static void stfsm_s25fl_read_dyb(struct stfsm *fsm, uint32_t offs, uint8_t *dby) 12625343a123SLee Jones { 12635343a123SLee Jones uint32_t tmp; 12645343a123SLee Jones struct stfsm_seq seq = { 12655343a123SLee Jones .data_size = TRANSFER_SIZE(4), 12665343a123SLee Jones .seq_opc[0] = (SEQ_OPC_PADS_1 | 12675343a123SLee Jones SEQ_OPC_CYCLES(8) | 12685343a123SLee Jones SEQ_OPC_OPCODE(S25FL_CMD_DYBRD)), 12695343a123SLee Jones .addr_cfg = (ADR_CFG_CYCLES_ADD1(16) | 12705343a123SLee Jones ADR_CFG_PADS_1_ADD1 | 12715343a123SLee Jones ADR_CFG_CYCLES_ADD2(16) | 12725343a123SLee Jones ADR_CFG_PADS_1_ADD2), 12735343a123SLee Jones .addr1 = (offs >> 16) & 0xffff, 12745343a123SLee Jones .addr2 = offs & 0xffff, 12755343a123SLee Jones .seq = { 12765343a123SLee Jones STFSM_INST_CMD1, 12775343a123SLee Jones STFSM_INST_ADD1, 12785343a123SLee Jones STFSM_INST_ADD2, 12795343a123SLee Jones STFSM_INST_DATA_READ, 12805343a123SLee Jones STFSM_INST_STOP, 12815343a123SLee Jones }, 12825343a123SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 12835343a123SLee Jones SEQ_CFG_READNOTWRITE | 12845343a123SLee Jones SEQ_CFG_CSDEASSERT | 12855343a123SLee Jones SEQ_CFG_STARTSEQ), 12865343a123SLee Jones }; 12875343a123SLee Jones 12885343a123SLee Jones stfsm_load_seq(fsm, &seq); 12895343a123SLee Jones 12905343a123SLee Jones stfsm_read_fifo(fsm, &tmp, 4); 12915343a123SLee Jones 12925343a123SLee Jones *dby = (uint8_t)(tmp >> 24); 12935343a123SLee Jones 12945343a123SLee Jones stfsm_wait_seq(fsm); 12955343a123SLee Jones } 12965343a123SLee Jones 12975343a123SLee Jones static void stfsm_s25fl_write_dyb(struct stfsm *fsm, uint32_t offs, uint8_t dby) 12985343a123SLee Jones { 12995343a123SLee Jones struct stfsm_seq seq = { 13005343a123SLee Jones .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 13015343a123SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WREN) | 13025343a123SLee Jones SEQ_OPC_CSDEASSERT), 13035343a123SLee Jones .seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) | 13045343a123SLee Jones SEQ_OPC_OPCODE(S25FL_CMD_DYBWR)), 13055343a123SLee Jones .addr_cfg = (ADR_CFG_CYCLES_ADD1(16) | 13065343a123SLee Jones ADR_CFG_PADS_1_ADD1 | 13075343a123SLee Jones ADR_CFG_CYCLES_ADD2(16) | 13085343a123SLee Jones ADR_CFG_PADS_1_ADD2), 13095343a123SLee Jones .status = (uint32_t)dby | STA_PADS_1 | STA_CSDEASSERT, 13105343a123SLee Jones .addr1 = (offs >> 16) & 0xffff, 13115343a123SLee Jones .addr2 = offs & 0xffff, 13125343a123SLee Jones .seq = { 13135343a123SLee Jones STFSM_INST_CMD1, 13145343a123SLee Jones STFSM_INST_CMD2, 13155343a123SLee Jones STFSM_INST_ADD1, 13165343a123SLee Jones STFSM_INST_ADD2, 13175343a123SLee Jones STFSM_INST_STA_WR1, 13185343a123SLee Jones STFSM_INST_STOP, 13195343a123SLee Jones }, 13205343a123SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 13215343a123SLee Jones SEQ_CFG_READNOTWRITE | 13225343a123SLee Jones SEQ_CFG_CSDEASSERT | 13235343a123SLee Jones SEQ_CFG_STARTSEQ), 13245343a123SLee Jones }; 13255343a123SLee Jones 13265343a123SLee Jones stfsm_load_seq(fsm, &seq); 13275343a123SLee Jones stfsm_wait_seq(fsm); 13285343a123SLee Jones 13295343a123SLee Jones stfsm_wait_busy(fsm); 13305343a123SLee Jones } 13315343a123SLee Jones 13325343a123SLee Jones static int stfsm_s25fl_clear_status_reg(struct stfsm *fsm) 13335343a123SLee Jones { 13345343a123SLee Jones struct stfsm_seq seq = { 13355343a123SLee Jones .seq_opc[0] = (SEQ_OPC_PADS_1 | 13365343a123SLee Jones SEQ_OPC_CYCLES(8) | 13375343a123SLee Jones SEQ_OPC_OPCODE(S25FL_CMD_CLSR) | 13385343a123SLee Jones SEQ_OPC_CSDEASSERT), 13395343a123SLee Jones .seq_opc[1] = (SEQ_OPC_PADS_1 | 13405343a123SLee Jones SEQ_OPC_CYCLES(8) | 13415343a123SLee Jones SEQ_OPC_OPCODE(FLASH_CMD_WRDI) | 13425343a123SLee Jones SEQ_OPC_CSDEASSERT), 13435343a123SLee Jones .seq = { 13445343a123SLee Jones STFSM_INST_CMD1, 13455343a123SLee Jones STFSM_INST_CMD2, 13465343a123SLee Jones STFSM_INST_WAIT, 13475343a123SLee Jones STFSM_INST_STOP, 13485343a123SLee Jones }, 13495343a123SLee Jones .seq_cfg = (SEQ_CFG_PADS_1 | 13505343a123SLee Jones SEQ_CFG_ERASE | 13515343a123SLee Jones SEQ_CFG_READNOTWRITE | 13525343a123SLee Jones SEQ_CFG_CSDEASSERT | 13535343a123SLee Jones SEQ_CFG_STARTSEQ), 13545343a123SLee Jones }; 13555343a123SLee Jones 13565343a123SLee Jones stfsm_load_seq(fsm, &seq); 13575343a123SLee Jones 13585343a123SLee Jones stfsm_wait_seq(fsm); 13595343a123SLee Jones 13605343a123SLee Jones return 0; 13615343a123SLee Jones } 13625343a123SLee Jones 13635343a123SLee Jones static int stfsm_s25fl_config(struct stfsm *fsm) 13645343a123SLee Jones { 13655343a123SLee Jones struct flash_info *info = fsm->info; 13665343a123SLee Jones uint32_t flags = info->flags; 13675343a123SLee Jones uint32_t data_pads; 13685343a123SLee Jones uint32_t offs; 13695343a123SLee Jones uint16_t sta_wr; 13705343a123SLee Jones uint8_t sr1, cr1, dyb; 13715343a123SLee Jones int ret; 13725343a123SLee Jones 13735343a123SLee Jones if (flags & FLASH_FLAG_32BIT_ADDR) { 13745343a123SLee Jones /* 13755343a123SLee Jones * Prepare Read/Write/Erase sequences according to S25FLxxx 13765343a123SLee Jones * 32-bit address command set 13775343a123SLee Jones */ 1378e6b1bb4eSLee Jones ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_read, 13795343a123SLee Jones stfsm_s25fl_read4_configs); 13805343a123SLee Jones if (ret) 13815343a123SLee Jones return ret; 13825343a123SLee Jones 1383e6b1bb4eSLee Jones ret = stfsm_search_prepare_rw_seq(fsm, &fsm->stfsm_seq_write, 13845343a123SLee Jones stfsm_s25fl_write4_configs); 13855343a123SLee Jones if (ret) 13865343a123SLee Jones return ret; 13875343a123SLee Jones 13885343a123SLee Jones stfsm_s25fl_prepare_erasesec_seq_32(&stfsm_seq_erase_sector); 13895343a123SLee Jones 13905343a123SLee Jones } else { 13915343a123SLee Jones /* Use default configurations for 24-bit addressing */ 13925343a123SLee Jones ret = stfsm_prepare_rwe_seqs_default(fsm); 13935343a123SLee Jones if (ret) 13945343a123SLee Jones return ret; 13955343a123SLee Jones } 13965343a123SLee Jones 13975343a123SLee Jones /* 13985343a123SLee Jones * For devices that support 'DYB' sector locking, check lock status and 13995343a123SLee Jones * unlock sectors if necessary (some variants power-on with sectors 14005343a123SLee Jones * locked by default) 14015343a123SLee Jones */ 14025343a123SLee Jones if (flags & FLASH_FLAG_DYB_LOCKING) { 14035343a123SLee Jones offs = 0; 14045343a123SLee Jones for (offs = 0; offs < info->sector_size * info->n_sectors;) { 14055343a123SLee Jones stfsm_s25fl_read_dyb(fsm, offs, &dyb); 14065343a123SLee Jones if (dyb == 0x00) 14075343a123SLee Jones stfsm_s25fl_write_dyb(fsm, offs, 0xff); 14085343a123SLee Jones 14095343a123SLee Jones /* Handle bottom/top 4KiB parameter sectors */ 14105343a123SLee Jones if ((offs < info->sector_size * 2) || 14115343a123SLee Jones (offs >= (info->sector_size - info->n_sectors * 4))) 14125343a123SLee Jones offs += 0x1000; 14135343a123SLee Jones else 14145343a123SLee Jones offs += 0x10000; 14155343a123SLee Jones } 14165343a123SLee Jones } 14175343a123SLee Jones 14185343a123SLee Jones /* Check status of 'QE' bit */ 1419e6b1bb4eSLee Jones data_pads = ((fsm->stfsm_seq_read.seq_cfg >> 16) & 0x3) + 1; 14205343a123SLee Jones stfsm_read_status(fsm, FLASH_CMD_RDSR2, &cr1); 14215343a123SLee Jones if (data_pads == 4) { 14225343a123SLee Jones if (!(cr1 & STFSM_S25FL_CONFIG_QE)) { 14235343a123SLee Jones /* Set 'QE' */ 14245343a123SLee Jones cr1 |= STFSM_S25FL_CONFIG_QE; 14255343a123SLee Jones 14265343a123SLee Jones stfsm_read_status(fsm, FLASH_CMD_RDSR, &sr1); 14275343a123SLee Jones sta_wr = ((uint16_t)cr1 << 8) | sr1; 14285343a123SLee Jones 14295343a123SLee Jones stfsm_write_status(fsm, sta_wr, 2); 14305343a123SLee Jones 14315343a123SLee Jones stfsm_wait_busy(fsm); 14325343a123SLee Jones } 14335343a123SLee Jones } else { 14345343a123SLee Jones if ((cr1 & STFSM_S25FL_CONFIG_QE)) { 14355343a123SLee Jones /* Clear 'QE' */ 14365343a123SLee Jones cr1 &= ~STFSM_S25FL_CONFIG_QE; 14375343a123SLee Jones 14385343a123SLee Jones stfsm_read_status(fsm, FLASH_CMD_RDSR, &sr1); 14395343a123SLee Jones sta_wr = ((uint16_t)cr1 << 8) | sr1; 14405343a123SLee Jones 14415343a123SLee Jones stfsm_write_status(fsm, sta_wr, 2); 14425343a123SLee Jones 14435343a123SLee Jones stfsm_wait_busy(fsm); 14445343a123SLee Jones } 14455343a123SLee Jones 14465343a123SLee Jones } 14475343a123SLee Jones 14485343a123SLee Jones /* 14495343a123SLee Jones * S25FLxxx devices support Program and Error error flags. 14505343a123SLee Jones * Configure driver to check flags and clear if necessary. 14515343a123SLee Jones */ 14525343a123SLee Jones fsm->configuration |= CFG_S25FL_CHECK_ERROR_FLAGS; 14535343a123SLee Jones 14545343a123SLee Jones return 0; 14555343a123SLee Jones } 14565343a123SLee Jones 1457cd7cac9eSLee Jones static int stfsm_w25q_config(struct stfsm *fsm) 1458cd7cac9eSLee Jones { 1459cd7cac9eSLee Jones uint32_t data_pads; 1460cd7cac9eSLee Jones uint16_t sta_wr; 1461cd7cac9eSLee Jones uint8_t sta1, sta2; 1462cd7cac9eSLee Jones int ret; 1463cd7cac9eSLee Jones 1464cd7cac9eSLee Jones ret = stfsm_prepare_rwe_seqs_default(fsm); 1465cd7cac9eSLee Jones if (ret) 1466cd7cac9eSLee Jones return ret; 1467cd7cac9eSLee Jones 1468cd7cac9eSLee Jones /* If using QUAD mode, set QE STATUS bit */ 1469e6b1bb4eSLee Jones data_pads = ((fsm->stfsm_seq_read.seq_cfg >> 16) & 0x3) + 1; 1470cd7cac9eSLee Jones if (data_pads == 4) { 1471cd7cac9eSLee Jones stfsm_read_status(fsm, FLASH_CMD_RDSR, &sta1); 1472cd7cac9eSLee Jones stfsm_read_status(fsm, FLASH_CMD_RDSR2, &sta2); 1473cd7cac9eSLee Jones 1474cd7cac9eSLee Jones sta_wr = ((uint16_t)sta2 << 8) | sta1; 1475cd7cac9eSLee Jones 1476cd7cac9eSLee Jones sta_wr |= W25Q_STATUS_QE; 1477cd7cac9eSLee Jones 1478cd7cac9eSLee Jones stfsm_write_status(fsm, sta_wr, 2); 1479cd7cac9eSLee Jones 1480cd7cac9eSLee Jones stfsm_wait_busy(fsm); 1481cd7cac9eSLee Jones } 1482cd7cac9eSLee Jones 1483cd7cac9eSLee Jones return 0; 1484cd7cac9eSLee Jones } 1485cd7cac9eSLee Jones 1486e514f105SLee Jones static int stfsm_read(struct stfsm *fsm, uint8_t *buf, uint32_t size, 1487e514f105SLee Jones uint32_t offset) 1488e514f105SLee Jones { 1489e6b1bb4eSLee Jones struct stfsm_seq *seq = &fsm->stfsm_seq_read; 1490e514f105SLee Jones uint32_t data_pads; 1491e514f105SLee Jones uint32_t read_mask; 1492e514f105SLee Jones uint32_t size_ub; 1493e514f105SLee Jones uint32_t size_lb; 1494e514f105SLee Jones uint32_t size_mop; 1495e514f105SLee Jones uint32_t tmp[4]; 1496e514f105SLee Jones uint32_t page_buf[FLASH_PAGESIZE_32]; 1497e514f105SLee Jones uint8_t *p; 1498e514f105SLee Jones 1499e514f105SLee Jones dev_dbg(fsm->dev, "reading %d bytes from 0x%08x\n", size, offset); 1500e514f105SLee Jones 1501e514f105SLee Jones /* Enter 32-bit address mode, if required */ 1502e514f105SLee Jones if (fsm->configuration & CFG_READ_TOGGLE_32BIT_ADDR) 1503e514f105SLee Jones stfsm_enter_32bit_addr(fsm, 1); 1504e514f105SLee Jones 1505e514f105SLee Jones /* Must read in multiples of 32 cycles (or 32*pads/8 Bytes) */ 1506e514f105SLee Jones data_pads = ((seq->seq_cfg >> 16) & 0x3) + 1; 1507e514f105SLee Jones read_mask = (data_pads << 2) - 1; 1508e514f105SLee Jones 1509e514f105SLee Jones /* Handle non-aligned buf */ 1510e514f105SLee Jones p = ((uint32_t)buf & 0x3) ? (uint8_t *)page_buf : buf; 1511e514f105SLee Jones 1512e514f105SLee Jones /* Handle non-aligned size */ 1513e514f105SLee Jones size_ub = (size + read_mask) & ~read_mask; 1514e514f105SLee Jones size_lb = size & ~read_mask; 1515e514f105SLee Jones size_mop = size & read_mask; 1516e514f105SLee Jones 1517e514f105SLee Jones seq->data_size = TRANSFER_SIZE(size_ub); 1518e514f105SLee Jones seq->addr1 = (offset >> 16) & 0xffff; 1519e514f105SLee Jones seq->addr2 = offset & 0xffff; 1520e514f105SLee Jones 1521e514f105SLee Jones stfsm_load_seq(fsm, seq); 1522e514f105SLee Jones 1523e514f105SLee Jones if (size_lb) 1524e514f105SLee Jones stfsm_read_fifo(fsm, (uint32_t *)p, size_lb); 1525e514f105SLee Jones 1526e514f105SLee Jones if (size_mop) { 1527e514f105SLee Jones stfsm_read_fifo(fsm, tmp, read_mask + 1); 1528e514f105SLee Jones memcpy(p + size_lb, &tmp, size_mop); 1529e514f105SLee Jones } 1530e514f105SLee Jones 1531e514f105SLee Jones /* Handle non-aligned buf */ 1532e514f105SLee Jones if ((uint32_t)buf & 0x3) 1533e514f105SLee Jones memcpy(buf, page_buf, size); 1534e514f105SLee Jones 1535e514f105SLee Jones /* Wait for sequence to finish */ 1536e514f105SLee Jones stfsm_wait_seq(fsm); 1537e514f105SLee Jones 1538e514f105SLee Jones stfsm_clear_fifo(fsm); 1539e514f105SLee Jones 1540e514f105SLee Jones /* Exit 32-bit address mode, if required */ 1541e514f105SLee Jones if (fsm->configuration & CFG_READ_TOGGLE_32BIT_ADDR) 1542e514f105SLee Jones stfsm_enter_32bit_addr(fsm, 0); 1543e514f105SLee Jones 1544e514f105SLee Jones return 0; 1545e514f105SLee Jones } 1546e514f105SLee Jones 1547176b4377SLee Jones static int stfsm_write(struct stfsm *fsm, const uint8_t *const buf, 1548176b4377SLee Jones const uint32_t size, const uint32_t offset) 1549176b4377SLee Jones { 1550e6b1bb4eSLee Jones struct stfsm_seq *seq = &fsm->stfsm_seq_write; 1551176b4377SLee Jones uint32_t data_pads; 1552176b4377SLee Jones uint32_t write_mask; 1553176b4377SLee Jones uint32_t size_ub; 1554176b4377SLee Jones uint32_t size_lb; 1555176b4377SLee Jones uint32_t size_mop; 1556176b4377SLee Jones uint32_t tmp[4]; 1557176b4377SLee Jones uint32_t page_buf[FLASH_PAGESIZE_32]; 1558176b4377SLee Jones uint8_t *t = (uint8_t *)&tmp; 1559176b4377SLee Jones const uint8_t *p; 1560176b4377SLee Jones int ret; 1561176b4377SLee Jones int i; 1562176b4377SLee Jones 1563176b4377SLee Jones dev_dbg(fsm->dev, "writing %d bytes to 0x%08x\n", size, offset); 1564176b4377SLee Jones 1565176b4377SLee Jones /* Enter 32-bit address mode, if required */ 1566176b4377SLee Jones if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) 1567176b4377SLee Jones stfsm_enter_32bit_addr(fsm, 1); 1568176b4377SLee Jones 1569176b4377SLee Jones /* Must write in multiples of 32 cycles (or 32*pads/8 bytes) */ 1570176b4377SLee Jones data_pads = ((seq->seq_cfg >> 16) & 0x3) + 1; 1571176b4377SLee Jones write_mask = (data_pads << 2) - 1; 1572176b4377SLee Jones 1573176b4377SLee Jones /* Handle non-aligned buf */ 1574176b4377SLee Jones if ((uint32_t)buf & 0x3) { 1575176b4377SLee Jones memcpy(page_buf, buf, size); 1576176b4377SLee Jones p = (uint8_t *)page_buf; 1577176b4377SLee Jones } else { 1578176b4377SLee Jones p = buf; 1579176b4377SLee Jones } 1580176b4377SLee Jones 1581176b4377SLee Jones /* Handle non-aligned size */ 1582176b4377SLee Jones size_ub = (size + write_mask) & ~write_mask; 1583176b4377SLee Jones size_lb = size & ~write_mask; 1584176b4377SLee Jones size_mop = size & write_mask; 1585176b4377SLee Jones 1586176b4377SLee Jones seq->data_size = TRANSFER_SIZE(size_ub); 1587176b4377SLee Jones seq->addr1 = (offset >> 16) & 0xffff; 1588176b4377SLee Jones seq->addr2 = offset & 0xffff; 1589176b4377SLee Jones 1590176b4377SLee Jones /* Need to set FIFO to write mode, before writing data to FIFO (see 1591176b4377SLee Jones * GNBvb79594) 1592176b4377SLee Jones */ 1593176b4377SLee Jones writel(0x00040000, fsm->base + SPI_FAST_SEQ_CFG); 1594176b4377SLee Jones 1595176b4377SLee Jones /* 1596176b4377SLee Jones * Before writing data to the FIFO, apply a small delay to allow a 1597176b4377SLee Jones * potential change of FIFO direction to complete. 1598176b4377SLee Jones */ 1599176b4377SLee Jones if (fsm->fifo_dir_delay == 0) 1600176b4377SLee Jones readl(fsm->base + SPI_FAST_SEQ_CFG); 1601176b4377SLee Jones else 1602176b4377SLee Jones udelay(fsm->fifo_dir_delay); 1603176b4377SLee Jones 1604176b4377SLee Jones 1605176b4377SLee Jones /* Write data to FIFO, before starting sequence (see GNBvd79593) */ 1606176b4377SLee Jones if (size_lb) { 1607176b4377SLee Jones stfsm_write_fifo(fsm, (uint32_t *)p, size_lb); 1608176b4377SLee Jones p += size_lb; 1609176b4377SLee Jones } 1610176b4377SLee Jones 1611176b4377SLee Jones /* Handle non-aligned size */ 1612176b4377SLee Jones if (size_mop) { 1613176b4377SLee Jones memset(t, 0xff, write_mask + 1); /* fill with 0xff's */ 1614176b4377SLee Jones for (i = 0; i < size_mop; i++) 1615176b4377SLee Jones t[i] = *p++; 1616176b4377SLee Jones 1617176b4377SLee Jones stfsm_write_fifo(fsm, tmp, write_mask + 1); 1618176b4377SLee Jones } 1619176b4377SLee Jones 1620176b4377SLee Jones /* Start sequence */ 1621176b4377SLee Jones stfsm_load_seq(fsm, seq); 1622176b4377SLee Jones 1623176b4377SLee Jones /* Wait for sequence to finish */ 1624176b4377SLee Jones stfsm_wait_seq(fsm); 1625176b4377SLee Jones 1626176b4377SLee Jones /* Wait for completion */ 1627176b4377SLee Jones ret = stfsm_wait_busy(fsm); 16285343a123SLee Jones if (ret && fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS) 16295343a123SLee Jones stfsm_s25fl_clear_status_reg(fsm); 1630176b4377SLee Jones 1631176b4377SLee Jones /* Exit 32-bit address mode, if required */ 1632176b4377SLee Jones if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) { 1633176b4377SLee Jones stfsm_enter_32bit_addr(fsm, 0); 1634176b4377SLee Jones if (fsm->configuration & CFG_WRITE_EX_32BIT_ADDR_DELAY) 1635176b4377SLee Jones udelay(1); 1636176b4377SLee Jones } 1637176b4377SLee Jones 1638176b4377SLee Jones return 0; 1639176b4377SLee Jones } 1640176b4377SLee Jones 1641e514f105SLee Jones /* 1642e514f105SLee Jones * Read an address range from the flash chip. The address range 1643e514f105SLee Jones * may be any size provided it is within the physical boundaries. 1644e514f105SLee Jones */ 1645e514f105SLee Jones static int stfsm_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, 1646e514f105SLee Jones size_t *retlen, u_char *buf) 1647e514f105SLee Jones { 1648e514f105SLee Jones struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); 1649e514f105SLee Jones uint32_t bytes; 1650e514f105SLee Jones 1651e514f105SLee Jones dev_dbg(fsm->dev, "%s from 0x%08x, len %zd\n", 1652e514f105SLee Jones __func__, (u32)from, len); 1653e514f105SLee Jones 1654e514f105SLee Jones mutex_lock(&fsm->lock); 1655e514f105SLee Jones 1656e514f105SLee Jones while (len > 0) { 1657e514f105SLee Jones bytes = min_t(size_t, len, FLASH_PAGESIZE); 1658e514f105SLee Jones 1659e514f105SLee Jones stfsm_read(fsm, buf, bytes, from); 1660e514f105SLee Jones 1661e514f105SLee Jones buf += bytes; 1662e514f105SLee Jones from += bytes; 1663e514f105SLee Jones len -= bytes; 1664e514f105SLee Jones 1665e514f105SLee Jones *retlen += bytes; 1666e514f105SLee Jones } 1667e514f105SLee Jones 1668e514f105SLee Jones mutex_unlock(&fsm->lock); 1669e514f105SLee Jones 1670e514f105SLee Jones return 0; 1671e514f105SLee Jones } 1672e514f105SLee Jones 16734a341fe7SLee Jones static int stfsm_erase_sector(struct stfsm *fsm, const uint32_t offset) 16744a341fe7SLee Jones { 16754a341fe7SLee Jones struct stfsm_seq *seq = &stfsm_seq_erase_sector; 16764a341fe7SLee Jones int ret; 16774a341fe7SLee Jones 16784a341fe7SLee Jones dev_dbg(fsm->dev, "erasing sector at 0x%08x\n", offset); 16794a341fe7SLee Jones 16804a341fe7SLee Jones /* Enter 32-bit address mode, if required */ 16814a341fe7SLee Jones if (fsm->configuration & CFG_ERASESEC_TOGGLE_32BIT_ADDR) 16824a341fe7SLee Jones stfsm_enter_32bit_addr(fsm, 1); 16834a341fe7SLee Jones 16844a341fe7SLee Jones seq->addr1 = (offset >> 16) & 0xffff; 16854a341fe7SLee Jones seq->addr2 = offset & 0xffff; 16864a341fe7SLee Jones 16874a341fe7SLee Jones stfsm_load_seq(fsm, seq); 16884a341fe7SLee Jones 16894a341fe7SLee Jones stfsm_wait_seq(fsm); 16904a341fe7SLee Jones 16914a341fe7SLee Jones /* Wait for completion */ 16924a341fe7SLee Jones ret = stfsm_wait_busy(fsm); 16935343a123SLee Jones if (ret && fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS) 16945343a123SLee Jones stfsm_s25fl_clear_status_reg(fsm); 16954a341fe7SLee Jones 16964a341fe7SLee Jones /* Exit 32-bit address mode, if required */ 16974a341fe7SLee Jones if (fsm->configuration & CFG_ERASESEC_TOGGLE_32BIT_ADDR) 16984a341fe7SLee Jones stfsm_enter_32bit_addr(fsm, 0); 16994a341fe7SLee Jones 17004a341fe7SLee Jones return ret; 17014a341fe7SLee Jones } 17024a341fe7SLee Jones 17034a341fe7SLee Jones static int stfsm_erase_chip(struct stfsm *fsm) 17044a341fe7SLee Jones { 17054a341fe7SLee Jones const struct stfsm_seq *seq = &stfsm_seq_erase_chip; 17064a341fe7SLee Jones 17074a341fe7SLee Jones dev_dbg(fsm->dev, "erasing chip\n"); 17084a341fe7SLee Jones 17094a341fe7SLee Jones stfsm_load_seq(fsm, seq); 17104a341fe7SLee Jones 17114a341fe7SLee Jones stfsm_wait_seq(fsm); 17124a341fe7SLee Jones 17134a341fe7SLee Jones return stfsm_wait_busy(fsm); 17144a341fe7SLee Jones } 17154a341fe7SLee Jones 1716176b4377SLee Jones /* 1717176b4377SLee Jones * Write an address range to the flash chip. Data must be written in 1718176b4377SLee Jones * FLASH_PAGESIZE chunks. The address range may be any size provided 1719176b4377SLee Jones * it is within the physical boundaries. 1720176b4377SLee Jones */ 1721176b4377SLee Jones static int stfsm_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, 1722176b4377SLee Jones size_t *retlen, const u_char *buf) 1723176b4377SLee Jones { 1724176b4377SLee Jones struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); 1725176b4377SLee Jones 1726176b4377SLee Jones u32 page_offs; 1727176b4377SLee Jones u32 bytes; 1728176b4377SLee Jones uint8_t *b = (uint8_t *)buf; 1729176b4377SLee Jones int ret = 0; 1730176b4377SLee Jones 1731176b4377SLee Jones dev_dbg(fsm->dev, "%s to 0x%08x, len %zd\n", __func__, (u32)to, len); 1732176b4377SLee Jones 1733176b4377SLee Jones *retlen = 0; 1734176b4377SLee Jones 1735176b4377SLee Jones if (!len) 1736176b4377SLee Jones return 0; 1737176b4377SLee Jones 1738176b4377SLee Jones if (to + len > mtd->size) 1739176b4377SLee Jones return -EINVAL; 1740176b4377SLee Jones 1741176b4377SLee Jones /* Offset within page */ 1742176b4377SLee Jones page_offs = to % FLASH_PAGESIZE; 1743176b4377SLee Jones 1744176b4377SLee Jones mutex_lock(&fsm->lock); 1745176b4377SLee Jones 1746176b4377SLee Jones while (len) { 1747176b4377SLee Jones /* Write up to page boundary */ 1748176b4377SLee Jones bytes = min(FLASH_PAGESIZE - page_offs, len); 1749176b4377SLee Jones 1750176b4377SLee Jones ret = stfsm_write(fsm, b, bytes, to); 1751176b4377SLee Jones if (ret) 1752176b4377SLee Jones goto out1; 1753176b4377SLee Jones 1754176b4377SLee Jones b += bytes; 1755176b4377SLee Jones len -= bytes; 1756176b4377SLee Jones to += bytes; 1757176b4377SLee Jones 1758176b4377SLee Jones /* We are now page-aligned */ 1759176b4377SLee Jones page_offs = 0; 1760176b4377SLee Jones 1761176b4377SLee Jones *retlen += bytes; 1762176b4377SLee Jones 1763176b4377SLee Jones } 1764176b4377SLee Jones 1765176b4377SLee Jones out1: 1766176b4377SLee Jones mutex_unlock(&fsm->lock); 1767176b4377SLee Jones 1768176b4377SLee Jones return ret; 1769176b4377SLee Jones } 1770176b4377SLee Jones 17714a341fe7SLee Jones /* 17724a341fe7SLee Jones * Erase an address range on the flash chip. The address range may extend 17734a341fe7SLee Jones * one or more erase sectors. Return an error is there is a problem erasing. 17744a341fe7SLee Jones */ 17754a341fe7SLee Jones static int stfsm_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) 17764a341fe7SLee Jones { 17774a341fe7SLee Jones struct stfsm *fsm = dev_get_drvdata(mtd->dev.parent); 17784a341fe7SLee Jones u32 addr, len; 17794a341fe7SLee Jones int ret; 17804a341fe7SLee Jones 17814a341fe7SLee Jones dev_dbg(fsm->dev, "%s at 0x%llx, len %lld\n", __func__, 17824a341fe7SLee Jones (long long)instr->addr, (long long)instr->len); 17834a341fe7SLee Jones 17844a341fe7SLee Jones addr = instr->addr; 17854a341fe7SLee Jones len = instr->len; 17864a341fe7SLee Jones 17874a341fe7SLee Jones mutex_lock(&fsm->lock); 17884a341fe7SLee Jones 17894a341fe7SLee Jones /* Whole-chip erase? */ 17904a341fe7SLee Jones if (len == mtd->size) { 17914a341fe7SLee Jones ret = stfsm_erase_chip(fsm); 17924a341fe7SLee Jones if (ret) 17934a341fe7SLee Jones goto out1; 17944a341fe7SLee Jones } else { 17954a341fe7SLee Jones while (len) { 17964a341fe7SLee Jones ret = stfsm_erase_sector(fsm, addr); 17974a341fe7SLee Jones if (ret) 17984a341fe7SLee Jones goto out1; 17994a341fe7SLee Jones 18004a341fe7SLee Jones addr += mtd->erasesize; 18014a341fe7SLee Jones len -= mtd->erasesize; 18024a341fe7SLee Jones } 18034a341fe7SLee Jones } 18044a341fe7SLee Jones 18054a341fe7SLee Jones mutex_unlock(&fsm->lock); 18064a341fe7SLee Jones 18074a341fe7SLee Jones instr->state = MTD_ERASE_DONE; 18084a341fe7SLee Jones mtd_erase_callback(instr); 18094a341fe7SLee Jones 18104a341fe7SLee Jones return 0; 18114a341fe7SLee Jones 18124a341fe7SLee Jones out1: 18134a341fe7SLee Jones instr->state = MTD_ERASE_FAILED; 18144a341fe7SLee Jones mutex_unlock(&fsm->lock); 18154a341fe7SLee Jones 18164a341fe7SLee Jones return ret; 18174a341fe7SLee Jones } 18184a341fe7SLee Jones 18191bd512b5SLee Jones static void stfsm_read_jedec(struct stfsm *fsm, uint8_t *const jedec) 18201bd512b5SLee Jones { 18211bd512b5SLee Jones const struct stfsm_seq *seq = &stfsm_seq_read_jedec; 18221bd512b5SLee Jones uint32_t tmp[2]; 18231bd512b5SLee Jones 18241bd512b5SLee Jones stfsm_load_seq(fsm, seq); 18251bd512b5SLee Jones 18261bd512b5SLee Jones stfsm_read_fifo(fsm, tmp, 8); 18271bd512b5SLee Jones 18281bd512b5SLee Jones memcpy(jedec, tmp, 5); 18291bd512b5SLee Jones 18301bd512b5SLee Jones stfsm_wait_seq(fsm); 18311bd512b5SLee Jones } 18321bd512b5SLee Jones 18331bd512b5SLee Jones static struct flash_info *stfsm_jedec_probe(struct stfsm *fsm) 18341bd512b5SLee Jones { 183524fec651SLee Jones struct flash_info *info; 18361bd512b5SLee Jones u16 ext_jedec; 18371bd512b5SLee Jones u32 jedec; 18381bd512b5SLee Jones u8 id[5]; 18391bd512b5SLee Jones 18401bd512b5SLee Jones stfsm_read_jedec(fsm, id); 18411bd512b5SLee Jones 18421bd512b5SLee Jones jedec = id[0] << 16 | id[1] << 8 | id[2]; 18431bd512b5SLee Jones /* 18441bd512b5SLee Jones * JEDEC also defines an optional "extended device information" 18451bd512b5SLee Jones * string for after vendor-specific data, after the three bytes 18461bd512b5SLee Jones * we use here. Supporting some chips might require using it. 18471bd512b5SLee Jones */ 18481bd512b5SLee Jones ext_jedec = id[3] << 8 | id[4]; 18491bd512b5SLee Jones 18501bd512b5SLee Jones dev_dbg(fsm->dev, "JEDEC = 0x%08x [%02x %02x %02x %02x %02x]\n", 18511bd512b5SLee Jones jedec, id[0], id[1], id[2], id[3], id[4]); 18521bd512b5SLee Jones 185324fec651SLee Jones for (info = flash_types; info->name; info++) { 185424fec651SLee Jones if (info->jedec_id == jedec) { 185524fec651SLee Jones if (info->ext_id && info->ext_id != ext_jedec) 185624fec651SLee Jones continue; 185724fec651SLee Jones return info; 185824fec651SLee Jones } 185924fec651SLee Jones } 186024fec651SLee Jones dev_err(fsm->dev, "Unrecognized JEDEC id %06x\n", jedec); 186124fec651SLee Jones 18621bd512b5SLee Jones return NULL; 18631bd512b5SLee Jones } 18641bd512b5SLee Jones 186586f309fdSLee Jones static int stfsm_set_mode(struct stfsm *fsm, uint32_t mode) 186686f309fdSLee Jones { 186786f309fdSLee Jones int ret, timeout = 10; 186886f309fdSLee Jones 186986f309fdSLee Jones /* Wait for controller to accept mode change */ 187086f309fdSLee Jones while (--timeout) { 187186f309fdSLee Jones ret = readl(fsm->base + SPI_STA_MODE_CHANGE); 187286f309fdSLee Jones if (ret & 0x1) 187386f309fdSLee Jones break; 187486f309fdSLee Jones udelay(1); 187586f309fdSLee Jones } 187686f309fdSLee Jones 187786f309fdSLee Jones if (!timeout) 187886f309fdSLee Jones return -EBUSY; 187986f309fdSLee Jones 188086f309fdSLee Jones writel(mode, fsm->base + SPI_MODESELECT); 188186f309fdSLee Jones 188286f309fdSLee Jones return 0; 188386f309fdSLee Jones } 188486f309fdSLee Jones 188586f309fdSLee Jones static void stfsm_set_freq(struct stfsm *fsm, uint32_t spi_freq) 188686f309fdSLee Jones { 188786f309fdSLee Jones uint32_t emi_freq; 188886f309fdSLee Jones uint32_t clk_div; 188986f309fdSLee Jones 189086f309fdSLee Jones /* TODO: Make this dynamic */ 189186f309fdSLee Jones emi_freq = STFSM_DEFAULT_EMI_FREQ; 189286f309fdSLee Jones 189386f309fdSLee Jones /* 189486f309fdSLee Jones * Calculate clk_div - values between 2 and 128 189586f309fdSLee Jones * Multiple of 2, rounded up 189686f309fdSLee Jones */ 189786f309fdSLee Jones clk_div = 2 * DIV_ROUND_UP(emi_freq, 2 * spi_freq); 189886f309fdSLee Jones if (clk_div < 2) 189986f309fdSLee Jones clk_div = 2; 190086f309fdSLee Jones else if (clk_div > 128) 190186f309fdSLee Jones clk_div = 128; 190286f309fdSLee Jones 190386f309fdSLee Jones /* 190486f309fdSLee Jones * Determine a suitable delay for the IP to complete a change of 190586f309fdSLee Jones * direction of the FIFO. The required delay is related to the clock 190686f309fdSLee Jones * divider used. The following heuristics are based on empirical tests, 190786f309fdSLee Jones * using a 100MHz EMI clock. 190886f309fdSLee Jones */ 190986f309fdSLee Jones if (clk_div <= 4) 191086f309fdSLee Jones fsm->fifo_dir_delay = 0; 191186f309fdSLee Jones else if (clk_div <= 10) 191286f309fdSLee Jones fsm->fifo_dir_delay = 1; 191386f309fdSLee Jones else 191486f309fdSLee Jones fsm->fifo_dir_delay = DIV_ROUND_UP(clk_div, 10); 191586f309fdSLee Jones 191686f309fdSLee Jones dev_dbg(fsm->dev, "emi_clk = %uHZ, spi_freq = %uHZ, clk_div = %u\n", 191786f309fdSLee Jones emi_freq, spi_freq, clk_div); 191886f309fdSLee Jones 191986f309fdSLee Jones writel(clk_div, fsm->base + SPI_CLOCKDIV); 192086f309fdSLee Jones } 192186f309fdSLee Jones 192286f309fdSLee Jones static int stfsm_init(struct stfsm *fsm) 192386f309fdSLee Jones { 192486f309fdSLee Jones int ret; 192586f309fdSLee Jones 192686f309fdSLee Jones /* Perform a soft reset of the FSM controller */ 192786f309fdSLee Jones writel(SEQ_CFG_SWRESET, fsm->base + SPI_FAST_SEQ_CFG); 192886f309fdSLee Jones udelay(1); 192986f309fdSLee Jones writel(0, fsm->base + SPI_FAST_SEQ_CFG); 193086f309fdSLee Jones 193186f309fdSLee Jones /* Set clock to 'safe' frequency initially */ 193286f309fdSLee Jones stfsm_set_freq(fsm, STFSM_FLASH_SAFE_FREQ); 193386f309fdSLee Jones 193486f309fdSLee Jones /* Switch to FSM */ 193586f309fdSLee Jones ret = stfsm_set_mode(fsm, SPI_MODESELECT_FSM); 193686f309fdSLee Jones if (ret) 193786f309fdSLee Jones return ret; 193886f309fdSLee Jones 193986f309fdSLee Jones /* Set timing parameters */ 194086f309fdSLee Jones writel(SPI_CFG_DEVICE_ST | 194186f309fdSLee Jones SPI_CFG_DEFAULT_MIN_CS_HIGH | 194286f309fdSLee Jones SPI_CFG_DEFAULT_CS_SETUPHOLD | 194386f309fdSLee Jones SPI_CFG_DEFAULT_DATA_HOLD, 194486f309fdSLee Jones fsm->base + SPI_CONFIGDATA); 194586f309fdSLee Jones writel(STFSM_DEFAULT_WR_TIME, fsm->base + SPI_STATUS_WR_TIME_REG); 194686f309fdSLee Jones 194786f309fdSLee Jones /* Clear FIFO, just in case */ 194886f309fdSLee Jones stfsm_clear_fifo(fsm); 194986f309fdSLee Jones 195086f309fdSLee Jones return 0; 195186f309fdSLee Jones } 195286f309fdSLee Jones 1953a63984c1SLee Jones static void stfsm_fetch_platform_configs(struct platform_device *pdev) 1954a63984c1SLee Jones { 1955a63984c1SLee Jones struct stfsm *fsm = platform_get_drvdata(pdev); 1956a63984c1SLee Jones struct device_node *np = pdev->dev.of_node; 1957a63984c1SLee Jones struct regmap *regmap; 1958a63984c1SLee Jones uint32_t boot_device_reg; 1959a63984c1SLee Jones uint32_t boot_device_spi; 1960a63984c1SLee Jones uint32_t boot_device; /* Value we read from *boot_device_reg */ 1961a63984c1SLee Jones int ret; 1962a63984c1SLee Jones 1963a63984c1SLee Jones /* Booting from SPI NOR Flash is the default */ 1964a63984c1SLee Jones fsm->booted_from_spi = true; 1965a63984c1SLee Jones 1966a63984c1SLee Jones regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); 1967a63984c1SLee Jones if (IS_ERR(regmap)) 1968a63984c1SLee Jones goto boot_device_fail; 1969a63984c1SLee Jones 19700ea7d706SLee Jones fsm->reset_signal = of_property_read_bool(np, "st,reset-signal"); 19710ea7d706SLee Jones 19720ea7d706SLee Jones fsm->reset_por = of_property_read_bool(np, "st,reset-por"); 19730ea7d706SLee Jones 1974a63984c1SLee Jones /* Where in the syscon the boot device information lives */ 1975a63984c1SLee Jones ret = of_property_read_u32(np, "st,boot-device-reg", &boot_device_reg); 1976a63984c1SLee Jones if (ret) 1977a63984c1SLee Jones goto boot_device_fail; 1978a63984c1SLee Jones 1979a63984c1SLee Jones /* Boot device value when booted from SPI NOR */ 1980a63984c1SLee Jones ret = of_property_read_u32(np, "st,boot-device-spi", &boot_device_spi); 1981a63984c1SLee Jones if (ret) 1982a63984c1SLee Jones goto boot_device_fail; 1983a63984c1SLee Jones 1984a63984c1SLee Jones ret = regmap_read(regmap, boot_device_reg, &boot_device); 1985a63984c1SLee Jones if (ret) 1986a63984c1SLee Jones goto boot_device_fail; 1987a63984c1SLee Jones 1988a63984c1SLee Jones if (boot_device != boot_device_spi) 1989a63984c1SLee Jones fsm->booted_from_spi = false; 1990a63984c1SLee Jones 1991a63984c1SLee Jones return; 1992a63984c1SLee Jones 1993a63984c1SLee Jones boot_device_fail: 1994a63984c1SLee Jones dev_warn(&pdev->dev, 1995a63984c1SLee Jones "failed to fetch boot device, assuming boot from SPI\n"); 1996a63984c1SLee Jones } 1997a63984c1SLee Jones 1998d90db4a0SLee Jones static int stfsm_probe(struct platform_device *pdev) 1999d90db4a0SLee Jones { 2000d90db4a0SLee Jones struct device_node *np = pdev->dev.of_node; 2001*221cff13SLee Jones struct mtd_part_parser_data ppdata; 200224fec651SLee Jones struct flash_info *info; 2003d90db4a0SLee Jones struct resource *res; 2004d90db4a0SLee Jones struct stfsm *fsm; 200586f309fdSLee Jones int ret; 2006d90db4a0SLee Jones 2007d90db4a0SLee Jones if (!np) { 2008d90db4a0SLee Jones dev_err(&pdev->dev, "No DT found\n"); 2009d90db4a0SLee Jones return -EINVAL; 2010d90db4a0SLee Jones } 2011*221cff13SLee Jones ppdata.of_node = np; 2012d90db4a0SLee Jones 2013d90db4a0SLee Jones fsm = devm_kzalloc(&pdev->dev, sizeof(*fsm), GFP_KERNEL); 2014d90db4a0SLee Jones if (!fsm) 2015d90db4a0SLee Jones return -ENOMEM; 2016d90db4a0SLee Jones 2017d90db4a0SLee Jones fsm->dev = &pdev->dev; 2018d90db4a0SLee Jones 2019d90db4a0SLee Jones platform_set_drvdata(pdev, fsm); 2020d90db4a0SLee Jones 2021d90db4a0SLee Jones res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2022d90db4a0SLee Jones if (!res) { 2023d90db4a0SLee Jones dev_err(&pdev->dev, "Resource not found\n"); 2024d90db4a0SLee Jones return -ENODEV; 2025d90db4a0SLee Jones } 2026d90db4a0SLee Jones 2027d90db4a0SLee Jones fsm->base = devm_ioremap_resource(&pdev->dev, res); 2028d90db4a0SLee Jones if (IS_ERR(fsm->base)) { 2029d90db4a0SLee Jones dev_err(&pdev->dev, 2030d90db4a0SLee Jones "Failed to reserve memory region %pR\n", res); 2031d90db4a0SLee Jones return PTR_ERR(fsm->base); 2032d90db4a0SLee Jones } 2033d90db4a0SLee Jones 2034d90db4a0SLee Jones mutex_init(&fsm->lock); 2035d90db4a0SLee Jones 203686f309fdSLee Jones ret = stfsm_init(fsm); 203786f309fdSLee Jones if (ret) { 203886f309fdSLee Jones dev_err(&pdev->dev, "Failed to initialise FSM Controller\n"); 203986f309fdSLee Jones return ret; 204086f309fdSLee Jones } 204186f309fdSLee Jones 2042a63984c1SLee Jones stfsm_fetch_platform_configs(pdev); 2043a63984c1SLee Jones 20441bd512b5SLee Jones /* Detect SPI FLASH device */ 204524fec651SLee Jones info = stfsm_jedec_probe(fsm); 204624fec651SLee Jones if (!info) 204724fec651SLee Jones return -ENODEV; 204824fec651SLee Jones fsm->info = info; 20491bd512b5SLee Jones 20503b5d1981SLee Jones /* Use device size to determine address width */ 20513b5d1981SLee Jones if (info->sector_size * info->n_sectors > 0x1000000) 20523b5d1981SLee Jones info->flags |= FLASH_FLAG_32BIT_ADDR; 20533b5d1981SLee Jones 2054218b870fSLee Jones /* 2055218b870fSLee Jones * Configure READ/WRITE/ERASE sequences according to platform and 2056218b870fSLee Jones * device flags. 2057218b870fSLee Jones */ 2058218b870fSLee Jones if (info->config) { 2059218b870fSLee Jones ret = info->config(fsm); 2060218b870fSLee Jones if (ret) 2061218b870fSLee Jones return ret; 20624eb3f0d8SLee Jones } else { 20634eb3f0d8SLee Jones ret = stfsm_prepare_rwe_seqs_default(fsm); 20644eb3f0d8SLee Jones if (ret) 20654eb3f0d8SLee Jones return ret; 2066218b870fSLee Jones } 2067218b870fSLee Jones 2068*221cff13SLee Jones fsm->mtd.name = info->name; 2069d90db4a0SLee Jones fsm->mtd.dev.parent = &pdev->dev; 2070d90db4a0SLee Jones fsm->mtd.type = MTD_NORFLASH; 2071d90db4a0SLee Jones fsm->mtd.writesize = 4; 2072d90db4a0SLee Jones fsm->mtd.writebufsize = fsm->mtd.writesize; 2073d90db4a0SLee Jones fsm->mtd.flags = MTD_CAP_NORFLASH; 207424fec651SLee Jones fsm->mtd.size = info->sector_size * info->n_sectors; 207524fec651SLee Jones fsm->mtd.erasesize = info->sector_size; 207624fec651SLee Jones 2077e514f105SLee Jones fsm->mtd._read = stfsm_mtd_read; 2078176b4377SLee Jones fsm->mtd._write = stfsm_mtd_write; 20794a341fe7SLee Jones fsm->mtd._erase = stfsm_mtd_erase; 2080e514f105SLee Jones 20814a341fe7SLee Jones dev_info(&pdev->dev, 208224fec651SLee Jones "Found serial flash device: %s\n" 208324fec651SLee Jones " size = %llx (%lldMiB) erasesize = 0x%08x (%uKiB)\n", 208424fec651SLee Jones info->name, 208524fec651SLee Jones (long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20), 208624fec651SLee Jones fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10)); 2087d90db4a0SLee Jones 2088*221cff13SLee Jones return mtd_device_parse_register(&fsm->mtd, NULL, &ppdata, NULL, 0); 2089d90db4a0SLee Jones } 2090d90db4a0SLee Jones 2091d90db4a0SLee Jones static int stfsm_remove(struct platform_device *pdev) 2092d90db4a0SLee Jones { 2093d90db4a0SLee Jones struct stfsm *fsm = platform_get_drvdata(pdev); 2094d90db4a0SLee Jones int err; 2095d90db4a0SLee Jones 2096d90db4a0SLee Jones err = mtd_device_unregister(&fsm->mtd); 2097d90db4a0SLee Jones if (err) 2098d90db4a0SLee Jones return err; 2099d90db4a0SLee Jones 2100d90db4a0SLee Jones return 0; 2101d90db4a0SLee Jones } 2102d90db4a0SLee Jones 2103d90db4a0SLee Jones static struct of_device_id stfsm_match[] = { 2104d90db4a0SLee Jones { .compatible = "st,spi-fsm", }, 2105d90db4a0SLee Jones {}, 2106d90db4a0SLee Jones }; 2107d90db4a0SLee Jones MODULE_DEVICE_TABLE(of, stfsm_match); 2108d90db4a0SLee Jones 2109d90db4a0SLee Jones static struct platform_driver stfsm_driver = { 2110d90db4a0SLee Jones .probe = stfsm_probe, 2111d90db4a0SLee Jones .remove = stfsm_remove, 2112d90db4a0SLee Jones .driver = { 2113d90db4a0SLee Jones .name = "st-spi-fsm", 2114d90db4a0SLee Jones .owner = THIS_MODULE, 2115d90db4a0SLee Jones .of_match_table = stfsm_match, 2116d90db4a0SLee Jones }, 2117d90db4a0SLee Jones }; 2118d90db4a0SLee Jones module_platform_driver(stfsm_driver); 2119d90db4a0SLee Jones 2120d90db4a0SLee Jones MODULE_AUTHOR("Angus Clark <angus.clark@st.com>"); 2121d90db4a0SLee Jones MODULE_DESCRIPTION("ST SPI FSM driver"); 2122d90db4a0SLee Jones MODULE_LICENSE("GPL"); 2123