2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <commonlib/helpers.h>
17 #include <console/console.h>
18 #include <intelblocks/itss.h>
19 #include <intelblocks/pcr.h>
21 #include <soc/pcr_ids.h>
23 void itss_irq_init(uint8_t pch_interrupt_routing
[MAX_PXRC_CONFIG
])
25 uint32_t regs
[MAX_PXRC_CONFIG
/sizeof(uint32_t)] = {0};
28 /* Fill in all the PIRx routes into one array. */
29 for (index
= 0; index
< ARRAY_SIZE(regs
); index
++) {
30 for (byte
= 0; byte
< sizeof(uint32_t); byte
++) {
31 uint8_t val
= pch_interrupt_routing
[index
*
32 sizeof(uint32_t) + byte
];
33 uint8_t irq
= val
& 0xf;
35 if ((irq
<= 2) || (irq
== 8) || (irq
== 13))
36 regs
[index
] |= (0x80 << (8 * byte
));
38 regs
[index
] |= (val
<< (8 * byte
));
40 /* Access the routing register in 32 bit mode to make this
41 function suitable for both IOSF 1.0 (where only 32 bit access
42 is supported) and later versions of the interface. */
44 PCR_ITSS_PIRQA_ROUT
+ (index
* sizeof(uint32_t)),
49 void itss_clock_gate_8254(void)
51 const uint32_t cge8254_mask
= (1 << 2);
53 pcr_rmw32(PID_ITSS
, PCR_ITSS_ITSSPRC
, ~cge8254_mask
, cge8254_mask
);
56 void itss_set_irq_polarity(int irq
, int active_low
)
60 const uint16_t port
= PID_ITSS
;
62 if (irq
< 0 || irq
> ITSS_MAX_IRQ
)
65 reg
= PCR_ITSS_IPC0_CONF
+ sizeof(uint32_t) * (irq
/ IRQS_PER_IPC
);
66 mask
= 1 << (irq
% IRQS_PER_IPC
);
68 pcr_rmw32(port
, reg
, ~mask
, (active_low
? mask
: 0));
71 static uint32_t irq_snapshot
[NUM_IPC_REGS
];
73 void itss_snapshot_irq_polarities(int start
, int end
)
78 const uint16_t port
= PID_ITSS
;
80 if (start
< 0 || start
> ITSS_MAX_IRQ
||
81 end
< 0 || end
> ITSS_MAX_IRQ
|| end
< start
)
84 reg_start
= start
/ IRQS_PER_IPC
;
85 reg_end
= (end
+ IRQS_PER_IPC
- 1) / IRQS_PER_IPC
;
87 for (i
= reg_start
; i
< reg_end
; i
++) {
88 uint16_t reg
= PCR_ITSS_IPC0_CONF
+ sizeof(uint32_t) * i
;
89 irq_snapshot
[i
] = pcr_read32(port
, reg
);
93 static void show_irq_polarities(const char *msg
)
96 const uint16_t port
= PID_ITSS
;
98 printk(BIOS_INFO
, "ITSS IRQ Polarities %s:\n", msg
);
99 for (i
= 0; i
< NUM_IPC_REGS
; i
++) {
100 uint16_t reg
= PCR_ITSS_IPC0_CONF
+ sizeof(uint32_t) * i
;
101 printk(BIOS_INFO
, "IPC%d: 0x%08x\n", i
, pcr_read32(port
, reg
));
105 void itss_restore_irq_polarities(int start
, int end
)
110 const uint16_t port
= PID_ITSS
;
112 if (start
< 0 || start
> ITSS_MAX_IRQ
||
113 end
< 0 || end
> ITSS_MAX_IRQ
|| end
< start
)
116 show_irq_polarities("Before");
118 reg_start
= start
/ IRQS_PER_IPC
;
119 reg_end
= (end
+ IRQS_PER_IPC
- 1) / IRQS_PER_IPC
;
121 for (i
= reg_start
; i
< reg_end
; i
++) {
127 irq_start
= i
* IRQS_PER_IPC
;
128 irq_end
= MIN(irq_start
+ IRQS_PER_IPC
- 1, ITSS_MAX_IRQ
);
135 /* Track bits within the bounds of of the register. */
136 irq_start
= MAX(start
, irq_start
) % IRQS_PER_IPC
;
137 irq_end
= MIN(end
, irq_end
) % IRQS_PER_IPC
;
139 /* Create bitmask of the inclusive range of start and end. */
140 mask
= (((1U << irq_end
) - 1) | (1U << irq_end
));
141 mask
&= ~((1U << irq_start
) - 1);
143 reg
= PCR_ITSS_IPC0_CONF
+ sizeof(uint32_t) * i
;
144 pcr_rmw32(port
, reg
, ~mask
, (mask
& irq_snapshot
[i
]));
147 show_irq_polarities("After");