1 /*
2  * Copyright (c) 2016 Adam Barth
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <dev/gpio.h>
9 #include <errno.h>
10 #include <platform/bcm28xx.h>
11 #include <lk/reg.h>
12 
13 #define NUM_PINS     54
14 #define BITS_PER_REG 32
15 #define BITS_PER_PIN 3
16 #define PINS_PER_REG (BITS_PER_REG / BITS_PER_PIN)
17 #define GPIOREG(base, nr) (REG32(base) + (nr / BITS_PER_REG))
18 
gpio_config(unsigned nr,unsigned flags)19 int gpio_config(unsigned nr, unsigned flags) {
20     unsigned mask = 0x7;
21     if (nr >= NUM_PINS || flags & ~mask)
22         return -EINVAL;
23     unsigned register_number = nr / PINS_PER_REG;
24     unsigned offset = (nr % PINS_PER_REG) * BITS_PER_PIN;
25     unsigned shifted_mask = mask << offset;
26     volatile uint32_t *reg = REG32(GPIO_GPFSEL0) + register_number;
27     *reg = (*reg & ~shifted_mask) | (flags << offset);
28     return 0;
29 }
30 
gpio_set(unsigned nr,unsigned on)31 void gpio_set(unsigned nr, unsigned on) {
32     unsigned offset = nr % BITS_PER_REG;
33     *GPIOREG(on ? GPIO_GPSET0 : GPIO_GPCLR0, nr) = 1 << offset;
34 }
35 
gpio_get(unsigned nr)36 int gpio_get(unsigned nr) {
37     unsigned offset = nr % BITS_PER_REG;
38     return (*GPIOREG(GPIO_GPLEV0, nr) & (1 << offset)) >> offset;
39 }
40