diff --git a/include/arm11/hardware/gpio.h b/include/arm11/hardware/gpio.h index 538365f..e372161 100644 --- a/include/arm11/hardware/gpio.h +++ b/include/arm11/hardware/gpio.h @@ -21,19 +21,51 @@ #include "types.h" +#define GPIO_INPUT (0u) +#define GPIO_OUTPUT (1u) +#define GPIO_EDGE_FALLING (0u) +#define GPIO_EDGE_RISING (1u<<1) +#define GPIO_IRQ_ENABLE (1u<<2) + + +typedef enum +{ + GPIO_1_0 = 0u<<4 | 0u, + GPIO_1_1 = 1u<<4 | 0u, + GPIO_1_2 = 2u<<4 | 0u, + + GPIO_2_0 = 0u<<4 | 1u, + GPIO_2_1 = 1u<<4 | 1u, + + GPIO_3_0 = 0u<<4 | 2u, + GPIO_3_1 = 1u<<4 | 2u, + GPIO_3_2 = 2u<<4 | 2u, + GPIO_3_3 = 3u<<4 | 2u, + GPIO_3_4 = 4u<<4 | 2u, + GPIO_3_5 = 5u<<4 | 2u, + GPIO_3_6 = 6u<<4 | 2u, + GPIO_3_7 = 7u<<4 | 2u, + GPIO_3_8 = 8u<<4 | 2u, + GPIO_3_9 = 9u<<4 | 2u, + GPIO_3_10 = 10u<<4 | 2u, + GPIO_3_11 = 11u<<4 | 2u, + + GPIO_4_0 = 0u<<4 | 3u, + + // Aliases + GPIO_1_TOUCHSCREEN = GPIO_1_1, // Unset while the touchscreen is used + GPIO_1_SHELL = GPIO_1_2, // 1 when closed + + GPIO_3_HEADPH_JACK = GPIO_3_8, // Unset while headphones are plugged in + GPIO_3_MCU = GPIO_3_9 +} Gpio; + + /** - * @brief Sets a bit in the specified GPIO register. + * @brief Configures the specified GPIO. * - * @param[in] reg The register number. - * @param[in] bitNum The bit number. + * @param[in] gpio The gpio. + * @param[in] cfg The configuration. */ -void GPIO_setBit(u16 reg, u8 bitNum); - -/** - * @brief Clears a bit in the specified GPIO register. - * - * @param[in] reg The register number. - * @param[in] bitNum The bit number. - */ -void GPIO_clearBit(u16 reg, u8 bitNum); +void GPIO_config(Gpio gpio, u8 cfg); diff --git a/source/arm11/hardware/gpio.c b/source/arm11/hardware/gpio.c index 4385ea1..6b78827 100644 --- a/source/arm11/hardware/gpio.c +++ b/source/arm11/hardware/gpio.c @@ -18,18 +18,72 @@ #include "types.h" #include "mem_map.h" +#include "arm11/hardware/gpio.h" -#define REGs_GPIO ((vu16*)(IO_MEM_ARM9_ARM11 + 0x47000)) +#define GPIO_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x47000) +#define REG_GPIO1_UNK0 *((vu16*)(GPIO_REGS_BASE + 0x00)) // ? 3 GPIOs (bits 0-2) +#define REG_GPIO1_UNK2 *((vu16*)(GPIO_REGS_BASE + 0x02)) // ? +#define REG_GPIO1_UNK4 *((vu32*)(GPIO_REGS_BASE + 0x04)) // ? + +// 2 GPIOs (bits 0-1) +#define REG_GPIO2 *((vu32*)(GPIO_REGS_BASE + 0x10)) +#define REG_GPIO2_DAT *((vu8* )(GPIO_REGS_BASE + 0x10)) +#define REG_GPIO2_DIR *((vu8* )(GPIO_REGS_BASE + 0x11)) // 0 = input, 1 = output +#define REG_GPIO2_EDGE *((vu8* )(GPIO_REGS_BASE + 0x12)) // IRQ edge 0 = falling, 1 = rising +#define REG_GPIO2_IRQ *((vu8* )(GPIO_REGS_BASE + 0x13)) // 1 = IRQ enable +#define REG_GPIO2_UNK4 *((vu8* )(GPIO_REGS_BASE + 0x14)) // Only bit 0 writable +#define REG_GPIO2_UNK5 *((vu8* )(GPIO_REGS_BASE + 0x15)) // Only 1 bit? + +// 12 GPIOs (bits 0-11) +#define REG_GPIO3_H1 *((vu32*)(GPIO_REGS_BASE + 0x20)) // First half +#define REG_GPIO3_DAT *((vu16*)(GPIO_REGS_BASE + 0x20)) +#define REG_GPIO3_DIR *((vu16*)(GPIO_REGS_BASE + 0x22)) +#define REG_GPIO3_H2 *((vu32*)(GPIO_REGS_BASE + 0x24)) // Second half +#define REG_GPIO3_EDGE *((vu16*)(GPIO_REGS_BASE + 0x24)) +#define REG_GPIO3_IRQ *((vu16*)(GPIO_REGS_BASE + 0x26)) + +// 1 GPIO (bit 0) +#define REG_GPIO4_DAT *((vu16*)(GPIO_REGS_BASE + 0x28)) // ? -void GPIO_setBit(u16 reg, u8 bitNum) +void GPIO_config(Gpio gpio, u8 cfg) { - REGs_GPIO[reg] |= 1u<>4; + + // GPIO1 and GPIO4 are not configurable. + if(bank == 1) + { + u32 reg = REG_GPIO2 & ~((1u<<24 | 1u<<16 | 1u<<8)<