1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 23:22:37 +02:00

asm106x: add programmer for ASM106x SATA controllers

The ASMedia ASM106x series is a PCIe-SATA controller chip.  It supports
an attached SPI flash chip that can contain configuration and PCI option
ROM.  The interface is a simple shifter accessed via PCI config space,
up to 4 bytes at a time.  Add a programmer driver for it.

Tested on a G536PCE1061V11 IO-PCE1061-V1.1 PCIe card, and
a MPCE2ST-A01 VER006S mini-PCIe card, both with chips marked ASM1061,
both enumerate as:

	01:00.0 SATA controller [0106]: ASMedia Technology Inc. ASM1062 Serial ATA Controller [1b21:0612] (rev 02) (prog-if 01 [AHCI 1.0])
	        Subsystem: ASMedia Technology Inc. ASM1062 Serial ATA Controller [1b21:1060]

Change-Id: I591b117be911bdb8249247c20530c1cf70f6e70d
Signed-off-by: Alex Badea <vamposdecampos@gmail.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/73037
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Thomas Heijligen <src@posteo.de>
This commit is contained in:
Alex Badea 2023-02-13 03:03:26 +00:00 committed by Thomas Heijligen
parent c4655409bb
commit 83b051a9b4
8 changed files with 190 additions and 9 deletions

View File

@ -137,6 +137,7 @@ DEPENDS_ON_X86_PORT_IO := \
CONFIG_SATAMV \ CONFIG_SATAMV \
DEPENDS_ON_LIBPCI := \ DEPENDS_ON_LIBPCI := \
CONFIG_ASM106X \
CONFIG_ATAHPT \ CONFIG_ATAHPT \
CONFIG_ATAPROMISE \ CONFIG_ATAPROMISE \
CONFIG_ATAVIA \ CONFIG_ATAVIA \
@ -437,6 +438,9 @@ CONFIG_GFXNVIDIA ?= yes
# Always enable SiI SATA controllers for now. # Always enable SiI SATA controllers for now.
CONFIG_SATASII ?= yes CONFIG_SATASII ?= yes
# ASMedia ASM106x
CONFIG_ASM106X ?= yes
# Highpoint (HPT) ATA/RAID controller support. # Highpoint (HPT) ATA/RAID controller support.
# IMPORTANT: This code is not yet working! # IMPORTANT: This code is not yet working!
CONFIG_ATAHPT ?= no CONFIG_ATAHPT ?= no
@ -642,6 +646,12 @@ PROGRAMMER_OBJS += satasii.o
ACTIVE_PROGRAMMERS += satasii ACTIVE_PROGRAMMERS += satasii
endif endif
ifeq ($(CONFIG_ASM106X), yes)
FEATURE_FLAGS += -D'CONFIG_ASM106X=1'
PROGRAMMER_OBJS += asm106x.o
ACTIVE_PROGRAMMERS += asm106x
endif
ifeq ($(CONFIG_ATAHPT), yes) ifeq ($(CONFIG_ATAHPT), yes)
FEATURE_FLAGS += -D'CONFIG_ATAHPT=1' FEATURE_FLAGS += -D'CONFIG_ATAHPT=1'
PROGRAMMER_OBJS += atahpt.o PROGRAMMER_OBJS += atahpt.o

156
asm106x.c Normal file
View File

