Konstantin Grudnev | 3d8868c | 2019-07-23 00:48:54 +0300 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the flashrom project. |
| 3 | * |
| 4 | * Copyright (C) 2019 Konstantin Grudnev |
| 5 | * Copyright (C) 2019 Nikolay Nikolaev |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, |
| 10 | * or any later version. |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | */ |
| 16 | |
| 17 | /* |
| 18 | * Contains SPI chip driver functions related to ST95XXX series (SPI EEPROM) |
| 19 | */ |
| 20 | #include <string.h> |
| 21 | #include <stdlib.h> |
| 22 | #include "flashchips.h" |
| 23 | #include "chipdrivers.h" |
| 24 | #include "spi.h" |
| 25 | |
| 26 | /* For ST95XXX chips which have RDID */ |
| 27 | int probe_spi_st95(struct flashctx *flash) |
| 28 | { |
| 29 | /* |
| 30 | * ST_M95_RDID_OUTSIZE depends on size of the flash and |
| 31 | * not all ST_M95XXX have RDID. |
| 32 | */ |
| 33 | static const unsigned char cmd[ST_M95_RDID_OUTSIZE_MAX] = { ST_M95_RDID }; |
| 34 | unsigned char readarr[ST_M95_RDID_INSIZE]; |
| 35 | uint32_t id1, id2; |
Patrick Georgi | b57f48f | 2020-05-02 16:07:11 +0200 | [diff] [blame] | 36 | int ret; |
Konstantin Grudnev | 3d8868c | 2019-07-23 00:48:54 +0300 | [diff] [blame] | 37 | |
| 38 | uint32_t rdid_outsize = ST_M95_RDID_2BA_OUTSIZE; // 16 bit address |
| 39 | if (flash->chip->total_size * KiB > 64 * KiB) |
| 40 | rdid_outsize = ST_M95_RDID_3BA_OUTSIZE; // 24 bit address |
| 41 | |
Patrick Georgi | b57f48f | 2020-05-02 16:07:11 +0200 | [diff] [blame] | 42 | ret = spi_send_command(flash, rdid_outsize, sizeof(readarr), cmd, readarr); |
| 43 | if (ret) |
| 44 | return ret; |
Konstantin Grudnev | 3d8868c | 2019-07-23 00:48:54 +0300 | [diff] [blame] | 45 | |
| 46 | id1 = readarr[0]; // manufacture id |
| 47 | id2 = (readarr[1] << 8) | readarr[2]; // SPI family code + model id |
| 48 | |
| 49 | msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); |
| 50 | |
| 51 | if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) |
| 52 | return 1; |
| 53 | |
| 54 | return 0; |
| 55 | } |
| 56 | |
| 57 | /* ST95XXX chips don't have erase operation and erase is made as part of write command */ |
| 58 | int spi_block_erase_emulation(struct flashctx *flash, unsigned int addr, unsigned int blocklen) |
| 59 | { |
| 60 | uint8_t *erased_contents = NULL; |
| 61 | int result = 0; |
| 62 | |
| 63 | erased_contents = (uint8_t *)malloc(blocklen * sizeof(uint8_t)); |
| 64 | if (!erased_contents) { |
| 65 | msg_cerr("Out of memory!\n"); |
| 66 | return 1; |
| 67 | } |
| 68 | memset(erased_contents, ERASED_VALUE(flash), blocklen * sizeof(uint8_t)); |
| 69 | result = spi_write_chunked(flash, erased_contents, 0, blocklen, flash->chip->page_size); |
| 70 | free(erased_contents); |
| 71 | return result; |
| 72 | } |