drivers/spi: Pass flash parameters from coreboot to payload
[coreboot.git] / src / drivers / spi / eon.c
blob004b62bc053cb8a9eb4b2cbc24e8012c9db5ce06
1 /*
2 * (C) Copyright 2010, ucRobotics Inc.
3 * Copyright (c) 2014, Sage Electronic Engineering, LLC
4 * .
5 * Author: Chong Huang <chuang@ucrobotics.com>
6 * Licensed under the GPL-2 or later.
7 */
9 #include <stdlib.h>
10 #include <spi_flash.h>
12 #include "spi_flash_internal.h"
14 /* EN25*-specific commands */
15 #define CMD_EN25_WREN 0x06 /* Write Enable */
16 #define CMD_EN25_WRDI 0x04 /* Write Disable */
17 #define CMD_EN25_RDSR 0x05 /* Read Status Register */
18 #define CMD_EN25_WRSR 0x01 /* Write Status Register */
19 #define CMD_EN25_READ 0x03 /* Read Data Bytes */
20 #define CMD_EN25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
21 #define CMD_EN25_PP 0x02 /* Page Program */
22 #define CMD_EN25_SE 0x20 /* Sector Erase */
23 #define CMD_EN25_BE 0xd8 /* Block Erase */
24 #define CMD_EN25_DP 0xb9 /* Deep Power-down */
25 #define CMD_EN25_RES 0xab /* Release from DP, and Read Signature */
27 #define EON_ID_EN25Q128 0x3018
28 #define EON_ID_EN25Q64 0x3017
29 #define EON_ID_EN25S64 0x3817
31 struct eon_spi_flash_params {
32 u16 id;
33 u16 page_size;
34 u16 pages_per_sector;
35 u16 sectors_per_block;
36 u16 nr_sectors;
37 const char *name;
40 /* spi_flash needs to be first so upper layers can free() it */
41 struct eon_spi_flash {
42 struct spi_flash flash;
43 const struct eon_spi_flash_params *params;
46 static inline struct eon_spi_flash *to_eon_spi_flash(struct spi_flash *flash)
48 return container_of(flash, struct eon_spi_flash, flash);
51 static const struct eon_spi_flash_params eon_spi_flash_table[] = {
53 .id = EON_ID_EN25Q128,
54 .page_size = 256,
55 .pages_per_sector = 16,
56 .sectors_per_block = 16,
57 .nr_sectors = 4096,
58 .name = "EN25Q128",
61 .id = EON_ID_EN25Q64,
62 .page_size = 256,
63 .pages_per_sector = 16,
64 .sectors_per_block = 16,
65 .nr_sectors = 2048,
66 .name = "EN25Q64",
69 .id = EON_ID_EN25S64,
70 .page_size = 256,
71 .pages_per_sector = 16,
72 .sectors_per_block = 16,
73 .nr_sectors = 2048,
74 .name = "EN25S64",
78 static int eon_write(struct spi_flash *flash,
79 u32 offset, size_t len, const void *buf)
81 struct eon_spi_flash *eon = to_eon_spi_flash(flash);
82 unsigned long byte_addr;
83 unsigned long page_size;
84 size_t chunk_len;
85 size_t actual;
86 int ret = 0;
87 u8 cmd[4];
89 page_size = 1 << eon->params->page_size;
90 byte_addr = offset % page_size;
92 flash->spi->rw = SPI_WRITE_FLAG;
94 for (actual = 0; actual < len; actual += chunk_len) {
95 chunk_len = min(len - actual, page_size - byte_addr);
96 chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
98 ret = spi_flash_cmd(flash->spi, CMD_EN25_WREN, NULL, 0);
99 if (ret < 0) {
100 printk(BIOS_WARNING, "SF: Enabling Write failed\n");
101 goto out;
104 cmd[0] = CMD_EN25_PP;
105 cmd[1] = (offset >> 16) & 0xff;
106 cmd[2] = (offset >> 8) & 0xff;
107 cmd[3] = offset & 0xff;
109 #if CONFIG_DEBUG_SPI_FLASH
110 printk(BIOS_SPEW,
111 "PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
112 buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
113 #endif
115 ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
116 buf + actual, chunk_len);
117 if (ret < 0) {
118 printk(BIOS_WARNING, "SF: EON Page Program failed\n");
119 goto out;
122 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
123 if (ret) {
124 printk(BIOS_WARNING, "SF: EON Page Program timeout\n");
125 goto out;
128 offset += chunk_len;
129 byte_addr = 0;
132 #if CONFIG_DEBUG_SPI_FLASH
133 printk(BIOS_SPEW, "SF: EON: Successfully programmed %zu bytes @ %#x\n",
134 len, (unsigned int)(offset - len));
135 #endif
137 out:
138 return ret;
141 struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
143 const struct eon_spi_flash_params *params;
144 struct eon_spi_flash *eon;
145 unsigned int i;
147 for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) {
148 params = &eon_spi_flash_table[i];
149 if (params->id == ((idcode[1] << 8) | idcode[2]))
150 break;
153 if (i == ARRAY_SIZE(eon_spi_flash_table)) {
154 printk(BIOS_WARNING, "SF: Unsupported EON ID %#02x%02x\n",
155 idcode[1], idcode[2]);
156 return NULL;
159 eon = malloc(sizeof(*eon));
160 if (!eon) {
161 printk(BIOS_WARNING, "SF: Failed to allocate memory\n");
162 return NULL;
165 eon->params = params;
166 eon->flash.spi = spi;
167 eon->flash.name = params->name;
169 eon->flash.write = eon_write;
170 eon->flash.erase = spi_flash_cmd_erase;
171 eon->flash.read = spi_flash_cmd_read_fast;
172 eon->flash.sector_size = params->page_size * params->pages_per_sector;
173 eon->flash.size = params->page_size * params->pages_per_sector
174 * params->nr_sectors;
175 eon->flash.erase_cmd = CMD_EN25_SE;
177 return &eon->flash;