@ -0,0 +1,156 @@
/*
* This file is part of the flashrom project.
*
* Copyright (C) 2023 Alex Badea <vamposdecampos@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdlib.h>
#include "programmer.h"
#include "platform/pci.h"
#define PCI_VENDOR_ID_ASMEDIA 0x1b21
#define ASM106X_REG_DATA 0xf0
#define ASM106X_REG_CTRL 0xf4
#define ASM106X_CTRL_RUN 0x20 /* SPI master is running */
#define ASM106X_CTRL_CSN 0x10 /* CS_n pin output */
#define ASM106X_CTRL_WRITE 0x08 /* 0=read, 1=write */
#define ASM106X_CTRL_MASK 0xc0 /* unknown, untouched */
struct asm106x_data {
struct pci_dev *pci;
};
static const struct dev_entry asm106x_devs[] = {
{PCI_VENDOR_ID_ASMEDIA, 0x0612, OK, "ASMedia", "ASM106x"},
{0},
};
static int asm106x_wait_ready(struct pci_dev *pci, uint8_t *pval)
{
unsigned int timeout = 100;
uint8_t val;
while (timeout) {
val = pci_read_byte(pci, ASM106X_REG_CTRL);
msg_pdbg2("asm106x status %#02"PRIx8" tries %d\n", val, timeout);
if (!(val & ASM106X_CTRL_RUN)) {
if (pval)
*pval = val;
return 0;
}
default_delay(10);
timeout--;
}
msg_pdbg("asm106x timed out, ctrl %#02"PRIx8"\n", val);
return 1;
}
static int asm106x_command(const struct flashctx *flash,
unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
struct asm106x_data *data = flash->mst->spi.data;
uint8_t ctrl;
int rv = 1;
msg_pdbg2("asm106x command: wr %d rd %d\n", writecnt, readcnt);
if (asm106x_wait_ready(data->pci, &ctrl))
return 1;
ctrl &= ASM106X_CTRL_MASK;
while (writecnt) {
const unsigned int chunk = min(writecnt, 4);
uint32_t val = 0;
for (int k = chunk-1; k >= 0; k--)
val = (val << 8) | writearr[k];
msg_pdbg2("asm106x write %#08"PRIx32" chunk %u\n", val, chunk);
pci_write_long(data->pci, ASM106X_REG_DATA, val);
pci_write_byte(data->pci, ASM106X_REG_CTRL,
ctrl | ASM106X_CTRL_RUN | ASM106X_CTRL_WRITE | chunk);
if (asm106x_wait_ready(data->pci, NULL))
goto out;
writecnt -= chunk;
writearr += chunk;
}
while (readcnt) {
const unsigned int chunk = min(readcnt, 4);
pci_write_byte(data->pci, ASM106X_REG_CTRL,
ctrl | ASM106X_CTRL_RUN | chunk);
if (asm106x_wait_ready(data->pci, NULL))
goto out;
uint32_t val = pci_read_long(data->pci, ASM106X_REG_DATA);
msg_pdbg2("asm106x read %#08"PRIx32" chunk %u\n", val, chunk);
for (unsigned int k = 0; k < chunk; k++) {
readarr[k] = val & 0xff;
val >>= 8;
}
readcnt -= chunk;
readarr += chunk;
}
rv = 0;
out:
pci_write_byte(data->pci, ASM106X_REG_CTRL, ctrl | ASM106X_CTRL_CSN);
return rv;
}
static int asm106x_shutdown(void *data)
{
free(data);
return 0;
}
static const struct spi_master asm106x_spi_master = {
.features = SPI_MASTER_4BA,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_WRITE_UNLIMITED,
.command = asm106x_command,
.shutdown = asm106x_shutdown,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
.write_256 = default_spi_write_256,
.probe_opcode = default_spi_probe_opcode,
};
static int asm106x_init(const struct programmer_cfg *cfg)
{
struct pci_dev *pci;
struct asm106x_data *data;
/* TODO: no BAR required (just config space) */
pci = pcidev_init(cfg, asm106x_devs, PCI_ROM_ADDRESS);
if (!pci)
return 1;
data = calloc(1, sizeof(*data));
if (!data) {
msg_perr("cannot allocate memory for asm106x_data\n");
return 1;
}
data->pci = pci;
return register_spi_master(&asm106x_spi_master, data);
}
const struct programmer_entry programmer_asm106x = {
.name = "asm106x",
.type = PCI,
.devs.dev = asm106x_devs,
.init = asm106x_init,
};

View File

