1package main 2 3import ( 4 "fmt" 5 "os" 6 "strings" 7) 8 9const ( 10 PIRQI = 0 11 PIRQJ = 1 12 PIRQK = 2 13 PIRQL = 3 14 PIRQM = 4 15 PIRQN = 5 16 PIRQO = 6 17 PIRQP = 7 18 PIRQQ = 8 19 PIRQR = 9 20 PIRQS = 10 21 PIRQT = 11 22 PIRQU = 12 23 PIRQV = 13 24 PIRQW = 14 25 PIRQX = 15 26) 27 28/* from sb/intel/lynxpoint/lp_gpio.c */ 29func lp_gpio_to_pirq(gpioNum uint16) int { 30 var pirqmap = map[uint16] int { 31 8: PIRQI, 32 9: PIRQJ, 33 10: PIRQK, 34 13: PIRQL, 35 14: PIRQM, 36 45: PIRQN, 37 46: PIRQO, 38 47: PIRQP, 39 48: PIRQQ, 40 49: PIRQR, 41 50: PIRQS, 42 51: PIRQT, 43 52: PIRQU, 44 53: PIRQV, 45 54: PIRQW, 46 55: PIRQX, 47 } 48 pirq, valid := pirqmap[gpioNum] 49 if (valid) { 50 return pirq 51 } else { 52 return -1 53 } 54} 55 56func conf0str(conf0 uint32) string { 57 if (conf0 & 1) == 0 { 58 return "GPIO_MODE_NATIVE" 59 } else { 60 s := []string{"GPIO_MODE_GPIO"} 61 var gpio_output bool 62 if ((conf0 >> 2) & 1) == 1 { 63 s = append(s, "GPIO_DIR_INPUT") 64 gpio_output = false 65 } else { 66 s = append(s, "GPIO_DIR_OUTPUT") 67 gpio_output = true 68 } 69 if ((conf0 >> 3) & 1) == 1 { 70 s = append(s, "GPIO_INVERT") 71 } 72 if ((conf0 >> 4) & 1) == 1 { 73 s = append(s, "GPIO_IRQ_LEVEL") 74 } 75 if gpio_output { 76 if ((conf0 >> 31) & 1) == 1 { 77 s = append(s, "GPO_LEVEL_HIGH") 78 } else { 79 s = append(s, "GPO_LEVEL_LOW") 80 } 81 } 82 return strings.Join(s, " | ") 83 } 84} 85 86func lpgpio_preset(conf0 uint32, owner uint32, route uint32, irqen uint32, pirq uint32) string { 87 if conf0 == 0xd { /* 0b1101: MODE_GPIO | INPUT | INVERT */ 88 if owner == 0 { /* OWNER_ACPI */ 89 if irqen == 0 && pirq == 0 { 90 if route == 0 { /* SCI */ 91 return "GPIO_ACPI_SCI" 92 } else { 93 return "GPIO_ACPI_SMI" 94 } 95 } 96 return "" 97 } else { /* OWNER_GPIO */ 98 if route == 0 && irqen == 0 && pirq != 0 { 99 return "GPIO_INPUT_INVERT" 100 } 101 return "" 102 } 103 } 104 105 if conf0 == 0x5 && owner == 1 { /* 0b101: MODE_GPIO | INPUT, OWNER_GPIO */ 106 if route == 0 && irqen == 0 { 107 if pirq == 1 { 108 return "GPIO_PIRQ" 109 } else { 110 return "GPIO_INPUT" 111 } 112 } 113 return "" 114 } 115 116 if owner == 1 && irqen == 1 { 117 if route == 0 && pirq == 0 { 118 if conf0 == 0x5 { /* 0b00101 */ 119 return "GPIO_IRQ_EDGE" 120 } 121 if conf0 == 0x15 { /* 0b10101 */ 122 return "GPIO_IRQ_LEVEL" 123 } 124 } 125 return "" 126 } 127 return "" 128} 129 130func gpio_str(conf0 uint32, conf1 uint32, owner uint32, route uint32, irqen uint32, reset uint32, blink uint32, pirq uint32) string { 131 s := []string{} 132 s = append(s, fmt.Sprintf(".conf0 = %s", conf0str(conf0))) 133 if conf1 != 0 { 134 s = append(s, fmt.Sprintf(".conf1 = 0x%x", conf1)) 135 } 136 if owner != 0 { 137 s = append(s, ".owner = GPIO_OWNER_GPIO") 138 } 139 if route != 0 { 140 s = append(s, ".route = GPIO_ROUTE_SMI") 141 } 142 if irqen != 0 { 143 s = append(s, ".irqen = GPIO_IRQ_ENABLE") 144 } 145 if reset != 0 { 146 s = append(s, ".reset = GPIO_RESET_RSMRST") 147 } 148 if blink != 0 { 149 s = append(s, ".blink = GPO_BLINK") 150 } 151 if pirq != 0 { 152 s = append(s, ".pirq = GPIO_PIRQ_APIC_ROUTE") 153 } 154 return strings.Join(s, ", ") 155} 156 157/* start addresses of GPIO registers */ 158const ( 159 GPIO_OWN = 0x0 160 GPIPIRQ2IOXAPIC = 0x10 161 GPO_BLINK = 0x18 162 GPI_ROUT = 0x30 163 GP_RST_SEL = 0x60 164 GPI_IE = 0x90 165 GPnCONFIGA = 0x100 166 GPnCONFIGB = 0x104 167) 168 169func PrintLPGPIO(gpio *os.File, inteltool InteltoolData) { 170 for gpioNum := uint16(0); gpioNum <= 94; gpioNum++ { 171 if gpioNum < 10 { 172 fmt.Fprintf(gpio, "\t[%d] = ", gpioNum) 173 } else { 174 fmt.Fprintf(gpio, "\t[%d] = ", gpioNum) 175 } 176 conf0 := inteltool.GPIO[GPnCONFIGA+gpioNum*8] 177 conf1 := inteltool.GPIO[GPnCONFIGB+gpioNum*8] 178 set := gpioNum / 32 179 bit := gpioNum % 32 180 /* owner only effective in GPIO mode */ 181 owner := (inteltool.GPIO[GPIO_OWN+set*4] >> bit) & 1 182 route := (inteltool.GPIO[GPI_ROUT+set*4] >> bit) & 1 183 irqen := (inteltool.GPIO[GPI_IE+set*4] >> bit) & 1 184 reset := (inteltool.GPIO[GP_RST_SEL+set*4] >> bit) & 1 185 var blink, pirq uint32 186 /* blink only effective in GPIO output mode */ 187 if set == 0 { 188 blink = (inteltool.GPIO[GPO_BLINK] >> bit) & 1 189 } else { 190 blink = 0 191 } 192 irqset := lp_gpio_to_pirq(gpioNum) 193 if irqset >= 0 { 194 pirq = (inteltool.GPIO[GPIPIRQ2IOXAPIC] >> uint(irqset)) & 1 195 } else { 196 pirq = 0 197 } 198 199 if (conf0 & 1) == 0 { 200 fmt.Fprintf(gpio, "LP_GPIO_NATIVE,\n") 201 } else if (conf0 & 4) == 0 { 202 /* configured as output */ 203 if ((conf0 >> 31) & 1) == 0 { 204 fmt.Fprintf(gpio, "LP_GPIO_OUT_LOW,\n") 205 } else { 206 fmt.Fprintf(gpio, "LP_GPIO_OUT_HIGH,\n") 207 } 208 } else if (conf1 & 4) != 0 { 209 /* configured as input and sensing disabled */ 210 fmt.Fprintf(gpio, "LP_GPIO_UNUSED,\n") 211 } else { 212 is_preset := false 213 if conf1 == 0 && reset == 0 && blink == 0 { 214 preset := lpgpio_preset(conf0, owner, route, irqen, pirq) 215 if preset != "" { 216 fmt.Fprintf(gpio, "LP_%s,\n", preset) 217 is_preset = true 218 } 219 } 220 if !is_preset { 221 fmt.Fprintf(gpio, "{ %s },\n", gpio_str(conf0, conf1, owner, route, irqen, reset, blink, pirq)) 222 } 223 } 224 } 225} 226 227func Lynxpoint_LP_GPIO(ctx Context, inteltool InteltoolData) { 228 gpio := Create(ctx, "gpio.c") 229 defer gpio.Close() 230 231 AddROMStageFile("gpio.c", "") 232 233 Add_gpl(gpio) 234 gpio.WriteString(`#include <southbridge/intel/lynxpoint/lp_gpio.h> 235 236const struct pch_lp_gpio_map mainboard_lp_gpio_map[] = { 237`) 238 PrintLPGPIO(gpio, inteltool) 239 gpio.WriteString("\tLP_GPIO_END\n};\n") 240} 241