blob: e7d9b9a9441f5de36643f36085cb023c78f4aec7 [file] [log] [blame]
Aaron Durbin6f115592016-08-11 18:24:54 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2016 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <arch/early_variables.h>
17#include <boot_device.h>
18#include <spi_flash.h>
Furquan Shaikhc28984d2016-11-20 21:04:00 -080019#include <spi-generic.h>
Aaron Durbin6f115592016-08-11 18:24:54 -050020
21static struct spi_flash *sfg CAR_GLOBAL;
22
23static ssize_t spi_readat(const struct region_device *rd, void *b,
24 size_t offset, size_t size)
25{
26 struct spi_flash *sf = car_get_var(sfg);
27
28 if (sf == NULL)
29 return -1;
30
Furquan Shaikhc28984d2016-11-20 21:04:00 -080031 if (spi_flash_read(sf, offset, size, b))
Aaron Durbin6f115592016-08-11 18:24:54 -050032 return -1;
33
34 return size;
35}
36
37static ssize_t spi_writeat(const struct region_device *rd, const void *b,
38 size_t offset, size_t size)
39{
40 struct spi_flash *sf = car_get_var(sfg);
41
42 if (sf == NULL)
43 return -1;
44
Furquan Shaikhc28984d2016-11-20 21:04:00 -080045 if (spi_flash_write(sf, offset, size, b))
Aaron Durbin6f115592016-08-11 18:24:54 -050046 return -1;
47
48 return size;
49}
50
51static ssize_t spi_eraseat(const struct region_device *rd,
52 size_t offset, size_t size)
53{
54 struct spi_flash *sf = car_get_var(sfg);
55
56 if (sf == NULL)
57 return -1;
58
Furquan Shaikhc28984d2016-11-20 21:04:00 -080059 if (spi_flash_erase(sf, offset, size))
Aaron Durbin6f115592016-08-11 18:24:54 -050060 return -1;
61
62 return size;
63}
64
65static const struct region_device_ops spi_ops = {
66 .readat = spi_readat,
67 .writeat = spi_writeat,
68 .eraseat = spi_eraseat,
69};
70
71static const struct region_device spi_rw =
72 REGION_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE);
73
Aaron Durbin67e4df82016-08-23 08:45:55 -050074static void boot_device_rw_init(void)
Aaron Durbin6f115592016-08-11 18:24:54 -050075{
76 const int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS;
77 const int cs = 0;
78
79 if (car_get_var(sfg) != NULL)
80 return;
81
Aaron Durbindf76f892016-08-22 17:41:13 -050082 /* Ensure any necessary setup is performed by the drivers. */
83 spi_init();
84
Aaron Durbin6f115592016-08-11 18:24:54 -050085 car_set_var(sfg, spi_flash_probe(bus, cs));
86}
87
88const struct region_device *boot_device_rw(void)
89{
Aaron Durbin67e4df82016-08-23 08:45:55 -050090 /* Probe for the SPI flash device if not already done. */
91 boot_device_rw_init();
92
Aaron Durbin6f115592016-08-11 18:24:54 -050093 if (car_get_var(sfg) == NULL)
94 return NULL;
95
96 return &spi_rw;
97}
Aaron Durbin305c0ca2016-12-03 17:04:06 -060098
99const struct spi_flash *boot_device_spi_flash(void)
100{
101 boot_device_rw_init();
102 return car_get_var(sfg);
103}