@ -433,6 +433,8 @@ bitbanging adapter)
.sp .sp
.BR "* dirtyjtag_spi" " (for SPI flash ROMs attached to DirtyJTAG-compatible devices)" .BR "* dirtyjtag_spi" " (for SPI flash ROMs attached to DirtyJTAG-compatible devices)"
.sp .sp
.BR "* asm106x" " (for SPI flash ROMs attached to ASM106x PCIe SATA controllers)"
.sp
Some programmers have optional or mandatory parameters which are described Some programmers have optional or mandatory parameters which are described
in detail in the in detail in the
.B PROGRAMMER-SPECIFIC INFORMATION .B PROGRAMMER-SPECIFIC INFORMATION
@ -1685,7 +1687,8 @@ need access to the respective USB device via libusb API version 1.0.
needs no access permissions at all. needs no access permissions at all.
.sp .sp
.BR internal ", " nic3com ", " nicrealtek ", " nicnatsemi ", " .BR internal ", " nic3com ", " nicrealtek ", " nicnatsemi ", "
.BR gfxnvidia ", " drkaiser ", " satasii ", " satamv ", " atahpt ", " atavia " and " atapromise .BR gfxnvidia ", " drkaiser ", " satasii ", " satamv ", " asm106x ", "
.BR atahpt ", " atavia " and " atapromise
have to be run as superuser/root, and need additional raw access permission. have to be run as superuser/root, and need additional raw access permission.
.sp .sp
.BR serprog ", " buspirate_spi ", " dediprog ", " usbblaster_spi ", " ft2232_spi ", " pickit2_spi ", " \ .BR serprog ", " buspirate_spi ", " dediprog ", " usbblaster_spi ", " ft2232_spi ", " pickit2_spi ", " \

View File

@ -55,6 +55,7 @@ extern const struct programmer_entry *const programmer_table[];
extern const size_t programmer_table_size; extern const size_t programmer_table_size;
/* programmer drivers */ /* programmer drivers */
extern const struct programmer_entry programmer_asm106x;
extern const struct programmer_entry programmer_atahpt; extern const struct programmer_entry programmer_atahpt;
extern const struct programmer_entry programmer_atapromise; extern const struct programmer_entry programmer_atapromise;
extern const struct programmer_entry programmer_atavia; extern const struct programmer_entry programmer_atavia;

View File

