soc/intel/common/block/pcr: Add function for executing PCH SBI message
This function performs SBI communication Input: * PID: Port ID of the SBI message * Offset: Register offset of the SBI message * Opcode: Opcode * Posted: Posted message * Fast_Byte_Enable: First Byte Enable * BAR: base address * FID: Function ID * Data: Read/Write Data * Response: Response Output: * 0: SBI message is successfully completed * -1: SBI message failure Change-Id: I4e49311564e20cedbfabaaceaf5f72c480e5ea26 Signed-off-by: Subrata Banik <subrata.banik@intel.com> Reviewed-on: https://review.coreboot.org/23809 Reviewed-by: Furquan Shaikh <furquan@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
5f1da55b49
commit
736a03fd24
|
@ -38,6 +38,47 @@ void pcr_or32(uint8_t pid, uint16_t offset, uint32_t ordata);
|
||||||
void pcr_or16(uint8_t pid, uint16_t offset, uint16_t ordata);
|
void pcr_or16(uint8_t pid, uint16_t offset, uint16_t ordata);
|
||||||
void pcr_or8(uint8_t pid, uint16_t offset, uint8_t ordata);
|
void pcr_or8(uint8_t pid, uint16_t offset, uint8_t ordata);
|
||||||
|
|
||||||
|
/* SBI command */
|
||||||
|
enum {
|
||||||
|
MEM_READ = 0,
|
||||||
|
MEM_WRITE = 1,
|
||||||
|
PCI_CONFIG_READ = 4,
|
||||||
|
PCI_CONFIG_WRITE = 5,
|
||||||
|
PCR_READ = 6,
|
||||||
|
PCR_WRITE = 7,
|
||||||
|
GPIO_LOCK_UNLOCK = 13,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pcr_sbi_msg {
|
||||||
|
uint8_t pid; /* 0x00 - Port ID of the SBI message */
|
||||||
|
uint32_t offset; /* 0x01 - Register offset of the SBI message */
|
||||||
|
uint8_t opcode; /* 0x05 - Opcode */
|
||||||
|
bool is_posted; /* 0x06 - Posted message */
|
||||||
|
uint16_t fast_byte_enable; /* 0x07 - First Byte Enable */
|
||||||
|
uint16_t bar; /* 0x09 - base address */
|
||||||
|
uint16_t fid; /* 0x0B - Function ID */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* API to perform sideband communication
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* struct pcr_sbi_msg
|
||||||
|
* data - read/write for sbi message
|
||||||
|
* response -
|
||||||
|
* 0 - successful
|
||||||
|
* 1 - unsuccessful
|
||||||
|
* 2 - powered down
|
||||||
|
* 3 - multi-cast mixed
|
||||||
|
*
|
||||||
|
* Output:
|
||||||
|
* 0: SBI message is successfully completed
|
||||||
|
* -1: SBI message failure
|
||||||
|
*/
|
||||||
|
int pcr_execute_sideband_msg(struct pcr_sbi_msg *msg, uint32_t *data,
|
||||||
|
uint8_t *response);
|
||||||
|
|
||||||
/* Get the starting address of the port's registers. */
|
/* Get the starting address of the port's registers. */
|
||||||
void *pcr_reg_address(uint8_t pid, uint16_t offset);
|
void *pcr_reg_address(uint8_t pid, uint16_t offset);
|
||||||
#endif /* if !defined(__ACPI__) */
|
#endif /* if !defined(__ACPI__) */
|
||||||
|
|
|
@ -15,13 +15,53 @@
|
||||||
|
|
||||||
#include <arch/io.h>
|
#include <arch/io.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <console/console.h>
|
||||||
#include <intelblocks/pcr.h>
|
#include <intelblocks/pcr.h>
|
||||||
|
#include <soc/pci_devs.h>
|
||||||
#include <soc/pcr_ids.h>
|
#include <soc/pcr_ids.h>
|
||||||
|
#include <timer.h>
|
||||||
|
|
||||||
#if !defined(CONFIG_PCR_BASE_ADDRESS) || (CONFIG_PCR_BASE_ADDRESS == 0)
|
#if !defined(CONFIG_PCR_BASE_ADDRESS) || (CONFIG_PCR_BASE_ADDRESS == 0)
|
||||||
#error "PCR_BASE_ADDRESS need to be non-zero!"
|
#error "PCR_BASE_ADDRESS need to be non-zero!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !IS_ENABLED(CONFIG_PCR_COMMON_IOSF_1_0)
|
||||||
|
|
||||||
|
#define PCR_SBI_CMD_TIMEOUT 10 /* 10ms */
|
||||||
|
|
||||||
|
/* P2SB PCI configuration register */
|
||||||
|
#define P2SB_CR_SBI_ADDR 0xd0
|
||||||
|
#define P2SB_CR_SBI_DESTID 24
|
||||||
|
#define P2SB_CR_SBI_DATA 0xd4
|
||||||
|
#define P2SB_CR_SBI_STATUS 0xd8
|
||||||
|
/* Bit 15:8 */
|
||||||
|
#define P2SB_CR_SBI_OPCODE 8
|
||||||
|
#define P2SB_CR_SBI_OPCODE_MASK 0xFF00
|
||||||
|
/* Bit 7 */
|
||||||
|
#define P2SB_CR_SBI_POSTED 7
|
||||||
|
#define P2SB_CR_SBI_POSTED_MASK 0x0080
|
||||||
|
/* Bit 2-1 */
|
||||||
|
#define P2SB_CR_SBI_STATUS_MASK 0x0006
|
||||||
|
#define P2SB_CR_SBI_STATUS_SUCCESS 0
|
||||||
|
#define P2SB_CR_SBI_STATUS_NOT_SUPPORTED 1
|
||||||
|
#define P2SB_CR_SBI_STATUS_POWERED_DOWN 2
|
||||||
|
#define P2SB_CR_SBI_STATUS_MULTI_CAST_MIXED 3
|
||||||
|
/* Bit 0 */
|
||||||
|
#define P2SB_CR_SBI_STATUS_READY 0
|
||||||
|
#define P2SB_CR_SBI_STATUS_BUSY 1
|
||||||
|
#define P2SB_CR_SBI_ROUTE_IDEN 0xda
|
||||||
|
/* Bit 15-12 */
|
||||||
|
#define P2SB_CR_SBI_FBE 12
|
||||||
|
#define P2SB_CR_SBI_FBE_MASK 0xF
|
||||||
|
/* Bit 10-8 */
|
||||||
|
#define P2SB_CR_SBI_BAR 8
|
||||||
|
#define P2SB_CR_SBI_MASK 0x7
|
||||||
|
/* Bit 7-0 */
|
||||||
|
#define P2SB_CR_SBI_FID 0
|
||||||
|
#define P2SB_CR_SBI_FID_MASK 0xFF
|
||||||
|
#define P2SB_CR_SBI_EXT_ADDR 0xdc
|
||||||
|
#endif
|
||||||
|
|
||||||
static void *__pcr_reg_address(uint8_t pid, uint16_t offset)
|
static void *__pcr_reg_address(uint8_t pid, uint16_t offset)
|
||||||
{
|
{
|
||||||
uintptr_t reg_addr;
|
uintptr_t reg_addr;
|
||||||
|
@ -178,3 +218,172 @@ void pcr_or8(uint8_t pid, uint16_t offset, uint8_t ordata)
|
||||||
data8 |= ordata;
|
data8 |= ordata;
|
||||||
pcr_write8(pid, offset, data8);
|
pcr_write8(pid, offset, data8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !IS_ENABLED(CONFIG_PCR_COMMON_IOSF_1_0)
|
||||||
|
|
||||||
|
static int pcr_wait_for_completion(device_t dev)
|
||||||
|
{
|
||||||
|
struct stopwatch sw;
|
||||||
|
|
||||||
|
stopwatch_init_msecs_expire(&sw, PCR_SBI_CMD_TIMEOUT);
|
||||||
|
do {
|
||||||
|
if ((pci_read_config16(dev, P2SB_CR_SBI_STATUS) &
|
||||||
|
P2SB_CR_SBI_STATUS_BUSY) == 0)
|
||||||
|
return 0;
|
||||||
|
} while (!stopwatch_expired(&sw));
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* API to perform sideband communication
|
||||||
|
*
|
||||||
|
* Input:
|
||||||
|
* struct pcr_sbi_msg
|
||||||
|
* data - read/write for sbi message
|
||||||
|
* response -
|
||||||
|
* 0 - successful
|
||||||
|
* 1 - unsuccessful
|
||||||
|
* 2 - powered down
|
||||||
|
* 3 - multi-cast mixed
|
||||||
|
*
|
||||||
|
* Output:
|
||||||
|
* 0: SBI message is successfully completed
|
||||||
|
* -1: SBI message failure
|
||||||
|
*/
|
||||||
|
int pcr_execute_sideband_msg(struct pcr_sbi_msg *msg, uint32_t *data,
|
||||||
|
uint8_t *response)
|
||||||
|
{
|
||||||
|
device_t dev = PCH_DEV_P2SB;
|
||||||
|
uint32_t sbi_data;
|
||||||
|
uint16_t sbi_status;
|
||||||
|
uint16_t sbi_rid;
|
||||||
|
|
||||||
|
assert(msg && data && response);
|
||||||
|
|
||||||
|
switch (msg->opcode) {
|
||||||
|
case MEM_READ:
|
||||||
|
case MEM_WRITE:
|
||||||
|
case PCI_CONFIG_READ:
|
||||||
|
case PCI_CONFIG_WRITE:
|
||||||
|
case PCR_READ:
|
||||||
|
case PCR_WRITE:
|
||||||
|
case GPIO_LOCK_UNLOCK:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printk(BIOS_ERR, "SBI Failure: Wrong Input!\n");
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pci_read_config16(dev, PCI_VENDOR_ID) == 0xffff) {
|
||||||
|
printk(BIOS_ERR, "SBI Failure: P2SB device Hidden!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BWG Section 2.2.1
|
||||||
|
* 1. Poll P2SB PCI offset D8h[0] = 0b
|
||||||
|
* Make sure the previous operation is completed.
|
||||||
|
*/
|
||||||
|
if (pcr_wait_for_completion(dev)) {
|
||||||
|
printk(BIOS_ERR, "SBI Failure: Time Out!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initial Response status */
|
||||||
|
*response = P2SB_CR_SBI_STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2. Write P2SB PCI offset D0h[31:0] with Address
|
||||||
|
* and Destination Port ID
|
||||||
|
*/
|
||||||
|
pci_write_config32(dev, P2SB_CR_SBI_ADDR,
|
||||||
|
(msg->pid << P2SB_CR_SBI_DESTID) | msg->offset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 3. Write P2SB PCI offset DCh[31:0] with extended address,
|
||||||
|
* which is expected to be 0
|
||||||
|
*/
|
||||||
|
pci_write_config32(dev, P2SB_CR_SBI_EXT_ADDR, msg->offset >> 16);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 4. Set P2SB PCI offset D8h[15:8] = 00000110b for read
|
||||||
|
* Set P2SB PCI offset D8h[15:8] = 00000111b for write
|
||||||
|
*
|
||||||
|
* Set SBISTAT[15:8] to the opcode passed in
|
||||||
|
* Set SBISTAT[7] to the posted passed in
|
||||||
|
*/
|
||||||
|
sbi_status = pci_read_config16(dev, P2SB_CR_SBI_STATUS);
|
||||||
|
sbi_status &= ~(P2SB_CR_SBI_OPCODE_MASK | P2SB_CR_SBI_POSTED_MASK);
|
||||||
|
sbi_status |= (msg->opcode << P2SB_CR_SBI_OPCODE) |
|
||||||
|
(msg->is_posted << P2SB_CR_SBI_POSTED);
|
||||||
|
pci_write_config16(dev, P2SB_CR_SBI_STATUS, sbi_status);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 5. Write P2SB PCI offset DAh[15:0] = F000h
|
||||||
|
*
|
||||||
|
* Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
|
||||||
|
*/
|
||||||
|
sbi_rid = ((msg->fast_byte_enable & P2SB_CR_SBI_FBE_MASK)
|
||||||
|
<< P2SB_CR_SBI_FBE) |
|
||||||
|
((msg->bar & P2SB_CR_SBI_MASK) << P2SB_CR_SBI_BAR) |
|
||||||
|
(msg->fid & P2SB_CR_SBI_FID_MASK);
|
||||||
|
pci_write_config16(dev, P2SB_CR_SBI_ROUTE_IDEN, sbi_rid);
|
||||||
|
|
||||||
|
switch (msg->opcode) {
|
||||||
|
case MEM_WRITE:
|
||||||
|
case PCI_CONFIG_WRITE:
|
||||||
|
case PCR_WRITE:
|
||||||
|
/*
|
||||||
|
* 6. Write P2SB PCI offset D4h[31:0] with the
|
||||||
|
* intended data accordingly
|
||||||
|
*/
|
||||||
|
sbi_data = *data;
|
||||||
|
pci_write_config32(dev, P2SB_CR_SBI_DATA, sbi_data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* 6. Write P2SB PCI offset D4h[31:0] with dummy data */
|
||||||
|
pci_write_config32(dev, P2SB_CR_SBI_DATA, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
|
||||||
|
*
|
||||||
|
* Set SBISTAT[0] = 1b, trigger the SBI operation
|
||||||
|
*/
|
||||||
|
sbi_status = pci_read_config16(dev, P2SB_CR_SBI_STATUS);
|
||||||
|
sbi_status |= P2SB_CR_SBI_STATUS_BUSY;
|
||||||
|
pci_write_config16(dev, P2SB_CR_SBI_STATUS, sbi_status);
|
||||||
|
|
||||||
|
/* Poll SBISTAT[0] = 0b, Polling for Busy bit */
|
||||||
|
if (pcr_wait_for_completion(dev)) {
|
||||||
|
printk(BIOS_ERR, "SBI Failure: Time Out!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 8. Check if P2SB PCI offset D8h[2:1] = 00b for
|
||||||
|
* successful transaction
|
||||||
|
*/
|
||||||
|
*response = (sbi_status & P2SB_CR_SBI_STATUS_MASK) >> 1;
|
||||||
|
if (*response == P2SB_CR_SBI_STATUS_SUCCESS) {
|
||||||
|
switch (msg->opcode) {
|
||||||
|
case MEM_READ:
|
||||||
|
case PCI_CONFIG_READ:
|
||||||
|
case PCR_READ:
|
||||||
|
sbi_data = pci_read_config32(dev, P2SB_CR_SBI_DATA);
|
||||||
|
*data = sbi_data;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
printk(BIOS_ERR, "SBI Failure: Transaction Status = %x\n",
|
||||||
|
*response);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue