mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
x86: spi: Support ValleyView in ICH SPI driver
The base address is found in a different way and the protection bit is also in a different place. Otherwise it is very similar. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
447f8b018e
commit
5093badbb5
2 changed files with 47 additions and 20 deletions
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <spi.h>
|
||||
#include <pci.h>
|
||||
|
@ -21,6 +22,7 @@
|
|||
struct ich_ctlr {
|
||||
pci_dev_t dev; /* PCI device number */
|
||||
int ich_version; /* Controller version, 7 or 9 */
|
||||
bool use_sbase; /* Use SBASE instead of RCB */
|
||||
int ichspi_lock;
|
||||
int locked;
|
||||
uint8_t *opmenu;
|
||||
|
@ -145,7 +147,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
|
|||
* ICH 7 SPI controller only supports array read command
|
||||
* and byte program command for SST flash
|
||||
*/
|
||||
if (ctlr.ich_version == 7) {
|
||||
if (ctlr.ich_version == 7 || ctlr.use_sbase) {
|
||||
ich->slave.op_mode_rx = SPI_OPM_RX_AS;
|
||||
ich->slave.op_mode_tx = SPI_OPM_TX_BP;
|
||||
}
|
||||
|
@ -181,7 +183,8 @@ static int get_ich_version(uint16_t device_id)
|
|||
if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
|
||||
device_id <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) ||
|
||||
(device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN &&
|
||||
device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX))
|
||||
device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX) ||
|
||||
device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
|
||||
return 9;
|
||||
|
||||
return 0;
|
||||
|
@ -204,14 +207,14 @@ static int ich9_can_do_33mhz(pci_dev_t dev)
|
|||
return speed == 1;
|
||||
}
|
||||
|
||||
static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
|
||||
static int ich_find_spi_controller(struct ich_ctlr *ich)
|
||||
{
|
||||
int last_bus = pci_last_busno();
|
||||
int bus;
|
||||
|
||||
if (last_bus == -1) {
|
||||
debug("No PCI busses?\n");
|
||||
return -1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (bus = 0; bus <= last_bus; bus++) {
|
||||
|
@ -225,24 +228,33 @@ static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
|
|||
device_id = ids >> 16;
|
||||
|
||||
if (vendor_id == PCI_VENDOR_ID_INTEL) {
|
||||
*devp = dev;
|
||||
*ich_versionp = get_ich_version(device_id);
|
||||
return 0;
|
||||
ich->dev = dev;
|
||||
ich->ich_version = get_ich_version(device_id);
|
||||
if (device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC)
|
||||
ich->use_sbase = true;
|
||||
return ich->ich_version == 0 ? -ENODEV : 0;
|
||||
}
|
||||
}
|
||||
|
||||
debug("ICH SPI: No ICH found.\n");
|
||||
return -1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int ich_init_controller(struct ich_ctlr *ctlr)
|
||||
{
|
||||
uint8_t *rcrb; /* Root Complex Register Block */
|
||||
uint32_t rcba; /* Root Complex Base Address */
|
||||
uint32_t sbase_addr;
|
||||
uint8_t *sbase;
|
||||
|
||||
pci_read_config_dword(ctlr->dev, 0xf0, &rcba);
|
||||
/* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */
|
||||
rcrb = (uint8_t *)(rcba & 0xffffc000);
|
||||
|
||||
/* SBASE is similar */
|
||||
pci_read_config_dword(ctlr->dev, 0x54, &sbase_addr);
|
||||
sbase = (uint8_t *)(sbase_addr & 0xfffffe00);
|
||||
|
||||
if (ctlr->ich_version == 7) {
|
||||
struct ich7_spi_regs *ich7_spi;
|
||||
|
||||
|
@ -262,7 +274,10 @@ static int ich_init_controller(struct ich_ctlr *ctlr)
|
|||
} else if (ctlr->ich_version == 9) {
|
||||
struct ich9_spi_regs *ich9_spi;
|
||||
|
||||
ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
|
||||
if (ctlr->use_sbase)
|
||||
ich9_spi = (struct ich9_spi_regs *)sbase;
|
||||
else
|
||||
ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
|
||||
ctlr->ichspi_lock = ich_readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
|
||||
ctlr->opmenu = ich9_spi->opmenu;
|
||||
ctlr->menubytes = sizeof(ich9_spi->opmenu);
|
||||
|
@ -282,12 +297,13 @@ static int ich_init_controller(struct ich_ctlr *ctlr)
|
|||
ctlr->ich_version);
|
||||
return -1;
|
||||
}
|
||||
debug("ICH SPI: Version %d detected\n", ctlr->ich_version);
|
||||
|
||||
/* Work out the maximum speed we can support */
|
||||
ctlr->max_speed = 20000000;
|
||||
if (ctlr->ich_version == 9 && ich9_can_do_33mhz(ctlr->dev))
|
||||
ctlr->max_speed = 33000000;
|
||||
debug("ICH SPI: Version %d detected at %p, speed %ld\n",
|
||||
ctlr->ich_version, ctlr->base, ctlr->max_speed);
|
||||
|
||||
ich_set_bbar(ctlr, 0);
|
||||
|
||||
|
@ -298,7 +314,7 @@ void spi_init(void)
|
|||
{
|
||||
uint8_t bios_cntl;
|
||||
|
||||
if (ich_find_spi_controller(&ctlr.dev, &ctlr.ich_version)) {
|
||||
if (ich_find_spi_controller(&ctlr)) {
|
||||
printf("ICH SPI: Cannot find device\n");
|
||||
return;
|
||||
}
|
||||
|
@ -312,10 +328,20 @@ void spi_init(void)
|
|||
* Disable the BIOS write protect so write commands are allowed. On
|
||||
* v9, deassert SMM BIOS Write Protect Disable.
|
||||
*/
|
||||
pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
|
||||
if (ctlr.ich_version == 9)
|
||||
bios_cntl &= ~(1 << 5);
|
||||
pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
|
||||
if (ctlr.use_sbase) {
|
||||
struct ich9_spi_regs *ich9_spi;
|
||||
|
||||
ich9_spi = (struct ich9_spi_regs *)ctlr.base;
|
||||
bios_cntl = ich_readb(&ich9_spi->bcr);
|
||||
bios_cntl &= ~(1 << 5); /* clear Enable InSMM_STS (EISS) */
|
||||
bios_cntl |= 1; /* Write Protect Disable (WPD) */
|
||||
ich_writeb(bios_cntl, &ich9_spi->bcr);
|
||||
} else {
|
||||
pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
|
||||
if (ctlr.ich_version == 9)
|
||||
bios_cntl &= ~(1 << 5);
|
||||
pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
|
||||
}
|
||||
}
|
||||
|
||||
int spi_claim_bus(struct spi_slave *slave)
|
||||
|
|
|
@ -37,18 +37,19 @@ struct ich9_spi_regs {
|
|||
uint8_t opmenu[8]; /* 0x98 */
|
||||
uint32_t bbar;
|
||||
uint8_t _reserved3[12];
|
||||
uint32_t fdoc;
|
||||
uint32_t fdoc; /* 0xb0 */
|
||||
uint32_t fdod;
|
||||
uint8_t _reserved4[8];
|
||||
uint32_t afc;
|
||||
uint32_t afc; /* 0xc0 */
|
||||
uint32_t lvscc;
|
||||
uint32_t uvscc;
|
||||
uint8_t _reserved5[4];
|
||||
uint32_t fpb;
|
||||
uint32_t fpb; /* 0xd0 */
|
||||
uint8_t _reserved6[28];
|
||||
uint32_t srdl;
|
||||
uint32_t srdl; /* 0xf0 */
|
||||
uint32_t srdc;
|
||||
uint32_t srd;
|
||||
uint32_t scs;
|
||||
uint32_t bcr;
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
|
|
Loading…
Reference in a new issue