@ -156,6 +156,13 @@ linux_headers = \
# 'active' : boolean, # added on runtime # 'active' : boolean, # added on runtime
# } # }
programmer = { programmer = {
'asm106x' : {
'systems' : systems_hwaccess,
'deps' : [ libpci ],
'groups' : [ group_pci, group_internal ],
'srcs' : files('asm106x.c', 'pcidev.c'),
'flags' : [ '-DCONFIG_ASM106X=1' ],
},
'atahpt' : { 'atahpt' : {
'systems' : systems_hwaccess, 'systems' : systems_hwaccess,
'cpu_families' : cpus_port_io, 'cpu_families' : cpus_port_io,

View File

@ -10,11 +10,11 @@ option('programmer', type : 'array', value : ['auto'], choices : [
'auto', 'all', 'auto', 'all',
'group_internal', 'group_external', 'group_internal', 'group_external',
'group_ftdi', 'group_i2c', 'group_jlink', 'group_pci', 'group_serial', 'group_usb', 'group_ftdi', 'group_i2c', 'group_jlink', 'group_pci', 'group_serial', 'group_usb',
'atahpt', 'atapromise', 'atavia', 'buspirate_spi', 'ch341a_spi', 'dediprog', 'developerbox_spi', 'asm106x', 'atahpt', 'atapromise', 'atavia', 'buspirate_spi', 'ch341a_spi', 'dediprog',
'digilent_spi', 'dirtyjtag_spi', 'drkaiser', 'dummy', 'ft2232_spi', 'gfxnvidia', 'internal', 'it8212', 'developerbox_spi', 'digilent_spi', 'dirtyjtag_spi', 'drkaiser', 'dummy', 'ft2232_spi',
'jlink_spi', 'linux_mtd', 'linux_spi', 'mediatek_i2c_spi', 'mstarddc_spi', 'nic3com', 'nicintel', 'gfxnvidia', 'internal', 'it8212', 'jlink_spi', 'linux_mtd', 'linux_spi', 'mediatek_i2c_spi',
'nicintel_eeprom', 'nicintel_spi', 'nicnatsemi', 'nicrealtek', 'ogp_spi', 'parade_lspcon', 'mstarddc_spi', 'nic3com', 'nicintel', 'nicintel_eeprom', 'nicintel_spi', 'nicnatsemi',
'pickit2_spi', 'pony_spi', 'raiden_debug_spi', 'rayer_spi', 'realtek_mst_i2c_spi', 'satamv', 'nicrealtek', 'ogp_spi', 'parade_lspcon', 'pickit2_spi', 'pony_spi', 'raiden_debug_spi',
'satasii', 'serprog', 'stlinkv3_spi', 'usbblaster_spi', 'rayer_spi', 'realtek_mst_i2c_spi', 'satamv', 'satasii', 'serprog', 'stlinkv3_spi', 'usbblaster_spi',
], description: 'Active programmers') ], description: 'Active programmers')
option('llvm_cov', type : 'feature', value : 'disabled', description : 'build for llvm code coverage') option('llvm_cov', type : 'feature', value : 'disabled', description : 'build for llvm code coverage')

View File

@ -52,6 +52,10 @@ const struct programmer_entry *const programmer_table[] = {
&programmer_satasii, &programmer_satasii,
#endif #endif
#if CONFIG_ASM106X == 1
&programmer_asm106x,
#endif
#if CONFIG_ATAHPT == 1 #if CONFIG_ATAHPT == 1
&programmer_atahpt, &programmer_atahpt,
#endif #endif

View File

@ -10,7 +10,7 @@ make_programmer_opts="INTERNAL INTERNAL_X86 SERPROG RAYER_SPI RAIDEN_DEBUG_SPI P
PICKIT2_SPI STLINKV3_SPI PARADE_LSPCON MEDIATEK_I2C_SPI REALTEK_MST_I2C_SPI DUMMY \ PICKIT2_SPI STLINKV3_SPI PARADE_LSPCON MEDIATEK_I2C_SPI REALTEK_MST_I2C_SPI DUMMY \
DRKAISER NICREALTEK NICNATSEMI NICINTEL NICINTEL_SPI NICINTEL_EEPROM OGP_SPI \ DRKAISER NICREALTEK NICNATSEMI NICINTEL NICINTEL_SPI NICINTEL_EEPROM OGP_SPI \
BUSPIRATE_SPI DEDIPROG DEVELOPERBOX_SPI SATAMV LINUX_MTD LINUX_SPI IT8212 \ BUSPIRATE_SPI DEDIPROG DEVELOPERBOX_SPI SATAMV LINUX_MTD LINUX_SPI IT8212 \
CH341A_SPI DIGILENT_SPI DIRTYJTAG_SPI JLINK_SPI" CH341A_SPI DIGILENT_SPI DIRTYJTAG_SPI JLINK_SPI ASM106X"
meson_programmer_opts="all auto group_ftdi group_i2c group_jlink group_pci group_serial group_usb \ meson_programmer_opts="all auto group_ftdi group_i2c group_jlink group_pci group_serial group_usb \
atahpt atapromise atavia buspirate_spi ch341a_spi dediprog developerbox_spi \ atahpt atapromise atavia buspirate_spi ch341a_spi dediprog developerbox_spi \
@ -18,7 +18,7 @@ meson_programmer_opts="all auto group_ftdi group_i2c group_jlink group_pci group
jlink_spi linux_mtd linux_spi parade_lspcon mediatek_i2c_spi mstarddc_spi \ jlink_spi linux_mtd linux_spi parade_lspcon mediatek_i2c_spi mstarddc_spi \
nic3com nicintel nicintel_eeprom nicintel_spi nicnatsemi nicrealtek \ nic3com nicintel nicintel_eeprom nicintel_spi nicnatsemi nicrealtek \
ogp_spi pickit2_spi pony_spi raiden_debug_spi rayer_spi realtek_mst_i2c_spi \ ogp_spi pickit2_spi pony_spi raiden_debug_spi rayer_spi realtek_mst_i2c_spi \
satamv satasii serprog stlinkv3_spi usbblaster_spi" satamv satasii serprog stlinkv3_spi usbblaster_spi asm106x"
if [ "$(basename "${CC}")" = "ccc-analyzer" ] || [ -n "${COVERITY_OUTPUT}" ]; then if [ "$(basename "${CC}")" = "ccc-analyzer" ] || [ -n "${COVERITY_OUTPUT}" ]; then