#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 }