doubao_chat/cpu/wl82/port_waked_up.c

206 lines
6.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "asm/includes.h"
#include "device/gpio.h"
#include "system/includes.h"
struct port_wakeup_work {
u8 event;
/* u8 wkup_edge; */
void (*handler)(void);
/* void *priv; */
/* unsigned int gpio; */
} port_wakeup_work;
#define CLEAR_PORT_PEND() JL_WAKEUP->CON2 = 0xffff
#define READ_PORT_PEND() JL_WAKEUP->CON3
#define WKUP_ENABLE(x) JL_WAKEUP->CON0 |= BIT(x)
#define WKUP_DISABLE(x) JL_WAKEUP->CON0 &= (~BIT(x))
#define WKUP_EDGE(x,edg) JL_WAKEUP->CON1 = ((JL_WAKEUP->CON1 & (~BIT(x))) | (edg? BIT(x): 0))
#define WKUP_CLEAR_PEND(x) (JL_WAKEUP->CON2 |= BIT(x))
#define PORT_WAKED_ID_BASE 0X2A
#define PORT_WAKED_ID_GIVE(i) (PORT_WAKED_ID_BASE + i)
#define PORT_WAKED_ID_GET(hdl) (hdl - PORT_WAKED_ID_BASE)
#define PORT_WAKED_ID_NUM (3) //最多16个事件
static struct port_wakeup_work g_wakeup_work[PORT_WAKED_ID_NUM];
static DEFINE_SPINLOCK(lock);
static const s32 port_table[64] = {
IO_PORTA_00, IO_PORTA_01, IO_PORTA_02, IO_PORTA_03, IO_PORTA_04, IO_PORTA_05, IO_PORTA_06, IO_PORTA_07, IO_PORTA_08, IO_PORTA_09, IO_PORTA_10,
IO_PORTB_00, IO_PORTB_01, IO_PORTB_02, IO_PORTB_03, IO_PORTB_04, IO_PORTB_05, IO_PORTB_06, IO_PORTB_07, IO_PORTB_08,
IO_PORTC_00, IO_PORTC_01, IO_PORTC_02, IO_PORTC_03, IO_PORTC_04, IO_PORTC_05, IO_PORTC_06, IO_PORTC_07, IO_PORTC_08, IO_PORTC_09, IO_PORTC_10,
IO_PORTE_00, IO_PORTE_01, IO_PORTE_02, IO_PORTE_03, IO_PORTE_04, IO_PORTE_05, IO_PORTE_06, IO_PORTE_07, IO_PORTE_08, IO_PORTE_09,
IO_PORTH_00, IO_PORTH_01, IO_PORTH_02, IO_PORTH_03, IO_PORTH_04, IO_PORTH_05, IO_PORTH_06, IO_PORTH_07, IO_PORTH_08, IO_PORTH_09,
IO_PORTG_08, IO_PORTG_09, IO_PORTG_10, IO_PORTG_11, IO_PORTG_12, IO_PORTG_13, IO_PORTG_14, IO_PORTG_15,
-1, /* TMR5_PWM_OUT,\ */
IO_PORT_USB_DPA, IO_PORT_USB_DMA,
IO_PORT_USB_DPB, IO_PORT_USB_DMB
};
___interrupt
static void port_wakeup_isr(void)
{
int i;
u16 wkup_pend;
//spin_lock(&lock);
wkup_pend = READ_PORT_PEND();
for (i = 0; i < sizeof(g_wakeup_work) / sizeof(struct port_wakeup_work); i++) {
if (wkup_pend & BIT(g_wakeup_work[i].event)) {
if (g_wakeup_work[i].handler) {
g_wakeup_work[i].handler();
}
WKUP_CLEAR_PEND(g_wakeup_work[i].event);
}
}
//spin_unlock(&lock);
}
static s32 get_remap_gpio(u32 gpio)
{
for (u32 idx = 0; idx < ARRAY_SIZE(port_table); idx++) {
if (port_table[idx] == gpio) {
return idx;
}
}
return -1;
}
static u8 gpio_2_port_bit(unsigned int gpio)
{
u8 port_bit;
u8 port_h;
u8 port_l;
port_h = gpio / IO_GROUP_NUM;
port_l = gpio % IO_GROUP_NUM;
if (port_h == 4) {
//PORTE
port_h = 6;
} else if (port_h == 6) {
//PORTG
port_h = 4;
} else if (port_h == 7) {
//PORTH
port_h = 5;
}
port_bit = (port_h << 4) | port_l;
return port_bit;
}
//event: event参数为EVENT_IO_0或EVENT_IO_1时,gpio为任意IO都可以唤醒
void *port_wakeup_reg(PORT_EVENT_E event, unsigned int gpio, PORT_EDGE_E edge, void (*handler)(void))
{
int i = 0;
s32 idx = -1;
if (!handler) {
return NULL;
}
//if (event > EVENT_PH7) {
// return NULL;
//}
if (gpio > IO_PORT_USB_DMB) {
return NULL;
}
static char port_wakeup_init_flag;
if (!port_wakeup_init_flag) {
port_wakeup_init_flag = 1;
JL_WAKEUP->CON0 = 0;
JL_WAKEUP->CON2 = 0xffffffff;
request_irq(IRQ_PORT_IDX, 3, port_wakeup_isr, 0x1);
}
spin_lock(&lock);
while (i < sizeof(g_wakeup_work) / sizeof(struct port_wakeup_work)) {
if (g_wakeup_work[i].handler == NULL) {
break;
}
++i;
}
if (i == sizeof(g_wakeup_work) / sizeof(struct port_wakeup_work)) {
spin_unlock(&lock);
printf("[error]>PORT_WAKED_ID_NUM to less = %d", PORT_WAKED_ID_NUM);
return NULL;
}
/* u8 port_io = gpio_2_port_bit(gpio); */
/* if (event == EVENT_IO_0) { */
/* JL_IOMAP->CON2 &= ~(0xff); */
/* JL_IOMAP->CON2 |= gpio; */
/* } else if (event == EVENT_IO_1) { */
/* JL_IOMAP->CON2 &= ~(0xff << 8); */
/* JL_IOMAP->CON2 |= (gpio << 8); */
/* } */
if ((event == EVENT_IO_0) || (event == EVENT_IO_1)) {
idx = get_remap_gpio(gpio);
if (idx != -1) {
if (event == EVENT_IO_0) {
JL_IOMAP->CON2 &= ~(0xff);
JL_IOMAP->CON2 |= idx;
} else if (event == EVENT_IO_1) {
JL_IOMAP->CON2 &= ~(0xff << 8);
JL_IOMAP->CON2 |= (idx << 8);
}
} else {
spin_unlock(&lock);
return NULL;
}
}
if (event < EVENT_SDC0_DAT1 && (event < EVENT_UT0_RX || event > EVENT_UT2_RX)) {
gpio_direction_input(gpio);
gpio_set_die(gpio, 1);
if (edge == EDGE_POSITIVE) {
gpio_set_pull_down(gpio, 1);
gpio_set_pull_up(gpio, 0);
} else if (edge == EDGE_NEGATIVE) {
gpio_set_pull_down(gpio, 0);
gpio_set_pull_up(gpio, 1);
}
}
g_wakeup_work[i].event = event;
/* g_wakeup_work[i].wkup_edge = edge; */
/* g_wakeup_work[i].gpio = gpio; */
g_wakeup_work[i].handler = handler;
/* g_wakeup_work[i].priv = priv; */
WKUP_EDGE(event, edge);
WKUP_CLEAR_PEND(event);
WKUP_ENABLE(event);
spin_unlock(&lock);
log_i("ENABLE REG = 0x%x.\n", JL_WAKEUP->CON0);
log_i("EDGE REG = 0x%x.\n", JL_WAKEUP->CON1);
log_i("PEND REG = 0x%x.\n", JL_WAKEUP->CON3);
log_i("JL_IOMAP->CON2=0x%x\n", JL_IOMAP->CON2);
return (void *)PORT_WAKED_ID_GIVE(i);
}
void port_wakeup_unreg(void *hdl)
{
if (!hdl || (int)hdl < PORT_WAKED_ID_BASE || (int)hdl >= (PORT_WAKED_ID_BASE + PORT_WAKED_ID_NUM)) {
log_i("hdl err = 0x%x \r\n", hdl);
return;
}
int i = PORT_WAKED_ID_GET((int)hdl);
spin_lock(&lock);
WKUP_DISABLE(g_wakeup_work[i].event);
WKUP_CLEAR_PEND(g_wakeup_work[i].event);
memset(&g_wakeup_work[i], 0, sizeof(struct port_wakeup_work));
spin_unlock(&lock);
}