@ -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 )