void gpio_set_level(enum gpio_signal signal, int value) { uint32_t mask = gpio_list[signal].mask; int i; if (mask == 0) return; i = GPIO_MASK_TO_NUM(mask); if (value) MEC1322_GPIO_CTL(gpio_list[signal].port, i) |= (1 << 16); else MEC1322_GPIO_CTL(gpio_list[signal].port, i) &= ~(1 << 16); }
void gpio_set_alternate_function(uint32_t port, uint32_t mask, int func) { int i; uint32_t val; while (mask) { i = __builtin_ffs(mask) - 1; val = MEC1322_GPIO_CTL(port, i); val &= ~((1 << 12) | (1 << 13)); val |= (func & 0x3) << 12; MEC1322_GPIO_CTL(port, i) = val; mask &= ~(1 << i); } }
static void system_unpower_gpio(void) { int i, j, k; uint32_t val; int want_skip; const int pins[16][2] = {{0, 7}, {1, 7}, {2, 7}, {3, 6}, {4, 7}, {5, 7}, {6, 7}, {10, 7}, {11, 7}, {12, 7}, {13, 6}, {14, 7}, {15, 7}, {16, 5}, {20, 6}, {21, 1} }; const int skip[5][2] = {{13, 1}, /* VCC1_nRST */ {6, 3}, /* VCC_PWRGD */ {12, 1}, /* nRESET_OUT */ {14, 3}, /* RSMRST# */ {20, 5}, /* Not exist */ }; for (i = 0; i < 16; ++i) { for (j = 0; j <= pins[i][1]; ++j) { want_skip = 0; for (k = 0; k < 5; ++k) if (skip[k][0] == pins[i][0] && skip[k][1] == j) want_skip = 1; if (want_skip) continue; /* * GPIO Input, pull-high, interrupt disabled * TODO(crosbug.com/p/25302): Unpower GPIO instead of * setting them to be input. */ val = MEC1322_GPIO_CTL(pins[i][0], j); val &= ~((1 << 12) | (1 << 13)); val &= ~(1 << 9); val = (val & ~(0xf << 4)) | (0x4 << 4); val = (val & ~0x3) | 0x1; MEC1322_GPIO_CTL(pins[i][0], j) = val; } } }
test_mockable int gpio_get_level(enum gpio_signal signal) { uint32_t mask = gpio_list[signal].mask; int i; uint32_t val; if (mask == 0) return 0; i = GPIO_MASK_TO_NUM(mask); val = MEC1322_GPIO_CTL(gpio_list[signal].port, i); return (val & (1 << 24)) ? 1 : 0; }
void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) { int i; uint32_t val; while (mask) { i = GPIO_MASK_TO_NUM(mask); mask &= ~(1 << i); val = MEC1322_GPIO_CTL(port, i); /* * Select open drain first, so that we don't glitch the signal * when changing the line to an output. */ if (flags & GPIO_OPEN_DRAIN) val |= (1 << 8); else val &= ~(1 << 8); if (flags & GPIO_OUTPUT) { val |= (1 << 9); val &= ~(1 << 10); } else { val &= ~(1 << 9); val |= (1 << 10); } /* Handle pullup / pulldown */ if (flags & GPIO_PULL_UP) val = (val & ~0x3) | 0x1; else if (flags & GPIO_PULL_DOWN) val = (val & ~0x3) | 0x2; else val &= ~0x3; /* Set up interrupt */ if (flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)) val |= (1 << 7); else val &= ~(1 << 7); val &= ~(0x7 << 4); if ((flags & GPIO_INT_F_RISING) && (flags & GPIO_INT_F_FALLING)) val |= 0x7 << 4; else if (flags & GPIO_INT_F_RISING) val |= 0x5 << 4; else if (flags & GPIO_INT_F_FALLING) val |= 0x6 << 4; else if (flags & GPIO_INT_F_HIGH) val |= 0x1 << 4; else if (!(flags & GPIO_INT_F_LOW)) /* No interrupt flag set */ val |= 0x4 << 4; /* Set up level */ if (flags & GPIO_HIGH) val |= (1 << 16); else if (flags & GPIO_LOW) val &= ~(1 << 16); MEC1322_GPIO_CTL(port, i) = val; } }
/* Run keyboard factory testing, scan out KSO/KSI if any shorted. */ int keyboard_factory_test_scan(void) { int i, j; uint16_t shorted = 0; uint32_t port, id, val; /* Disable keyboard scan while testing */ keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_CLOSED); /* Set all of KSO/KSI pins to internal pull-up and input */ for (i = 0; i < keyboard_factory_scan_pins_used; i++) { if (keyboard_factory_scan_pins[i][0] < 0) continue; port = keyboard_factory_scan_pins[i][0]; id = keyboard_factory_scan_pins[i][1]; gpio_set_alternate_function(port, 1 << id, -1); gpio_set_flags_by_mask(port, 1 << id, GPIO_INPUT | GPIO_PULL_UP); } /* * Set start pin to output low, then check other pins * going to low level, it indicate the two pins are shorted. */ for (i = 0; i < keyboard_factory_scan_pins_used; i++) { if (keyboard_factory_scan_pins[i][0] < 0) continue; port = keyboard_factory_scan_pins[i][0]; id = keyboard_factory_scan_pins[i][1]; gpio_set_flags_by_mask(port, 1 << id, GPIO_OUT_LOW); for (j = 0; j < i; j++) { if (keyboard_factory_scan_pins[j][0] < 0) continue; /* * Get gpio pin control register, * bit 24 indicate GPIO input from the pad. */ val = MEC1322_GPIO_CTL(keyboard_factory_scan_pins[j][0], keyboard_factory_scan_pins[j][1]); if ((val & (1 << 24)) == 0) { shorted = i << 8 | j; goto done; } } gpio_set_flags_by_mask(port, 1 << id, GPIO_INPUT | GPIO_PULL_UP); } done: gpio_config_module(MODULE_KEYBOARD_SCAN, 1); keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_CLOSED); return shorted; }