soc/intel/apollolake: Use common PCR module
[coreboot.git] / src / soc / intel / apollolake / itss.c
blob17b197547fe7f20dd9a88fd35506d476b73164ff
1 /*
2 * This file is part of the coreboot project.
4 * Copyright 2016 Google Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
13 * GNU General Public License for more details.
16 #include <commonlib/helpers.h>
17 #include <console/console.h>
18 #include <intelblocks/pcr.h>
19 #include <stdint.h>
20 #include <soc/itss.h>
21 #include <soc/pcr_ids.h>
23 #define ITSS_MAX_IRQ 119
24 #define IRQS_PER_IPC 32
25 #define NUM_IPC_REGS ((ITSS_MAX_IRQ + IRQS_PER_IPC - 1)/IRQS_PER_IPC)
26 #define PCR_IPC0_CONF 0x3200
28 void itss_set_irq_polarity(int irq, int active_low)
30 uint32_t mask;
31 uint16_t reg;
32 const uint16_t port = PID_ITSS;
34 if (irq < 0 || irq > ITSS_MAX_IRQ)
35 return;
37 reg = PCR_IPC0_CONF + sizeof(uint32_t) * (irq / IRQS_PER_IPC);
38 mask = 1 << (irq % IRQS_PER_IPC);
40 pcr_rmw32(port, reg, ~mask, (active_low ? mask : 0));
43 static uint32_t irq_snapshot[NUM_IPC_REGS];
45 void itss_snapshot_irq_polarities(int start, int end)
47 int i;
48 int reg_start;
49 int reg_end;
50 const uint16_t port = PID_ITSS;
52 if (start < 0 || start > ITSS_MAX_IRQ ||
53 end < 0 || end > ITSS_MAX_IRQ || end < start)
54 return;
56 reg_start = start / IRQS_PER_IPC;
57 reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
59 for (i = reg_start; i < reg_end; i++) {
60 uint16_t reg = PCR_IPC0_CONF + sizeof(uint32_t) * i;
61 irq_snapshot[i] = pcr_read32(port, reg);
65 static void show_irq_polarities(const char *msg)
67 int i;
68 const uint16_t port = PID_ITSS;
70 printk(BIOS_INFO, "ITSS IRQ Polarities %s:\n", msg);
71 for (i = 0; i < NUM_IPC_REGS; i++) {
72 uint16_t reg = PCR_IPC0_CONF + sizeof(uint32_t) * i;
73 printk(BIOS_INFO, "IPC%d: 0x%08x\n", i, pcr_read32(port, reg));
77 void itss_restore_irq_polarities(int start, int end)
79 int i;
80 int reg_start;
81 int reg_end;
82 const uint16_t port = PID_ITSS;
84 if (start < 0 || start > ITSS_MAX_IRQ ||
85 end < 0 || end > ITSS_MAX_IRQ || end < start)
86 return;
88 show_irq_polarities("Before");
90 reg_start = start / IRQS_PER_IPC;
91 reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
93 for (i = reg_start; i < reg_end; i++) {
94 uint32_t mask;
95 uint16_t reg;
96 int irq_start;
97 int irq_end;
99 irq_start = i * IRQS_PER_IPC;
100 irq_end = MIN(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ);
102 if (start > irq_end)
103 continue;
104 if (end < irq_start)
105 break;
107 /* Track bits within the bounds of of the register. */
108 irq_start = MAX(start, irq_start) % IRQS_PER_IPC;
109 irq_end = MIN(end, irq_end) % IRQS_PER_IPC;
111 /* Create bitmask of the inclusive range of start and end. */
112 mask = (((1U << irq_end) - 1) | (1U << irq_end));
113 mask &= ~((1U << irq_start) - 1);
115 reg = PCR_IPC0_CONF + sizeof(uint32_t) * i;
116 pcr_rmw32(port, reg, ~mask, (mask & irq_snapshot[i]));
119 show_irq_polarities("After");