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>
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
)
32 const uint16_t port
= PID_ITSS
;
34 if (irq
< 0 || irq
> ITSS_MAX_IRQ
)
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
)
50 const uint16_t port
= PID_ITSS
;
52 if (start
< 0 || start
> ITSS_MAX_IRQ
||
53 end
< 0 || end
> ITSS_MAX_IRQ
|| end
< start
)
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
)
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
)
82 const uint16_t port
= PID_ITSS
;
84 if (start
< 0 || start
> ITSS_MAX_IRQ
||
85 end
< 0 || end
> ITSS_MAX_IRQ
|| end
< start
)
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
++) {
99 irq_start
= i
* IRQS_PER_IPC
;
100 irq_end
= MIN(irq_start
+ IRQS_PER_IPC
- 1, ITSS_MAX_IRQ
);
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");