1cba65a77SJagan Teki /* 2cba65a77SJagan Teki * SPI Flash Core 3cba65a77SJagan Teki * 4cba65a77SJagan Teki * Copyright (C) 2015 Jagan Teki <jteki@openedev.com> 5cba65a77SJagan Teki * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. 6cba65a77SJagan Teki * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik 7cba65a77SJagan Teki * Copyright (C) 2008 Atmel Corporation 8cba65a77SJagan Teki * 9cba65a77SJagan Teki * SPDX-License-Identifier: GPL-2.0+ 10cba65a77SJagan Teki */ 11cba65a77SJagan Teki 12cba65a77SJagan Teki #include <common.h> 13cba65a77SJagan Teki #include <errno.h> 14cba65a77SJagan Teki #include <malloc.h> 15cba65a77SJagan Teki #include <mapmem.h> 16cba65a77SJagan Teki #include <spi.h> 17cba65a77SJagan Teki #include <spi_flash.h> 18cba65a77SJagan Teki #include <linux/log2.h> 197bd1c59bSMugunthan V N #include <dma.h> 20cba65a77SJagan Teki 21cba65a77SJagan Teki #include "sf_internal.h" 22cba65a77SJagan Teki 23cba65a77SJagan Teki DECLARE_GLOBAL_DATA_PTR; 24cba65a77SJagan Teki 25cba65a77SJagan Teki static void spi_flash_addr(u32 addr, u8 *cmd) 26cba65a77SJagan Teki { 27cba65a77SJagan Teki /* cmd[0] is actual command */ 28cba65a77SJagan Teki cmd[1] = addr >> 16; 29cba65a77SJagan Teki cmd[2] = addr >> 8; 30cba65a77SJagan Teki cmd[3] = addr >> 0; 31cba65a77SJagan Teki } 32cba65a77SJagan Teki 33cba65a77SJagan Teki static int read_sr(struct spi_flash *flash, u8 *rs) 34cba65a77SJagan Teki { 35cba65a77SJagan Teki int ret; 36cba65a77SJagan Teki u8 cmd; 37cba65a77SJagan Teki 38cba65a77SJagan Teki cmd = CMD_READ_STATUS; 39cba65a77SJagan Teki ret = spi_flash_read_common(flash, &cmd, 1, rs, 1); 40cba65a77SJagan Teki if (ret < 0) { 41cba65a77SJagan Teki debug("SF: fail to read status register\n"); 42cba65a77SJagan Teki return ret; 43cba65a77SJagan Teki } 44cba65a77SJagan Teki 45cba65a77SJagan Teki return 0; 46cba65a77SJagan Teki } 47cba65a77SJagan Teki 48cba65a77SJagan Teki static int read_fsr(struct spi_flash *flash, u8 *fsr) 49cba65a77SJagan Teki { 50cba65a77SJagan Teki int ret; 51cba65a77SJagan Teki const u8 cmd = CMD_FLAG_STATUS; 52cba65a77SJagan Teki 53cba65a77SJagan Teki ret = spi_flash_read_common(flash, &cmd, 1, fsr, 1); 54cba65a77SJagan Teki if (ret < 0) { 55cba65a77SJagan Teki debug("SF: fail to read flag status register\n"); 56cba65a77SJagan Teki return ret; 57cba65a77SJagan Teki } 58cba65a77SJagan Teki 59cba65a77SJagan Teki return 0; 60cba65a77SJagan Teki } 61cba65a77SJagan Teki 62cba65a77SJagan Teki static int write_sr(struct spi_flash *flash, u8 ws) 63cba65a77SJagan Teki { 64cba65a77SJagan Teki u8 cmd; 65cba65a77SJagan Teki int ret; 66cba65a77SJagan Teki 67cba65a77SJagan Teki cmd = CMD_WRITE_STATUS; 68cba65a77SJagan Teki ret = spi_flash_write_common(flash, &cmd, 1, &ws, 1); 69cba65a77SJagan Teki if (ret < 0) { 70cba65a77SJagan Teki debug("SF: fail to write status register\n"); 71cba65a77SJagan Teki return ret; 72cba65a77SJagan Teki } 73cba65a77SJagan Teki 74cba65a77SJagan Teki return 0; 75cba65a77SJagan Teki } 76cba65a77SJagan Teki 77cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) 78cba65a77SJagan Teki static int read_cr(struct spi_flash *flash, u8 *rc) 79cba65a77SJagan Teki { 80cba65a77SJagan Teki int ret; 81cba65a77SJagan Teki u8 cmd; 82cba65a77SJagan Teki 83cba65a77SJagan Teki cmd = CMD_READ_CONFIG; 84cba65a77SJagan Teki ret = spi_flash_read_common(flash, &cmd, 1, rc, 1); 85cba65a77SJagan Teki if (ret < 0) { 86cba65a77SJagan Teki debug("SF: fail to read config register\n"); 87cba65a77SJagan Teki return ret; 88cba65a77SJagan Teki } 89cba65a77SJagan Teki 90cba65a77SJagan Teki return 0; 91cba65a77SJagan Teki } 92cba65a77SJagan Teki 93cba65a77SJagan Teki static int write_cr(struct spi_flash *flash, u8 wc) 94cba65a77SJagan Teki { 95cba65a77SJagan Teki u8 data[2]; 96cba65a77SJagan Teki u8 cmd; 97cba65a77SJagan Teki int ret; 98cba65a77SJagan Teki 99cba65a77SJagan Teki ret = read_sr(flash, &data[0]); 100cba65a77SJagan Teki if (ret < 0) 101cba65a77SJagan Teki return ret; 102cba65a77SJagan Teki 103cba65a77SJagan Teki cmd = CMD_WRITE_STATUS; 104cba65a77SJagan Teki data[1] = wc; 105cba65a77SJagan Teki ret = spi_flash_write_common(flash, &cmd, 1, &data, 2); 106cba65a77SJagan Teki if (ret) { 107cba65a77SJagan Teki debug("SF: fail to write config register\n"); 108cba65a77SJagan Teki return ret; 109cba65a77SJagan Teki } 110cba65a77SJagan Teki 111cba65a77SJagan Teki return 0; 112cba65a77SJagan Teki } 113cba65a77SJagan Teki #endif 114cba65a77SJagan Teki 115cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR 1162e1c78b4SLukasz Majewski /* 1172e1c78b4SLukasz Majewski * This "clean_bar" is necessary in a situation when one was accessing 1182e1c78b4SLukasz Majewski * spi flash memory > 16 MiB by using Bank Address Register's BA24 bit. 1192e1c78b4SLukasz Majewski * 1202e1c78b4SLukasz Majewski * After it the BA24 bit shall be cleared to allow access to correct 1212e1c78b4SLukasz Majewski * memory region after SW reset (by calling "reset" command). 1222e1c78b4SLukasz Majewski * 1232e1c78b4SLukasz Majewski * Otherwise, the BA24 bit may be left set and then after reset, the 1242e1c78b4SLukasz Majewski * ROM would read/write/erase SPL from 16 MiB * bank_sel address. 1252e1c78b4SLukasz Majewski */ 1262e1c78b4SLukasz Majewski static int clean_bar(struct spi_flash *flash) 1272e1c78b4SLukasz Majewski { 1282e1c78b4SLukasz Majewski u8 cmd, bank_sel = 0; 1292e1c78b4SLukasz Majewski 1302e1c78b4SLukasz Majewski if (flash->bank_curr == 0) 1312e1c78b4SLukasz Majewski return 0; 1322e1c78b4SLukasz Majewski cmd = flash->bank_write_cmd; 1332e1c78b4SLukasz Majewski 1342e1c78b4SLukasz Majewski return spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); 1352e1c78b4SLukasz Majewski } 1362e1c78b4SLukasz Majewski 1377b4ab88eSJagan Teki static int write_bar(struct spi_flash *flash, u32 offset) 138cba65a77SJagan Teki { 139cba65a77SJagan Teki u8 cmd, bank_sel; 140cba65a77SJagan Teki int ret; 141cba65a77SJagan Teki 142cba65a77SJagan Teki bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift); 143cba65a77SJagan Teki if (bank_sel == flash->bank_curr) 144cba65a77SJagan Teki goto bar_end; 145cba65a77SJagan Teki 146cba65a77SJagan Teki cmd = flash->bank_write_cmd; 147cba65a77SJagan Teki ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); 148cba65a77SJagan Teki if (ret < 0) { 149cba65a77SJagan Teki debug("SF: fail to write bank register\n"); 150cba65a77SJagan Teki return ret; 151cba65a77SJagan Teki } 152cba65a77SJagan Teki 153cba65a77SJagan Teki bar_end: 154cba65a77SJagan Teki flash->bank_curr = bank_sel; 155cba65a77SJagan Teki return flash->bank_curr; 156cba65a77SJagan Teki } 157cba65a77SJagan Teki 1587b4ab88eSJagan Teki static int read_bar(struct spi_flash *flash, const struct spi_flash_info *info) 159cba65a77SJagan Teki { 160cba65a77SJagan Teki u8 curr_bank = 0; 161cba65a77SJagan Teki int ret; 162cba65a77SJagan Teki 163cba65a77SJagan Teki if (flash->size <= SPI_FLASH_16MB_BOUN) 1646f309658SJagan Teki goto bar_end; 165cba65a77SJagan Teki 166f790ca7cSJagan Teki switch (JEDEC_MFR(info)) { 167cba65a77SJagan Teki case SPI_FLASH_CFI_MFR_SPANSION: 168cba65a77SJagan Teki flash->bank_read_cmd = CMD_BANKADDR_BRRD; 169cba65a77SJagan Teki flash->bank_write_cmd = CMD_BANKADDR_BRWR; 170cba65a77SJagan Teki break; 171cba65a77SJagan Teki default: 172cba65a77SJagan Teki flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; 173cba65a77SJagan Teki flash->bank_write_cmd = CMD_EXTNADDR_WREAR; 174cba65a77SJagan Teki } 175cba65a77SJagan Teki 176cba65a77SJagan Teki ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1, 177cba65a77SJagan Teki &curr_bank, 1); 178cba65a77SJagan Teki if (ret) { 179cba65a77SJagan Teki debug("SF: fail to read bank addr register\n"); 180cba65a77SJagan Teki return ret; 181cba65a77SJagan Teki } 182cba65a77SJagan Teki 1836f309658SJagan Teki bar_end: 184cba65a77SJagan Teki flash->bank_curr = curr_bank; 185cba65a77SJagan Teki return 0; 186cba65a77SJagan Teki } 187cba65a77SJagan Teki #endif 188cba65a77SJagan Teki 189cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH 190cba65a77SJagan Teki static void spi_flash_dual(struct spi_flash *flash, u32 *addr) 191cba65a77SJagan Teki { 192cba65a77SJagan Teki switch (flash->dual_flash) { 193cba65a77SJagan Teki case SF_DUAL_STACKED_FLASH: 194cba65a77SJagan Teki if (*addr >= (flash->size >> 1)) { 195cba65a77SJagan Teki *addr -= flash->size >> 1; 19620343ff3SJagan Teki flash->flags |= SNOR_F_USE_UPAGE; 197cba65a77SJagan Teki } else { 19820343ff3SJagan Teki flash->flags &= ~SNOR_F_USE_UPAGE; 199cba65a77SJagan Teki } 200cba65a77SJagan Teki break; 201cba65a77SJagan Teki case SF_DUAL_PARALLEL_FLASH: 202cba65a77SJagan Teki *addr >>= flash->shift; 203cba65a77SJagan Teki break; 204cba65a77SJagan Teki default: 205cba65a77SJagan Teki debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash); 206cba65a77SJagan Teki break; 207cba65a77SJagan Teki } 208cba65a77SJagan Teki } 209cba65a77SJagan Teki #endif 210cba65a77SJagan Teki 211cba65a77SJagan Teki static int spi_flash_sr_ready(struct spi_flash *flash) 212cba65a77SJagan Teki { 213cba65a77SJagan Teki u8 sr; 214cba65a77SJagan Teki int ret; 215cba65a77SJagan Teki 216cba65a77SJagan Teki ret = read_sr(flash, &sr); 217cba65a77SJagan Teki if (ret < 0) 218cba65a77SJagan Teki return ret; 219cba65a77SJagan Teki 220cba65a77SJagan Teki return !(sr & STATUS_WIP); 221cba65a77SJagan Teki } 222cba65a77SJagan Teki 223cba65a77SJagan Teki static int spi_flash_fsr_ready(struct spi_flash *flash) 224cba65a77SJagan Teki { 225cba65a77SJagan Teki u8 fsr; 226cba65a77SJagan Teki int ret; 227cba65a77SJagan Teki 228cba65a77SJagan Teki ret = read_fsr(flash, &fsr); 229cba65a77SJagan Teki if (ret < 0) 230cba65a77SJagan Teki return ret; 231cba65a77SJagan Teki 232cba65a77SJagan Teki return fsr & STATUS_PEC; 233cba65a77SJagan Teki } 234cba65a77SJagan Teki 235cba65a77SJagan Teki static int spi_flash_ready(struct spi_flash *flash) 236cba65a77SJagan Teki { 237cba65a77SJagan Teki int sr, fsr; 238cba65a77SJagan Teki 239cba65a77SJagan Teki sr = spi_flash_sr_ready(flash); 240cba65a77SJagan Teki if (sr < 0) 241cba65a77SJagan Teki return sr; 242cba65a77SJagan Teki 243cba65a77SJagan Teki fsr = 1; 244cba65a77SJagan Teki if (flash->flags & SNOR_F_USE_FSR) { 245cba65a77SJagan Teki fsr = spi_flash_fsr_ready(flash); 246cba65a77SJagan Teki if (fsr < 0) 247cba65a77SJagan Teki return fsr; 248cba65a77SJagan Teki } 249cba65a77SJagan Teki 250cba65a77SJagan Teki return sr && fsr; 251cba65a77SJagan Teki } 252cba65a77SJagan Teki 2537b4ab88eSJagan Teki static int spi_flash_wait_till_ready(struct spi_flash *flash, 254cba65a77SJagan Teki unsigned long timeout) 255cba65a77SJagan Teki { 25611b9a4d8SStephen Warren unsigned long timebase; 25711b9a4d8SStephen Warren int ret; 258cba65a77SJagan Teki 259cba65a77SJagan Teki timebase = get_timer(0); 260cba65a77SJagan Teki 261cba65a77SJagan Teki while (get_timer(timebase) < timeout) { 262cba65a77SJagan Teki ret = spi_flash_ready(flash); 263cba65a77SJagan Teki if (ret < 0) 264cba65a77SJagan Teki return ret; 265cba65a77SJagan Teki if (ret) 266cba65a77SJagan Teki return 0; 267cba65a77SJagan Teki } 268cba65a77SJagan Teki 269cba65a77SJagan Teki printf("SF: Timeout!\n"); 270cba65a77SJagan Teki 271cba65a77SJagan Teki return -ETIMEDOUT; 272cba65a77SJagan Teki } 273cba65a77SJagan Teki 274cba65a77SJagan Teki int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, 275cba65a77SJagan Teki size_t cmd_len, const void *buf, size_t buf_len) 276cba65a77SJagan Teki { 277cba65a77SJagan Teki struct spi_slave *spi = flash->spi; 278cba65a77SJagan Teki unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; 279cba65a77SJagan Teki int ret; 280cba65a77SJagan Teki 281cba65a77SJagan Teki if (buf == NULL) 282cba65a77SJagan Teki timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; 283cba65a77SJagan Teki 284e228d6deSJagan Teki ret = spi_claim_bus(spi); 285cba65a77SJagan Teki if (ret) { 286cba65a77SJagan Teki debug("SF: unable to claim SPI bus\n"); 287cba65a77SJagan Teki return ret; 288cba65a77SJagan Teki } 289cba65a77SJagan Teki 290cba65a77SJagan Teki ret = spi_flash_cmd_write_enable(flash); 291cba65a77SJagan Teki if (ret < 0) { 292cba65a77SJagan Teki debug("SF: enabling write failed\n"); 293cba65a77SJagan Teki return ret; 294cba65a77SJagan Teki } 295cba65a77SJagan Teki 296cba65a77SJagan Teki ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); 297cba65a77SJagan Teki if (ret < 0) { 298cba65a77SJagan Teki debug("SF: write cmd failed\n"); 299cba65a77SJagan Teki return ret; 300cba65a77SJagan Teki } 301cba65a77SJagan Teki 3027b4ab88eSJagan Teki ret = spi_flash_wait_till_ready(flash, timeout); 303cba65a77SJagan Teki if (ret < 0) { 304cba65a77SJagan Teki debug("SF: write %s timed out\n", 305cba65a77SJagan Teki timeout == SPI_FLASH_PROG_TIMEOUT ? 306cba65a77SJagan Teki "program" : "page erase"); 307cba65a77SJagan Teki return ret; 308cba65a77SJagan Teki } 309cba65a77SJagan Teki 310cba65a77SJagan Teki spi_release_bus(spi); 311cba65a77SJagan Teki 312cba65a77SJagan Teki return ret; 313cba65a77SJagan Teki } 314cba65a77SJagan Teki 315cba65a77SJagan Teki int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) 316cba65a77SJagan Teki { 317cba65a77SJagan Teki u32 erase_size, erase_addr; 318cba65a77SJagan Teki u8 cmd[SPI_FLASH_CMD_LEN]; 319cba65a77SJagan Teki int ret = -1; 320cba65a77SJagan Teki 321cba65a77SJagan Teki erase_size = flash->erase_size; 322cba65a77SJagan Teki if (offset % erase_size || len % erase_size) { 323cba65a77SJagan Teki debug("SF: Erase offset/length not multiple of erase size\n"); 324cba65a77SJagan Teki return -1; 325cba65a77SJagan Teki } 326cba65a77SJagan Teki 327cba65a77SJagan Teki if (flash->flash_is_locked) { 328cba65a77SJagan Teki if (flash->flash_is_locked(flash, offset, len) > 0) { 329cba65a77SJagan Teki printf("offset 0x%x is protected and cannot be erased\n", 330cba65a77SJagan Teki offset); 331cba65a77SJagan Teki return -EINVAL; 332cba65a77SJagan Teki } 333cba65a77SJagan Teki } 334cba65a77SJagan Teki 335cba65a77SJagan Teki cmd[0] = flash->erase_cmd; 336cba65a77SJagan Teki while (len) { 337cba65a77SJagan Teki erase_addr = offset; 338cba65a77SJagan Teki 339cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH 340cba65a77SJagan Teki if (flash->dual_flash > SF_SINGLE_FLASH) 341cba65a77SJagan Teki spi_flash_dual(flash, &erase_addr); 342cba65a77SJagan Teki #endif 343cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR 3447b4ab88eSJagan Teki ret = write_bar(flash, erase_addr); 345cba65a77SJagan Teki if (ret < 0) 346cba65a77SJagan Teki return ret; 347cba65a77SJagan Teki #endif 348cba65a77SJagan Teki spi_flash_addr(erase_addr, cmd); 349cba65a77SJagan Teki 350cba65a77SJagan Teki debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], 351cba65a77SJagan Teki cmd[2], cmd[3], erase_addr); 352cba65a77SJagan Teki 353cba65a77SJagan Teki ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); 354cba65a77SJagan Teki if (ret < 0) { 355cba65a77SJagan Teki debug("SF: erase failed\n"); 356cba65a77SJagan Teki break; 357cba65a77SJagan Teki } 358cba65a77SJagan Teki 359cba65a77SJagan Teki offset += erase_size; 360cba65a77SJagan Teki len -= erase_size; 361cba65a77SJagan Teki } 362cba65a77SJagan Teki 3632e1c78b4SLukasz Majewski #ifdef CONFIG_SPI_FLASH_BAR 3642e1c78b4SLukasz Majewski ret = clean_bar(flash); 3652e1c78b4SLukasz Majewski #endif 3662e1c78b4SLukasz Majewski 367cba65a77SJagan Teki return ret; 368cba65a77SJagan Teki } 369cba65a77SJagan Teki 370cba65a77SJagan Teki int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, 371cba65a77SJagan Teki size_t len, const void *buf) 372cba65a77SJagan Teki { 373e228d6deSJagan Teki struct spi_slave *spi = flash->spi; 374cba65a77SJagan Teki unsigned long byte_addr, page_size; 375cba65a77SJagan Teki u32 write_addr; 376cba65a77SJagan Teki size_t chunk_len, actual; 377cba65a77SJagan Teki u8 cmd[SPI_FLASH_CMD_LEN]; 378cba65a77SJagan Teki int ret = -1; 379cba65a77SJagan Teki 380cba65a77SJagan Teki page_size = flash->page_size; 381cba65a77SJagan Teki 382cba65a77SJagan Teki if (flash->flash_is_locked) { 383cba65a77SJagan Teki if (flash->flash_is_locked(flash, offset, len) > 0) { 384cba65a77SJagan Teki printf("offset 0x%x is protected and cannot be written\n", 385cba65a77SJagan Teki offset); 386cba65a77SJagan Teki return -EINVAL; 387cba65a77SJagan Teki } 388cba65a77SJagan Teki } 389cba65a77SJagan Teki 390cba65a77SJagan Teki cmd[0] = flash->write_cmd; 391cba65a77SJagan Teki for (actual = 0; actual < len; actual += chunk_len) { 392cba65a77SJagan Teki write_addr = offset; 393cba65a77SJagan Teki 394cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH 395cba65a77SJagan Teki if (flash->dual_flash > SF_SINGLE_FLASH) 396cba65a77SJagan Teki spi_flash_dual(flash, &write_addr); 397cba65a77SJagan Teki #endif 398cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR 3997b4ab88eSJagan Teki ret = write_bar(flash, write_addr); 400cba65a77SJagan Teki if (ret < 0) 401cba65a77SJagan Teki return ret; 402cba65a77SJagan Teki #endif 403cba65a77SJagan Teki byte_addr = offset % page_size; 404cba65a77SJagan Teki chunk_len = min(len - actual, (size_t)(page_size - byte_addr)); 405cba65a77SJagan Teki 406e228d6deSJagan Teki if (spi->max_write_size) 407cba65a77SJagan Teki chunk_len = min(chunk_len, 408*d2a88c91SÁlvaro Fernández Rojas spi->max_write_size - sizeof(cmd)); 409cba65a77SJagan Teki 410cba65a77SJagan Teki spi_flash_addr(write_addr, cmd); 411cba65a77SJagan Teki 412cba65a77SJagan Teki debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", 413cba65a77SJagan Teki buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); 414cba65a77SJagan Teki 415cba65a77SJagan Teki ret = spi_flash_write_common(flash, cmd, sizeof(cmd), 416cba65a77SJagan Teki buf + actual, chunk_len); 417cba65a77SJagan Teki if (ret < 0) { 418cba65a77SJagan Teki debug("SF: write failed\n"); 419cba65a77SJagan Teki break; 420cba65a77SJagan Teki } 421cba65a77SJagan Teki 422cba65a77SJagan Teki offset += chunk_len; 423cba65a77SJagan Teki } 424cba65a77SJagan Teki 4252e1c78b4SLukasz Majewski #ifdef CONFIG_SPI_FLASH_BAR 4262e1c78b4SLukasz Majewski ret = clean_bar(flash); 4272e1c78b4SLukasz Majewski #endif 4282e1c78b4SLukasz Majewski 429cba65a77SJagan Teki return ret; 430cba65a77SJagan Teki } 431cba65a77SJagan Teki 432cba65a77SJagan Teki int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, 433cba65a77SJagan Teki size_t cmd_len, void *data, size_t data_len) 434cba65a77SJagan Teki { 435cba65a77SJagan Teki struct spi_slave *spi = flash->spi; 436cba65a77SJagan Teki int ret; 437cba65a77SJagan Teki 438e228d6deSJagan Teki ret = spi_claim_bus(spi); 439cba65a77SJagan Teki if (ret) { 440cba65a77SJagan Teki debug("SF: unable to claim SPI bus\n"); 441cba65a77SJagan Teki return ret; 442cba65a77SJagan Teki } 443cba65a77SJagan Teki 444cba65a77SJagan Teki ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); 445cba65a77SJagan Teki if (ret < 0) { 446cba65a77SJagan Teki debug("SF: read cmd failed\n"); 447cba65a77SJagan Teki return ret; 448cba65a77SJagan Teki } 449cba65a77SJagan Teki 450cba65a77SJagan Teki spi_release_bus(spi); 451cba65a77SJagan Teki 452cba65a77SJagan Teki return ret; 453cba65a77SJagan Teki } 454cba65a77SJagan Teki 4557bd1c59bSMugunthan V N /* 4567bd1c59bSMugunthan V N * TODO: remove the weak after all the other spi_flash_copy_mmap 4577bd1c59bSMugunthan V N * implementations removed from drivers 4587bd1c59bSMugunthan V N */ 459cba65a77SJagan Teki void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len) 460cba65a77SJagan Teki { 4617bd1c59bSMugunthan V N #ifdef CONFIG_DMA 4627bd1c59bSMugunthan V N if (!dma_memcpy(data, offset, len)) 4637bd1c59bSMugunthan V N return; 4647bd1c59bSMugunthan V N #endif 465cba65a77SJagan Teki memcpy(data, offset, len); 466cba65a77SJagan Teki } 467cba65a77SJagan Teki 468cba65a77SJagan Teki int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, 469cba65a77SJagan Teki size_t len, void *data) 470cba65a77SJagan Teki { 471e228d6deSJagan Teki struct spi_slave *spi = flash->spi; 472cba65a77SJagan Teki u8 *cmd, cmdsz; 473cba65a77SJagan Teki u32 remain_len, read_len, read_addr; 474cba65a77SJagan Teki int bank_sel = 0; 475cba65a77SJagan Teki int ret = -1; 476cba65a77SJagan Teki 477cba65a77SJagan Teki /* Handle memory-mapped SPI */ 478cba65a77SJagan Teki if (flash->memory_map) { 479e228d6deSJagan Teki ret = spi_claim_bus(spi); 480cba65a77SJagan Teki if (ret) { 481cba65a77SJagan Teki debug("SF: unable to claim SPI bus\n"); 482cba65a77SJagan Teki return ret; 483cba65a77SJagan Teki } 484e228d6deSJagan Teki spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP); 485cba65a77SJagan Teki spi_flash_copy_mmap(data, flash->memory_map + offset, len); 486e228d6deSJagan Teki spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP_END); 487e228d6deSJagan Teki spi_release_bus(spi); 488cba65a77SJagan Teki return 0; 489cba65a77SJagan Teki } 490cba65a77SJagan Teki 491cba65a77SJagan Teki cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; 492cba65a77SJagan Teki cmd = calloc(1, cmdsz); 493cba65a77SJagan Teki if (!cmd) { 494cba65a77SJagan Teki debug("SF: Failed to allocate cmd\n"); 495cba65a77SJagan Teki return -ENOMEM; 496cba65a77SJagan Teki } 497cba65a77SJagan Teki 498cba65a77SJagan Teki cmd[0] = flash->read_cmd; 499cba65a77SJagan Teki while (len) { 500cba65a77SJagan Teki read_addr = offset; 501cba65a77SJagan Teki 502cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH 503cba65a77SJagan Teki if (flash->dual_flash > SF_SINGLE_FLASH) 504cba65a77SJagan Teki spi_flash_dual(flash, &read_addr); 505cba65a77SJagan Teki #endif 506cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR 5077b4ab88eSJagan Teki ret = write_bar(flash, read_addr); 508cba65a77SJagan Teki if (ret < 0) 509cba65a77SJagan Teki return ret; 510cba65a77SJagan Teki bank_sel = flash->bank_curr; 511cba65a77SJagan Teki #endif 512cba65a77SJagan Teki remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * 513cba65a77SJagan Teki (bank_sel + 1)) - offset; 514cba65a77SJagan Teki if (len < remain_len) 515cba65a77SJagan Teki read_len = len; 516cba65a77SJagan Teki else 517cba65a77SJagan Teki read_len = remain_len; 518cba65a77SJagan Teki 519d68b9b84SÁlvaro Fernández Rojas if (spi->max_read_size) 520d68b9b84SÁlvaro Fernández Rojas read_len = min(read_len, spi->max_read_size); 521d68b9b84SÁlvaro Fernández Rojas 522cba65a77SJagan Teki spi_flash_addr(read_addr, cmd); 523cba65a77SJagan Teki 524cba65a77SJagan Teki ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); 525cba65a77SJagan Teki if (ret < 0) { 526cba65a77SJagan Teki debug("SF: read failed\n"); 527cba65a77SJagan Teki break; 528cba65a77SJagan Teki } 529cba65a77SJagan Teki 530cba65a77SJagan Teki offset += read_len; 531cba65a77SJagan Teki len -= read_len; 532cba65a77SJagan Teki data += read_len; 533cba65a77SJagan Teki } 534cba65a77SJagan Teki 5352e1c78b4SLukasz Majewski #ifdef CONFIG_SPI_FLASH_BAR 5362e1c78b4SLukasz Majewski ret = clean_bar(flash); 5372e1c78b4SLukasz Majewski #endif 5382e1c78b4SLukasz Majewski 539cba65a77SJagan Teki free(cmd); 540cba65a77SJagan Teki return ret; 541cba65a77SJagan Teki } 542cba65a77SJagan Teki 543cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_SST 544cba65a77SJagan Teki static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) 545cba65a77SJagan Teki { 546e228d6deSJagan Teki struct spi_slave *spi = flash->spi; 547cba65a77SJagan Teki int ret; 548cba65a77SJagan Teki u8 cmd[4] = { 549cba65a77SJagan Teki CMD_SST_BP, 550cba65a77SJagan Teki offset >> 16, 551cba65a77SJagan Teki offset >> 8, 552cba65a77SJagan Teki offset, 553cba65a77SJagan Teki }; 554cba65a77SJagan Teki 555cba65a77SJagan Teki debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", 556e228d6deSJagan Teki spi_w8r8(spi, CMD_READ_STATUS), buf, cmd[0], offset); 557cba65a77SJagan Teki 558cba65a77SJagan Teki ret = spi_flash_cmd_write_enable(flash); 559cba65a77SJagan Teki if (ret) 560cba65a77SJagan Teki return ret; 561cba65a77SJagan Teki 562e228d6deSJagan Teki ret = spi_flash_cmd_write(spi, cmd, sizeof(cmd), buf, 1); 563cba65a77SJagan Teki if (ret) 564cba65a77SJagan Teki return ret; 565cba65a77SJagan Teki 5667b4ab88eSJagan Teki return spi_flash_wait_till_ready(flash, SPI_FLASH_PROG_TIMEOUT); 567cba65a77SJagan Teki } 568cba65a77SJagan Teki 569cba65a77SJagan Teki int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, 570cba65a77SJagan Teki const void *buf) 571cba65a77SJagan Teki { 572e228d6deSJagan Teki struct spi_slave *spi = flash->spi; 573cba65a77SJagan Teki size_t actual, cmd_len; 574cba65a77SJagan Teki int ret; 575cba65a77SJagan Teki u8 cmd[4]; 576cba65a77SJagan Teki 577e228d6deSJagan Teki ret = spi_claim_bus(spi); 578cba65a77SJagan Teki if (ret) { 579cba65a77SJagan Teki debug("SF: Unable to claim SPI bus\n"); 580cba65a77SJagan Teki return ret; 581cba65a77SJagan Teki } 582cba65a77SJagan Teki 583cba65a77SJagan Teki /* If the data is not word aligned, write out leading single byte */ 584cba65a77SJagan Teki actual = offset % 2; 585cba65a77SJagan Teki if (actual) { 586cba65a77SJagan Teki ret = sst_byte_write(flash, offset, buf); 587cba65a77SJagan Teki if (ret) 588cba65a77SJagan Teki goto done; 589cba65a77SJagan Teki } 590cba65a77SJagan Teki offset += actual; 591cba65a77SJagan Teki 592cba65a77SJagan Teki ret = spi_flash_cmd_write_enable(flash); 593cba65a77SJagan Teki if (ret) 594cba65a77SJagan Teki goto done; 595cba65a77SJagan Teki 596cba65a77SJagan Teki cmd_len = 4; 597cba65a77SJagan Teki cmd[0] = CMD_SST_AAI_WP; 598cba65a77SJagan Teki cmd[1] = offset >> 16; 599cba65a77SJagan Teki cmd[2] = offset >> 8; 600cba65a77SJagan Teki cmd[3] = offset; 601cba65a77SJagan Teki 602cba65a77SJagan Teki for (; actual < len - 1; actual += 2) { 603cba65a77SJagan Teki debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", 604e228d6deSJagan Teki spi_w8r8(spi, CMD_READ_STATUS), buf + actual, 605cba65a77SJagan Teki cmd[0], offset); 606cba65a77SJagan Teki 607e228d6deSJagan Teki ret = spi_flash_cmd_write(spi, cmd, cmd_len, 608cba65a77SJagan Teki buf + actual, 2); 609cba65a77SJagan Teki if (ret) { 610cba65a77SJagan Teki debug("SF: sst word program failed\n"); 611cba65a77SJagan Teki break; 612cba65a77SJagan Teki } 613cba65a77SJagan Teki 6147b4ab88eSJagan Teki ret = spi_flash_wait_till_ready(flash, SPI_FLASH_PROG_TIMEOUT); 615cba65a77SJagan Teki if (ret) 616cba65a77SJagan Teki break; 617cba65a77SJagan Teki 618cba65a77SJagan Teki cmd_len = 1; 619cba65a77SJagan Teki offset += 2; 620cba65a77SJagan Teki } 621cba65a77SJagan Teki 622cba65a77SJagan Teki if (!ret) 623cba65a77SJagan Teki ret = spi_flash_cmd_write_disable(flash); 624cba65a77SJagan Teki 625cba65a77SJagan Teki /* If there is a single trailing byte, write it out */ 626cba65a77SJagan Teki if (!ret && actual != len) 627cba65a77SJagan Teki ret = sst_byte_write(flash, offset, buf + actual); 628cba65a77SJagan Teki 629cba65a77SJagan Teki done: 630cba65a77SJagan Teki debug("SF: sst: program %s %zu bytes @ 0x%zx\n", 631cba65a77SJagan Teki ret ? "failure" : "success", len, offset - actual); 632cba65a77SJagan Teki 633e228d6deSJagan Teki spi_release_bus(spi); 634cba65a77SJagan Teki return ret; 635cba65a77SJagan Teki } 636cba65a77SJagan Teki 637cba65a77SJagan Teki int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, 638cba65a77SJagan Teki const void *buf) 639cba65a77SJagan Teki { 640e228d6deSJagan Teki struct spi_slave *spi = flash->spi; 641cba65a77SJagan Teki size_t actual; 642cba65a77SJagan Teki int ret; 643cba65a77SJagan Teki 644e228d6deSJagan Teki ret = spi_claim_bus(spi); 645cba65a77SJagan Teki if (ret) { 646cba65a77SJagan Teki debug("SF: Unable to claim SPI bus\n"); 647cba65a77SJagan Teki return ret; 648cba65a77SJagan Teki } 649cba65a77SJagan Teki 650cba65a77SJagan Teki for (actual = 0; actual < len; actual++) { 651cba65a77SJagan Teki ret = sst_byte_write(flash, offset, buf + actual); 652cba65a77SJagan Teki if (ret) { 653cba65a77SJagan Teki debug("SF: sst byte program failed\n"); 654cba65a77SJagan Teki break; 655cba65a77SJagan Teki } 656cba65a77SJagan Teki offset++; 657cba65a77SJagan Teki } 658cba65a77SJagan Teki 659cba65a77SJagan Teki if (!ret) 660cba65a77SJagan Teki ret = spi_flash_cmd_write_disable(flash); 661cba65a77SJagan Teki 662cba65a77SJagan Teki debug("SF: sst: program %s %zu bytes @ 0x%zx\n", 663cba65a77SJagan Teki ret ? "failure" : "success", len, offset - actual); 664cba65a77SJagan Teki 665e228d6deSJagan Teki spi_release_bus(spi); 666cba65a77SJagan Teki return ret; 667cba65a77SJagan Teki } 668cba65a77SJagan Teki #endif 669cba65a77SJagan Teki 670cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) 671cba65a77SJagan Teki static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, 672ea9619aeSMarek Vasut u64 *len) 673cba65a77SJagan Teki { 674cba65a77SJagan Teki u8 mask = SR_BP2 | SR_BP1 | SR_BP0; 675cba65a77SJagan Teki int shift = ffs(mask) - 1; 676cba65a77SJagan Teki int pow; 677cba65a77SJagan Teki 678cba65a77SJagan Teki if (!(sr & mask)) { 679cba65a77SJagan Teki /* No protection */ 680cba65a77SJagan Teki *ofs = 0; 681cba65a77SJagan Teki *len = 0; 682cba65a77SJagan Teki } else { 683cba65a77SJagan Teki pow = ((sr & mask) ^ mask) >> shift; 684cba65a77SJagan Teki *len = flash->size >> pow; 685cba65a77SJagan Teki *ofs = flash->size - *len; 686cba65a77SJagan Teki } 687cba65a77SJagan Teki } 688cba65a77SJagan Teki 689cba65a77SJagan Teki /* 690cba65a77SJagan Teki * Return 1 if the entire region is locked, 0 otherwise 691cba65a77SJagan Teki */ 692ea9619aeSMarek Vasut static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, u64 len, 693cba65a77SJagan Teki u8 sr) 694cba65a77SJagan Teki { 695cba65a77SJagan Teki loff_t lock_offs; 696ea9619aeSMarek Vasut u64 lock_len; 697cba65a77SJagan Teki 698cba65a77SJagan Teki stm_get_locked_range(flash, sr, &lock_offs, &lock_len); 699cba65a77SJagan Teki 700cba65a77SJagan Teki return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); 701cba65a77SJagan Teki } 702cba65a77SJagan Teki 703cba65a77SJagan Teki /* 704cba65a77SJagan Teki * Check if a region of the flash is (completely) locked. See stm_lock() for 705cba65a77SJagan Teki * more info. 706cba65a77SJagan Teki * 707cba65a77SJagan Teki * Returns 1 if entire region is locked, 0 if any portion is unlocked, and 708cba65a77SJagan Teki * negative on errors. 709cba65a77SJagan Teki */ 710cba65a77SJagan Teki int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len) 711cba65a77SJagan Teki { 712cba65a77SJagan Teki int status; 713cba65a77SJagan Teki u8 sr; 714cba65a77SJagan Teki 715cba65a77SJagan Teki status = read_sr(flash, &sr); 716cba65a77SJagan Teki if (status < 0) 717cba65a77SJagan Teki return status; 718cba65a77SJagan Teki 719cba65a77SJagan Teki return stm_is_locked_sr(flash, ofs, len, sr); 720cba65a77SJagan Teki } 721cba65a77SJagan Teki 722cba65a77SJagan Teki /* 723cba65a77SJagan Teki * Lock a region of the flash. Compatible with ST Micro and similar flash. 724cba65a77SJagan Teki * Supports only the block protection bits BP{0,1,2} in the status register 725cba65a77SJagan Teki * (SR). Does not support these features found in newer SR bitfields: 726cba65a77SJagan Teki * - TB: top/bottom protect - only handle TB=0 (top protect) 727cba65a77SJagan Teki * - SEC: sector/block protect - only handle SEC=0 (block protect) 728cba65a77SJagan Teki * - CMP: complement protect - only support CMP=0 (range is not complemented) 729cba65a77SJagan Teki * 730cba65a77SJagan Teki * Sample table portion for 8MB flash (Winbond w25q64fw): 731cba65a77SJagan Teki * 732cba65a77SJagan Teki * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion 733cba65a77SJagan Teki * -------------------------------------------------------------------------- 734cba65a77SJagan Teki * X | X | 0 | 0 | 0 | NONE | NONE 735cba65a77SJagan Teki * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 736cba65a77SJagan Teki * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 737cba65a77SJagan Teki * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 738cba65a77SJagan Teki * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 739cba65a77SJagan Teki * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 740cba65a77SJagan Teki * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 741cba65a77SJagan Teki * X | X | 1 | 1 | 1 | 8 MB | ALL 742cba65a77SJagan Teki * 743cba65a77SJagan Teki * Returns negative on errors, 0 on success. 744cba65a77SJagan Teki */ 745cba65a77SJagan Teki int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) 746cba65a77SJagan Teki { 747cba65a77SJagan Teki u8 status_old, status_new; 748cba65a77SJagan Teki u8 mask = SR_BP2 | SR_BP1 | SR_BP0; 749cba65a77SJagan Teki u8 shift = ffs(mask) - 1, pow, val; 750cba65a77SJagan Teki int ret; 751cba65a77SJagan Teki 752cba65a77SJagan Teki ret = read_sr(flash, &status_old); 753cba65a77SJagan Teki if (ret < 0) 754cba65a77SJagan Teki return ret; 755cba65a77SJagan Teki 756cba65a77SJagan Teki /* SPI NOR always locks to the end */ 757cba65a77SJagan Teki if (ofs + len != flash->size) { 758cba65a77SJagan Teki /* Does combined region extend to end? */ 759cba65a77SJagan Teki if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len, 760cba65a77SJagan Teki status_old)) 761cba65a77SJagan Teki return -EINVAL; 762cba65a77SJagan Teki len = flash->size - ofs; 763cba65a77SJagan Teki } 764cba65a77SJagan Teki 765cba65a77SJagan Teki /* 766cba65a77SJagan Teki * Need smallest pow such that: 767cba65a77SJagan Teki * 768cba65a77SJagan Teki * 1 / (2^pow) <= (len / size) 769cba65a77SJagan Teki * 770cba65a77SJagan Teki * so (assuming power-of-2 size) we do: 771cba65a77SJagan Teki * 772cba65a77SJagan Teki * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) 773cba65a77SJagan Teki */ 774cba65a77SJagan Teki pow = ilog2(flash->size) - ilog2(len); 775cba65a77SJagan Teki val = mask - (pow << shift); 776cba65a77SJagan Teki if (val & ~mask) 777cba65a77SJagan Teki return -EINVAL; 778cba65a77SJagan Teki 779cba65a77SJagan Teki /* Don't "lock" with no region! */ 780cba65a77SJagan Teki if (!(val & mask)) 781cba65a77SJagan Teki return -EINVAL; 782cba65a77SJagan Teki 783cba65a77SJagan Teki status_new = (status_old & ~mask) | val; 784cba65a77SJagan Teki 785cba65a77SJagan Teki /* Only modify protection if it will not unlock other areas */ 786cba65a77SJagan Teki if ((status_new & mask) <= (status_old & mask)) 787cba65a77SJagan Teki return -EINVAL; 788cba65a77SJagan Teki 789cba65a77SJagan Teki write_sr(flash, status_new); 790cba65a77SJagan Teki 791cba65a77SJagan Teki return 0; 792cba65a77SJagan Teki } 793cba65a77SJagan Teki 794cba65a77SJagan Teki /* 795cba65a77SJagan Teki * Unlock a region of the flash. See stm_lock() for more info 796cba65a77SJagan Teki * 797cba65a77SJagan Teki * Returns negative on errors, 0 on success. 798cba65a77SJagan Teki */ 799cba65a77SJagan Teki int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) 800cba65a77SJagan Teki { 801cba65a77SJagan Teki uint8_t status_old, status_new; 802cba65a77SJagan Teki u8 mask = SR_BP2 | SR_BP1 | SR_BP0; 803cba65a77SJagan Teki u8 shift = ffs(mask) - 1, pow, val; 804cba65a77SJagan Teki int ret; 805cba65a77SJagan Teki 806cba65a77SJagan Teki ret = read_sr(flash, &status_old); 807cba65a77SJagan Teki if (ret < 0) 808cba65a77SJagan Teki return ret; 809cba65a77SJagan Teki 810cba65a77SJagan Teki /* Cannot unlock; would unlock larger region than requested */ 81150921583SFabio Estevam if (stm_is_locked_sr(flash, ofs - flash->erase_size, flash->erase_size, 81250921583SFabio Estevam status_old)) 813cba65a77SJagan Teki return -EINVAL; 814cba65a77SJagan Teki /* 815cba65a77SJagan Teki * Need largest pow such that: 816cba65a77SJagan Teki * 817cba65a77SJagan Teki * 1 / (2^pow) >= (len / size) 818cba65a77SJagan Teki * 819cba65a77SJagan Teki * so (assuming power-of-2 size) we do: 820cba65a77SJagan Teki * 821cba65a77SJagan Teki * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) 822cba65a77SJagan Teki */ 823cba65a77SJagan Teki pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len)); 824cba65a77SJagan Teki if (ofs + len == flash->size) { 825cba65a77SJagan Teki val = 0; /* fully unlocked */ 826cba65a77SJagan Teki } else { 827cba65a77SJagan Teki val = mask - (pow << shift); 828cba65a77SJagan Teki /* Some power-of-two sizes are not supported */ 829cba65a77SJagan Teki if (val & ~mask) 830cba65a77SJagan Teki return -EINVAL; 831cba65a77SJagan Teki } 832cba65a77SJagan Teki 833cba65a77SJagan Teki status_new = (status_old & ~mask) | val; 834cba65a77SJagan Teki 835cba65a77SJagan Teki /* Only modify protection if it will not lock other areas */ 836cba65a77SJagan Teki if ((status_new & mask) >= (status_old & mask)) 837cba65a77SJagan Teki return -EINVAL; 838cba65a77SJagan Teki 839cba65a77SJagan Teki write_sr(flash, status_new); 840cba65a77SJagan Teki 841cba65a77SJagan Teki return 0; 842cba65a77SJagan Teki } 843cba65a77SJagan Teki #endif 844cba65a77SJagan Teki 845cba65a77SJagan Teki 8466f775b34SAndy Yan #if defined(CONFIG_SPI_FLASH_MACRONIX) || defined(CONFIG_SPI_FLASH_GIGADEVICE) 8479275929cSJagan Teki static int macronix_quad_enable(struct spi_flash *flash) 848cba65a77SJagan Teki { 849cba65a77SJagan Teki u8 qeb_status; 850cba65a77SJagan Teki int ret; 851cba65a77SJagan Teki 852cba65a77SJagan Teki ret = read_sr(flash, &qeb_status); 853cba65a77SJagan Teki if (ret < 0) 854cba65a77SJagan Teki return ret; 855cba65a77SJagan Teki 856bfcdc395SJagan Teki if (qeb_status & STATUS_QEB_MXIC) 857bfcdc395SJagan Teki return 0; 858bfcdc395SJagan Teki 859d9a0ab6cSJagan Teki ret = write_sr(flash, qeb_status | STATUS_QEB_MXIC); 860cba65a77SJagan Teki if (ret < 0) 861cba65a77SJagan Teki return ret; 862bfcdc395SJagan Teki 863bfcdc395SJagan Teki /* read SR and check it */ 864bfcdc395SJagan Teki ret = read_sr(flash, &qeb_status); 865bfcdc395SJagan Teki if (!(ret >= 0 && (qeb_status & STATUS_QEB_MXIC))) { 866bfcdc395SJagan Teki printf("SF: Macronix SR Quad bit not clear\n"); 867bfcdc395SJagan Teki return -EINVAL; 868cba65a77SJagan Teki } 869cba65a77SJagan Teki 870cba65a77SJagan Teki return ret; 871cba65a77SJagan Teki } 872cba65a77SJagan Teki #endif 873cba65a77SJagan Teki 874cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) 8759275929cSJagan Teki static int spansion_quad_enable(struct spi_flash *flash) 876cba65a77SJagan Teki { 877cba65a77SJagan Teki u8 qeb_status; 878cba65a77SJagan Teki int ret; 879cba65a77SJagan Teki 880cba65a77SJagan Teki ret = read_cr(flash, &qeb_status); 881cba65a77SJagan Teki if (ret < 0) 882cba65a77SJagan Teki return ret; 883cba65a77SJagan Teki 884ffecb0fcSJagan Teki if (qeb_status & STATUS_QEB_WINSPAN) 885ffecb0fcSJagan Teki return 0; 886ffecb0fcSJagan Teki 887d9a0ab6cSJagan Teki ret = write_cr(flash, qeb_status | STATUS_QEB_WINSPAN); 888cba65a77SJagan Teki if (ret < 0) 889cba65a77SJagan Teki return ret; 890ffecb0fcSJagan Teki 891ffecb0fcSJagan Teki /* read CR and check it */ 892ffecb0fcSJagan Teki ret = read_cr(flash, &qeb_status); 893ffecb0fcSJagan Teki if (!(ret >= 0 && (qeb_status & STATUS_QEB_WINSPAN))) { 894ffecb0fcSJagan Teki printf("SF: Spansion CR Quad bit not clear\n"); 895ffecb0fcSJagan Teki return -EINVAL; 896cba65a77SJagan Teki } 897cba65a77SJagan Teki 898cba65a77SJagan Teki return ret; 899cba65a77SJagan Teki } 900cba65a77SJagan Teki #endif 901cba65a77SJagan Teki 902f790ca7cSJagan Teki static const struct spi_flash_info *spi_flash_read_id(struct spi_flash *flash) 903cba65a77SJagan Teki { 904f790ca7cSJagan Teki int tmp; 905ed363b53SJagan Teki u8 id[SPI_FLASH_MAX_ID_LEN]; 906f790ca7cSJagan Teki const struct spi_flash_info *info; 907f790ca7cSJagan Teki 908ed363b53SJagan Teki tmp = spi_flash_cmd(flash->spi, CMD_READ_ID, id, SPI_FLASH_MAX_ID_LEN); 909f790ca7cSJagan Teki if (tmp < 0) { 910f790ca7cSJagan Teki printf("SF: error %d reading JEDEC ID\n", tmp); 911f790ca7cSJagan Teki return ERR_PTR(tmp); 912f790ca7cSJagan Teki } 913f790ca7cSJagan Teki 914f790ca7cSJagan Teki info = spi_flash_ids; 915f790ca7cSJagan Teki for (; info->name != NULL; info++) { 916f790ca7cSJagan Teki if (info->id_len) { 917f790ca7cSJagan Teki if (!memcmp(info->id, id, info->id_len)) 918f790ca7cSJagan Teki return info; 919f790ca7cSJagan Teki } 920f790ca7cSJagan Teki } 921f790ca7cSJagan Teki 922f790ca7cSJagan Teki printf("SF: unrecognized JEDEC id bytes: %02x, %02x, %02x\n", 923f790ca7cSJagan Teki id[0], id[1], id[2]); 924f790ca7cSJagan Teki return ERR_PTR(-ENODEV); 925f790ca7cSJagan Teki } 926f790ca7cSJagan Teki 927f790ca7cSJagan Teki static int set_quad_mode(struct spi_flash *flash, 928f790ca7cSJagan Teki const struct spi_flash_info *info) 929f790ca7cSJagan Teki { 930f790ca7cSJagan Teki switch (JEDEC_MFR(info)) { 9316f775b34SAndy Yan #if defined(CONFIG_SPI_FLASH_MACRONIX) || defined(CONFIG_SPI_FLASH_GIGADEVICE) 932cba65a77SJagan Teki case SPI_FLASH_CFI_MFR_MACRONIX: 9336f775b34SAndy Yan case SPI_FLASH_CIF_MFR_GIGADEVICE: 9349275929cSJagan Teki return macronix_quad_enable(flash); 935cba65a77SJagan Teki #endif 936cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) 937cba65a77SJagan Teki case SPI_FLASH_CFI_MFR_SPANSION: 938cba65a77SJagan Teki case SPI_FLASH_CFI_MFR_WINBOND: 9399275929cSJagan Teki return spansion_quad_enable(flash); 940cba65a77SJagan Teki #endif 941cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_STMICRO 942cba65a77SJagan Teki case SPI_FLASH_CFI_MFR_STMICRO: 9439bcb0188SCyrille Pitchen debug("SF: QEB is volatile for %02x flash\n", JEDEC_MFR(info)); 9449bcb0188SCyrille Pitchen return 0; 945cba65a77SJagan Teki #endif 946cba65a77SJagan Teki default: 947f790ca7cSJagan Teki printf("SF: Need set QEB func for %02x flash\n", 948f790ca7cSJagan Teki JEDEC_MFR(info)); 949cba65a77SJagan Teki return -1; 950cba65a77SJagan Teki } 951cba65a77SJagan Teki } 952cba65a77SJagan Teki 953cba65a77SJagan Teki #if CONFIG_IS_ENABLED(OF_CONTROL) 954656f29d1SSimon Glass int spi_flash_decode_fdt(struct spi_flash *flash) 955cba65a77SJagan Teki { 956d178a1c5SSimon Glass #ifdef CONFIG_DM_SPI_FLASH 957cba65a77SJagan Teki fdt_addr_t addr; 958cba65a77SJagan Teki fdt_size_t size; 959cba65a77SJagan Teki 960656f29d1SSimon Glass addr = dev_read_addr_size(flash->dev, "memory-map", &size); 961cba65a77SJagan Teki if (addr == FDT_ADDR_T_NONE) { 962cba65a77SJagan Teki debug("%s: Cannot decode address\n", __func__); 963cba65a77SJagan Teki return 0; 964cba65a77SJagan Teki } 965cba65a77SJagan Teki 966db9225baSPhil Edworthy if (flash->size > size) { 967cba65a77SJagan Teki debug("%s: Memory map must cover entire device\n", __func__); 968cba65a77SJagan Teki return -1; 969cba65a77SJagan Teki } 970cba65a77SJagan Teki flash->memory_map = map_sysmem(addr, size); 971d178a1c5SSimon Glass #endif 972cba65a77SJagan Teki 973cba65a77SJagan Teki return 0; 974cba65a77SJagan Teki } 975cba65a77SJagan Teki #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ 976cba65a77SJagan Teki 977cba65a77SJagan Teki int spi_flash_scan(struct spi_flash *flash) 978cba65a77SJagan Teki { 979cba65a77SJagan Teki struct spi_slave *spi = flash->spi; 980f790ca7cSJagan Teki const struct spi_flash_info *info = NULL; 981304decddSFabien Parent int ret; 982cba65a77SJagan Teki 983f790ca7cSJagan Teki info = spi_flash_read_id(flash); 984f790ca7cSJagan Teki if (IS_ERR_OR_NULL(info)) 985f790ca7cSJagan Teki return -ENOENT; 986cba65a77SJagan Teki 987294f2050SBin Meng /* 988294f2050SBin Meng * Flash powers up read-only, so clear BP# bits. 989294f2050SBin Meng * 990294f2050SBin Meng * Note on some flash (like Macronix), QE (quad enable) bit is in the 991294f2050SBin Meng * same status register as BP# bits, and we need preserve its original 992294f2050SBin Meng * value during a reboot cycle as this is required by some platforms 993294f2050SBin Meng * (like Intel ICH SPI controller working under descriptor mode). 994294f2050SBin Meng */ 995f790ca7cSJagan Teki if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_ATMEL || 996294f2050SBin Meng (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST) || 997294f2050SBin Meng (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX)) { 998294f2050SBin Meng u8 sr = 0; 999294f2050SBin Meng 1000294f2050SBin Meng if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX) { 1001294f2050SBin Meng read_sr(flash, &sr); 1002294f2050SBin Meng sr &= STATUS_QEB_MXIC; 1003294f2050SBin Meng } 1004294f2050SBin Meng write_sr(flash, sr); 1005294f2050SBin Meng } 1006cba65a77SJagan Teki 1007f790ca7cSJagan Teki flash->name = info->name; 1008cba65a77SJagan Teki flash->memory_map = spi->memory_map; 1009cba65a77SJagan Teki 1010f790ca7cSJagan Teki if (info->flags & SST_WR) 1011cba65a77SJagan Teki flash->flags |= SNOR_F_SST_WR; 1012cba65a77SJagan Teki 1013cba65a77SJagan Teki #ifndef CONFIG_DM_SPI_FLASH 1014cba65a77SJagan Teki flash->write = spi_flash_cmd_write_ops; 1015cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_SST) 1016cba65a77SJagan Teki if (flash->flags & SNOR_F_SST_WR) { 1017cdf33938SJagan Teki if (spi->mode & SPI_TX_BYTE) 1018cba65a77SJagan Teki flash->write = sst_write_bp; 1019cba65a77SJagan Teki else 1020cba65a77SJagan Teki flash->write = sst_write_wp; 1021cba65a77SJagan Teki } 1022cba65a77SJagan Teki #endif 1023cba65a77SJagan Teki flash->erase = spi_flash_cmd_erase_ops; 1024cba65a77SJagan Teki flash->read = spi_flash_cmd_read_ops; 1025cba65a77SJagan Teki #endif 1026cba65a77SJagan Teki 1027cba65a77SJagan Teki #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) 1028dda06a43SJagan Teki /* NOR protection support for STmicro/Micron chips and similar */ 1029dda06a43SJagan Teki if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_STMICRO || 1030dda06a43SJagan Teki JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST) { 1031cba65a77SJagan Teki flash->flash_lock = stm_lock; 1032cba65a77SJagan Teki flash->flash_unlock = stm_unlock; 1033cba65a77SJagan Teki flash->flash_is_locked = stm_is_locked; 1034cba65a77SJagan Teki } 1035dda06a43SJagan Teki #endif 1036cba65a77SJagan Teki 1037cba65a77SJagan Teki /* Compute the flash size */ 1038cba65a77SJagan Teki flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; 1039f790ca7cSJagan Teki flash->page_size = info->page_size; 1040cba65a77SJagan Teki /* 1041cba65a77SJagan Teki * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the 1042cba65a77SJagan Teki * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with 1043cba65a77SJagan Teki * the 0x4d00 Extended JEDEC code have 512b pages. All of the others 1044cba65a77SJagan Teki * have 256b pages. 1045cba65a77SJagan Teki */ 1046f790ca7cSJagan Teki if (JEDEC_EXT(info) == 0x4d00) { 1047f790ca7cSJagan Teki if ((JEDEC_ID(info) != 0x0215) && 1048f790ca7cSJagan Teki (JEDEC_ID(info) != 0x0216)) 1049cba65a77SJagan Teki flash->page_size = 512; 1050cba65a77SJagan Teki } 1051cba65a77SJagan Teki flash->page_size <<= flash->shift; 1052f790ca7cSJagan Teki flash->sector_size = info->sector_size << flash->shift; 1053eccb6be0SJagan Teki flash->size = flash->sector_size * info->n_sectors << flash->shift; 1054cba65a77SJagan Teki #ifdef CONFIG_SF_DUAL_FLASH 1055cba65a77SJagan Teki if (flash->dual_flash & SF_DUAL_STACKED_FLASH) 1056cba65a77SJagan Teki flash->size <<= 1; 1057cba65a77SJagan Teki #endif 1058cba65a77SJagan Teki 1059de059928SJagan Teki #ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS 1060cba65a77SJagan Teki /* Compute erase sector and command */ 1061f790ca7cSJagan Teki if (info->flags & SECT_4K) { 1062cba65a77SJagan Teki flash->erase_cmd = CMD_ERASE_4K; 1063cba65a77SJagan Teki flash->erase_size = 4096 << flash->shift; 1064de059928SJagan Teki } else 1065de059928SJagan Teki #endif 1066de059928SJagan Teki { 1067cba65a77SJagan Teki flash->erase_cmd = CMD_ERASE_64K; 1068cba65a77SJagan Teki flash->erase_size = flash->sector_size; 1069cba65a77SJagan Teki } 1070cba65a77SJagan Teki 1071cba65a77SJagan Teki /* Now erase size becomes valid sector size */ 1072cba65a77SJagan Teki flash->sector_size = flash->erase_size; 1073cba65a77SJagan Teki 1074edd35f71SJagan Teki /* Look for read commands */ 1075cba65a77SJagan Teki flash->read_cmd = CMD_READ_ARRAY_FAST; 107608fe9c29SJagan Teki if (spi->mode & SPI_RX_SLOW) 1077edd35f71SJagan Teki flash->read_cmd = CMD_READ_ARRAY_SLOW; 1078f790ca7cSJagan Teki else if (spi->mode & SPI_RX_QUAD && info->flags & RD_QUAD) 1079edd35f71SJagan Teki flash->read_cmd = CMD_READ_QUAD_OUTPUT_FAST; 1080f790ca7cSJagan Teki else if (spi->mode & SPI_RX_DUAL && info->flags & RD_DUAL) 1081edd35f71SJagan Teki flash->read_cmd = CMD_READ_DUAL_OUTPUT_FAST; 1082cba65a77SJagan Teki 1083edd35f71SJagan Teki /* Look for write commands */ 1084f790ca7cSJagan Teki if (info->flags & WR_QPP && spi->mode & SPI_TX_QUAD) 1085cba65a77SJagan Teki flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; 1086cba65a77SJagan Teki else 1087cba65a77SJagan Teki /* Go for default supported write cmd */ 1088cba65a77SJagan Teki flash->write_cmd = CMD_PAGE_PROGRAM; 1089cba65a77SJagan Teki 1090cba65a77SJagan Teki /* Set the quad enable bit - only for quad commands */ 1091cba65a77SJagan Teki if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || 1092cba65a77SJagan Teki (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || 1093cba65a77SJagan Teki (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { 1094f790ca7cSJagan Teki ret = set_quad_mode(flash, info); 1095cba65a77SJagan Teki if (ret) { 1096f790ca7cSJagan Teki debug("SF: Fail to set QEB for %02x\n", 1097f790ca7cSJagan Teki JEDEC_MFR(info)); 1098cba65a77SJagan Teki return -EINVAL; 1099cba65a77SJagan Teki } 1100cba65a77SJagan Teki } 1101cba65a77SJagan Teki 1102cba65a77SJagan Teki /* Read dummy_byte: dummy byte is determined based on the 1103cba65a77SJagan Teki * dummy cycles of a particular command. 1104cba65a77SJagan Teki * Fast commands - dummy_byte = dummy_cycles/8 1105cba65a77SJagan Teki * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 1106cba65a77SJagan Teki * For I/O commands except cmd[0] everything goes on no.of lines 1107cba65a77SJagan Teki * based on particular command but incase of fast commands except 1108cba65a77SJagan Teki * data all go on single line irrespective of command. 1109cba65a77SJagan Teki */ 1110cba65a77SJagan Teki switch (flash->read_cmd) { 1111cba65a77SJagan Teki case CMD_READ_QUAD_IO_FAST: 1112cba65a77SJagan Teki flash->dummy_byte = 2; 1113cba65a77SJagan Teki break; 1114cba65a77SJagan Teki case CMD_READ_ARRAY_SLOW: 1115cba65a77SJagan Teki flash->dummy_byte = 0; 1116cba65a77SJagan Teki break; 1117cba65a77SJagan Teki default: 1118cba65a77SJagan Teki flash->dummy_byte = 1; 1119cba65a77SJagan Teki } 1120cba65a77SJagan Teki 1121cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_STMICRO 1122f790ca7cSJagan Teki if (info->flags & E_FSR) 1123cba65a77SJagan Teki flash->flags |= SNOR_F_USE_FSR; 1124cba65a77SJagan Teki #endif 1125cba65a77SJagan Teki 1126cba65a77SJagan Teki /* Configure the BAR - discover bank cmds and read current bank */ 1127cba65a77SJagan Teki #ifdef CONFIG_SPI_FLASH_BAR 11287b4ab88eSJagan Teki ret = read_bar(flash, info); 1129cba65a77SJagan Teki if (ret < 0) 1130cba65a77SJagan Teki return ret; 1131cba65a77SJagan Teki #endif 1132cba65a77SJagan Teki 113371634f28SSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 1134656f29d1SSimon Glass ret = spi_flash_decode_fdt(flash); 1135cba65a77SJagan Teki if (ret) { 1136cba65a77SJagan Teki debug("SF: FDT decode error\n"); 1137cba65a77SJagan Teki return -EINVAL; 1138cba65a77SJagan Teki } 1139cba65a77SJagan Teki #endif 1140cba65a77SJagan Teki 1141cba65a77SJagan Teki #ifndef CONFIG_SPL_BUILD 1142cba65a77SJagan Teki printf("SF: Detected %s with page size ", flash->name); 1143cba65a77SJagan Teki print_size(flash->page_size, ", erase size "); 1144cba65a77SJagan Teki print_size(flash->erase_size, ", total "); 1145cba65a77SJagan Teki print_size(flash->size, ""); 1146cba65a77SJagan Teki if (flash->memory_map) 1147cba65a77SJagan Teki printf(", mapped at %p", flash->memory_map); 1148cba65a77SJagan Teki puts("\n"); 1149cba65a77SJagan Teki #endif 1150cba65a77SJagan Teki 1151cba65a77SJagan Teki #ifndef CONFIG_SPI_FLASH_BAR 1152cba65a77SJagan Teki if (((flash->dual_flash == SF_SINGLE_FLASH) && 1153cba65a77SJagan Teki (flash->size > SPI_FLASH_16MB_BOUN)) || 1154cba65a77SJagan Teki ((flash->dual_flash > SF_SINGLE_FLASH) && 1155cba65a77SJagan Teki (flash->size > SPI_FLASH_16MB_BOUN << 1))) { 1156cba65a77SJagan Teki puts("SF: Warning - Only lower 16MiB accessible,"); 1157cba65a77SJagan Teki puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); 1158cba65a77SJagan Teki } 1159cba65a77SJagan Teki #endif 1160cba65a77SJagan Teki 1161304decddSFabien Parent return 0; 1162cba65a77SJagan Teki } 1163