LCOV - code coverage report
Current view: top level - external/gard/libflash - libflash.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 0 419 0.0 %
Date: 2024-01-02 21:04:04 Functions: 0 24 0.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :            : /* Copyright 2013-2017 IBM Corp. */
       3                 :            : 
       4                 :            : #include <stdlib.h>
       5                 :            : #include <stdio.h>
       6                 :            : #include <string.h>
       7                 :            : #include <inttypes.h>
       8                 :            : 
       9                 :            : #include "libflash.h"
      10                 :            : #include "libflash-priv.h"
      11                 :            : #include "ecc.h"
      12                 :            : #include "blocklevel.h"
      13                 :            : 
      14                 :            : static const struct flash_info flash_info[] = {
      15                 :            :         { 0xc22018, 0x01000000, FL_ERASE_ALL | FL_CAN_4B, "Macronix MXxxL12835F"},
      16                 :            :         { 0xc22019, 0x02000000, FL_ERASE_ALL | FL_CAN_4B, "Macronix MXxxL25635F"},
      17                 :            :         { 0xc2201a, 0x04000000, FL_ERASE_ALL | FL_CAN_4B, "Macronix MXxxL51235F"},
      18                 :            :         { 0xc2201b, 0x08000000, FL_ERASE_ALL | FL_CAN_4B, "Macronix MX66L1G45G"},
      19                 :            :         { 0xef4018, 0x01000000, FL_ERASE_ALL,             "Winbond W25Q128BV"   },
      20                 :            :         { 0xef4019, 0x02000000, FL_ERASE_ALL | FL_ERASE_64K | FL_CAN_4B |
      21                 :            :                                 FL_ERASE_BULK,
      22                 :            :                                                         "Winbond W25Q256BV"},
      23                 :            :         { 0x20ba20, 0x04000000, FL_ERASE_4K  | FL_ERASE_64K | FL_CAN_4B |
      24                 :            :                                 FL_ERASE_BULK | FL_MICRON_BUGS,
      25                 :            :                                                           "Micron N25Qx512Ax"   },
      26                 :            :         { 0x20ba19, 0x02000000, FL_ERASE_4K  | FL_ERASE_64K | FL_CAN_4B |
      27                 :            :                                 FL_ERASE_BULK | FL_MICRON_BUGS,
      28                 :            :                                                           "Micron N25Q256Ax"    },
      29                 :            :         { 0x1940ef, 0x02000000, FL_ERASE_4K  | FL_ERASE_64K | FL_CAN_4B |
      30                 :            :                                 FL_ERASE_BULK | FL_MICRON_BUGS,
      31                 :            :                                                         "Micron N25Qx256Ax"   },
      32                 :            :         { 0x4d5444, 0x02000000, FL_ERASE_ALL | FL_CAN_4B, "File Abstraction"},
      33                 :            :         { 0x55aa55, 0x00100000, FL_ERASE_ALL | FL_CAN_4B, "TEST_FLASH" },
      34                 :            :         { 0xaa55aa, 0x02000000, FL_ERASE_ALL | FL_CAN_4B, "EMULATED_FLASH"},
      35                 :            : };
      36                 :            : 
      37                 :            : struct flash_chip {
      38                 :            :         struct spi_flash_ctrl   *ctrl;          /* Controller */
      39                 :            :         struct flash_info       info;           /* Flash info */
      40                 :            :         uint32_t                tsize;          /* Corrected flash size */
      41                 :            :         uint32_t                min_erase_mask; /* Minimum erase size */
      42                 :            :         bool                    mode_4b;        /* Flash currently in 4b mode */
      43                 :            :         struct flash_req        *cur_req;       /* Current request */
      44                 :            :         void                    *smart_buf;     /* Buffer for smart writes */
      45                 :            :         struct blocklevel_device bl;
      46                 :            : };
      47                 :            : 
      48                 :            : #ifndef __SKIBOOT__
      49                 :            : bool libflash_debug;
      50                 :            : #endif
      51                 :            : 
      52                 :          0 : int fl_read_stat(struct spi_flash_ctrl *ct, uint8_t *stat)
      53                 :            : {
      54                 :          0 :         return ct->cmd_rd(ct, CMD_RDSR, false, 0, stat, 1);
      55                 :            : }
      56                 :            : 
      57                 :          0 : static void fl_micron_status(struct spi_flash_ctrl *ct)
      58                 :            : {
      59                 :          0 :         uint8_t flst;
      60                 :            : 
      61                 :            :         /*
      62                 :            :          * After a success status on a write or erase, we
      63                 :            :          * need to do that command or some chip variants will
      64                 :            :          * lock
      65                 :            :          */
      66                 :          0 :         ct->cmd_rd(ct, CMD_MIC_RDFLST, false, 0, &flst, 1);
      67                 :          0 : }
      68                 :            : 
      69                 :            : /* Synchronous write completion, probably need a yield hook */
      70                 :          0 : int fl_sync_wait_idle(struct spi_flash_ctrl *ct)
      71                 :            : {
      72                 :          0 :         uint8_t stat;
      73                 :          0 :         int rc;
      74                 :            : 
      75                 :            :         /* XXX Add timeout */
      76                 :          0 :         for (;;) {
      77                 :          0 :                 rc = fl_read_stat(ct, &stat);
      78                 :          0 :                 if (rc) return rc;
      79                 :          0 :                 if (!(stat & STAT_WIP)) {
      80                 :          0 :                         if (ct->finfo->flags & FL_MICRON_BUGS)
      81                 :          0 :                                 fl_micron_status(ct);
      82                 :          0 :                         return 0;
      83                 :            :                 }
      84                 :            :         }
      85                 :            :         /* return FLASH_ERR_WIP_TIMEOUT; */
      86                 :            : }
      87                 :            : 
      88                 :            : /* Exported for internal use */
      89                 :          0 : int fl_wren(struct spi_flash_ctrl *ct)
      90                 :            : {
      91                 :          0 :         int i, rc;
      92                 :          0 :         uint8_t stat;
      93                 :            : 
      94                 :            :         /* Some flashes need it to be hammered */
      95                 :          0 :         for (i = 0; i < 1000; i++) {
      96                 :          0 :                 rc = ct->cmd_wr(ct, CMD_WREN, false, 0, NULL, 0);
      97                 :          0 :                 if (rc) return rc;
      98                 :          0 :                 rc = fl_read_stat(ct, &stat);
      99                 :          0 :                 if (rc) return rc;
     100                 :          0 :                 if (stat & STAT_WIP) {
     101                 :          0 :                         FL_ERR("LIBFLASH: WREN has WIP status set !\n");
     102                 :          0 :                         rc = fl_sync_wait_idle(ct);
     103                 :          0 :                         if (rc)
     104                 :          0 :                                 return rc;
     105                 :          0 :                         continue;
     106                 :            :                 }
     107                 :          0 :                 if (stat & STAT_WEN)
     108                 :            :                         return 0;
     109                 :            :         }
     110                 :            :         return FLASH_ERR_WREN_TIMEOUT;
     111                 :            : }
     112                 :            : 
     113                 :          0 : static int flash_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
     114                 :            : {
     115                 :          0 :         struct flash_chip *c = container_of(bl, struct flash_chip, bl);
     116                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     117                 :            : 
     118                 :            :         /* XXX Add sanity/bound checking */
     119                 :            : 
     120                 :            :         /*
     121                 :            :          * If the controller supports read and either we are in 3b mode
     122                 :            :          * or we are in 4b *and* the controller supports it, then do a
     123                 :            :          * high level read.
     124                 :            :          */
     125                 :          0 :         if ((!c->mode_4b || ct->set_4b) && ct->read)
     126                 :          0 :                 return ct->read(ct, pos, buf, len);
     127                 :            : 
     128                 :            :         /* Otherwise, go manual if supported */
     129                 :          0 :         if (!ct->cmd_rd)
     130                 :            :                 return FLASH_ERR_CTRL_CMD_UNSUPPORTED;
     131                 :          0 :         return ct->cmd_rd(ct, CMD_READ, true, pos, buf, len);
     132                 :            : }
     133                 :            : 
     134                 :            : #define COPY_BUFFER_LENGTH 4096
     135                 :            : 
     136                 :            : /*
     137                 :            :  * This provides a wrapper around flash_read on ECCed data
     138                 :            :  * len is length of data without ECC attached
     139                 :            :  */
     140                 :          0 : int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
     141                 :            :                 uint32_t len, bool ecc)
     142                 :            : {
     143                 :          0 :         struct ecc64 *bufecc;
     144                 :          0 :         uint32_t copylen;
     145                 :          0 :         int rc;
     146                 :          0 :         uint8_t ret;
     147                 :            : 
     148                 :          0 :         if (!ecc)
     149                 :          0 :                 return flash_read(bl, pos, buf, len);
     150                 :            : 
     151                 :            :         /* Copy the buffer in chunks */
     152                 :          0 :         bufecc = malloc(ecc_buffer_size(COPY_BUFFER_LENGTH));
     153                 :          0 :         if (!bufecc)
     154                 :            :                 return FLASH_ERR_MALLOC_FAILED;
     155                 :            : 
     156                 :          0 :         while (len > 0) {
     157                 :            :                 /* What's left to copy? */
     158                 :          0 :                 copylen = MIN(len, COPY_BUFFER_LENGTH);
     159                 :            : 
     160                 :            :                 /* Read ECCed data from flash */
     161                 :          0 :                 rc = flash_read(bl, pos, bufecc, ecc_buffer_size(copylen));
     162                 :          0 :                 if (rc)
     163                 :          0 :                         goto err;
     164                 :            : 
     165                 :            :                 /* Extract data from ECCed data */
     166                 :          0 :                 ret = memcpy_from_ecc(buf, bufecc, copylen);
     167                 :          0 :                 if (ret) {
     168                 :          0 :                         rc = FLASH_ERR_ECC_INVALID;
     169                 :          0 :                         goto err;
     170                 :            :                 }
     171                 :            : 
     172                 :            :                 /* Update for next copy */
     173                 :          0 :                 len -= copylen;
     174                 :          0 :                 buf = (uint8_t *)buf + copylen;
     175                 :          0 :                 pos += ecc_buffer_size(copylen);
     176                 :            :         }
     177                 :            : 
     178                 :            :         rc = 0;
     179                 :            : 
     180                 :          0 : err:
     181                 :          0 :         free(bufecc);
     182                 :          0 :         return rc;
     183                 :            : }
     184                 :            : 
     185                 :          0 : static void fl_get_best_erase(struct flash_chip *c, uint32_t dst, uint32_t size,
     186                 :            :                               uint32_t *chunk, uint8_t *cmd)
     187                 :            : {
     188                 :            :         /* Smaller than 32k, use 4k */
     189                 :          0 :         if ((dst & 0x7fff) || (size < 0x8000)) {
     190                 :          0 :                 *chunk = 0x1000;
     191                 :          0 :                 *cmd = CMD_SE;
     192                 :          0 :                 return;
     193                 :            :         }
     194                 :            :         /* Smaller than 64k and 32k is supported, use it */
     195                 :          0 :         if ((c->info.flags & FL_ERASE_32K) &&
     196                 :          0 :             ((dst & 0xffff) || (size < 0x10000))) {
     197                 :          0 :                 *chunk = 0x8000;
     198                 :          0 :                 *cmd = CMD_BE32K;
     199                 :          0 :                 return;
     200                 :            :         }
     201                 :            :         /* If 64K is not supported, use whatever smaller size is */
     202                 :          0 :         if (!(c->info.flags & FL_ERASE_64K)) {
     203                 :          0 :                 if (c->info.flags & FL_ERASE_32K) {
     204                 :          0 :                         *chunk = 0x8000;
     205                 :          0 :                         *cmd = CMD_BE32K;
     206                 :            :                 } else {
     207                 :          0 :                         *chunk = 0x1000;
     208                 :          0 :                         *cmd = CMD_SE;
     209                 :            :                 }
     210                 :          0 :                 return;
     211                 :            :         }
     212                 :            :         /* Allright, let's go for 64K */
     213                 :          0 :         *chunk = 0x10000;
     214                 :          0 :         *cmd = CMD_BE;
     215                 :            : }
     216                 :            : 
     217                 :          0 : static int flash_erase(struct blocklevel_device *bl, uint64_t dst, uint64_t size)
     218                 :            : {
     219                 :          0 :         struct flash_chip *c = container_of(bl, struct flash_chip, bl);
     220                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     221                 :          0 :         uint32_t chunk;
     222                 :          0 :         uint8_t cmd;
     223                 :          0 :         int rc;
     224                 :            : 
     225                 :            :         /* Some sanity checking */
     226                 :          0 :         if (((dst + size) <= dst) || !size || (dst + size) > c->tsize)
     227                 :            :                 return FLASH_ERR_PARM_ERROR;
     228                 :            : 
     229                 :            :         /* Check boundaries fit erase blocks */
     230                 :          0 :         if ((dst | size) & c->min_erase_mask)
     231                 :            :                 return FLASH_ERR_ERASE_BOUNDARY;
     232                 :            : 
     233                 :          0 :         FL_DBG("LIBFLASH: Erasing 0x%" PRIx64"..0%" PRIx64 "...\n",
     234                 :            :                dst, dst + size);
     235                 :            : 
     236                 :            :         /* Use controller erase if supported */
     237                 :          0 :         if (ct->erase)
     238                 :          0 :                 return ct->erase(ct, dst, size);
     239                 :            : 
     240                 :            :         /* Allright, loop as long as there's something to erase */
     241                 :          0 :         while(size) {
     242                 :            :                 /* How big can we make it based on alignent & size */
     243                 :          0 :                 fl_get_best_erase(c, dst, size, &chunk, &cmd);
     244                 :            : 
     245                 :            :                 /* Poke write enable */
     246                 :          0 :                 rc = fl_wren(ct);
     247                 :          0 :                 if (rc)
     248                 :          0 :                         return rc;
     249                 :            : 
     250                 :            :                 /* Send erase command */
     251                 :          0 :                 rc = ct->cmd_wr(ct, cmd, true, dst, NULL, 0);
     252                 :          0 :                 if (rc)
     253                 :          0 :                         return rc;
     254                 :            : 
     255                 :            :                 /* Wait for write complete */
     256                 :          0 :                 rc = fl_sync_wait_idle(ct);
     257                 :          0 :                 if (rc)
     258                 :          0 :                         return rc;
     259                 :            : 
     260                 :          0 :                 size -= chunk;
     261                 :          0 :                 dst += chunk;
     262                 :            :         }
     263                 :            :         return 0;
     264                 :            : }
     265                 :            : 
     266                 :          0 : int flash_erase_chip(struct flash_chip *c)
     267                 :            : {
     268                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     269                 :          0 :         int rc;
     270                 :            : 
     271                 :            :         /* XXX TODO: Fallback to using normal erases */
     272                 :          0 :         if (!(c->info.flags & (FL_ERASE_CHIP|FL_ERASE_BULK)))
     273                 :            :                 return FLASH_ERR_CHIP_ER_NOT_SUPPORTED;
     274                 :            : 
     275                 :          0 :         FL_DBG("LIBFLASH: Erasing chip...\n");
     276                 :            :         
     277                 :            :         /* Use controller erase if supported */
     278                 :          0 :         if (ct->erase)
     279                 :          0 :                 return ct->erase(ct, 0, 0xffffffff);
     280                 :            : 
     281                 :          0 :         rc = fl_wren(ct);
     282                 :          0 :         if (rc) return rc;
     283                 :            : 
     284                 :          0 :         if (c->info.flags & FL_ERASE_CHIP)
     285                 :          0 :                 rc = ct->cmd_wr(ct, CMD_CE, false, 0, NULL, 0);
     286                 :            :         else
     287                 :          0 :                 rc = ct->cmd_wr(ct, CMD_MIC_BULK_ERASE, false, 0, NULL, 0);
     288                 :          0 :         if (rc)
     289                 :            :                 return rc;
     290                 :            : 
     291                 :            :         /* Wait for write complete */
     292                 :          0 :         return fl_sync_wait_idle(ct);
     293                 :            : }
     294                 :            : 
     295                 :          0 : static int fl_wpage(struct flash_chip *c, uint32_t dst, const void *src,
     296                 :            :                     uint32_t size)
     297                 :            : {
     298                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     299                 :          0 :         int rc;
     300                 :            : 
     301                 :          0 :         if (size < 1 || size > 0x100)
     302                 :            :                 return FLASH_ERR_BAD_PAGE_SIZE;
     303                 :            : 
     304                 :          0 :         rc = fl_wren(ct);
     305                 :          0 :         if (rc) return rc;
     306                 :            : 
     307                 :          0 :         rc = ct->cmd_wr(ct, CMD_PP, true, dst, src, size);
     308                 :          0 :         if (rc)
     309                 :            :                 return rc;
     310                 :            : 
     311                 :            :         /* Wait for write complete */
     312                 :          0 :         return fl_sync_wait_idle(ct);
     313                 :            : }
     314                 :            : 
     315                 :          0 : static int flash_write(struct blocklevel_device *bl, uint32_t dst, const void *src,
     316                 :            :                 uint32_t size, bool verify)
     317                 :            : {
     318                 :          0 :         struct flash_chip *c = container_of(bl, struct flash_chip, bl);
     319                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     320                 :          0 :         uint32_t todo = size;
     321                 :          0 :         uint32_t d = dst;
     322                 :          0 :         const void *s = src;
     323                 :          0 :         uint8_t vbuf[0x100];
     324                 :          0 :         int rc; 
     325                 :            : 
     326                 :            :         /* Some sanity checking */
     327                 :          0 :         if (((dst + size) <= dst) || !size || (dst + size) > c->tsize)
     328                 :            :                 return FLASH_ERR_PARM_ERROR;
     329                 :            : 
     330                 :          0 :         FL_DBG("LIBFLASH: Writing to 0x%08x..0%08x...\n", dst, dst + size);
     331                 :            : 
     332                 :            :         /*
     333                 :            :          * If the controller supports write and either we are in 3b mode
     334                 :            :          * or we are in 4b *and* the controller supports it, then do a
     335                 :            :          * high level write.
     336                 :            :          */
     337                 :          0 :         if ((!c->mode_4b || ct->set_4b) && ct->write) {
     338                 :          0 :                 rc = ct->write(ct, dst, src, size);
     339                 :          0 :                 if (rc)
     340                 :            :                         return rc;
     341                 :          0 :                 goto writing_done;
     342                 :            :         }
     343                 :            : 
     344                 :            :         /* Otherwise, go manual if supported */
     345                 :          0 :         if (!ct->cmd_wr)
     346                 :            :                 return FLASH_ERR_CTRL_CMD_UNSUPPORTED;
     347                 :            : 
     348                 :            :         /* Iterate for each page to write */
     349                 :          0 :         while(todo) {
     350                 :          0 :                 uint32_t chunk;
     351                 :            : 
     352                 :            :                 /* Handle misaligned start */
     353                 :          0 :                 chunk = 0x100 - (d & 0xff);
     354                 :          0 :                 if (chunk > todo)
     355                 :            :                         chunk = todo;
     356                 :            : 
     357                 :          0 :                 rc = fl_wpage(c, d, s, chunk);
     358                 :          0 :                 if (rc) return rc;
     359                 :          0 :                 d += chunk;
     360                 :          0 :                 s += chunk;
     361                 :          0 :                 todo -= chunk;
     362                 :            :         }
     363                 :            : 
     364                 :          0 :  writing_done:
     365                 :          0 :         if (!verify)
     366                 :            :                 return 0;
     367                 :            : 
     368                 :            :         /* Verify */
     369                 :          0 :         FL_DBG("LIBFLASH: Verifying...\n");
     370                 :            : 
     371                 :          0 :         while(size) {
     372                 :          0 :                 uint32_t chunk;
     373                 :            : 
     374                 :          0 :                 chunk = sizeof(vbuf);
     375                 :          0 :                 if (chunk > size)
     376                 :          0 :                         chunk = size;
     377                 :          0 :                 rc = flash_read(bl, dst, vbuf, chunk);
     378                 :          0 :                 if (rc) return rc;
     379                 :          0 :                 if (memcmp(vbuf, src, chunk)) {
     380                 :          0 :                         FL_ERR("LIBFLASH: Miscompare at 0x%08x\n", dst);
     381                 :          0 :                         return FLASH_ERR_VERIFY_FAILURE;
     382                 :            :                 }
     383                 :          0 :                 dst += chunk;
     384                 :          0 :                 src += chunk;
     385                 :          0 :                 size -= chunk;
     386                 :            :         }
     387                 :            :         return 0;
     388                 :            : }
     389                 :            : 
     390                 :          0 : int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void *buf,
     391                 :            :                 uint32_t len, bool verify, bool ecc)
     392                 :            : {
     393                 :          0 :         struct ecc64 *bufecc;
     394                 :          0 :         uint32_t copylen, copylen_minus_ecc;
     395                 :          0 :         int rc;
     396                 :          0 :         uint8_t ret;
     397                 :            : 
     398                 :          0 :         if (!ecc)
     399                 :          0 :                 return flash_write(bl, pos, buf, len, verify);
     400                 :            : 
     401                 :            :         /* Copy the buffer in chunks */
     402                 :          0 :         bufecc = malloc(ecc_buffer_size(COPY_BUFFER_LENGTH));
     403                 :          0 :         if (!bufecc)
     404                 :            :                 return FLASH_ERR_MALLOC_FAILED;
     405                 :            : 
     406                 :          0 :         while (len > 0) {
     407                 :            :                 /* What's left to copy? */
     408                 :          0 :                 copylen = MIN(len, COPY_BUFFER_LENGTH);
     409                 :          0 :                 copylen_minus_ecc = ecc_buffer_size_minus_ecc(copylen);
     410                 :            : 
     411                 :            :                 /* Add the ecc byte to the data */
     412                 :          0 :                 ret = memcpy_to_ecc(bufecc, buf, copylen_minus_ecc);
     413                 :          0 :                 if (ret) {
     414                 :          0 :                         rc = FLASH_ERR_ECC_INVALID;
     415                 :          0 :                         goto err;
     416                 :            :                 }
     417                 :            : 
     418                 :            :                 /* Write ECCed data to the flash */
     419                 :          0 :                 rc = flash_write(bl, pos, bufecc, copylen, verify);
     420                 :          0 :                 if (rc)
     421                 :          0 :                         goto err;
     422                 :            : 
     423                 :            :                 /* Update for next copy */
     424                 :          0 :                 len -= copylen_minus_ecc;
     425                 :          0 :                 buf = (uint8_t *)buf + copylen_minus_ecc;
     426                 :          0 :                 pos += copylen;
     427                 :            :         }
     428                 :            : 
     429                 :            :         rc = 0;
     430                 :            : 
     431                 :          0 : err:
     432                 :          0 :         free(bufecc);
     433                 :          0 :         return rc;
     434                 :            : }
     435                 :            : 
     436                 :            : enum sm_comp_res {
     437                 :            :         sm_no_change,
     438                 :            :         sm_need_write,
     439                 :            :         sm_need_erase,
     440                 :            : };
     441                 :            : 
     442                 :          0 : static enum sm_comp_res flash_smart_comp(struct flash_chip *c,
     443                 :            :                                          const void *src,
     444                 :            :                                          uint32_t offset, uint32_t size)
     445                 :            : {
     446                 :          0 :         uint8_t *b = c->smart_buf + offset;
     447                 :          0 :         const uint8_t *s = src;
     448                 :          0 :         bool is_same = true;
     449                 :          0 :         uint32_t i;
     450                 :            : 
     451                 :            :         /* SRC DEST  NEED_ERASE
     452                 :            :          *  0   1       0
     453                 :            :          *  1   1       0
     454                 :            :          *  0   0       0
     455                 :            :          *  1   0       1
     456                 :            :          */
     457                 :          0 :         for (i = 0; i < size; i++) {
     458                 :            :                 /* Any bit need to be set, need erase */
     459                 :          0 :                 if (s[i] & ~b[i])
     460                 :            :                         return sm_need_erase;
     461                 :          0 :                 if (is_same && (b[i] != s[i]))
     462                 :          0 :                         is_same = false;
     463                 :            :         }
     464                 :          0 :         return is_same ? sm_no_change : sm_need_write;
     465                 :            : }
     466                 :            : 
     467                 :          0 : static int flash_smart_write(struct blocklevel_device *bl, uint64_t dst, const void *src, uint64_t size)
     468                 :            : {
     469                 :          0 :         struct flash_chip *c = container_of(bl, struct flash_chip, bl);
     470                 :          0 :         uint32_t er_size = c->min_erase_mask + 1;
     471                 :          0 :         uint32_t end = dst + size;
     472                 :          0 :         int rc;
     473                 :            : 
     474                 :            :         /* Some sanity checking */
     475                 :          0 :         if (end <= dst || !size || end > c->tsize) {
     476                 :          0 :                 FL_DBG("LIBFLASH: Smart write param error\n");
     477                 :          0 :                 return FLASH_ERR_PARM_ERROR;
     478                 :            :         }
     479                 :            : 
     480                 :          0 :         FL_DBG("LIBFLASH: Smart writing to 0x%" PRIx64 "..0%" PRIx64 "...\n",
     481                 :            :                dst, dst + size);
     482                 :            : 
     483                 :            :         /* As long as we have something to write ... */
     484                 :          0 :         while(dst < end) {
     485                 :          0 :                 uint32_t page, off, chunk;
     486                 :          0 :                 enum sm_comp_res sr;
     487                 :            : 
     488                 :            :                 /* Figure out which erase page we are in and read it */
     489                 :          0 :                 page = dst & ~c->min_erase_mask;
     490                 :          0 :                 off = dst & c->min_erase_mask;
     491                 :          0 :                 FL_DBG("LIBFLASH:   reading page 0x%08x..0x%08x...\n",
     492                 :            :                        page, page + er_size);
     493                 :          0 :                 rc = flash_read(bl, page, c->smart_buf, er_size);
     494                 :          0 :                 if (rc) {
     495                 :          0 :                         FL_DBG("LIBFLASH:    ...error %d!\n", rc);
     496                 :          0 :                         return rc;
     497                 :            :                 }
     498                 :            : 
     499                 :            :                 /* Locate the chunk of data we are working on */
     500                 :          0 :                 chunk = er_size - off;
     501                 :          0 :                 if (size < chunk)
     502                 :          0 :                         chunk = size;
     503                 :            : 
     504                 :            :                 /* Compare against what we are writing and ff */
     505                 :          0 :                 sr = flash_smart_comp(c, src, off, chunk);
     506                 :          0 :                 switch(sr) {
     507                 :          0 :                 case sm_no_change:
     508                 :            :                         /* Identical, skip it */
     509                 :          0 :                         FL_DBG("LIBFLASH:    ...same !\n");
     510                 :            :                         break;
     511                 :          0 :                 case sm_need_write:
     512                 :            :                         /* Just needs writing over */
     513                 :          0 :                         FL_DBG("LIBFLASH:    ...need write !\n");
     514                 :          0 :                         rc = flash_write(bl, dst, src, chunk, true);
     515                 :          0 :                         if (rc) {
     516                 :          0 :                                 FL_DBG("LIBFLASH: Write error %d !\n", rc);
     517                 :          0 :                                 return rc;
     518                 :            :                         }
     519                 :            :                         break;
     520                 :          0 :                 case sm_need_erase:
     521                 :          0 :                         FL_DBG("LIBFLASH:    ...need erase !\n");
     522                 :          0 :                         rc = flash_erase(bl, page, er_size);
     523                 :          0 :                         if (rc) {
     524                 :          0 :                                 FL_DBG("LIBFLASH: erase error %d !\n", rc);
     525                 :          0 :                                 return rc;
     526                 :            :                         }
     527                 :            :                         /* Then update the portion of the buffer and write the block */
     528                 :          0 :                         memcpy(c->smart_buf + off, src, chunk);
     529                 :          0 :                         rc = flash_write(bl, page, c->smart_buf, er_size, true);
     530                 :          0 :                         if (rc) {
     531                 :          0 :                                 FL_DBG("LIBFLASH: write error %d !\n", rc);
     532                 :          0 :                                 return rc;
     533                 :            :                         }
     534                 :            :                         break;
     535                 :            :                 }
     536                 :          0 :                 dst += chunk;
     537                 :          0 :                 src += chunk;
     538                 :          0 :                 size -= chunk;
     539                 :            :         }
     540                 :            :         return 0;
     541                 :            : }
     542                 :            : 
     543                 :          0 : int flash_smart_write_corrected(struct blocklevel_device *bl, uint32_t dst, const void *src,
     544                 :            :                       uint32_t size, bool ecc)
     545                 :            : {
     546                 :          0 :         struct ecc64 *buf;
     547                 :          0 :         int rc;
     548                 :            : 
     549                 :          0 :         if (!ecc)
     550                 :          0 :                 return flash_smart_write(bl, dst, src, size);
     551                 :            : 
     552                 :          0 :         buf = malloc(ecc_buffer_size(size));
     553                 :          0 :         if (!buf)
     554                 :            :                 return FLASH_ERR_MALLOC_FAILED;
     555                 :            : 
     556                 :          0 :         rc = memcpy_to_ecc(buf, src, size);
     557                 :          0 :         if (rc) {
     558                 :          0 :                 rc = FLASH_ERR_ECC_INVALID;
     559                 :          0 :                 goto out;
     560                 :            :         }
     561                 :            : 
     562                 :          0 :         rc = flash_smart_write(bl, dst, buf, ecc_buffer_size(size));
     563                 :            : 
     564                 :          0 : out:
     565                 :          0 :         free(buf);
     566                 :          0 :         return rc;
     567                 :            : }
     568                 :            : 
     569                 :          0 : static int fl_chip_id(struct spi_flash_ctrl *ct, uint8_t *id_buf,
     570                 :            :                       uint32_t *id_size)
     571                 :            : {
     572                 :          0 :         int rc;
     573                 :          0 :         uint8_t stat;
     574                 :            : 
     575                 :            :         /* Check initial status */
     576                 :          0 :         rc = fl_read_stat(ct, &stat);
     577                 :          0 :         if (rc)
     578                 :            :                 return rc;
     579                 :            : 
     580                 :            :         /* If stuck writing, wait for idle */
     581                 :          0 :         if (stat & STAT_WIP) {
     582                 :          0 :                 FL_ERR("LIBFLASH: Flash in writing state ! Waiting...\n");
     583                 :          0 :                 rc = fl_sync_wait_idle(ct);
     584                 :          0 :                 if (rc)
     585                 :            :                         return rc;
     586                 :            :         } else
     587                 :          0 :                 FL_DBG("LIBFLASH: Init status: %02x\n", stat);
     588                 :            : 
     589                 :            :         /* Fallback to get ID manually */
     590                 :          0 :         rc = ct->cmd_rd(ct, CMD_RDID, false, 0, id_buf, 3);
     591                 :          0 :         if (rc)
     592                 :            :                 return rc;
     593                 :          0 :         *id_size = 3;
     594                 :            : 
     595                 :          0 :         return 0;
     596                 :            : }
     597                 :            : 
     598                 :          0 : static int flash_identify(struct flash_chip *c)
     599                 :            : {
     600                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     601                 :          0 :         const struct flash_info *info = NULL;
     602                 :          0 :         uint32_t iid, id_size;
     603                 :            : #define MAX_ID_SIZE     16
     604                 :          0 :         uint8_t id[MAX_ID_SIZE];
     605                 :          0 :         int rc, i;
     606                 :            : 
     607                 :          0 :         if (ct->chip_id) {
     608                 :            :                 /* High level controller interface */
     609                 :          0 :                 id_size = MAX_ID_SIZE;
     610                 :          0 :                 rc = ct->chip_id(ct, id, &id_size);
     611                 :            :         } else
     612                 :          0 :                 rc = fl_chip_id(ct, id, &id_size);
     613                 :          0 :         if (rc)
     614                 :            :                 return rc;
     615                 :          0 :         if (id_size < 3)
     616                 :            :                 return FLASH_ERR_CHIP_UNKNOWN;
     617                 :            : 
     618                 :            :         /* Convert to a dword for lookup */
     619                 :          0 :         iid = id[0];
     620                 :          0 :         iid = (iid << 8) | id[1];
     621                 :          0 :         iid = (iid << 8) | id[2];
     622                 :            : 
     623                 :          0 :         FL_DBG("LIBFLASH: Flash ID: %02x.%02x.%02x (%06x)\n",
     624                 :            :                id[0], id[1], id[2], iid);
     625                 :            : 
     626                 :            :         /* Lookup in flash_info */
     627                 :          0 :         for (i = 0; i < ARRAY_SIZE(flash_info); i++) {
     628                 :          0 :                 info = &flash_info[i];
     629                 :          0 :                 if (info->id == iid)
     630                 :            :                         break;          
     631                 :            :         }
     632                 :          0 :         if (!info || info->id != iid)
     633                 :            :                 return FLASH_ERR_CHIP_UNKNOWN;
     634                 :            : 
     635                 :          0 :         c->info = *info;
     636                 :          0 :         c->tsize = info->size;
     637                 :          0 :         ct->finfo = &c->info;
     638                 :            : 
     639                 :            :         /*
     640                 :            :          * Let controller know about our settings and possibly
     641                 :            :          * override them
     642                 :            :          */
     643                 :          0 :         if (ct->setup) {
     644                 :          0 :                 rc = ct->setup(ct, &c->tsize);
     645                 :          0 :                 if (rc)
     646                 :            :                         return rc;
     647                 :            :         }
     648                 :            : 
     649                 :            :         /* Calculate min erase granularity */
     650                 :          0 :         if (c->info.flags & FL_ERASE_4K)
     651                 :          0 :                 c->min_erase_mask = 0xfff;
     652                 :          0 :         else if (c->info.flags & FL_ERASE_32K)
     653                 :          0 :                 c->min_erase_mask = 0x7fff;
     654                 :          0 :         else if (c->info.flags & FL_ERASE_64K)
     655                 :          0 :                 c->min_erase_mask = 0xffff;
     656                 :            :         else {
     657                 :            :                 /* No erase size ? oops ... */
     658                 :          0 :                 FL_ERR("LIBFLASH: No erase sizes !\n");
     659                 :          0 :                 return FLASH_ERR_CTRL_CONFIG_MISMATCH;
     660                 :            :         }
     661                 :            : 
     662                 :          0 :         FL_DBG("LIBFLASH: Found chip %s size %dM erase granule: %dK\n",
     663                 :            :                c->info.name, c->tsize >> 20, (c->min_erase_mask + 1) >> 10);
     664                 :            : 
     665                 :            :         return 0;
     666                 :            : }
     667                 :            : 
     668                 :          0 : static int flash_set_4b(struct flash_chip *c, bool enable)
     669                 :            : {
     670                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     671                 :          0 :         int rc;
     672                 :            : 
     673                 :            :         /* Don't have low level interface, assume all is well */
     674                 :          0 :         if (!ct->cmd_wr)
     675                 :            :                 return 0;
     676                 :            : 
     677                 :            :         /* Some flash chips want this */
     678                 :          0 :         rc = fl_wren(ct);
     679                 :          0 :         if (rc) {
     680                 :          0 :                 FL_ERR("LIBFLASH: Error %d enabling write for set_4b\n", rc);
     681                 :            :                 /* Ignore the error & move on (could be wrprotect chip) */
     682                 :            :         }
     683                 :            : 
     684                 :            :         /* Ignore error in case chip is write protected */
     685                 :          0 :         return ct->cmd_wr(ct, enable ? CMD_EN4B : CMD_EX4B, false, 0, NULL, 0);
     686                 :            : }
     687                 :            : 
     688                 :          0 : int flash_force_4b_mode(struct flash_chip *c, bool enable_4b)
     689                 :            : {
     690                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     691                 :          0 :         int rc = FLASH_ERR_4B_NOT_SUPPORTED;
     692                 :            : 
     693                 :            :         /*
     694                 :            :          * We only allow force 4b if both controller and flash do 4b
     695                 :            :          * as this is mainly used if a 3rd party tries to directly
     696                 :            :          * access a direct mapped read region
     697                 :            :          */
     698                 :          0 :         if (enable_4b && !((c->info.flags & FL_CAN_4B) && ct->set_4b))
     699                 :            :                 return rc;
     700                 :            : 
     701                 :            :         /* Only send to flash directly on controllers that implement
     702                 :            :          * the low level callbacks
     703                 :            :          */
     704                 :          0 :         if (ct->cmd_wr) {
     705                 :          0 :                 rc = flash_set_4b(c, enable_4b);
     706                 :          0 :                 if (rc)
     707                 :            :                         return rc;
     708                 :            :         }
     709                 :            : 
     710                 :            :         /* Then inform the controller */
     711                 :          0 :         if (ct->set_4b)
     712                 :          0 :                 rc = ct->set_4b(ct, enable_4b);
     713                 :            :         return rc;
     714                 :            : }
     715                 :            : 
     716                 :          0 : static int flash_configure(struct flash_chip *c)
     717                 :            : {
     718                 :          0 :         struct spi_flash_ctrl *ct = c->ctrl;
     719                 :          0 :         int rc;
     720                 :            : 
     721                 :            :         /* Crop flash size if necessary */
     722                 :          0 :         if (c->tsize > 0x01000000 && !(c->info.flags & FL_CAN_4B)) {
     723                 :          0 :                 FL_ERR("LIBFLASH: Flash chip cropped to 16M, no 4b mode\n");
     724                 :          0 :                 c->tsize = 0x01000000;
     725                 :            :         }
     726                 :            : 
     727                 :            :         /* If flash chip > 16M, enable 4b mode */
     728                 :          0 :         if (c->tsize > 0x01000000) {
     729                 :          0 :                 FL_DBG("LIBFLASH: Flash >16MB, enabling 4B mode...\n");
     730                 :            : 
     731                 :            :                 /* Set flash to 4b mode if we can */
     732                 :          0 :                 if (ct->cmd_wr) {
     733                 :          0 :                         rc = flash_set_4b(c, true);
     734                 :          0 :                         if (rc) {
     735                 :          0 :                                 FL_ERR("LIBFLASH: Failed to set flash 4b mode\n");
     736                 :          0 :                                 return rc;
     737                 :            :                         }
     738                 :            :                 }
     739                 :            : 
     740                 :            : 
     741                 :            :                 /* Set controller to 4b mode if supported */
     742                 :          0 :                 if (ct->set_4b) {
     743                 :          0 :                         FL_DBG("LIBFLASH: Enabling controller 4B mode...\n");
     744                 :          0 :                         rc = ct->set_4b(ct, true);
     745                 :          0 :                         if (rc) {
     746                 :          0 :                                 FL_ERR("LIBFLASH: Failed to set controller 4b mode\n");
     747                 :          0 :                                 return rc;
     748                 :            :                         }
     749                 :            :                 }
     750                 :            :         } else {
     751                 :          0 :                 FL_DBG("LIBFLASH: Flash <=16MB, disabling 4B mode...\n");
     752                 :            : 
     753                 :            :                 /*
     754                 :            :                  * If flash chip supports 4b mode, make sure we disable
     755                 :            :                  * it in case it was left over by the previous user
     756                 :            :                  */
     757                 :          0 :                 if (c->info.flags & FL_CAN_4B) {
     758                 :          0 :                         rc = flash_set_4b(c, false);
     759                 :          0 :                         if (rc) {
     760                 :          0 :                                 FL_ERR("LIBFLASH: Failed to"
     761                 :            :                                        " clear flash 4b mode\n");
     762                 :          0 :                                 return rc;
     763                 :            :                         }
     764                 :            :                 }
     765                 :            :                 /* Set controller to 3b mode if mode switch is supported */
     766                 :          0 :                 if (ct->set_4b) {
     767                 :          0 :                         FL_DBG("LIBFLASH: Disabling controller 4B mode...\n");
     768                 :          0 :                         rc = ct->set_4b(ct, false);
     769                 :          0 :                         if (rc) {
     770                 :          0 :                                 FL_ERR("LIBFLASH: Failed to"
     771                 :            :                                        " clear controller 4b mode\n");
     772                 :          0 :                                 return rc;
     773                 :            :                         }
     774                 :            :                 }
     775                 :            :         }
     776                 :            :         return 0;
     777                 :            : }
     778                 :            : 
     779                 :          0 : static int flash_get_info(struct blocklevel_device *bl, const char **name,
     780                 :            :                    uint64_t *total_size, uint32_t *erase_granule)
     781                 :            : {
     782                 :          0 :         struct flash_chip *c = container_of(bl, struct flash_chip, bl);
     783                 :          0 :         if (name)
     784                 :          0 :                 *name = c->info.name;
     785                 :          0 :         if (total_size)
     786                 :          0 :                 *total_size = c->tsize;
     787                 :          0 :         if (erase_granule)
     788                 :          0 :                 *erase_granule = c->min_erase_mask + 1;
     789                 :          0 :         return 0;
     790                 :            : }
     791                 :            : 
     792                 :          0 : int flash_init(struct spi_flash_ctrl *ctrl, struct blocklevel_device **bl,
     793                 :            :                 struct flash_chip **flash_chip)
     794                 :            : {
     795                 :          0 :         struct flash_chip *c;
     796                 :          0 :         int rc;
     797                 :            : 
     798                 :          0 :         if (!bl)
     799                 :            :                 return FLASH_ERR_PARM_ERROR;
     800                 :            : 
     801                 :          0 :         *bl = NULL;
     802                 :            : 
     803                 :          0 :         c = malloc(sizeof(struct flash_chip));
     804                 :          0 :         if (!c)
     805                 :            :                 return FLASH_ERR_MALLOC_FAILED;
     806                 :          0 :         memset(c, 0, sizeof(*c));
     807                 :          0 :         c->ctrl = ctrl;
     808                 :            : 
     809                 :          0 :         rc = flash_identify(c);
     810                 :          0 :         if (rc) {
     811                 :          0 :                 FL_ERR("LIBFLASH: Flash identification failed\n");
     812                 :          0 :                 goto bail;
     813                 :            :         }
     814                 :          0 :         c->smart_buf = malloc(c->min_erase_mask + 1);
     815                 :          0 :         if (!c->smart_buf) {
     816                 :          0 :                 FL_ERR("LIBFLASH: Failed to allocate smart buffer !\n");
     817                 :          0 :                 rc = FLASH_ERR_MALLOC_FAILED;
     818                 :          0 :                 goto bail;
     819                 :            :         }
     820                 :          0 :         rc = flash_configure(c);
     821                 :          0 :         if (rc)
     822                 :          0 :                 FL_ERR("LIBFLASH: Flash configuration failed\n");
     823                 :          0 : bail:
     824                 :          0 :         if (rc) {
     825                 :          0 :                 free(c);
     826                 :          0 :                 return rc;
     827                 :            :         }
     828                 :            : 
     829                 :            :         /* The flash backend doesn't support reiniting it */
     830                 :          0 :         c->bl.keep_alive = true;
     831                 :          0 :         c->bl.reacquire = NULL;
     832                 :          0 :         c->bl.release = NULL;
     833                 :          0 :         c->bl.read = &flash_read;
     834                 :          0 :         c->bl.write = &flash_smart_write;
     835                 :          0 :         c->bl.erase = &flash_erase;
     836                 :          0 :         c->bl.get_info = &flash_get_info;
     837                 :          0 :         c->bl.erase_mask = c->min_erase_mask;
     838                 :          0 :         c->bl.flags = WRITE_NEED_ERASE;
     839                 :            : 
     840                 :          0 :         *bl = &(c->bl);
     841                 :          0 :         if (flash_chip)
     842                 :          0 :                 *flash_chip = c;
     843                 :            : 
     844                 :            :         return 0;
     845                 :            : }
     846                 :            : 
     847                 :          0 : void flash_exit(struct blocklevel_device *bl)
     848                 :            : {
     849                 :            :         /* XXX Make sure we are idle etc... */
     850                 :          0 :         if (bl) {
     851                 :          0 :                 struct flash_chip *c = container_of(bl, struct flash_chip, bl);
     852                 :          0 :                 free(c->smart_buf);
     853                 :          0 :                 free(c);
     854                 :            :         }
     855                 :          0 : }
     856                 :            : 
     857                 :          0 : void flash_exit_close(struct blocklevel_device *bl, void (*close)(struct spi_flash_ctrl *ctrl))
     858                 :            : {
     859                 :          0 :         if (bl) {
     860                 :          0 :                 struct flash_chip *c = container_of(bl, struct flash_chip, bl);
     861                 :          0 :                 close(c->ctrl);
     862                 :          0 :                 free(c);
     863                 :            :         }
     864                 :          0 : }

Generated by: LCOV version 1.14