#include "oem_portmisc.h"
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/drv_api.h>
#define GINT_FEDGE_0 0x10000660
#define GINT_STAT_0 0x10000690
typedef union gpio1mode_data {
u32 d32;
struct {
u32 gpio_mode:2;
u32 rsvd2_5:4;
u32 i2s_mode:2;
u32 rsvd8_19:12;
u32 i2c_mode:2;
u32 rsvd22_23:2;
u32 uart1_mode:2;
u32 rsvd26_31:6;
} b;
} gpio1mode_data_t;
typedef union gpio2mode_data {
u32 d32;
struct {
u32 rsvd0_19:20;
u32 p1_led_kn_mode:2;
u32 p2_led_kn_mode:2;
u32 p3_led_kn_mode:2;
u32 p4_led_kn_mode:2;
u32 rsvd28_31:4;
} b;
} gpio2mode_data_t;
#if defined(CONFIG_GPIO_INTR_MODE)
typedef struct gpio_intr_info {
CYG_WORD int_num;
cyg_interrupt gpio_interrupt;
cyg_handle_t gpio_interrupt_handle;
} gpio_intr_info_t;
static gpio_intr_info_t gii_1 = {
.int_num = CYGNUM_HAL_INTERRUPT_PIO,
};
static u32 va(u32 addr);
static void toggle_relay_gpio(uint8_t gpio)
{
if (gpio_get_value(gpio) > 0) {
gpio_set_value(gpio, 0);
// TODO: save it to nv
} else {
gpio_set_value(gpio, 1);
// TODO: save it to nv
}
}
static cyg_uint32 gpio_isr(cyg_vector_t vector, cyg_addrword_t data)
{
gpio_intr_info_t * gii = (gpio_intr_info_t *)data;
cyg_drv_interrupt_mask(gii->int_num);
cyg_drv_interrupt_acknowledge(gii->int_num);
// Cause DSR to be run
return CYG_ISR_CALL_DSR;
}
static void gpio_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
gpio_intr_info_t * gii = (gpio_intr_info_t *)data;
u32 val = HAL_REG32(va(GINT_STAT_0));
if ((val >> SUMPWR_KEY_GPIO) & 0x1) {
toggle_relay_gpio(RELAY1_GPIO);
}
if ((val >> KEY2_GPIO) & 0x1) {
toggle_relay_gpio(RELAY2_GPIO);
}
if ((val >> KEY3_GPIO) & 0x1) {
toggle_relay_gpio(RELAY3_GPIO);
}
if ((val >> KEY4_GPIO) & 0x1) {
toggle_relay_gpio(RELAY4_GPIO);
}
cyg_drv_interrupt_unmask(gii->int_num);
diag_printf("%p\n", gii);
}
#endif
static inline u32 va(u32 addr)
{
u32 phy_addr = addr;
// kseg1: 0xA000 0000 - 0xBFFF FFFF(512M)
phy_addr &= 0x0FFFFFFC;
//phy_addr &= 0x0FFFFFFF;
phy_addr |= 0xb0000000;
return phy_addr;
}
static int8_t gpio_direction_input(uint8_t gpio)
{
mem_data_t reg_val;
u32 ctrl_addr;
if (gpio > 95) {
return -1;
}
if (gpio <= 31) {
// GPIO_CTRL_0
ctrl_addr = va(0x10000600);
} else if (gpio >= 32 && gpio <= 63) {
// GPIO_CTRL_1
ctrl_addr = va(0x10000604);
gpio = gpio - 32;
} else {
// 64 ... 95
// GPIO_CTRL_2
ctrl_addr = va(0x10000608);
gpio = gpio - 64;;
}
reg_val.d32 = HAL_REG32(ctrl_addr);
reg_val.d32 &= ~(1 << gpio);
HAL_REG32(ctrl_addr) = reg_val.d32;
return 0;
}
int8_t gpio_get_value(uint8_t gpio)
{
mem_data_t reg_val;
u32 ctrl_addr;
u32 data_addr;
if (gpio > 95) {
return -1;
}
if (gpio <= 31) {
// GPIO_CTRL_0
//ctrl_addr = va(0x10000600);
// GPIO_DATA_0
data_addr = va(0x10000620);
} else if (gpio >= 32 && gpio <= 63) {
// GPIO_CTRL_1
//ctrl_addr = va(0x10000604);
// GPIO_DATA_1
data_addr = va(0x10000624);
gpio = gpio - 32;
} else {
// 64 ... 95
// GPIO_CTRL_2
//ctrl_addr = va(0x10000608);
// GPIO_DATA_2
data_addr = va(0x10000628);
gpio = gpio - 64;;
}
// reg_val.d32 = HAL_REG32(ctrl_addr);
// reg_val.d32 &= ~(1 << gpio);
// HAL_REG32(ctrl_addr) = reg_val.d32;
reg_val.d32 = HAL_REG32(data_addr);
return ((reg_val.d32 >> gpio) & 0x1);
}
void gpio_set_value(uint8_t gpio, uint8_t value)
{
mem_data_t reg_val;
u32 ctrl_addr;
u32 data_addr;
if (gpio > 95) {
return;
}
if (gpio <= 31) {
// GPIO_CTRL_0
ctrl_addr = va(0x10000600);
if (value > 0) {
// GPIO_DSET_0
data_addr = va(0x10000630);
} else {
// GPIO_DCLR_0
data_addr = va(0x10000640);
}
} else if (gpio >= 32 && gpio <= 63) {
// GPIO_CTRL_1
ctrl_addr = va(0x10000604);
if (value > 0) {
// GPIO_DSET_1
data_addr = va(0x10000634);
} else {
// GPIO_DCLR_1
data_addr = va(0x10000644);
}
gpio = gpio - 32;
} else {
// 64 ... 95
// GPIO_CTRL_2
ctrl_addr = va(0x10000608);
if (value > 0) {
// GPIO_DSET_2
data_addr = va(0x10000638);
} else {
// GPIO_DCLR_2
data_addr = va(0x10000648);
}
gpio = gpio - 64;
}
reg_val.d32 = HAL_REG32(ctrl_addr);
reg_val.d32 |= 1 << gpio;
HAL_REG32(ctrl_addr) = reg_val.d32;
reg_val.d32 = HAL_REG32(data_addr);
reg_val.d32 |= 1 << gpio;
HAL_REG32(data_addr) = reg_val.d32;
}
void gpio_init(void)
{
#if defined(CONFIG_GPIO_INTR_MODE)
gpio_intr_info_t *gii;
#endif
gpio1mode_data_t gpio1mode;
gpio2mode_data_t gpio2mode;
u32 addr, val;
// pin mux
// Reference to "MT7628 PROGRAMMING GUIDE", p15 of System Control
// GPIO1_MODE 0x10000060
// GPIO2_MODE 0x10000064
// GPIO00,02,03,04,05,11, key4,key3,key2,sumpwr_led1,sumpwr_key,zero
addr = va(0x10000060);
gpio1mode.d32 = HAL_REG32(addr);
// GPIO11
gpio1mode.b.gpio_mode = 0;
// GPIO00,02,03
gpio1mode.b.i2s_mode = 1;
// GPIO04,05
gpio1mode.b.i2c_mode = 1;
//gpio1mode.b.uart1_mode = 0;
HAL_REG32(addr) = gpio1mode.d32;
/* falling edge */
gpio_direction_input(SUMPWR_KEY_GPIO);
gpio_direction_input(KEY2_GPIO);
gpio_direction_input(KEY3_GPIO);
gpio_direction_input(KEY4_GPIO);
// GPIO30,31,32,33, r4,r3,r2,r1
addr = va(0x10000064);
gpio2mode.d32 = HAL_REG32(addr);
// GPIO33
gpio2mode.b.p1_led_kn_mode = 1;
// GPIO32
gpio2mode.b.p2_led_kn_mode = 1;
// GPIO31
gpio2mode.b.p3_led_kn_mode = 1;
// GPIO30
gpio2mode.b.p4_led_kn_mode = 1;
HAL_REG32(addr) = gpio2mode.d32;
/* relay on: LOW, relay off: HIGH */
gpio_set_value(RELAY1_GPIO, 1);
gpio_set_value(RELAY2_GPIO, 1);
gpio_set_value(RELAY3_GPIO, 1);
gpio_set_value(RELAY4_GPIO, 1);
#if defined(CONFIG_GPIO_INTR_MODE)
val = HAL_REG32(va(GINT_FEDGE_0));
val |= (1 << SUMPWR_KEY_GPIO) | (1 << KEY2_GPIO) | (1 << KEY3_GPIO) | (1 << KEY4_GPIO);
HAL_REG32(va(GINT_FEDGE_0)) = val;
gii = &gii_1;
cyg_drv_interrupt_create(gii->int_num,
5, // can change IRQ0 priority
(cyg_addrword_t)gii, // Data item passed to interrupt handler
gpio_isr,
gpio_dsr,
&gii->gpio_interrupt_handle,
&gii->gpio_interrupt);
cyg_drv_interrupt_attach(gii->gpio_interrupt_handle);
cyg_drv_interrupt_unmask(gii->int_num);
#endif
}
module_init(gpio_init);