237 changes: 184 additions & 53 deletions sortbootorder.c
Expand Up @@ -21,6 +21,8 @@
#include <curses.h>
#include <flash_access.h>
#include <sec_reg_menu.h>
#include <spi/spi_lock_menu.h>

#include "version.h"

/*** defines ***/
Expand All @@ -30,27 +32,46 @@

// These names come from bootorder_map file
// indexes depend on device order in this file
#define USB_1_SS 0
#define USB_2_SS 1
#define USB_1_HS 2
#define USB_2_HS 3
#define SDCARD 4
#define MSATA 5
#define SATA 6
#define MPCIE1_SATA1 7
#define MPCIE1_SATA2 8
#define IPXE 9
#define USB_1 0
#define USB_2 1
#define USB_3 2
#define USB_4 3
#define USB_5 4
#define USB_6 5
#define USB_7 6
#define USB_8 7
#define USB_9 8
#define USB_10 9
#define USB_11 10
#define USB_12 11
#define SDCARD 12
#define MSATA 13
#define SATA 14
#define MPCIE1_SATA1 15
#define MPCIE1_SATA2 16
#define IPXE 17

#define RESET() outb(0x06, 0x0cf9)

/*** prototypes ***/
static void show_boot_device_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt, u8 lineDef_cnt );
static void move_boot_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line, u8 max_lines );
static void copy_list_line( char *src, char *dest );
static int fetch_file_from_cbfs( char *filename, char destination[MAX_DEVICES][MAX_LENGTH], u8 *line_count);
static int get_line_number(u8 line_start, u8 line_end, char key );
static void int_ids( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt, u8 lineDef_cnt );
static void update_tag_value(char buffer[MAX_DEVICES][MAX_LENGTH], u8 *max_lines, const char * tag, char value);
static void show_boot_device_list(char buffer[MAX_DEVICES][MAX_LENGTH],
u8 line_cnt, u8 lineDef_cnt);
static void move_boot_list(char buffer[MAX_DEVICES][MAX_LENGTH], u8 line,
u8 max_lines);
static void copy_list_line(char *src, char *dest);
static int fetch_file_from_cbfs(char *filename,
char destination[MAX_DEVICES][MAX_LENGTH],
u8 *line_count);
static int get_line_number(u8 line_start, u8 line_end, char key);
static void int_ids(char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt,
u8 lineDef_cnt );
static void update_tag_value(char buffer[MAX_DEVICES][MAX_LENGTH],
u8 *max_lines, const char * tag, char value);
#ifndef TARGET_APU1
static void update_wdg_timeout(char buffer[MAX_DEVICES][MAX_LENGTH],
u8 *max_lines, u16 value);
#endif
static void update_tags(char bootlist[MAX_DEVICES][MAX_LENGTH], u8 *max_lines);
static void refresh_tag_values(u8 max_lines);

/*** local variables ***/
Expand All @@ -71,6 +92,8 @@ static u8 com2_available;
static u8 ehci0_toggle;
static u8 mpcie2_clk_toggle;
static u8 boost_toggle;
static u8 sd3_toggle;
static u16 wdg_timeout;
#endif

