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 const struct pch_lp_gpio_map mainboard_lp_gpio_map[] = { `) PrintLPGPIO(gpio, inteltool) gpio.WriteString("\tLP_GPIO_END\n};\n") }