blob: ed0d12165b4bf3379899204adcf9c0fb63787808 [file] [log] [blame]
Martin Roth433659a2014-05-12 21:55:00 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
5 * Copyright (C) 2014 Sage Electronic Engineering, LLC.
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; version 2 of the License.
10 *
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.
Martin Roth433659a2014-05-12 21:55:00 -060015 */
16
17#include <stdint.h>
18#include <stddef.h>
19#include <console/console.h>
20#include <string.h>
21#include <spi-generic.h>
22#include <spi_flash.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060023#include <soc/nvm.h>
Martin Roth433659a2014-05-12 21:55:00 -060024
25/* This module assumes the flash is memory mapped just below 4GiB in the
26 * address space for reading. Also this module assumes an area it erased
27 * when all bytes read as all 0xff's. */
28
29static struct spi_flash *flash;
30
31static int nvm_init(void)
32{
33 if (flash != NULL)
34 return 0;
35
36 spi_init();
Gabe Black1e187352014-03-27 20:37:03 -070037 flash = spi_flash_probe(0, 0);
Martin Roth433659a2014-05-12 21:55:00 -060038 if (!flash) {
39 printk(BIOS_DEBUG, "Could not find SPI device\n");
40 return -1;
41 }
42
43 return 0;
44}
45
Kyösti Mälkki9b29aad2015-01-06 07:08:46 +010046/* Convert memory mapped pointer to flash offset. */
47static inline uint32_t to_flash_offset(void *p)
48{
Kyösti Mälkki9b29aad2015-01-06 07:08:46 +010049 return CONFIG_ROM_SIZE + (uintptr_t)p;
50}
51
Martin Roth433659a2014-05-12 21:55:00 -060052int nvm_is_erased(const void *start, size_t size)
53{
54 const uint8_t *cur = start;
55 const uint8_t erased_value = 0xff;
56
57 while (size > 0) {
58 if (*cur != erased_value)
59 return 0;
60 cur++;
61 size--;
62 }
63 return 1;
64}
65
66int nvm_erase(void *start, size_t size)
67{
68 if (nvm_init() < 0)
69 return -1;
Kyösti Mälkki9b29aad2015-01-06 07:08:46 +010070 flash->erase(flash, to_flash_offset(start), size);
Martin Roth433659a2014-05-12 21:55:00 -060071 return 0;
72}
73
74/* Write data to NVM. Returns 0 on success < 0 on error. */
75int nvm_write(void *start, const void *data, size_t size)
76{
77 if (nvm_init() < 0)
78 return -1;
Kyösti Mälkki9b29aad2015-01-06 07:08:46 +010079 flash->write(flash, to_flash_offset(start), size, data);
Martin Roth433659a2014-05-12 21:55:00 -060080 return 0;
81}