static u8 uartc_toggle;
Expand Down Expand Up @@ -186,6 +209,14 @@ int main(void) {
token = strstr(bootorder_data, "boosten");
token += strlen("boosten");
boost_toggle = token ? strtoul(token, NULL, 10) : 0;

token = strstr(bootorder_data, "sd3mode");
token += strlen("sd3mode");
sd3_toggle = token ? strtoul(token, NULL, 10) : 0;

token = strstr(bootorder_data, "watchdog");
token += strlen("watchdog");
wdg_timeout = token ? (u16) strtoul(token, NULL, 16) : 0;
#endif

token = strstr(bootorder_data, "uartc");
Expand Down Expand Up @@ -255,24 +286,28 @@ int main(void) {
case 'L':
boost_toggle ^= 0x1;
break;
case 'i':
case 'I':
; // empty statement to avoid compilation error
char *prompt = readline("Specify the watchdog"
" timeout in seconds (0 to disable): ");
wdg_timeout = (u16) strtoul(prompt, NULL, 10);
prompt[0] = '\0';
break;
case 'j':
case 'J':
sd3_toggle ^= 0x1;
break;
case 'Q':
handle_spi_lock_menu();
break;
case 'Z':
handle_reg_sec_menu();
break;
#endif
case 's':
case 'S':
update_tag_value(bootlist, &max_lines, "pxen", ipxe_toggle + '0');
update_tag_value(bootlist, &max_lines, "usben", usb_toggle + '0');
update_tag_value(bootlist, &max_lines, "scon", console_toggle + '0');
if (com2_available)
update_tag_value(bootlist, &max_lines, "com2en", com2_toggle + '0');
update_tag_value(bootlist, &max_lines, "uartc", uartc_toggle + '0');
update_tag_value(bootlist, &max_lines, "uartd", uartd_toggle + '0');
#ifndef TARGET_APU1
update_tag_value(bootlist, &max_lines, "mpcie2_clk", mpcie2_clk_toggle + '0');
update_tag_value(bootlist, &max_lines, "ehcien", ehci0_toggle + '0');
update_tag_value(bootlist, &max_lines, "boosten", boost_toggle + '0');
#endif
update_tags(bootlist, &max_lines);
save_flash(flash_address, bootlist, max_lines, spi_wp_toggle);
// fall through to exit ...
case 'x':
Expand Down Expand Up @@ -311,7 +346,8 @@ static int strcmp_printable_char(const char *s1, const char *s2)
}

/*******************************************************************************/
static int get_line_number( u8 line_start, u8 line_end, char key ) {
static int get_line_number(u8 line_start, u8 line_end, char key)
{
int i;
for (i = line_end - 1; i >= line_start; i-- ) {
if(id[i] == key)
Expand All @@ -321,8 +357,9 @@ static int get_line_number( u8 line_start, u8 line_end, char key ) {
}

/*******************************************************************************/
static void copy_list_line( char *src, char *dest ) {
u8 i=0;
static void copy_list_line(char *src, char *dest)
{
u8 i=0;

do {
dest[i] = src[i];
Expand All @@ -331,15 +368,25 @@ u8 i=0;
}

/*******************************************************************************/
static void show_boot_device_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt, u8 lineDef_cnt ) {
static void show_boot_device_list(char buffer[MAX_DEVICES][MAX_LENGTH],
u8 line_cnt, u8 lineDef_cnt )
{
int i,j,y,unique;
char print_device[MAX_LENGTH];

device_toggle[USB_1_SS] = usb_toggle;
device_toggle[USB_2_SS] = usb_toggle;
device_toggle[USB_1_HS] = usb_toggle;
device_toggle[USB_2_HS] = usb_toggle;
device_toggle[IPXE] = ipxe_toggle;
device_toggle[USB_1] = usb_toggle;
device_toggle[USB_2] = usb_toggle;
device_toggle[USB_3] = usb_toggle;
device_toggle[USB_4] = usb_toggle;
device_toggle[USB_5] = usb_toggle;
device_toggle[USB_6] = usb_toggle;
device_toggle[USB_7] = usb_toggle;
device_toggle[USB_8] = usb_toggle;
device_toggle[USB_9] = usb_toggle;
device_toggle[USB_10] = usb_toggle;
device_toggle[USB_11] = usb_toggle;
device_toggle[USB_12] = usb_toggle;
device_toggle[IPXE] = ipxe_toggle;

printf("Boot order - type letter to move device to top.\n\n");
for (i = 0; i < line_cnt; i++ ) {
Expand All @@ -363,26 +410,42 @@ static void show_boot_device_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line
}
printf("\n\n");
printf(" r Restore boot order defaults\n");
printf(" n Network/PXE boot - Currently %s\n", (ipxe_toggle) ? "Enabled" : "Disabled");
printf(" u USB boot - Currently %s\n", (usb_toggle) ? "Enabled" : "Disabled");
printf(" t Serial console - Currently %s\n", (console_toggle) ? "Enabled" : "Disabled");
printf(" n Network/PXE boot - Currently %s\n",
(ipxe_toggle) ? "Enabled" : "Disabled");
printf(" u USB boot - Currently %s\n",
(usb_toggle) ? "Enabled" : "Disabled");
printf(" t Serial console - Currently %s\n",
(console_toggle) ? "Enabled" : "Disabled");
if (com2_available)
printf(" k Redirect console output to COM2 - Currently %s\n", (com2_toggle) ? "Enabled" : "Disabled");
printf(" o UART C - Currently %s\n", (uartc_toggle) ? "Enabled" : "Disabled");
printf(" p UART D - Currently %s\n", (uartd_toggle) ? "Enabled" : "Disabled");
printf(" k Redirect console output to COM2 - Currently %s\n",
(com2_toggle) ? "Enabled" : "Disabled");
printf(" o UART C - Currently %s\n",
(uartc_toggle) ? "Enabled" : "Disabled");
printf(" p UART D - Currently %s\n",
(uartd_toggle) ? "Enabled" : "Disabled");
#ifndef TARGET_APU1
printf(" m Force mPCIe2 slot CLK (GPP3 PCIe) - Currently %s\n", (mpcie2_clk_toggle) ? "Enabled" : "Disabled");
printf(" h EHCI0 controller - Currently %s\n", (ehci0_toggle) ? "Enabled" : "Disabled");
printf(" l Core Performance Boost - Currently %s\n", (boost_toggle) ? "Enabled" : "Disabled");
printf(" m Force mPCIe2 slot CLK (GPP3 PCIe) - Currently %s\n",
(mpcie2_clk_toggle) ? "Enabled" : "Disabled");
printf(" h EHCI0 controller - Currently %s\n",
(ehci0_toggle) ? "Enabled" : "Disabled");
printf(" l Core Performance Boost - Currently %s\n",
(boost_toggle) ? "Enabled" : "Disabled");
printf(" i Watchdog - Currently %s\n",
(wdg_timeout) ? "Enabled" : "Disabled");
printf(" j SD 3.0 mode - Currently %s\n",
(sd3_toggle) ? "Enabled" : "Disabled");
#endif
printf(" w Enable BIOS write protect - Currently %s\n", (spi_wp_toggle) ? "Enabled" : "Disabled");
printf(" w Enable BIOS write protect - Currently %s\n",
(spi_wp_toggle) ? "Enabled" : "Disabled");
printf(" x Exit setup without save\n");
printf(" s Save configuration and exit\n");
}

/*******************************************************************************/
static void int_ids( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt, u8 lineDef_cnt ) {
int i,y;
static void int_ids(char buffer[MAX_DEVICES][MAX_LENGTH], u8 line_cnt,
u8 lineDef_cnt )
{
int i,y;
for (i = 0; i < line_cnt; i++ ) {
if (buffer[i][0] == '/') {
for (y = 0; y < lineDef_cnt; y++) {
Expand All @@ -396,7 +459,10 @@ int i,y;
}

/*******************************************************************************/
static int fetch_file_from_cbfs( char *filename, char destination[MAX_DEVICES][MAX_LENGTH], u8 *line_count) {
static int fetch_file_from_cbfs(char *filename,
char destination[MAX_DEVICES][MAX_LENGTH],
u8 *line_count)
{
char *cbfs_dat, tmp;
int cbfs_offset = 0, char_cnt = 0;
size_t cbfs_length;
Expand Down Expand Up @@ -438,7 +504,9 @@ static int fetch_file_from_cbfs( char *filename, char destination[MAX_DEVICES][M
}

/*******************************************************************************/
static void move_boot_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line, u8 max_lines ) {
static void move_boot_list(char buffer[MAX_DEVICES][MAX_LENGTH], u8 line,
u8 max_lines )
{
char temp_line[MAX_LENGTH];
char ln;
u8 x;
Expand All @@ -463,7 +531,8 @@ static void move_boot_list( char buffer[MAX_DEVICES][MAX_LENGTH], u8 line, u8 ma
}

/*******************************************************************************/
static void update_tag_value(char buffer[MAX_DEVICES][MAX_LENGTH], u8 *max_lines, const char * tag, char value)
static void update_tag_value(char buffer[MAX_DEVICES][MAX_LENGTH],
u8 *max_lines, const char * tag, char value)
{
int i;
bool found = FALSE;
Expand All @@ -488,7 +557,58 @@ static void update_tag_value(char buffer[MAX_DEVICES][MAX_LENGTH], u8 *max_lines
(*max_lines)++;
}
}
#ifndef TARGET_APU1
static void update_wdg_timeout(char buffer[MAX_DEVICES][MAX_LENGTH],
u8 *max_lines, u16 value)
{
int i;
bool found = FALSE;
char *tag = "watchdog";

for (i = 0; i < *max_lines; i++) {
if (!strncmp(tag, &buffer[i][0], strlen(tag))) {
found = TRUE;
snprintf(&buffer[i][strlen(tag)], 5, "%04x", value);
buffer[*max_lines][strlen(tag)+4] = '\r';
buffer[*max_lines][strlen(tag)+5] = '\n';
break;
}
}

if (!found) {
if ((*max_lines + 1) > MAX_DEVICES) {
return;
}
strcpy(&buffer[*max_lines][0], tag);
snprintf(&buffer[*max_lines][strlen(tag)], 5, "%04x", value);
buffer[*max_lines][strlen(tag)+4] = '\r';
buffer[*max_lines][strlen(tag)+5] = '\n';
buffer[*max_lines][strlen(tag)+6] = '0';
(*max_lines)++;
}
}
#endif

static void update_tags(char bootlist[MAX_DEVICES][MAX_LENGTH], u8 *max_lines)
{
update_tag_value(bootlist, max_lines, "pxen", ipxe_toggle + '0');
update_tag_value(bootlist, max_lines, "usben", usb_toggle + '0');
update_tag_value(bootlist, max_lines, "scon", console_toggle + '0');
if (com2_available) {
update_tag_value(bootlist, max_lines, "com2en",
com2_toggle + '0');
}
update_tag_value(bootlist, max_lines, "uartc", uartc_toggle + '0');
update_tag_value(bootlist, max_lines, "uartd", uartd_toggle + '0');
#ifndef TARGET_APU1
update_tag_value(bootlist, max_lines, "mpcie2_clk",
mpcie2_clk_toggle + '0');
update_tag_value(bootlist, max_lines, "ehcien", ehci0_toggle + '0');
update_tag_value(bootlist, max_lines, "boosten", boost_toggle + '0');
update_tag_value(bootlist, max_lines, "sd3mode", sd3_toggle + '0');
update_wdg_timeout(bootlist, max_lines, wdg_timeout);
#endif
}
/*******************************************************************************/
static void refresh_tag_values(u8 max_lines)
{
Expand Down Expand Up @@ -547,6 +667,17 @@ static void refresh_tag_values(u8 max_lines)
token += strlen("boosten");
boost_toggle = strtoul(token, NULL, 10);
}
token = strstr(&(bootlist_def[i][0]), "sd3mode");
if(token) {
token += strlen("sd3mode");
sd3_toggle = strtoul(token, NULL, 10);
}

token = strstr(&(bootlist_def[i][0]), "watchdog");
if(token) {
token += strlen("watchdog");
wdg_timeout = (u16) strtoul(token, NULL, 16);
}
#endif
}
}
376 changes: 376 additions & 0 deletions spi/adesto.c
@@ -0,0 +1,376 @@
/*
* adesto.c
* Driver for Adesto Technologies SPI flash
* Copyright 2014 Orion Technologies, LLC
* Author: Chris Douglass <cdouglass <at> oriontechnologies.com>
*
* based on winbond.c
* Copyright 2008, Network Appliance Inc.
* Author: Jason McMullan <mcmullan <at> netapp.com>
* Licensed under the GPL-2 or later.
*/

#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include <spi/spi_flash_internal.h>

/* at25dfxx-specific commands */
#define CMD_AT25DF_WREN 0x06 /* Write Enable */
#define CMD_AT25DF_WRDI 0x04 /* Write Disable */
#define CMD_AT25DF_RDSR1 0x05 /* Read Status Register 1 */
#define CMD_AT25DF_RDSR2 0x35 /* Read Status Register 2 */
#define CMD_AT25DF_WRSR1 0x01 /* Write Status Register 1 */
#define CMD_AT25DF_WRSR2 0x31 /* Write Status Register 2 */
#define CMD_AT25DF_READ 0x03 /* Read Data Bytes */
#define CMD_AT25DF_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
#define CMD_AT25DF_PP 0x02 /* Page Program */
#define CMD_AT25DF_SE 0x20 /* Sector (4K) Erase */
#define CMD_AT25DF_BE 0xd8 /* Block (64K) Erase */
#define CMD_AT25DF_CE 0xc7 /* Chip Erase */
#define CMD_AT25DF_DP 0xb9 /* Deep Power-down */
#define CMD_AT25DF_RES 0xab /* Release from DP, and Read Signature */

#define REG_W25_BP0 (1 << 2)
#define REG_W25_BP1 (1 << 3)
#define REG_W25_BP2 (1 << 4)
#define REG_W25_TB (1 << 5)
#define REG_W25_SEC (1 << 6)
#define REG_W25_SRP0 (1 << 7)
#define REG_W25_SRP1 (1 << 0)
#define REG_W25_CMP (1 << 6)
#define REG_W25_WPS (1 << 2)
#define REG_W25_LB1 (1 << 3)
#define REG_W25_LB2 (1 << 4)
#define REG_W25_LB3 (1 << 5)


struct adesto_spi_flash_params {
uint16_t id;
/* Log2 of page size in power-of-two mode */
uint8_t l2_page_size;
uint16_t pages_per_sector;
uint16_t sectors_per_block;
uint16_t nr_blocks;
const char *name;
};

/* spi_flash needs to be first so upper layers can free() it */
struct adesto_spi_flash {
struct spi_flash flash;
const struct adesto_spi_flash_params *params;
};

static inline struct adesto_spi_flash *
to_adesto_spi_flash(struct spi_flash *flash)
{
return container_of(flash, struct adesto_spi_flash, flash);
}

static const struct adesto_spi_flash_params adesto_spi_flash_table[] = {
{
.id = 0x4218,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 256,
.name = "AT25SL128A",
},
{
.id = 0x4501,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 16,
.name = "AT25DF081A", /* Yes, 81A id < 81 */
},
{
.id = 0x4502,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 16,
.name = "AT25DF081",
},
{
.id = 0x4602,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 32,
.name = "AT25DF161",
},
{
.id = 0x4603,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 32,
.name = "AT25DL161",
},
{
.id = 0x4700,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 64,
.name = "AT25DF321",
},
{
.id = 0x4701,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 64,
.name = "AT25DF321A",
},
{
.id = 0x4800,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 128,
.name = "AT25DF641",
},
{
.id = 0x3217,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 128,
.name = "AT25QF641",
},
{
.id = 0x8501,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 16,
.name = "AT25SF081",
},
{
.id = 0x8600,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 32,
.name = "AT25DQ161",
},
{
.id = 0x8601,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 32,
.name = "AT25SF161",
},
{
.id = 0x8700,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 64,
.name = "AT25DQ321",
},
};

static int adesto_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
{
struct adesto_spi_flash *stm = to_adesto_spi_flash(flash);
unsigned long byte_addr;
unsigned long page_size;
size_t chunk_len;
size_t actual;
int ret;
u8 cmd[4];

page_size = min(1 << stm->params->l2_page_size, CONTROLLER_PAGE_LIMIT);
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
spi_debug("SF: Unable to claim SPI bus\n");
return ret;
}

for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);

cmd[0] = CMD_AT25DF_PP;
cmd[1] = (offset >> 16) & 0xff;
cmd[2] = (offset >> 8) & 0xff;
cmd[3] = offset & 0xff;

spi_debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x }"
" chunk_len = %u\n", buf + actual,
cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);

ret = spi_flash_cmd(flash->spi, CMD_AT25DF_WREN, NULL, 0);
if (ret < 0) {
spi_debug("SF: Enabling Write failed\n");
goto out;
}

ret = spi_flash_cmd_write(flash->spi, cmd, 4,
buf + actual, chunk_len);
if (ret < 0) {
spi_debug("SF: Adesto Page Program failed\n");
goto out;
}

ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
if (ret)
goto out;

offset += chunk_len;
byte_addr = 0;
}

spi_debug("SF: Adesto: Successfully programmed %u bytes @"
" 0x%lx\n", len, (unsigned long)(offset - len));

ret = 0;

out:
spi_release_bus(flash->spi);
return ret;
}

static int adesto_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_AT25DF_SE, offset, len);
}

static int adesto_set_lock_flags(struct spi_flash *flash, int lock)
{
int ret;
u8 cmd;
u8 status[2];

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
spi_debug("SF: Unable to claim SPI bus\n");
return ret;
}

ret = spi_flash_cmd(flash->spi, CMD_AT25DF_RDSR1, &status[0], 1);
if (ret) {
spi_debug("SF: Unable to read Status Register 1\n");
goto out;
}

ret = spi_flash_cmd(flash->spi, CMD_AT25DF_RDSR2, &status[1], 1);
if (ret) {
spi_debug("SF: Unable to read Status Register 2\n");
goto out;
}

if (lock) {
status[0] |= REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0;
} else {
status[0] &= ~(REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0);
}

status[0] &= ~(REG_W25_SEC | REG_W25_TB);
status[1] &= ~(REG_W25_SRP1 | REG_W25_CMP);

ret = spi_flash_cmd(flash->spi, CMD_AT25DF_WREN, NULL, 0);
if (ret < 0) {
spi_debug("SF: Enabling Write failed\n");
goto out;
}

cmd = CMD_AT25DF_WRSR1;
ret = spi_flash_cmd_write(flash->spi, &cmd, sizeof(cmd),
status, sizeof(status));
if (ret < 0) {
spi_debug("SF: Status register write failed\n");
goto out;
}

out:
spi_release_bus(flash->spi);
return ret;
}

static int adesto_unlock(struct spi_flash *flash)
{
return adesto_set_lock_flags(flash, 0);
}

static int adesto_lock(struct spi_flash *flash)
{
return adesto_set_lock_flags(flash, 1);
}

static int adesto_is_locked(struct spi_flash *flash)
{
u8 status = 0;

spi_flash_cmd(flash->spi, CMD_AT25DF_RDSR1, &status, 1);

if ((status & (REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0))
== (REG_W25_SRP0 | REG_W25_BP2 | REG_W25_BP1 | REG_W25_BP0)) {
return 1;
}

return 0;
}

struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode)
{
const struct adesto_spi_flash_params *params;
unsigned page_size;
struct adesto_spi_flash *stm;
unsigned int i;

for (i = 0; i < ARRAY_SIZE(adesto_spi_flash_table); i++) {
params = &adesto_spi_flash_table[i];
if (params->id == ((idcode[1] << 8) | idcode[2]))
break;
}

if (i == ARRAY_SIZE(adesto_spi_flash_table)) {
spi_debug("SF: Unsupported Adesto ID %02x%02x\n",
idcode[1], idcode[2]);
return NULL;
}

stm = malloc(sizeof(struct adesto_spi_flash));
if (!stm) {
spi_debug("SF: Failed to allocate memory\n");
return NULL;
}

stm->params = params;
stm->flash.spi = spi;
stm->flash.name = params->name;

/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;

stm->flash.write = adesto_write;
stm->flash.spi_erase = adesto_erase;
stm->flash.lock = adesto_lock;
stm->flash.unlock = adesto_unlock;
stm->flash.is_locked = adesto_is_locked;
stm->flash.sec_sts = NULL;
stm->flash.sec_read = NULL;
stm->flash.sec_prog = NULL;
stm->flash.sec_erase = NULL;
stm->flash.sec_lock = NULL;
#if CONFIG_SPI_FLASH_NO_FAST_READ
stm->flash.read = spi_flash_cmd_read_slow;
#else
stm->flash.read = spi_flash_cmd_read_fast;
#endif
stm->flash.sector_size = (1 << stm->params->l2_page_size) *
stm->params->pages_per_sector;
stm->flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;

return &stm->flash;
}
2 changes: 1 addition & 1 deletion spi/eon.c
Expand Up @@ -11,7 +11,7 @@
#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"
#include <spi/spi_flash_internal.h>


/* EN25Q128-specific commands */
Expand Down
2 changes: 1 addition & 1 deletion spi/gigadevice.c
Expand Up @@ -28,7 +28,7 @@
#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"
#include <spi/spi_flash_internal.h>

/* GD25Pxx-specific commands */
#define CMD_GD25_WREN 0x06 /* Write Enable */
Expand Down
2 changes: 1 addition & 1 deletion spi/macronix.c
Expand Up @@ -33,7 +33,7 @@
#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"
#include <spi/spi_flash_internal.h>

/* MX25xx-specific commands */
#define CMD_MX25XX_WREN 0x06 /* Write Enable */
Expand Down
2 changes: 1 addition & 1 deletion spi/spansion.c
Expand Up @@ -29,7 +29,7 @@
#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"
#include <spi/spi_flash_internal.h>

/* S25FLxx-specific commands */
#define CMD_S25FLXX_READ 0x03 /* Read Data Bytes */
Expand Down
3 changes: 2 additions & 1 deletion spi/spi_flash.c
Expand Up @@ -15,7 +15,7 @@
#include <string.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"
#include <spi/spi_flash_internal.h>

static void spi_flash_addr(u32 addr, u8 *cmd)
{
Expand Down Expand Up @@ -217,6 +217,7 @@ static struct {
struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
} flashes[] = {
/* Keep it sorted by define name */
{ 0, 0x1f, spi_flash_probe_adesto, },
{ 0, 0x1c, spi_flash_probe_eon, },
{ 0, 0xc8, spi_flash_probe_gigadevice, },
{ 0, 0xc2, spi_flash_probe_macronix, },
Expand Down
2 changes: 1 addition & 1 deletion spi/sst.c
Expand Up @@ -18,7 +18,7 @@
#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"
#include <spi/spi_flash_internal.h>

#define CMD_SST_WREN 0x06 /* Write Enable */
#define CMD_SST_WRDI 0x04 /* Write Disable */
Expand Down
2 changes: 1 addition & 1 deletion spi/stmicro.c
Expand Up @@ -31,7 +31,7 @@
#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"
#include <spi/spi_flash_internal.h>

/* M25Pxx-specific commands */
#define CMD_M25PXX_WREN 0x06 /* Write Enable */
Expand Down
38 changes: 2 additions & 36 deletions spi/winbond.c
Expand Up @@ -12,42 +12,8 @@
#include <stdlib.h>
#include <spi/spi_flash.h>
#include <spi/spi.h>
#include "spi_flash_internal.h"

/* M25Pxx-specific commands */
#define CMD_W25_WREN 0x06 /* Write Enable */
#define CMD_W25_WRDI 0x04 /* Write Disable */
#define CMD_W25_RDSR1 0x05 /* Read 1st Status Register */
#define CMD_W25_RDSR2 0x35 /* Read 2nd Status Register */
#define CMD_W25_WRSR 0x01 /* Write Status Register */
#define CMD_W25_READ 0x03 /* Read Data Bytes */
#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
#define CMD_W25_PP 0x02 /* Page Program */
#define CMD_W25_SE 0x20 /* Sector (4K) Erase */
#define CMD_W25_BE 0xd8 /* Block (64K) Erase */
#define CMD_W25_CE 0xc7 /* Chip Erase */
#define CMD_W25_DP 0xb9 /* Deep Power-down */
#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */
#define CMD_W25_ER_SEC 0x44 /* Erase security registers */
#define CMD_W25_WR_SEC 0x42 /* Write security registers */
#define CMD_W25_RD_SEC 0x48 /* Read security registers */

#define REG_W25_BP0 (1 << 2)
#define REG_W25_BP1 (1 << 3)
#define REG_W25_BP2 (1 << 4)
#define REG_W25_TB (1 << 5)
#define REG_W25_SEC (1 << 6)
#define REG_W25_SRP0 (1 << 7)
#define REG_W25_SRP1 (1 << 0)
#define REG_W25_CMP (1 << 6)
#define REG_W25_WPS (1 << 2)
#define REG_W25_LB1 (1 << 3)
#define REG_W25_LB2 (1 << 4)
#define REG_W25_LB3 (1 << 5)

#define ADDR_W25_SEC1 0x10
#define ADDR_W25_SEC2 0x20
#define ADDR_W25_SEC3 0x30
#include <spi/winbond_flash.h>
#include <spi/spi_flash_internal.h>

struct winbond_spi_flash_params {
uint16_t id;
Expand Down
14 changes: 14 additions & 0 deletions utils/flash_access.c
Expand Up @@ -19,6 +19,7 @@

#include <spi/spi_flash.h>
#include <flash_access.h>
#include <spi/spi_flash_internal.h>

#define FLASH_SIZE_CHUNK 0x1000 //4k

Expand Down Expand Up @@ -78,6 +79,19 @@ inline int lock_sec(u8 reg)
return spi_flash_sec_lock(flash_device, reg);
}

inline int send_flash_cmd(u8 cmd, void *response, size_t len)
{
return spi_flash_cmd(flash_device->spi, cmd, response, len);
}

inline int send_flash_cmd_write(u8 command, size_t cmd_len, const void *data,
size_t data_len)
{
const u8 cmd = command;
return spi_flash_cmd_write(flash_device->spi, &cmd, cmd_len, data,
data_len);
}

/*******************************************************************************/
void save_flash(int flash_address, char buffer[MAX_DEVICES][MAX_LENGTH],
u8 max_lines, u8 spi_wp_toggle) {
Expand Down
629 changes: 629 additions & 0 deletions utils/spi_lock_menu.c

Large diffs are not rendered by default.