soc/amd/stoneyridge/gpio.c: Fix gpio_output()
[coreboot.git] / src / soc / amd / stoneyridge / gpio.c
blob4520df7a6f2b57ac7e3c9439bed6272a493c344c
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2015 Google Inc.
5 * Copyright (C) 2015 Intel Corporation
6 * Copyright (C) 2017 Advanced Micro Devices, Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <arch/io.h>
19 #include <console/console.h>
20 #include <gpio.h>
21 #include <soc/gpio.h>
23 static uintptr_t gpio_get_address(gpio_t gpio_num)
25 uintptr_t gpio_address;
27 if (gpio_num < 64)
28 gpio_address = GPIO_BANK0_CONTROL(gpio_num);
29 else if (gpio_num < 128)
30 gpio_address = GPIO_BANK1_CONTROL(gpio_num);
31 else
32 gpio_address = GPIO_BANK2_CONTROL(gpio_num);
34 return gpio_address;
37 int gpio_get(gpio_t gpio_num)
39 uint32_t reg;
40 uintptr_t gpio_address = gpio_get_address(gpio_num);
42 reg = read32((void *)gpio_address);
44 return !!(reg & GPIO_PIN_STS);
47 void gpio_set(gpio_t gpio_num, int value)
49 uint32_t reg;
50 uintptr_t gpio_address = gpio_get_address(gpio_num);
52 reg = read32((void *)gpio_address);
53 reg &= ~GPIO_OUTPUT_MASK;
54 reg |= !!value << GPIO_OUTPUT_SHIFT;
55 write32((void *)(uintptr_t)gpio_num, reg);
58 void gpio_input_pulldown(gpio_t gpio_num)
60 uint32_t reg;
61 uintptr_t gpio_address = gpio_get_address(gpio_num);
63 reg = read32((void *)gpio_address);
64 reg &= ~GPIO_PULLUP_ENABLE;
65 reg |= GPIO_PULLDOWN_ENABLE;
66 write32((void *)(uintptr_t)gpio_num, reg);
69 void gpio_input_pullup(gpio_t gpio_num)
71 uint32_t reg;
72 uintptr_t gpio_address = gpio_get_address(gpio_num);
74 reg = read32((void *)gpio_address);
75 reg &= ~GPIO_PULLDOWN_ENABLE;
76 reg |= GPIO_PULLUP_ENABLE;
77 write32((void *)(uintptr_t)gpio_num, reg);
80 void gpio_input(gpio_t gpio_num)
82 uint32_t reg;
83 uintptr_t gpio_address = gpio_get_address(gpio_num);
85 reg = read32((void *)gpio_address);
86 reg &= ~GPIO_OUTPUT_ENABLE;
87 write32((void *)(uintptr_t)gpio_num, reg);
90 void gpio_output(gpio_t gpio_num, int value)
92 uint32_t reg;
93 uintptr_t gpio_address = gpio_get_address(gpio_num);
95 reg = read32((void *)gpio_address);
96 reg |= GPIO_OUTPUT_ENABLE;
97 write32((void *)(uintptr_t)gpio_num, reg);
98 gpio_set(gpio_num, value);
101 const char *gpio_acpi_path(gpio_t gpio)
103 return "\\_SB.GPIO";
106 uint16_t gpio_acpi_pin(gpio_t gpio)
108 return gpio;
111 void gpio_set_interrupt(gpio_t gpio, uint32_t flags)
113 uintptr_t gpio_address = gpio_get_address(gpio);
114 uint32_t reg = read32((void *)gpio_address);
116 /* Clear registers that are being updated */
117 reg &= ~(GPIO_TRIGGER_MASK | GPIO_ACTIVE_MASK | GPIO_INTERRUPT_MASK);
119 /* Clear any extra bits in the flags */
120 flags &= (GPIO_TRIGGER_MASK | GPIO_ACTIVE_MASK | GPIO_INTERRUPT_MASK);
122 write32((void *)gpio_address, reg | flags);
125 int gpio_interrupt_status(gpio_t gpio)
127 uintptr_t gpio_address = gpio_get_address(gpio);
128 uint32_t reg = read32((void *)gpio_address);
130 if (reg & GPIO_INT_STATUS) {
131 /* Clear interrupt status, preserve wake status */
132 reg &= ~GPIO_WAKE_STATUS;
133 write32((void *)gpio_address, reg);
134 return 1;
137 return 0;