blob: c761476ff0761ae146a5b1e2a4005cb2af4b26be [file] [log] [blame]
/**
* \file gpio-test.c
* \brief A Documented file.
*
* Detailed description
* \Author: Sniper <js.wang@mobiletek.cn>
* \Version: 1.0.0
* \Date: 2022-04-26
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/mount.h>
#include "mbtk_log.h"
#include <sys/mman.h>
#include <ctype.h>
#include <cutils/properties.h>
#include "gpio-define.h"
#define gpio_log(...) if(gpio_debug)printf(__VA_ARGS__)
static int gpio_debug = 0;
struct gpio_register_function gpio_func_register[128] = {
{GPIO_FUNC_GPIO_00, 0},
{GPIO_FUNC_GPIO_01, 0},
{GPIO_FUNC_GPIO_02, 0},
{GPIO_FUNC_GPIO_03, 0},
{GPIO_FUNC_GPIO_04, 0},
{GPIO_FUNC_GPIO_05, 0},
{GPIO_FUNC_GPIO_06, 0},
{GPIO_FUNC_GPIO_07, 0},
{GPIO_FUNC_GPIO_08, 0},
{GPIO_FUNC_GPIO_09, 0},
{GPIO_FUNC_GPIO_10, 0},
{GPIO_FUNC_GPIO_11, 0},
{GPIO_FUNC_GPIO_12, 0},
{GPIO_FUNC_GPIO_13, 0},
{GPIO_FUNC_GPIO_14, 0},
{GPIO_FUNC_GPIO_15, 0},
{GPIO_FUNC_GPIO_16, 0},
{GPIO_FUNC_GPIO_17, 0},
{GPIO_FUNC_GPIO_18, 0},
{GPIO_FUNC_GPIO_19, 0},
{GPIO_FUNC_GPIO_20, 0},
{GPIO_FUNC_GPIO_21, 0},
{GPIO_FUNC_GPIO_22, 0},
{GPIO_FUNC_GPIO_23, 0},
{GPIO_FUNC_GPIO_24, 0},
{GPIO_FUNC_GPIO_25, 0},
{GPIO_FUNC_GPIO_26, 0},
{GPIO_FUNC_GPIO_27, 0},
{GPIO_FUNC_GPIO_28, 0},
{GPIO_FUNC_GPIO_29, 0},
{GPIO_FUNC_GPIO_30, 0},
{GPIO_FUNC_GPIO_31, 0},
{GPIO_FUNC_GPIO_32, 0},
{GPIO_FUNC_GPIO_33, 0},
{GPIO_FUNC_GPIO_34, 0},
{GPIO_FUNC_GPIO_35, 0},
{GPIO_FUNC_GPIO_36, 0},
{GPIO_FUNC_MMC1_DAT3, 5}, // GPIO_37
{GPIO_FUNC_MMC1_DAT2, 5}, // GPIO_38
{GPIO_FUNC_MMC1_DAT1, 5}, // GPIO_39
{GPIO_FUNC_MMC1_DAT0, 5}, // GPIO_40
{GPIO_FUNC_MMC1_CMD, 5}, //GPIO_41
{GPIO_FUNC_MMC1_CLK, 5}, //GPIO_42
{GPIO_FUNC_MMC1_CD , 1}, //GPIO_43
{0,0},{0,0},{0,0},{0,0},
{GPIO_FUNC_SDIO_DAT3, 1}, //GPIO_48
{GPIO_FUNC_GPIO_49, 0},
{GPIO_FUNC_GPIO_50, 0},
{GPIO_FUNC_GPIO_51, 0},
{GPIO_FUNC_GPIO_52, 0},
{GPIO_FUNC_GPIO_53, 0},
{GPIO_FUNC_GPIO_54, 0},
{GPIO_FUNC_SDIO_DAT2, 1}, //GPIO_55
{GPIO_FUNC_SDIO_DAT1, 1}, //GPIO_56
{GPIO_FUNC_SDIO_DAT0, 1}, //GPIO_57
{GPIO_FUNC_SDIO_CMD, 1}, //GPIO_58
{GPIO_FUNC_SDIO_CLK, 1}, //GPIO_59
{GPIO_FUNC_GPIO_60, 0},
{0,0},{0,0},{0,0},{0,0},
{0,0},{0,0},
{GPIO_FUNC_DVL_0, 1},//GPIO_67
{GPIO_FUNC_DVL_1, 1},//GPIO_68
{GPIO_FUNC_GPIO_69, 0},
{GPIO_FUNC_GPIO_70, 0},
{GPIO_FUNC_QSPI_DAT3, 1}, //GPIO_71
{GPIO_FUNC_QSPI_DAT2, 1}, //GPIO_72
{GPIO_FUNC_QSPI_DAT1, 1}, //GPIO_73
{GPIO_FUNC_QSPI_DAT0, 1}, //GPIO_74
{GPIO_FUNC_QSPI_CLK, 1}, //GPIO_75
{GPIO_FUNC_QSPI_CS1, 1}, //GPIO_76
{GPIO_FUNC_GPIO_77, 0},
{GPIO_FUNC_GPIO_78, 0},
{GPIO_FUNC_GPIO_79, 0},
{GPIO_FUNC_GPIO_80, 0},
{GPIO_FUNC_USIM_UCLK, 1},//GPIO_81
{GPIO_FUNC_USIM_UIO, 1},//GPIO_82
{GPIO_FUNC_USIM_URSTn, 1},//GPIO_83
{0,0},{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0},
{GPIO_FUNC_USB_ID, 1},//GPIO_99
{0,0},{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0},{0,0},
{0,0},{0,0},{0,0},{0,0},
{0,0},
{GPIO_FUNC_PRI_TDI, 1}, //GPIO_117
{GPIO_FUNC_PRI_TMS, 1}, //GPIO_118
{GPIO_FUNC_PRI_TCK, 1}, //GPIO_119
{GPIO_FUNC_PRI_TDO, 1}, //GPIO_120
{GPIO_FUNC_QSPI_VMODE_GPIO, 1}, //GPIO_121
{GPIO_FUNC_VBUS_DRV, 1}, //GPIO_122
{GPIO_FUNC_CLK_REQ, 1}, //GPIO_123
{0,0},
{GPIO_FUNC_VCXO_REQ, 1}, //GPIO_125
{GPIO_FUNC_VCXO_OUT, 1}, //GPIO_126
{0,0},
};
#if 0
/**
* \brief strstr_n
*
* find string return number
*
* \param param
* \return return type
*/
int strstr_n(const char *s1, const char *s2)
{
int n;
int strlen = 0;
if(*s2)
{
while(*s1)
{
for(n = 0; *(s1+n) == *(s2 + n); n++)
{
if(!*(s2 + n + 1))
{
strlen++;
return strlen;
}
}
s1++;
strlen++;
}
return 0;
}else
return 0;
}
static short int from_hex(char a)
{
if (a >= 'A' && a <= 'F')
return a - 'A' + 10;
else if (a >= 'a' && a <= 'f')
return a - 'a' + 10;
else
return a - '0';
}
int str_to_hex(char *str)
{
unsigned char str_len = strlen(str);
int i;
int ret = 0;
if(str[0] != '0' || (str[1] != 'x' && str[1] != 'X'))
{
printf("%s error, %s!\n", __FUNCTION__, str);
return ret;
}
for (i = 2; i < str_len; ++i) {
ret = ret * 16 + from_hex(str[i]);
}
return ret;
}
#endif
#define HWMAP_DEVICE "/dev/hwmap"
#define PAGE_OFFS_BITS(pgsz) ((unsigned int)(pgsz)-1)
#define PAGE_MASK_BITS(pgsz) (~PAGE_OFFS_BITS(pgsz))
static int hwacc_register(int rw, unsigned int addr, unsigned int *data)
{
int fid;
unsigned int pagesize, len, len_aligned;
unsigned int addr_aligned;
volatile unsigned int *pa;
void *vpa;
len = pagesize = sysconf(_SC_PAGESIZE);
if((fid = open(HWMAP_DEVICE, O_RDWR)) < 0)
{
printf("Failed to open %s\n", HWMAP_DEVICE);
exit(-1);
}
// Align the length so the mapped area is page-aligned and contains the requested area
addr_aligned = addr & PAGE_MASK_BITS(pagesize);
len_aligned =((addr + len - addr_aligned) + pagesize - 1) & PAGE_MASK_BITS(pagesize);
/* Notes on flags: MAP_PRIVATE results in copy on write; MAP_SHARED allows normal write */
/* MAP_SHARED required O_RDWR in open above, otherwise mmap fails with errno=EACCES */
/* Notes on prot: PROT_WRITE allows read and write; PROT_READ allows read only */
/* Notes on off: an unsigned 32-bit value, should be aligned to page size according to mmap manpage */
if((vpa = mmap(0, len_aligned, PROT_READ|PROT_WRITE, MAP_SHARED, fid, addr_aligned)) == MAP_FAILED)
{
printf("mmap failed (%d)\n", errno);
}
else
{
pa = (volatile unsigned int *)((unsigned char *)vpa + (addr & PAGE_OFFS_BITS(pagesize)));
if(rw == 0)
{
*data = *pa;
gpio_log("Value read from 0x%.8x via MVA=0x%p is 0x%.8x\n", addr, pa, *data);
}
else if(rw == 1)
{
*pa = *data;
gpio_log("Value %.8x written to 0x%.8x via MVA=0x%p\n", *data, addr, pa);
#if defined(HWACC_DEBUG)
{
unsigned int val;
val = *pa;
printf("Value read from 0x%.8x via MVA=0x%p is 0x%.8x\n", addr, pa, val);
}
#endif
}
munmap(vpa, len);
}
close(fid);
return 0;
}
/*
设置GPIO 模式:第一步读GPIO22默认function
root@OpenWrt:/# hwacc r 0xd401e134
Option = r Addr = d401e134
Value read from 0xd401e134 via MVA=0x0xb6fc3134 is 0x0000d040 //默认GPIO功能
Bit0~bit2值对应上面表格各function,0代表GPIO功能
*/
static int gpio_register_read(int reg)
{
int ret = -1;
#if 0
FILE * fp;
// "/bin/hwacc r 0xd401e134";
char command[36] = {0};
char buffer[1024];
int i = 0;
sprintf(command, "/bin/hwacc r 0x%x", reg);
fp = popen(command, "r");
while(1)
{
if( fgets (buffer, sizeof(buffer), fp)!=NULL ) {
buffer[strlen(buffer) - 1] = 0;
// gpio_log("out [%d]: %s\n", strlen(buffer), buffer);
}else{
break;
}
i = strstr_n(buffer, "is");
if(i)
{
ret = str_to_hex(&buffer[i + 2]);
gpio_log("read 0x%x value:%s, %x\n", reg, &buffer[i + 2], ret);
}
}
pclose(fp);
#else
hwacc_register(0, reg, &ret);
#endif
return ret;
}
/*
设置输入输出状态,设置PDR寄存器GPIO22为output
root@OpenWrt:/# hwacc w 0xD401900c 0x00c03800
Option = w Addr = d401900c Data=00c03800
Value 00c03800 written to 0xd401900c via MVA=0x0xb6f9f00c
*/
static void gpio_register_write(int reg, int value)
{
#if 0
FILE * fp;
// "/bin/hwacc w 0xD401900c 0x00c03800"
char command[36] = {0};
char buffer[1024];
sprintf(command, "/bin/hwacc w 0x%x 0x%x", reg, value);
gpio_log("command: %s\n", command);
fp = popen(command, "r");
while(1)
{
if( fgets (buffer, sizeof(buffer), fp)!=NULL ) {
gpio_log("%s\n", buffer);
}else{
break;
}
}
pclose(fp);
#else
hwacc_register(1, reg, &value);
#endif
}
/*
AF SEL<p>This field is used for alternate function selection for a pin.
It selects between the eight possible alternate functions for the pin.
Alternate function 0 is always the reset case.
<p>0x0 = Alternate function 0 (primary function at reset)
<p>0x1 = Alternate function 1
<p>0x2 = Alternate function 2
<p>0x3 = Alternate function 3
<p>0x4 = Alternate function 4
<p>0x5 = Alternate function 5
<p>0x6 = Alternate function 6
<p>0x7 = Alternate function 7
*/
static int gpio_register_set_func_0(int port)
{
int ret;
struct gpio_register_function *reg = NULL;
if(port > 128)
return -1;
reg = &gpio_func_register[port];
if(0 == reg->reg)
return -1;
ret = gpio_register_read(reg->reg);
if((ret & 0x7) != reg->func_gpio)
{
gpio_log("Gpio set func [%d] [0x%x]!\n", reg->func_gpio, (ret & 0xfffffff8) | reg->func_gpio);
gpio_register_write(reg->reg, (ret & 0xfffffff8) | reg->func_gpio);
}
return 0;
}
/*
设置GPIO 方向
读取输入输出状态,读PDR寄存器:0x0c
root@OpenWrt:/# hwacc r 0xD401900c
Option = r Addr = d401900c
Value read from 0xd401900c via MVA=0x0xb6f3900c is 0x00803800 //bit22为0,代表Input
*/
static void gpio_register_set_direction(int port, int dir)
{
int ret;
int reg = 0xD4019000;
if(port > (32 - 1))
reg = 0xD4019004;
if(port > (32 * 2 - 1))
reg = 0xD4019008;
if(port > (32 * 3 - 1))
reg = 0xD4019100;
reg += 0x0c;
port = port % 0x20;
ret = gpio_register_read(reg);
// 设置 输出 0 && 1
if(!(ret & (0x1 << port)) && dir)
{
gpio_register_write(reg, ret | (0x1 << port));
}
// 设置 输入 1 && 0
if((ret & (0x1 << port)) && !dir)
{
gpio_register_write(reg, ret | !(0x1 << port));
}
}
/*
设置GPIO 输出电平
读取电平状态,先读PLR寄存器:0x00
root@OpenWrt:/# hwacc r 0xD4019000
Option = r Addr = d4019000
Value read from 0xd4019000 via MVA=0x0xb6f1c000 is 0x81e82a30
对应下面具体BIT
1000 0001 1110 1000 0010 1010 0011 0000 BIT22默认电平高
设置输出高:设置PSR寄存器:0x18(只写寄存器)
root@OpenWrt:/# hwacc w 0xD4019018 0x400000
Option = w Addr = d4019018 Data=00400000
Value 00400000 written to 0xd4019018 via MVA=0x0xb6f56018 //bit22写1,输出高
设置输出低:设置PCR寄存器:0x24
root@OpenWrt:/# hwacc w 0xD4019024 0x400000
Option = w Addr = d4019024 Data=00400000
Value 00400000 written to 0xd4019024 via MVA=0x0xb6faa024 //Bit22写1,GPIO22输出低
*/
static void gpio_register_set_value(int port, int value)
{
int ret;
int reg = 0xD4019000;
if(port > (32 - 1))
reg = 0xD4019004;
if(port > (32 * 2 - 1))
reg = 0xD4019008;
if(port > (32 * 3 - 1))
reg = 0xD4019100;
if(value)
{
reg += 0x18;
}
else
reg += 0x24;
port = port % 0x20;
ret = gpio_register_read(reg);
// 设置 高电平 0 && 1
if(value)
{
gpio_register_write(reg, ret | (0x1 << port));
return;
}
// 设置 低电平 1 && 0
if(!(ret & (0x1 << port)) && !value)
{
gpio_register_write(reg, ret | (0x1 << port));
}
}
/*
读取电平状态,先读PLR寄存器:0x00
root@OpenWrt:/# hwacc r 0xD4019000
Option = r Addr = d4019000
Value read from 0xd4019000 via MVA=0x0xb6f1c000 is 0x81e82a30
对应下面具体BIT
1000 0001 1110 1000 0010 1010 0011 0000 BIT22默认电平高
*/
static int gpio_register_get_value(int port)
{
int ret = -1;
int reg = 0xD4019000;
if(port > (32 - 1))
reg = 0xD4019004;
if(port > (32 * 2 - 1))
reg = 0xD4019008;
if(port > (32 * 3 - 1))
reg = 0xD4019100;
port = port % 0x20;
ret = gpio_register_read(reg);
if(ret & (0x1 << port))
{
return 1;
}
return 0;
}
void gpio_debug_set(int enable)
{
gpio_debug = enable;
}
int gpio_register_test_out(int port, int value)
{
int ret;
gpio_log("Gpio port [%d] test start!\n", port);
ret = gpio_register_set_func_0(port);
if(ret)
{
printf("gpio_port can't support!\n");
return -1;
}
gpio_register_set_direction(port, 1);
ret = gpio_register_get_value(port);
gpio_log("gpio default value is : %d.\n", ret);
gpio_register_set_value(port, 1);
ret = gpio_register_get_value(port);
gpio_log("######gpio should is high: %d.######\n", ret);
if(1 != ret)
goto exit;
usleep(50);
gpio_register_set_value(port, 0);
ret = gpio_register_get_value(port);
gpio_log("######gpio should is low: %d.######\n", ret);
if(0 != ret)
{
goto exit;
}
exit:
gpio_register_set_direction(port, 0);
return ret;
}
int mbtk_at_gpio(void* arg)
{
int test_gpio[] = {33, 35, 36, 34, 82, 83, 81, /*41, 40, 39, 38, 37, 42,*/
21, 4, 122, 123, 20, 43, 13, 12, 14, 118, 19, 120,
49, 50, 32, 31, /*51, 52, */53, 54, 119, 23, 24, 27, 28, 26, 25, 5, 9,
0, 1, 2, 3, 6, 7, 15, 18, 16, 17,
126, 125, 56, 55, 58, 48, 57, 59, 117, 29, 30};
int i, ret, total, n = 0;
int *fail_io = (int *)arg;
total = (sizeof(test_gpio)/sizeof(int));
printf("Start test gpio total: %d\n", total);
for(i = 0; i < total; i++)
{
ret = gpio_register_test_out(test_gpio[i], 0);
if(-1 == ret)
{
LOGI("######gpio [%d] test failed!!!!!!######\n", test_gpio[i]);
fail_io[n] = test_gpio[i];
n++;
}else{
LOGI("######gpio [%d] test success!!!!!!######\n", test_gpio[i]);
}
}
return n;
}