summaryrefslogtreecommitdiff
path: root/arch/x86/cpu/intel_common/itss.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-07-16 21:22:30 -0600
committerBin Meng <bmeng.cn@gmail.com>2020-07-17 14:32:24 +0800
commitb95611f67e709f8c98c1a31714dc941d436c0d5c (patch)
treee83c7d924f0f22e3d2e5c4feee61442b0f23435c /arch/x86/cpu/intel_common/itss.c
parenta8c2789c09681660bfdbda489e504d12b0ab74b5 (diff)
x86: apl: Fix save/restore of ITSS priorities
The FSP-S changes the ITSS priorities. The code that tries to save it before running FSP-S and restore it afterwards does not work as U-Boot relocates in between the save and restore. This means that the driver data saved before relocation is lost and the new driver just sees zeroes. Fix this by allocating space in the relocated memory for the ITSS data. Save it there and access it from the driver after relocation. This fixes interrupt handling on coral. Also drop the log_msg_ret() in irq_first_device_type() since this function can be called speculatively in places where we are not sure if there is an interrupt controller of that type. The resulting log errors are confusing when there is no error. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com>
Diffstat (limited to 'arch/x86/cpu/intel_common/itss.c')
-rw-r--r--arch/x86/cpu/intel_common/itss.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/arch/x86/cpu/intel_common/itss.c b/arch/x86/cpu/intel_common/itss.c
index 963afa8f5be..fe84ebe29f7 100644
--- a/arch/x86/cpu/intel_common/itss.c
+++ b/arch/x86/cpu/intel_common/itss.c
@@ -65,14 +65,23 @@ static int snapshot_polarities(struct udevice *dev)
int i;
reg_start = start / IRQS_PER_IPC;
- reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+ reg_end = DIV_ROUND_UP(end, IRQS_PER_IPC);
+ log_info("ITSS IRQ Polarities snapshot %p\n", priv->irq_snapshot);
for (i = reg_start; i < reg_end; i++) {
uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
priv->irq_snapshot[i] = pcr_read32(dev, reg);
+ log_debug(" - %d, reg %x: irq_snapshot[i] %x\n", i, reg,
+ priv->irq_snapshot[i]);
}
+ /* Save the snapshot for use after relocation */
+ gd->start_addr_sp -= sizeof(*priv);
+ gd->start_addr_sp &= ~0xf;
+ gd->arch.itss_priv = (void *)gd->start_addr_sp;
+ memcpy(gd->arch.itss_priv, priv, sizeof(*priv));
+
return 0;
}
@@ -91,16 +100,26 @@ static void show_polarities(struct udevice *dev, const char *msg)
static int restore_polarities(struct udevice *dev)
{
struct itss_priv *priv = dev_get_priv(dev);
+ struct itss_priv *old_priv;
const int start = GPIO_IRQ_START;
const int end = GPIO_IRQ_END;
int reg_start;
int reg_end;
int i;
+ /* Get the snapshot which was stored by the pre-reloc device */
+ old_priv = gd->arch.itss_priv;
+ if (!old_priv)
+ return log_msg_ret("priv", -EFAULT);
+ memcpy(priv->irq_snapshot, old_priv->irq_snapshot,
+ sizeof(priv->irq_snapshot));
+
show_polarities(dev, "Before");
+ log_info("priv->irq_snapshot %p\n", priv->irq_snapshot);
reg_start = start / IRQS_PER_IPC;
- reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+ reg_end = DIV_ROUND_UP(end, IRQS_PER_IPC);
+
for (i = reg_start; i < reg_end; i++) {
u32 mask;
@@ -125,6 +144,8 @@ static int restore_polarities(struct udevice *dev)
mask &= ~((1U << irq_start) - 1);
reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i;
+ log_debug(" - %d, reg %x: mask %x, irq_snapshot[i] %x\n",
+ i, reg, mask, priv->irq_snapshot[i]);
pcr_clrsetbits32(dev, reg, mask, mask & priv->irq_snapshot[i]);
}