summaryrefslogtreecommitdiff
path: root/util/autoport/lynxpoint_lp_gpio.go
diff options
context:
space:
mode:
Diffstat (limited to 'util/autoport/lynxpoint_lp_gpio.go')
-rw-r--r--util/autoport/lynxpoint_lp_gpio.go252
1 files changed, 252 insertions, 0 deletions
diff --git a/util/autoport/lynxpoint_lp_gpio.go b/util/autoport/lynxpoint_lp_gpio.go
new file mode 100644
index 00000000..fbc1686a
--- /dev/null
+++ b/util/autoport/lynxpoint_lp_gpio.go
@@ -0,0 +1,252 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+const (
+ PIRQI = 0
+ PIRQJ = 1
+ PIRQK = 2
+ PIRQL = 3
+ PIRQM = 4
+ PIRQN = 5
+ PIRQO = 6
+ PIRQP = 7
+ PIRQQ = 8
+ PIRQR = 9
+ PIRQS = 10
+ PIRQT = 11
+ PIRQU = 12
+ PIRQV = 13
+ PIRQW = 14
+ PIRQX = 15
+)
+
+/* from sb/intel/lynxpoint/lp_gpio.c */
+func lp_gpio_to_pirq(gpioNum uint16) int {
+ switch gpioNum {
+ case 8:
+ return PIRQI
+ case 9:
+ return PIRQJ
+ case 10:
+ return PIRQK
+ case 13:
+ return PIRQL
+ case 14:
+ return PIRQM
+ case 45:
+ return PIRQN
+ case 46:
+ return PIRQO
+ case 47:
+ return PIRQP
+ case 48:
+ return PIRQQ
+ case 49:
+ return PIRQR
+ case 50:
+ return PIRQS
+ case 51:
+ return PIRQT
+ case 52:
+ return PIRQU
+ case 53:
+ return PIRQV
+ case 54:
+ return PIRQW
+ case 55:
+ return PIRQX
+ default:
+ return -1
+ }
+}
+
+func conf0str(conf0 uint32) string {
+ if (conf0 & 1) == 0 {
+ return "GPIO_MODE_NATIVE"
+ } else {
+ s := []string{"GPIO_MODE_GPIO"}
+ var gpio_output bool
+ if ((conf0 >> 2) & 1) == 1 {
+ s = append(s, "GPIO_DIR_INPUT")
+ gpio_output = false
+ } else {
+ s = append(s, "GPIO_DIR_OUTPUT")
+ gpio_output = true
+ }
+ if ((conf0 >> 3) & 1) == 1 {
+ s = append(s, "GPIO_INVERT")
+ }
+ if ((conf0 >> 4) & 1) == 1 {
+ s = append(s, "GPIO_IRQ_LEVEL")
+ }
+ if gpio_output {
+ if ((conf0 >> 31) & 1) == 1 {
+ s = append(s, "GPO_LEVEL_HIGH")
+ } else {
+ s = append(s, "GPO_LEVEL_LOW")
+ }
+ }
+ return strings.Join(s, " | ")
+ }
+}
+
+func lpgpio_preset(conf0 uint32, owner uint32, route uint32, irqen uint32, pirq uint32) string {
+ if conf0 == 0xd { /* 0b1101: MODE_GPIO | INPUT | INVERT */
+ if owner == 0 { /* OWNER_ACPI */
+ if irqen == 0 && pirq == 0 {
+ if route == 0 { /* SCI */
+ return "GPIO_ACPI_SCI"
+ } else {
+ return "GPIO_ACPI_SMI"
+ }
+ }
+ return ""
+ } else { /* OWNER_GPIO */
+ if route == 0 && irqen == 0 && pirq != 0 {
+ return "GPIO_INPUT_INVERT"
+ }
+ return ""
+ }
+ }
+
+ if conf0 == 0x5 && owner == 1 { /* 0b101: MODE_GPIO | INPUT, OWNER_GPIO */
+ if route == 0 && irqen == 0 {
+ if pirq == 1 {
+ return "GPIO_PIRQ"
+ } else {
+ return "GPIO_INPUT"
+ }
+ }
+ return ""
+ }
+
+ if owner == 1 && irqen == 1 {
+ if route == 0 && pirq == 0 {
+ if conf0 == 0x5 { /* 0b00101 */
+ return "GPIO_IRQ_EDGE"
+ }
+ if conf0 == 0x15 { /* 0b10101 */
+ return "GPIO_IRQ_LEVEL"
+ }
+ }
+ return ""
+ }
+ return ""
+}
+
+func gpio_str(conf0 uint32, conf1 uint32, owner uint32, route uint32, irqen uint32, reset uint32, blink uint32, pirq uint32) string {
+ s := []string{}
+ s = append(s, fmt.Sprintf(".conf0 = %s", conf0str(conf0)))
+ if conf1 != 0 {
+ s = append(s, fmt.Sprintf(".conf1 = 0x%x", conf1))
+ }
+ if owner != 0 {
+ s = append(s, ".owner = GPIO_OWNER_GPIO")
+ }
+ if route != 0 {
+ s = append(s, ".route = GPIO_ROUTE_SMI")
+ }
+ if irqen != 0 {
+ s = append(s, ".irqen = GPIO_IRQ_ENABLE")
+ }
+ if reset != 0 {
+ s = append(s, ".reset = GPIO_RESET_RSMRST")
+ }
+ if blink != 0 {
+ s = append(s, ".blink = GPO_BLINK")
+ }
+ if pirq != 0 {
+ s = append(s, ".pirq = GPIO_PIRQ_APIC_ROUTE")
+ }
+ return strings.Join(s, ", ")
+}
+
+/* start addresses of GPIO registers */
+const (
+ GPIO_OWN = 0x0
+ GPIPIRQ2IOXAPIC = 0x10
+ GPO_BLINK = 0x18
+ GPI_ROUT = 0x30
+ GP_RST_SEL = 0x60
+ GPI_IE = 0x90
+ GPnCONFIGA = 0x100
+ GPnCONFIGB = 0x104
+)
+
+func PrintLPGPIO(gpio *os.File, inteltool InteltoolData) {
+ for gpioNum := uint16(0); gpioNum <= 94; gpioNum++ {
+ if gpioNum < 10 {
+ fmt.Fprintf(gpio, "\t[%d] = ", gpioNum)
+ } else {
+ fmt.Fprintf(gpio, "\t[%d] = ", gpioNum)
+ }
+ conf0 := inteltool.GPIO[GPnCONFIGA+gpioNum*8]
+ conf1 := inteltool.GPIO[GPnCONFIGB+gpioNum*8]
+ set := gpioNum / 32
+ bit := gpioNum % 32
+ /* owner only effective in GPIO mode */
+ owner := (inteltool.GPIO[GPIO_OWN+set*4] >> bit) & 1
+ route := (inteltool.GPIO[GPI_ROUT+set*4] >> bit) & 1
+ irqen := (inteltool.GPIO[GPI_IE+set*4] >> bit) & 1
+ reset := (inteltool.GPIO[GP_RST_SEL+set*4] >> bit) & 1
+ var blink, pirq uint32
+ /* blink only effective in GPIO output mode */
+ if set == 0 {
+ blink = (inteltool.GPIO[GPO_BLINK] >> bit) & 1
+ } else {
+ blink = 0
+ }
+ irqset := lp_gpio_to_pirq(gpioNum)
+ if irqset >= 0 {
+ pirq = (inteltool.GPIO[GPIPIRQ2IOXAPIC] >> uint(irqset)) & 1
+ } else {
+ pirq = 0
+ }
+
+ if (conf0 & 1) == 0 {
+ fmt.Fprintf(gpio, "LP_GPIO_NATIVE,\n")
+ } else if (conf0 & 4) == 0 {
+ /* configured as output */
+ if ((conf0 >> 31) & 1) == 0 {
+ fmt.Fprintf(gpio, "LP_GPIO_OUT_LOW,\n")
+ } else {
+ fmt.Fprintf(gpio, "LP_GPIO_OUT_HIGH,\n")
+ }
+ } else if (conf1 & 4) != 0 {
+ /* configured as input and sensing disabled */
+ fmt.Fprintf(gpio, "LP_GPIO_UNUSED,\n")
+ } else {
+ is_preset := false
+ if conf1 == 0 && reset == 0 && blink == 0 {
+ preset := lpgpio_preset(conf0, owner, route, irqen, pirq)
+ if preset != "" {
+ fmt.Fprintf(gpio, "LP_%s,\n", preset)
+ is_preset = true
+ }
+ }
+ if !is_preset {
+ fmt.Fprintf(gpio, "{ %s },\n", gpio_str(conf0, conf1, owner, route, irqen, reset, blink, pirq))
+ }
+ }
+ }
+}
+
+func Lynxpoint_LP_GPIO(ctx Context, inteltool InteltoolData) {
+ gpio := Create(ctx, "gpio.c")
+ defer gpio.Close()
+
+ AddROMStageFile("gpio.c", "")
+
+ Add_gpl(gpio)
+ gpio.WriteString(`#include <southbridge/intel/lynxpoint/lp_gpio.h>
+
+const struct pch_lp_gpio_map mainboard_lp_gpio_map[] = {
+`)
+ PrintLPGPIO(gpio, inteltool)
+ gpio.WriteString("\tLP_GPIO_END\n};\n")
+}