高通8255 GPIO 测试方法

目录

QNX侧

GPIO-TLMM

测试命令:msmgpiotool

相关代码路径:

相关文档:

GPIO-PMIC

测试命令: pmicgpiotool

相关代码路径:

相关文档:

Android侧

查看GPIO信息

命令1 : lsgpio

命令2 : cat /sys/kernel/debug/gpio

命令3 :cat /sys/kernel/debug/pinctrl/xxxxx/相关状态

配置GPIO信息

命令: gpio-setget

使用示例:

PS :


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 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值