Files
99_7018_lmx/cpu/br28/rdec.c

182 lines
4.2 KiB
C
Raw Normal View History

2025-10-29 13:10:02 +08:00
#include "asm/includes.h"
#include "generic/gpio.h"
#include "asm/rdec.h"
#include "timer.h"
#define RDEC_DEBUG_ENABLE
#ifdef RDEC_DEBUG_ENABLE
#define rdec_debug(fmt, ...) printf("[RDEC] "fmt, ##__VA_ARGS__)
#else
#define rdec_debug(...)
#endif
#define RDEC_IRQ_MODE 0
#define rdec_error(fmt, ...) printf("[RDEC] ERR: "fmt, ##__VA_ARGS__)
struct rdec {
u8 init;
const struct rdec_platform_data *user_data;
};
static struct rdec _rdec = {0};
#define __this (&_rdec)
typedef struct {
u32 con;
int dat;
int smp;
} RDEC_REG;
RDEC_REG *rdec_get_reg(u8 index)
{
RDEC_REG *reg = NULL;
switch (index) {
case 0:
reg = (RDEC_REG *)JL_RDEC0;
break;
case 1:
reg = (RDEC_REG *)JL_RDEC1;
break;
case 2:
reg = (RDEC_REG *)JL_RDEC2;
break;
}
return reg;
}
s8 get_rdec_rdat(int i);
___interrupt
static void rdec0_isr()
{
get_rdec_rdat(0);
}
___interrupt
static void rdec1_isr()
{
get_rdec_rdat(1);
}
___interrupt
static void rdec2_isr()
{
get_rdec_rdat(2);
}
static void __rdec_port_init(u8 port)
{
gpio_set_pull_down(port, 0);
gpio_set_pull_up(port, 1);
gpio_set_die(port, 1);
gpio_set_direction(port, 1);
}
static void rdec_port_init(const struct rdec_device *rdec)
{
const u32 d0_table[] = {PFI_RDEC0_DAT0, PFI_RDEC1_DAT0, PFI_RDEC2_DAT0};
const u32 d1_table[] = {PFI_RDEC0_DAT1, PFI_RDEC1_DAT1, PFI_RDEC2_DAT1};
u32 index = rdec->index;
__rdec_port_init(rdec->sin_port0);
__rdec_port_init(rdec->sin_port1);
printf("rdec->sin_port0 = %d", rdec->sin_port0);
printf("rdec->sin_port1 = %d", rdec->sin_port1);
gpio_set_fun_input_port(rdec->sin_port0, d0_table[index], LOW_POWER_FREE);
gpio_set_fun_input_port(rdec->sin_port1, d1_table[index], LOW_POWER_FREE);
}
static void log_rdec_info(u32 index)
{
RDEC_REG *reg = NULL;
reg = rdec_get_reg(index);
rdec_debug("RDEC CON = 0x%x", reg->con);
printf("FI_RDEC3_DA0 = 0x%x", JL_IMAP->FI_RDEC0_DAT0);
printf("FI_RDEC3_DA1 = 0x%x", JL_IMAP->FI_RDEC0_DAT1);
printf("PB_DIR = 0x%x", JL_PORTB->DIR);
printf("PB_OUT = 0x%x", JL_PORTB->OUT);
printf("PB_PU = 0x%x", JL_PORTB->PU);
printf("PB_PD = 0x%x", JL_PORTB->PD);
}
int rdec_init(const struct rdec_platform_data *user_data)
{
u8 i;
RDEC_REG *reg = NULL;
rdec_debug("rdec init...");
__this->init = 0;
if (user_data == NULL) {
return -1;
}
for (i = 0; i < user_data->num; i++) {
u32 index = user_data->rdec[i].index;
reg = rdec_get_reg(index);
rdec_port_init(&(user_data->rdec[i]));
//module init
reg->con = 0;
reg->con |= (0xe << 2); //2^14, fpga lsb = 24MHz, 2^14 / 24us = 682us = 0.68ms
reg->con &= ~BIT(1); //pol = 0, io should pull up
reg->con |= BIT(6); //clear pending
reg->con |= BIT(8); //mouse mode
reg->con |= BIT(0); //RDECx EN
#if RDEC_IRQ_MODE
const u32 irq_table[] = {IRQ_RDEC0_IDX, IRQ_RDEC1_IDX, IRQ_RDEC2_IDX};
const void (*irq_fun[3])(void) = {rdec0_isr, rdec1_isr, rdec2_isr};
request_irq(irq_table[index], 1, irq_fun[index], 0);
#endif
log_rdec_info(index);
}
__this->init = 1;
__this->user_data = user_data;
return 0;
}
s8 get_rdec_rdat(int i)
{
RDEC_REG *reg = NULL;
s8 rdat = 0;
s8 _rdat = 0;
reg = rdec_get_reg(i);
if (reg->con & BIT(7)) {
asm("csync");
rdat = reg->dat;
reg->con |= BIT(6);
asm("csync");
_rdat = reg->dat;
}
if (_rdat != 0) {
rdec_debug("RDEC: %d , rdat: %d, _rdat: %d", i, rdat, _rdat);
}
return _rdat;
}
#define JL_RDEC_SEL 0
#define RDEC_TEST 1
#if RDEC_TEST
const struct rdec_device rdec_device_list[] = {
{
.index = JL_RDEC_SEL,
.sin_port0 = IO_PORTA_01,
.sin_port1 = IO_PORTA_02,
},
};
RDEC_PLATFORM_DATA_BEGIN(rdec_data)
.enable = 1,
.num = ARRAY_SIZE(rdec_device_list),
.rdec = rdec_device_list,
RDEC_PLATFORM_DATA_END()
#endif
static void rdec_poll(void *p)
{
for (int i = 0; i < 3; i++) {
get_rdec_rdat(i);
}
}
void rdec_test()
{
rdec_init(&rdec_data);
#if RDEC_TEST
sys_timer_add(NULL, rdec_poll, 100);
#endif
}