目录
命令2 : cat /sys/kernel/debug/gpio
命令3 :cat /sys/kernel/debug/pinctrl/xxxxx/相关状态
QNX侧
GPIO-TLMM
测试命令:msmgpiotool
相关代码路径:
/SD-QNX4.5.6.0/apps/qnx_ap/AMSS/platform/services/applications/msmgpiotool/gpiotool.c
static void display_help(void)
{
fprintf(stdout, ""
"msmgpiotool\n"
" usage: gpiotool <command> <gpio> <arg>\n"
" Provides a mechanism to easily view and reconfigure GPIOs on the command line.\n"
" All GPIO Configuration commands can be used for island domain GPIOs by providing an additional agrument for the GPIO type.\n"
" By default all GPIO Configuration commands will run for TLMM GPIOs.\n"
" Ex: info <gpio number> <gpio type>\n"
" info 4 lpass\n\n"
"GPIO Configuration Commands:\n"
" dump \n"
" info <gpio number>\n"
" write <gpio number> <value>\n"
" read <gpio number>\n"
" set-dir <gpio number> <value>\n"
" set-drive <gpio number> <value>\n"
" set-pull <gpio number> <value>\n"
" set-func <gpio number> <value>\n\n"
"Interrupt Configuration Commands:\n"
" enable-irq <gpio number> <value>\n"
" clear-irq <gpio number>\n"
" set-pol <gpio number> <value>\n"
" set-trigger <gpio number> <value>\n\n"
"Description:\n"
" dump Prints the entire GPIO configuration table.\n\n"
" info Prints the configuration for the specified gpio.\n\n"
" write Set the value for the specified gpio.\n"
" [0] Low [1] High\n\n"
" read Prints the value for the specified gpio.\n\n"
" set-dir Sets the direction when in gpio mode\n"
" [0] Input, [1] Output\n\n"
" set-drive Sets the pin drive strength regardless of mode\n"
" drive strength = [n] * 2mA for n[0..15]\n\n"
" set-pull Sets internal pull on the pin regardless of mode\n"
" [0] No pull [1] Pull Down [2] Keeper [3] Pull Up\n\n"
" set-func Sets the pin function.\n"
" valid for n[0..15]\n\n"
" enable-irq Configures the pin as a gpio interrupt source\n"
" [0] Disable [1] Enable\n\n"
" clear-irq Clears the pending IRQ status\n\n"
" set-pol Sets the interrupt polarity of the gpio\n"
" [0] Inverted [1] Normal\n\n"
" set-trigger Sets the irq trigger type\n"
" [0] Level [1] Edge\n\n"
);
}
相关文档:
80-PH451-20_REV_B_GPIO_Configuration_User_Guide.pdf (qualcomm.com) page17
GPIO-PMIC
测试命令: pmicgpiotool
相关代码路径:
/SD-QNX4.5.6.0/apps/qnx_ap/AMSS/platform/services/applications/pmicgpiotool/pmicgpiotool.c
static const struct gpio_cfg {
uint32_t off;
uint32_t rmask;
uint32_t bmask;
const char* cmd;
const char** valid_values ;
const char* desc;
} cfgs [] = {
{
EN_CTL_OFF,
EN_CTL_RMSK,
EN_CTL_PERPH_EN_BMSK,
"gpio-master", gpio_master_values, "GPIO master enable" ,
},
{
DIG_OUT_SOURCE_CTL_OFF,
DIG_OUT_SOURCE_CTL_RMSK ,
DIG_OUT_SOURCE_CTL_OUTPUT_SOURCE_SEL_BMSK,
"source-select", output_source_select_values, "Output source select",
},
{
DIG_OUT_SOURCE_CTL_OFF,
DIG_OUT_SOURCE_CTL_RMSK,
DIG_OUT_SOURCE_CTL_OUTPUT_INVERT_BMSK,
"mode-inversion", mode_inversion_values, "Invert the output" ,
},
{
DIG_VIN_CTL_OFF,
DIG_VIN_CTL_RMSK,
DIG_VIN_CTL_VOLTAGE_SEL_BMSK,
"voltage-select", voltage_select_values, "Select Voltage source" ,
},
{
DIG_PULL_CTL_OFF,
DIG_PULL_CTL_RMSK,
DIG_PULL_CTL_PULLUP_SEL_BMSK,
"pullup-select", pullup_select_values, "Current source pulls",
},
{
DIG_OUT_DRV_CTL_OFF,
DIG_OUT_DRV_CTL_RMSK,
DIG_OUT_DRV_CTL_OUTPUT_TYPE_BMSK,
"output-type", output_type_values , "Output buffer configuration"
},
{
DIG_OUT_DRV_CTL_OFF,
DIG_OUT_DRV_CTL_RMSK,
DIG_OUT_SOURCE_CTL_OUTPUT_SOURCE_SEL_BMSK,
"output-drive-select", output_drive_select_values, "Output buffer drive strength"
},
{
MODE_CTL_OFF,
MODE_CTL_RMSK,
MODE_CTL_MODE_BMSK,
"mode", mode_values, "GPIO Mode",
},
{
INT_SET_TYPE_OFF,
INT_SET_TYPE_RMSK,
INT_SET_TYPE_GPIO_IN_TYPE_BMSK,
"in-set-type", in_set_type_values, "Trigger Interrupts types"
},
{
INT_POLARITY_HIGH_OFF,
INT_POLARITY_HIGH_RMSK,
INT_POLARITY_HIGH_GPIO_IN_HIGH_BMSK,
"int-polarity-high", int_polarity_high_values, "Interrupt High Level Trigger",
},
{
INT_POLARITY_LOW_OFF,
INT_POLARITY_LOW_RMSK,
INT_POLARITY_LOW_GPIO_IN_LOW_BMSK,
"int-polarity-low", int_polarity_low_values, "Interrupt Low Level Trigger"
},
{
INT_EN_SET_OFF,
INT_EN_SET_RMSK,
INT_EN_SET_GPIO_IN_EN_SET_BMSK,
"int-enable-set", int_en_set_and_clr_values,
"Enable the interrupt, writing 0 has no effect"
},
{
INT_EN_CLR_OFF,
INT_EN_CLR_RMSK,
INT_EN_CLR_GPIO_IN_EN_CLR_BMSK,
"int-enable-clear", int_en_set_and_clr_values,
"Disable the interrupt, writing 0 has no effect"
},
{
INT_MID_SEL_OFF,
INT_MID_SEL_RMSK,
INT_MID_SEL_INT_MID_SEL_BMSK,
"int-mid-select", int_mid_sel_values, "Selects the MID that will recieve interrupt"
},
{
INT_PRIORITY_OFF,
INT_PRIORITY_RMSK,
INT_PRIORITY_INT_PRIORITY_BMSK,
"int-priority", int_priority_values, "Sets the Interrupt Priority"
},
};
相关文档:
80-PH451-20_REV_B_GPIO_Configuration_User_Guide.pdf (qualcomm.com) page18
Android侧
对于TLMM和PMIC可使用相同的测试命令查看gpio信息
查看GPIO信息
命令1 : lsgpio
输出效果:
命令2 : cat /sys/kernel/debug/gpio
详细参考 Android&Linux GPIO控制方法_android gpio-CSDN博客 2.3章节 2.4章节
注意:需要先使用 mount -t debugfs nodev /sys/kernel/debug 挂载debug分区
输出效果:
命令3 :cat /sys/kernel/debug/pinctrl/xxxxx/相关状态
详细参考 Android&Linux GPIO控制方法_android gpio-CSDN博客 2.4章节
注意:需要先使用 mount -t debugfs nodev /sys/kernel/debug 挂载debug分区
配置GPIO信息
命令: gpio-setget
详细参考 Android&Linux GPIO控制方法_android gpio-CSDN博客 2.3 章节
高通没有自带此命令,需要自己组入代码,本质上还是使用的是ioctrl
/*! @ingroup gpiosetget */
/* @{ */
/*
* --------------------------------------------------------------------------
* INCLUDE FILES
* --------------------------------------------------------------------------
*/
/* -------------------- global header files --------------------------------- */
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>
/* ----------------------- private files ------------------------------------ */
#include "gpio-utils.h"
/*
* --------------------------------------------------------------------------
* PRIVATE DECLARATIONS Defined here, used only here
* --------------------------------------------------------------------------
*/
/* -------------------------- debugs ---------------------------------------- */
/* -------------------------- macros ---------------------------------------- */
/* -------------------------- type ------------------------------------------ */
/* -------------------------- struct ---------------------------------------- */
struct gpio_line_info {
char name[32];
int line;
int value;
};
/* -------------------------- prototype ------------------------------------- */
/* -------------------------- data ------------------------------------------ */
/* -------------------------- func ------------------------------------------ */
/**
* strtobool - string to boolean
*
* convert string to boolean value.
*
* Return:
* 0 if successful, otherwise a proper error code.
*/
static int strtobool(const char *s, bool *res)
{
if (!s)
return -EINVAL;
switch (s[0]) {
case 'y':
case 'Y':
case '1':
*res = true;
return 0;
case 'n':
case 'N':
case '0':
*res = false;
return 0;
case 'o':
case 'O':
switch (s[1]) {
case 'n':
case 'N':
*res = true;
return 0;
case 'f':
case 'F':
*res = false;
return 0;
default:
break;
}
default:
break;
}
return -EINVAL;
}
/**
* get_line_param - get line parameter
*
* parse GPIO line parameter.
*
* Return:
* 0 if successful, otherwise a proper error code.
*/
static int get_line_param(const char *option, struct gpio_line_info *line_info)
{
int ret = 0;
char *str = NULL;
do {
char *v, *e;
long line;
bool res;
if (!line_info) {
ret = -EINVAL;
break;
}
line_info->name[0] = 0;
line_info->line = -1;
line_info->value = -1;
str = strdup(option);
if (!str) {
ret = -errno;
break;
}
v = strchr(str, '=');
if (v) {
*v++ = '\0';
ret = strtobool(v, &res);
if (ret < 0)
break;
line_info->value = res ? 1 : 0;
}
line = strtol(str, &e, 0);
if (*e != '\0')
strlcpy(line_info->name, str, sizeof(line_info->name));
else
line_info->line = line;
} while (0);
if (str)
free(str);
return ret;
}
/**
* find_gpio_line - find gpio line
*
* find GPIO line on a named device.
*
* Return:
* 0 if successful, otherwise a proper error code.
*/
static int find_gpio_line(const char *device_name,
struct gpio_line_info *line_info)
{
int ret = 0;
char *chrdev_name = NULL;
int fd = -1;
do {
struct gpiochip_info cinfo;
struct gpioline_info linfo;
int i, start, end;
if (!device_name || !line_info) {
ret = -EINVAL;
break;
}
if ((line_info->name[0] == '\0') && (line_info->line < 0)) {
fprintf(stderr, "Invalid params\n");
ret = -EINVAL;
break;
}
/* create char dev string */
ret = asprintf(&chrdev_name, "/dev/%s", device_name);
if (ret < 0) {
ret = -ENOMEM;
break;
}
/* open GPIO chip */
fd = open(chrdev_name, 0);
if (fd == -1) {
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
break;
}
/* Inspect this GPIO chip */
ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo);
if (ret == -1) {
ret = -errno;
perror("Failed to issue CHIPINFO IOCTL\n");
break;
}
if (line_info->line >= 0) {
start = line_info->line;
end = start + 1;
} else {
start = 0;
end = cinfo.lines;
}
/* Loop over the lines and print info */
for (i = start; i < end; i++) {
memset(&linfo, 0, sizeof(linfo));
linfo.line_offset = i;
ret = ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &linfo);
if (ret == -1) {
ret = -errno;
perror("Failed to issue LINEINFO IOCTL\n");
break;
}
if (line_info->line >= 0) {
strlcpy(line_info->name, linfo.name,
sizeof(line_info->name));
ret = 0;
break;
}
if (!strcmp(linfo.name, line_info->name)) {
line_info->line = linfo.line_offset;
ret = 0;
break;
}
}
if (i >= end)
ret = -ENODEV;
} while (0);
if (fd >= 0)
close(fd);
if (chrdev_name)
free(chrdev_name);
return ret;
}
/**
* gpio_control_main - main function
*
* Control GPIO line.
*
* Return:
* 0 if successful, otherwise a proper error code.
*/
static int gpio_control_main(const char *device_name,
struct gpio_line_info *line_info)
{
int ret = 0;
int fd = -1;
do {
struct gpio_v2_line_config config;
struct gpio_v2_line_values lv;
/* validate gpio line */
ret = find_gpio_line(device_name, line_info);
if (ret)
break;
memset(&config, 0, sizeof(config));
config.flags = ((line_info->value >= 0)
? GPIO_V2_LINE_FLAG_OUTPUT
: GPIO_V2_LINE_FLAG_INPUT);
fd = gpiotools_request_line(device_name,
(unsigned int *)&line_info->line, 1,
&config, "gpiosetget");
if (fd < 0) {
ret = fd;
break;
}
memset(&lv, 0, sizeof(lv));
gpiotools_set_bit(&lv.mask, 0);
if (line_info->value >= 0) {
/* set */
(line_info->value == 1)
? gpiotools_set_bit(&lv.bits, 0)
: gpiotools_clear_bit(&lv.bits, 0);
ret = gpiotools_set_values(fd, &lv);
} else {
/* get */
ret = gpiotools_get_values(fd, &lv);
}
if (ret < 0)
break;
fprintf(stdout, "line %2d(%s) = %d\n",
line_info->line, line_info->name, gpiotools_test_bit(lv.bits, 0));
} while (0);
if (fd >= 0)
gpiotools_release_line(fd);
return ret;
}
/**
* print_usage - show usage
*
* Show ussage.
*
* Return:
* None.
*/
static void print_usage(const char *name)
{
fprintf(stderr, "Usage: %s [options]...\n"
"set/get GPIO line states\n"
" -n <name> Set/Get GPIOs on a named device\n"
" -l <offset>[=<value>] Offset (and value) to set/get\n"
" -l <linename>[=<value>] Linename (and value) to set/get\n"
" -? This helptext\n",
name
);
}
/**
* main
*
* Entry point.
*
* Return:
* 0 if successful, otherwise a proper error code.
*/
int main(int argc, char **argv)
{
int ret = 0;
const char *device_name = NULL;
struct gpio_line_info line_info = { .line = -1, .name[0] = '\0', };
int c;
while ((c = getopt(argc, argv, "n:l:?h")) != -1) {
switch (c) {
case 'n':
device_name = optarg;
break;
case 'l':
ret = get_line_param(optarg, &line_info);
if (ret) {
fprintf(stderr, "Invalid params\n");
return ret;
}
break;
case '?':
case 'h':
print_usage(argv[0]);
return 0;
default:
print_usage(argv[0]);
return -1;
}
}
return gpio_control_main(device_name, &line_info);
}
使用示例:
读gpio电平状态高低
gpio-setget -n <gpiochipx> -l <gpio-line-num>
写gpio电平状态为高
gpio-setget -n <gpiochipx> -l <gpio-line-num> = 1
PS :
高通某些test工具组入需要 更改Android.dp文件
可参考路径 /SD-HQX4.5.6.0/lagvm/LINUX/android/kernel_platform/msm-kernel/Android.bp