SmartAudio/lichee/linux-4.9/drivers/pinctrl/sunxi/pinctrl-sunxi-test.c

1696 lines
52 KiB
C
Executable File

/*
* Allwinner SoCs pinctrl driver.
*
* Copyright (C) 2013 Shaorui Huang
*
* Shaorui Huang<huangshr@allwinnertech.com>
* 2013-06-10 add sunxi pinctrl testing case.
*
* WimHuang<huangwei@allwinnertech.com>
* 2015-07-20 transplant it from linux-3.4 to linux-3.10.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/sunxi-gpio.h>
#include "../core.h"
#define SUNXI_DEV_NAME_MAX_LEN 20
#define SUNXI_FUNC_NAME_MAX_LEN 80
struct sunxi_pctrltest_data {
char dev_name[SUNXI_DEV_NAME_MAX_LEN];
char exec[SUNXI_FUNC_NAME_MAX_LEN];
struct completion done;
int result;
int gpio_index;
int funcs;
int pull;
int data;
int dlevel;
};
struct sunxi_pctrltest_case {
const char *name;
int (*func)(void);
};
/*
* struct sunxi_gpio_config - gpio config info
* @name: gpio name
* @mul_sel: multi sel val: 0 - input, 1 - output.
* @pull: pull val: 0 - pull up/down disable, 1 - pull up
* @drive: driver level val: 0 - level 0, 1 - level 1
* @data: data val: 0 - low, 1 - high, only valid when mul_sel is input/output
*/
struct sunxi_gpio_config {
const char *name;
u32 mulsel;
u32 pull;
u32 drive;
u32 data;
};
static struct sunxi_pctrltest_data *sunxi_ptest_data;
static int dt_node_to_gpio(struct device_node *np_cfg,
struct sunxi_gpio_config **gpio_list,
unsigned *gpio_count)
{
struct property *prop = NULL;
const char *name = NULL;
int val;
int i = 0;
*gpio_count = of_property_count_strings(np_cfg, "allwinner,pins");
if (*gpio_count < 0) {
pr_warn("missing allwinner,pins property in node %s\n",
np_cfg->name);
return -EINVAL;
}
*gpio_list = kmalloc_array(*gpio_count, sizeof(struct sunxi_gpio_config), GFP_KERNEL);
if (!*gpio_list) {
pr_warn("No enougt memory for gpio_list\n");
return -ENOMEM;
}
of_property_for_each_string(np_cfg, "allwinner,pins", prop, name) {
(*gpio_list)[i].name = name;
if (of_property_read_u32(np_cfg, "allwinner,muxsel", &val)) {
pr_warn("missing allwinner,mux property in node %s\n",
np_cfg->name);
return -EINVAL;
}
(*gpio_list)[i].mulsel = val;
if (of_property_read_u32(np_cfg, "allwinner,drive", &val)) {
pr_warn("missing allwinner,dirve property in node %s\n",
np_cfg->name);
return -EINVAL;
}
(*gpio_list)[i].drive = val;
if (of_property_read_u32(np_cfg, "allwinner,pull", &val)) {
pr_warn("missing allwinner,pull property in node %s\n",
np_cfg->name);
return -EINVAL;
}
(*gpio_list)[i].pull = val;
if (of_property_read_u32(np_cfg, "allwinner,data", &val)) {
pr_warn("missing allwinner,data property in node %s\n",
np_cfg->name);
return -EINVAL;
}
(*gpio_list)[i].data = val;
i++;
}
return 0;
}
static int dt_get_gpio_list(struct device_node *np,
struct sunxi_gpio_config **gpio_list,
unsigned *gpio_count)
{
struct property *prop;
int size;
const __be32 *list;
struct device_node *np_cfg;
phandle phandle;
int ret;
int i;
/* only need pin whose state is default */
prop = of_find_property(np, "pinctrl-0", &size);
if (!prop) {
pr_warn("missing pinctrl-0 property in node %s\n", np->name);
return -EINVAL;
}
list = prop->value;
size /= sizeof(*list);
/* For every referenced pin configuration node in it */
for (i = 0; i < size; i++) {
phandle = be32_to_cpup(list++);
/* Look up the pin configuration node */
np_cfg = of_find_node_by_phandle(phandle);
if (!np_cfg) {
pr_warn("prop %s index 0 invalid phandle\n", prop->name);
return -EINVAL;
}
/* Parse the node */
ret = dt_node_to_gpio(np_cfg, gpio_list, gpio_count);
if (ret < 0)
return -EINVAL;
}
return 0;
}
static irqreturn_t sunxi_pinctrl_irq_handler_demo1(int irq, void *dev_id)
{
pr_warn("-----------------------------------------------\n");
pr_warn("%s: demo1 for test pinctrl repeat eint api.\n", __func__);
pr_warn("-----------------------------------------------\n");
disable_irq_nosync(irq);
complete(&sunxi_ptest_data->done);
return IRQ_HANDLED;
}
static irqreturn_t sunxi_pinctrl_irq_handler_demo2(int irq, void *dev_id)
{
pr_warn("-----------------------------------------------\n");
pr_warn("%s: demo2 for test pinctrl repeat eint api.\n", __func__);
pr_warn("-----------------------------------------------\n");
disable_irq_nosync(irq);
return IRQ_HANDLED;
}
static int pctrltest_request_all_resource(void)
{
struct device *dev;
struct device_node *node;
struct pinctrl *pinctrl;
struct sunxi_gpio_config *gpio_list = NULL;
struct sunxi_gpio_config *gpio_cfg;
unsigned gpio_count = 0;
unsigned gpio_index;
unsigned long config;
int ret;
dev = bus_find_device_by_name(&platform_bus_type, NULL, sunxi_ptest_data->dev_name);
if (!dev) {
pr_warn("find device [%s] failed...\n", sunxi_ptest_data->dev_name);
return -EINVAL;
}
node = of_find_node_by_type(NULL, dev_name(dev));
if (!node) {
pr_warn("find node for device [%s] failed...\n", dev_name(dev));
return -EINVAL;
}
dev->of_node = node;
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("device[%s] all pin resource we want to request\n", dev_name(dev));
pr_warn("-----------------------------------------------\n");
pr_warn("step1: request pin all resource.\n");
pinctrl = devm_pinctrl_get_select_default(dev);
if (IS_ERR_OR_NULL(pinctrl)) {
pr_warn("request pinctrl handle for device [%s] failed...\n", dev_name(dev));
return -EINVAL;
}
pr_warn("step2: get device[%s] pin count.\n", dev_name(dev));
ret = dt_get_gpio_list(node, &gpio_list, &gpio_count);
if (ret < 0 || gpio_count == 0) {
pr_warn(" devices own 0 pin resource or look for main key failed!\n");
return -EINVAL;
}
pr_warn("step3: get device[%s] pin configure and check.\n", dev_name(dev));
for (gpio_index = 0; gpio_index < gpio_count; gpio_index++) {
gpio_cfg = &gpio_list[gpio_index];
/*check function config */
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, gpio_cfg->name, &config);
if (gpio_cfg->mulsel != SUNXI_PINCFG_UNPACK_VALUE(config)) {
pr_warn("failed! mul value isn't equal as dt.\n");
return -EINVAL;
}
/*check pull config */
if (gpio_cfg->pull != GPIO_PULL_DEFAULT) {
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, gpio_cfg->name, &config);
if (gpio_cfg->pull != SUNXI_PINCFG_UNPACK_VALUE(config)) {
pr_warn("failed! pull value isn't equal as dt.\n");
return -EINVAL;
}
}
/*check dlevel config */
if (gpio_cfg->drive != GPIO_DRVLVL_DEFAULT) {
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, gpio_cfg->name, &config);
if (gpio_cfg->drive != SUNXI_PINCFG_UNPACK_VALUE(config)) {
pr_warn("failed! dlevel value isn't equal as dt.\n");
return -EINVAL;
}
}
/*check data config */
if (gpio_cfg->data != GPIO_DATA_DEFAULT) {
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, gpio_cfg->name, &config);
if (gpio_cfg->data != SUNXI_PINCFG_UNPACK_VALUE(config)) {
pr_warn("failed! pin data value isn't equal as dt.\n");
return -EINVAL;
}
}
}
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl request all resource success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_re_request_all_resource(void)
{
struct device *dev;
struct device_node *node;
struct pinctrl *pinctrl_1;
struct pinctrl *pinctrl_2;
dev = bus_find_device_by_name(&platform_bus_type, NULL, sunxi_ptest_data->dev_name);
if (!dev) {
pr_warn("find device [%s] failed...\n", sunxi_ptest_data->dev_name);
return -EINVAL;
}
node = of_find_node_by_type(NULL, dev_name(dev));
if (!node) {
pr_warn("find node for device [%s] failed...\n", dev_name(dev));
return -EINVAL;
}
dev->of_node = node;
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("device[%s] all pin resource we want to repeat request\n", dev_name(dev));
pr_warn("-----------------------------------------------\n");
pr_warn("step1: first time request pin all resource.\n");
/*request all resource */
pinctrl_1 = devm_pinctrl_get_select_default(dev);
if (IS_ERR_OR_NULL(pinctrl_1)) {
pr_warn("request pinctrl handle for device [%s] failed!\n", dev_name(dev));
return -EINVAL;
}
/*repeat request */
pr_warn("step2: secondary request pin all resource.\n");
pinctrl_2 = devm_pinctrl_get_select_default(dev);
if (IS_ERR_OR_NULL(pinctrl_2)) {
pr_warn("repeat request device[%s] all pin resource failed\n", dev_name(dev));
return -EINVAL;
}
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl repeat request all resource success.\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_request_gpio(void)
{
int req_status;
int gpio_index;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
pinctrl_free_gpio(gpio_index);
/* request signal pin as gpio*/
pr_warn("step1: pinctrl request gpio[%s]\n", pin_name);
req_status = pinctrl_request_gpio(gpio_index);
if (req_status != 0) {
pr_warn("pinctrl request gpio failed! return value %d\n", req_status);
return -EINVAL;
}
pr_warn(" pinctrl request gpio[%s] success\n", pin_name);
pinctrl_free_gpio(gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl request gpio api success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_free_gpio(void)
{
int req_status;
int gpio_index;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
pinctrl_free_gpio(gpio_index);
/*request signal pin as gpio*/
pr_warn("step1: pinctrl request gpio[%s]\n", pin_name);
req_status = pinctrl_request_gpio(gpio_index);
if (req_status != 0) {
pr_warn("pinctrl request gpio failed !return value %d\n", req_status);
return -EINVAL;
}
pr_warn(" pinctrl request gpio[%s]success\n", pin_name);
pr_warn("step2: pinctrl free gpio[%s]\n", pin_name);
pinctrl_free_gpio(gpio_index);
pr_warn("step3: pinctrl request the same gpio[%s] again..\n", pin_name);
req_status = pinctrl_request_gpio(gpio_index);
if (req_status != 0) {
pr_warn("pinctrl request gpio failed !return value %d\n", req_status);
return -EINVAL;
}
pr_warn(" pinctrl request gpio[%s] again success.\n", pin_name);
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl free gpio api success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
pinctrl_free_gpio(gpio_index);
return 0;
}
static int pctrltest_lookup_state(void)
{
struct device *dev;
struct pinctrl *pinctrl;
struct pinctrl_state *state;
char device_name[SUNXI_DEV_NAME_MAX_LEN];
dev = bus_find_device_by_name(&platform_bus_type, NULL, sunxi_ptest_data->dev_name);
if (!dev) {
pr_warn("find device [%s] failed...\n", sunxi_ptest_data->dev_name);
return -EINVAL;
}
dev_set_name(dev, sunxi_ptest_data->dev_name);
strcpy(device_name, sunxi_ptest_data->dev_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("device[%s] test lookup state api\n", dev_name(dev));
pr_warn("-----------------------------------------------\n");
pr_warn("step1: get pinctrl handle.\n");
pinctrl = pinctrl_get(dev);
if (IS_ERR_OR_NULL(pinctrl)) {
pr_warn("get pinctrl handle [%s] failed...,return value %ld\n",
device_name, PTR_ERR(pinctrl));
return -EINVAL;
}
pr_warn("step2: printk pinctrl current state.\n");
pr_warn(" device: %s current state: %s\n", dev_name(pinctrl->dev),
pinctrl->state ? pinctrl->state->name : "none");
pr_warn("step3: pinctrl lookup state(default state name: default).\n");
state = pinctrl_lookup_state(pinctrl, "default");
if (IS_ERR(state)) {
pr_warn("can not find state: default.\n");
return -EINVAL;
}
pr_warn("step4: check the state we lookup if the one needed.\n");
if (strcmp(state->name, "default")) {
pr_warn("find state,but isn't the one we need.\n");
return -EINVAL;
}
pinctrl_put(pinctrl);
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl look up state api success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_select_state(void)
{
struct device *dev;
struct pinctrl *pinctrl;
struct pinctrl_state *state;
char device_name[SUNXI_DEV_NAME_MAX_LEN];
int req_status;
dev = bus_find_device_by_name(&platform_bus_type, NULL, sunxi_ptest_data->dev_name);
if (!dev) {
pr_warn("find device [%s] failed...\n", sunxi_ptest_data->dev_name);
return -EINVAL;
}
dev_set_name(dev, sunxi_ptest_data->dev_name);
strcpy(device_name, sunxi_ptest_data->dev_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("device[%s] test select state api\n", dev_name(dev));
pr_warn("-----------------------------------------------\n");
pr_warn("step1: get pinctrl handle.\n");
pinctrl = pinctrl_get(dev);
if (IS_ERR_OR_NULL(pinctrl)) {
pr_warn("get pinctrl handle [%s] failed..., return value %ld\n",
device_name, PTR_ERR(pinctrl));
return -EINVAL;
}
pr_warn("step2: printk pinctrl current state.\n");
pr_warn(" device: %s current state: %s\n", dev_name(pinctrl->dev),
pinctrl->state ? pinctrl->state->name : "none");
pr_warn("step3: pinctrl lookup state(default state name: default).\n");
state = pinctrl_lookup_state(pinctrl, "default");
if (IS_ERR(state)) {
pinctrl_put(pinctrl);
pr_warn("can not find state: default.\n");
return -EINVAL;
}
pr_warn("step4: check the state we lookup if the one needed.\n");
if (strcmp(state->name, "default")) {
pinctrl_put(pinctrl);
pr_warn("find state,but isn't the one we need.\n");
return -EINVAL;
}
pr_warn("step5: select state for pinctrl handle.\n");
req_status = pinctrl_select_state(pinctrl, state);
if (req_status < 0) {
pinctrl_put(pinctrl);
pr_warn("pinctrl select state failed. return value %d.\n", req_status);
}
pinctrl_put(pinctrl);
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl select state api success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_get(void)
{
struct device *dev;
struct pinctrl *pinctrl;
struct pinctrl_state *state;
struct pinctrl_setting *setting;
char device_name[SUNXI_DEV_NAME_MAX_LEN];
dev = bus_find_device_by_name(&platform_bus_type, NULL, sunxi_ptest_data->dev_name);
if (!dev) {
pr_warn("find device [%s] failed...\n", sunxi_ptest_data->dev_name);
return -EINVAL;
}
dev_set_name(dev, sunxi_ptest_data->dev_name);
strcpy(device_name, sunxi_ptest_data->dev_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("device[%s] test pinctrl get api\n", dev_name(dev));
pr_warn("-----------------------------------------------\n");
pr_warn("step1: get pinctrl handle.\n");
pinctrl = pinctrl_get(dev);
if (IS_ERR_OR_NULL(pinctrl)) {
pr_warn("get pinctrl handle [%s] failed..., return value %ld\n",
dev_name(dev), PTR_ERR(pinctrl));
return -EINVAL;
}
pr_warn("step2: check pinctrl handle we have getted.\n");
if (dev_name(dev) != dev_name(pinctrl->dev)) {
pinctrl_put(pinctrl);
pr_warn("check: pinctrl handle isn't that one we want\n ");
return -EINVAL;
}
pr_warn("step3: get current statep.\n");
pr_warn(" device: %s current state: %s\n", dev_name(pinctrl->dev),
pinctrl->state ? pinctrl->state->name : "none");
list_for_each_entry(state, &pinctrl->states, node) {
pr_warn("state: %s\n", state->name);
list_for_each_entry(setting, &state->settings, node) {
struct pinctrl_dev *pctldev = setting->pctldev;
pr_warn(" setting type: %d pin controller %s\n",
setting->type, pinctrl_dev_get_name(pctldev));
}
}
pinctrl_put(pinctrl);
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl get api success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_put(void)
{
struct device *dev;
struct pinctrl *pinctrl;
struct pinctrl_state *state;
struct pinctrl_setting *setting;
char device_name[SUNXI_DEV_NAME_MAX_LEN];
dev = bus_find_device_by_name(&platform_bus_type, NULL, sunxi_ptest_data->dev_name);
if (!dev) {
pr_warn("find device [%s] failed...\n", sunxi_ptest_data->dev_name);
return -EINVAL;
}
dev_set_name(dev, sunxi_ptest_data->dev_name);
strcpy(device_name, sunxi_ptest_data->dev_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("device[%s] test pinctrl put api\n", dev_name(dev));
pr_warn("-----------------------------------------------\n");
pr_warn("step1: get pinctrl handle.\n");
pinctrl = pinctrl_get(dev);
if (IS_ERR_OR_NULL(pinctrl)) {
pr_warn("get pinctrl handle [%s] failed...,return value %ld\n",
device_name, PTR_ERR(pinctrl));
return -EINVAL;
}
pr_warn("step2: check pinctrl handle we have getted.\n");
if (dev_name(dev) != dev_name(pinctrl->dev)) {
pinctrl_put(pinctrl);
pr_warn("check: pinctrl handle isn't that one we want\n");
return -EINVAL;
}
pr_warn("step3: get current statep.\n");
pr_warn(" device: %s current state: %s\n", dev_name(pinctrl->dev),
pinctrl->state ? pinctrl->state->name : "none");
list_for_each_entry(state, &pinctrl->states, node) {
pr_warn("state: %s\n", state->name);
list_for_each_entry(setting, &state->settings, node) {
struct pinctrl_dev *pctldev = setting->pctldev;
pr_warn(" setting type: %d pin controller %s\n",
setting->type, pinctrl_dev_get_name(pctldev));
}
}
pr_warn("step4: free pinctrl handle we have getted.\n");
pinctrl_put(pinctrl);
pr_warn("step5: then repeat get. if get success, previous free operate success.\n");
pinctrl = pinctrl_get(dev);
if (IS_ERR_OR_NULL(pinctrl)) {
pr_warn(" after free, we repeat get pinctrl handle [%s] failed..., return value %ld\n",
device_name, PTR_ERR(pinctrl));
return -EINVAL;
}
pinctrl_put(pinctrl);
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl put api success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_devm_get_and_put(void)
{
struct device *dev;
struct pinctrl *pinctrl;
struct pinctrl_state *state;
struct pinctrl_setting *setting;
char device_name[SUNXI_DEV_NAME_MAX_LEN];
dev = bus_find_device_by_name(&platform_bus_type, NULL, sunxi_ptest_data->dev_name);
if (!dev) {
pr_warn("find device [%s] failed...\n", sunxi_ptest_data->dev_name);
return -EINVAL;
}
dev_set_name(dev, sunxi_ptest_data->dev_name);
strcpy(device_name, sunxi_ptest_data->dev_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("device[%s] test pinctrl devm get and put api\n", dev_name(dev));
pr_warn("-----------------------------------------------\n");
pr_warn("step1: devm get pinctrl handle.\n");
pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(pinctrl)) {
pr_warn("get pinctrl handle [%s] failed..., return value %ld\n",
device_name, PTR_ERR(pinctrl));
return -EINVAL;
}
pr_warn("step2: check pinctrl handle we have getted.\n");
if (dev_name(dev) != dev_name(pinctrl->dev)) {
devm_pinctrl_put(pinctrl);
pr_warn("check: pinctrl handle isn't that one we want\n ");
return -EINVAL;
}
pr_warn("step3: get current statep.\n");
pr_warn(" device: %s current state: %s\n", dev_name(pinctrl->dev),
pinctrl->state ? pinctrl->state->name : "none");
list_for_each_entry(state, &pinctrl->states, node) {
pr_warn("state: %s\n", state->name);
list_for_each_entry(setting, &state->settings, node) {
struct pinctrl_dev *pctldev = setting->pctldev;
pr_warn(" setting type: %d pin controller %s\n",
setting->type, pinctrl_dev_get_name(pctldev));
}
}
pr_warn("step4: devm free pinctrl handle we have getted.\n");
devm_pinctrl_put(pinctrl);
pr_warn("step5: then repeat get. if get success, previous free operate success.\n");
pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(pinctrl)) {
pr_warn(" after free,we repeat get pinctrl handle [%s] failed..., return value %ld\n",
device_name, PTR_ERR(pinctrl));
return -EINVAL;
}
devm_pinctrl_put(pinctrl);
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl devm get and put api success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_function_set(void)
{
unsigned long config_set;
unsigned long config_get;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int func;
func = sunxi_ptest_data->funcs;
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("pin function we want to set:\n");
pr_warn(" gpio name: %s gpio index: %d gpio function: %d\n",
pin_name, sunxi_ptest_data->gpio_index, func);
pr_warn("-----------------------------------------------\n");
/*check if pin mul setting right */
pr_warn("step1: get [%s] function value.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
pr_warn(" [%s] function value: %ld\n", pin_name, SUNXI_PINCFG_UNPACK_VALUE(config_get));
pr_warn("step2: set [%s] function value to %d\n", pin_name, func);
config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, func);
pin_config_set(SUNXI_PINCTRL, pin_name, config_set);
pr_warn("step3: get [%s] function value and check.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
if (func != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {
pr_warn("test pin config for mul setting failed !\n");
return -EINVAL;
}
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl function set success !\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_data_set(void)
{
unsigned long config_set;
unsigned long config_get;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int data;
data = sunxi_ptest_data->data;
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("pin data we want to set:\n");
pr_warn(" gpio name: %s gpio index: %d gpio data: %d\n",
pin_name, sunxi_ptest_data->gpio_index, data);
pr_warn("-----------------------------------------------\n");
/*check if pin data setting right */
pr_warn("step1: get [%s] data value.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
pr_warn(" [%s] data value: %ld\n", pin_name, SUNXI_PINCFG_UNPACK_VALUE(config_get));
pr_warn("step2: set [%s] data value to %d\n", pin_name, data);
config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, data);
pin_config_set(SUNXI_PINCTRL, pin_name, config_set);
pr_warn("step3: get [%s] data value and check.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
if (data != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {
pr_warn("test pin config for dlevel setting failed !\n");
return -EINVAL;
}
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl data set success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_pull_set(void)
{
unsigned long config_set;
unsigned long config_get;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int pull;
pull = sunxi_ptest_data->pull;
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("pin data we want to set:\n");
pr_warn(" gpio name: %s gpio index: %d gpio pull: %d\n",
pin_name, sunxi_ptest_data->gpio_index, pull);
pr_warn("-----------------------------------------------\n");
/*check if pin pull setting right */
pr_warn("step1: get [%s] pull value.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
pr_warn(" [%s] pull value: %ld\n", pin_name, SUNXI_PINCFG_UNPACK_VALUE(config_get));
pr_warn("step2: set [%s] pull value to %d\n", pin_name, pull);
config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, pull);
pin_config_set(SUNXI_PINCTRL, pin_name, config_set);
pr_warn("step3: get [%s] function value and check.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
if (pull != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {
pr_warn("test pin config for pull setting failed !\n");
return -EINVAL;
}
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl pull set success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_dlevel_set(void)
{
unsigned long config_set;
unsigned long config_get;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int dlevel;
dlevel = sunxi_ptest_data->dlevel;
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("pin data we want to set:\n");
pr_warn(" gpio name: %s gpio index: %d gpio dlevel: %d\n",
pin_name, sunxi_ptest_data->gpio_index, dlevel);
pr_warn("-----------------------------------------------\n");
/*check if pin dlevel setting right */
pr_warn("step1: get [%s] dlevel value.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
pr_warn(" [%s] dlevel value: %ld\n", pin_name, SUNXI_PINCFG_UNPACK_VALUE(config_get));
pr_warn("step2: set [%s] dlevel value to %d\n", pin_name, dlevel);
config_set = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, dlevel);
pin_config_set(SUNXI_PINCTRL, pin_name, config_set);
pr_warn("step3: get [%s] dlevel value and check.\n", pin_name);
config_get = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, 0XFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config_get);
if (dlevel != SUNXI_PINCFG_UNPACK_VALUE(config_get)) {
pr_warn("test pin config for dlevel setting failed !\n");
return -EINVAL;
}
pr_warn("-----------------------------------------------\n");
pr_warn("test pinctrl drive level set success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_direction_input(void)
{
int gpio_index;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int req_status;
int direct_status;
unsigned long config;
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pinctrl_free_gpio(gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("step1: Pinctrl request gpio.\n");
req_status = pinctrl_request_gpio(gpio_index);
if (req_status != 0) {
pr_warn("pinctrl request gpio failed !return value %d\n", req_status);
return -EINVAL;
}
pr_warn("step2: Set gpio direction input.\n");
direct_status = pinctrl_gpio_direction_input(gpio_index);
if (IS_ERR_VALUE(direct_status)) {
pr_warn("set pinctrl gpio direction input failed! return value: %d\n",
direct_status);
return -EINVAL;
}
pr_warn("step3: Get pin mux value and check.\n");
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config);
if (SUNXI_PINCFG_UNPACK_VALUE(config) != 0) {
pr_warn("check: set pin direction input failed !\n");
return -EINVAL;
}
pr_warn("step4: Pinctrl free gpio.\n");
pinctrl_free_gpio(gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("test gpio direction input success!\n");
pr_warn("+++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_direction_output(void)
{
int gpio_index;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int req_status;
int direct_status;
unsigned long config;
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
pinctrl_free_gpio(gpio_index);
pr_warn("step1: Pinctrl request gpio.\n");
req_status = pinctrl_request_gpio(gpio_index);
if (req_status != 0) {
pr_warn("pinctrl request gpio failed !return value %d\n", req_status);
return -EINVAL;
}
pr_warn("step2: Set gpio direction output.\n");
direct_status = pinctrl_gpio_direction_output(gpio_index);
if (IS_ERR_VALUE(direct_status)) {
pr_warn("set pinctrl gpio direction output failed! return value: %d\n",
direct_status);
return -EINVAL;
}
pr_warn("step3: Get pin mux value and check.\n");
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config);
if (SUNXI_PINCFG_UNPACK_VALUE(config) != 1) {
pr_warn("check: set pinctrl gpio direction output failed !\n");
return -EINVAL;
}
pr_warn("step4: Pinctrl free gpio.\n");
pinctrl_free_gpio(gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("test gpio direction output success!\n");
pr_warn("+++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int pctrltest_request_eint(void)
{
int ret;
int virq;
int gpio_index;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int trigger;
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(gpio_index, pin_name);
reinit_completion(&sunxi_ptest_data->done);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("step1: request gpio [%s].\n", pin_name);
ret = gpio_request(gpio_index, NULL);
if (ret != 0) {
pr_warn("gpio request failed\n");
return -EINVAL;
}
gpio_direction_input(gpio_index);
trigger = gpio_get_value_cansleep(gpio_index);
pr_warn("step2: get gpio[%s] trigger level:0x%x\n", pin_name, trigger);
trigger = trigger ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW;
gpio_free(gpio_index);
pr_warn("step3: generate virtual irq number.\n");
virq = gpio_to_irq(gpio_index);
if (IS_ERR_VALUE(virq)) {
pr_warn("map gpio [%d] to virq [%d] failed !\n ", gpio_index, virq);
return -EINVAL;
}
pr_warn("step4: request irq(%s level).\n",
trigger == IRQF_TRIGGER_HIGH ? "high" : "low");
ret = request_irq(virq, sunxi_pinctrl_irq_handler_demo1,
trigger, "PIN_EINT", NULL);
if (IS_ERR_VALUE(ret)) {
pr_warn("request irq failed !\n");
return -EINVAL;
}
pr_warn("step5: wait for irq.\n");
ret = wait_for_completion_timeout(&sunxi_ptest_data->done, HZ);
if (ret == 0) {
pr_warn("wait for irq timeout!\n");
free_irq(virq, NULL);
return -EINVAL;
}
free_irq(virq, NULL);
pr_warn("-----------------------------------------------\n");
pr_warn("test pin eint success !\n");
pr_warn("+++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n\n");
return 0;
}
static int pctrltest_re_request_eint(void)
{
int ret;
int virq;
int gpio_index;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int trigger;
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("step1: request gpio [%s].\n", pin_name);
ret = gpio_request(gpio_index, NULL);
if (ret != 0) {
pr_warn("gpio request failed\n");
return -EINVAL;
}
gpio_direction_input(gpio_index);
trigger = gpio_get_value_cansleep(gpio_index);
pr_warn("step2: get gpio[%s] trigger level:0x%x\n", pin_name, trigger);
trigger = trigger ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW;
gpio_free(gpio_index);
pr_warn("step3: generate virtual irq number.\n");
virq = gpio_to_irq(gpio_index);
if (IS_ERR_VALUE(virq)) {
pr_warn("map gpio [%d] to virq [%d] failed !\n ", gpio_index, virq);
return -EINVAL;
}
pr_warn("step4: first time request irq(%s level trigger).\n",
trigger == IRQF_TRIGGER_HIGH ? "high" : "low");
ret = request_irq(virq, sunxi_pinctrl_irq_handler_demo1,
trigger, "PIN_EINT", NULL);
if (IS_ERR_VALUE(ret)) {
free_irq(virq, NULL);
pr_warn("test pin request irq failed !\n");
return -EINVAL;
}
pr_warn("step5: repeat request irq(%s level trigger).\n",
trigger == IRQF_TRIGGER_HIGH ? "high" : "low");
ret = request_irq(virq, sunxi_pinctrl_irq_handler_demo2,
trigger, "PIN_EINT", NULL);
free_irq(virq, NULL);
if (!IS_ERR_VALUE(ret)) {
pr_warn(" repeat request irq success!\n\n");
pr_warn("test failed! for repeat request is umpermitted.\n");
return -EINVAL;
}
pr_warn(" repeat request irq failed!\n");
pr_warn("test success! for repeat request is umpermitted.\n");
pr_warn("-----------------------------------------------\n");
pr_warn("test picntrl repeat eint success!\n");
pr_warn("+++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int gpiotest_request_free(void)
{
int gpio_index;
int req_status;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("step1: request gpio[%s]\n", pin_name);
gpio_free(gpio_index);
req_status = gpio_request(gpio_index, NULL);
if (req_status != 0) {
pr_warn("gpio request failed !return value %d\n", req_status);
return -EINVAL;
}
pr_warn(" request gpio[%s] success\n", pin_name);
pr_warn("step2: free gpio[%s]\n", pin_name);
gpio_free(gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("test gpio request and free success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int gpiotest_re_request_free(void)
{
int gpio_index;
int req_status;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("step1: first time request gpio[%s]\n", pin_name);
req_status = gpio_request(gpio_index, NULL);
if (req_status != 0) {
pr_warn(" first time request gpio [%s]failed !\n", pin_name);
return -EINVAL;
}
pr_warn(" first time request gpio[%s] success!\n", pin_name);
pr_warn("step2: repeat request gpio[%s]\n", pin_name);
req_status = gpio_request(gpio_index, NULL);
if (!req_status) {
pr_warn(" repeat request gpio[%s] success.\n", pin_name);
pr_warn("test failed: for repeat request is unpermitted.\n");
return -EINVAL;
}
pr_warn(" repeat request gpio [%s] failed.\n", pin_name);
pr_warn("test success: for repeat request is unpermitted.\n");
pr_warn("-----------------------------------------------\n");
pr_warn("test gpio repeat request and free success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
gpio_free(gpio_index);
return 0;
}
static int gpiotest_set_debounce(void)
{
int gpio_index;
int req_status;
int get_status;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
/*
* test gpio set debounce api
*/
pr_warn("step1: request gpio.\n");
req_status = gpio_request(gpio_index, NULL);
if (req_status != 0) {
pr_warn("gpio request failed !\n");
return -EINVAL;
}
pr_warn("step2: set gpio debounce value 0x11.\n");
get_status = gpio_set_debounce(gpio_index, 0x11);
if (get_status) {
pr_warn(" gpio set debounce failed! return value: %d\n", get_status);
gpio_free(gpio_index);
return -EINVAL;
}
pr_warn("step3: gpio free.\n");
gpio_free(gpio_index);
pr_warn("-----------------------------------------------\n");
pr_warn("test gpio set debounce success!\n");
pr_warn("++++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
}
static int gpiotest_gpiolib(void)
{
int gpio_index;
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
int req_status;
int set_direct_status;
unsigned long config;
int val;
gpio_index = sunxi_ptest_data->gpio_index;
sunxi_gpio_to_name(gpio_index, pin_name);
pr_warn("++++++++++++++++++++++++++++%s++++++++++++++++++++++++++++\n", __func__);
pr_warn("gpio name is : %s gpio index is : %d\n", pin_name, gpio_index);
pr_warn("-----------------------------------------------\n");
/*
* test gpio set direction input api
*/
pr_warn("-----------------------------------------------\n");
pr_warn("1. test gpio direction input api:\n");
pr_warn("step1: request gpio.\n");
req_status = gpio_request(gpio_index, NULL);
if (req_status != 0) {
pr_warn("gpio request failed !\n");
return -EINVAL;
}
pr_warn("step2: set gpio direction input.\n");
set_direct_status = gpio_direction_input(gpio_index);
if (IS_ERR_VALUE(set_direct_status)) {
pr_warn("set gpio direction input failed!\n");
goto test_gpiolib_api_failed;
}
pr_warn("step3: get gpio mux value and check.\n");
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config);
if (SUNXI_PINCFG_UNPACK_VALUE(config) != 0) {
pr_warn("test gpio set direction input failed !\n");
goto test_gpiolib_api_failed;
}
gpio_free(gpio_index);
pr_warn("step4: gpio free.\n");
pr_warn("finish API(gpio_direction_input)testing.\n");
pr_warn("-----------------------------------------------\n\n");
/*
* test gpio set direction output api
*/
pr_warn("2. test gpio direction output api:\n");
pr_warn("step1: request gpio.\n");
req_status = gpio_request(gpio_index, NULL);
if (req_status != 0) {
pr_warn("gpio request failed!\n");
return -EINVAL;
}
pr_warn("step2: set gpio direction output(data value 1).\n");
set_direct_status = gpio_direction_output(gpio_index, 1);
if (IS_ERR_VALUE(set_direct_status)) {
pr_warn("set gpio direction output failed!\n");
goto test_gpiolib_api_failed;
}
pr_warn("step3: get gpio mux value and check.\n");
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config);
if (SUNXI_PINCFG_UNPACK_VALUE(config) != 1) {
pr_warn("faile!FUNC value not the same as expectation.\n");
goto test_gpiolib_api_failed;
}
pr_warn("step4: get gpio data value and check.\n");
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config);
if (SUNXI_PINCFG_UNPACK_VALUE(config) != 1) {
pr_warn("failed!DATA value not the same as expectation(1).\n");
goto test_gpiolib_api_failed;
}
pr_warn("step5: set gpio direction output(data value 0).\n");
set_direct_status = gpio_direction_output(gpio_index, 0);
if (IS_ERR_VALUE(set_direct_status)) {
pr_warn("set gpio direction output failed!\n");
goto test_gpiolib_api_failed;
}
pr_warn("step6: get gpio data value and check.\n");
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, 0xFFFF);
pin_config_get(SUNXI_PINCTRL, pin_name, &config);
if (SUNXI_PINCFG_UNPACK_VALUE(config) != 0) {
pr_warn("failed!DATA value not the same as expectation(0).\n");
goto test_gpiolib_api_failed;
}
gpio_free(gpio_index);
pr_warn("step7: gpio free.\n");
pr_warn("finish API(gpio_direction_output)testing.\n");
pr_warn("-----------------------------------------------\n\n");
/*
* test gpio get value api
*/
pr_warn("3. test gpio get value api:\n");
pr_warn("step1: request gpio.\n");
req_status = gpio_request(gpio_index, NULL);
if (req_status != 0) {
pr_warn("gpio request failed!\n");
return -EINVAL;
}
pr_warn("step2: set gpio direction output(data value 0).\n");
set_direct_status = gpio_direction_output(gpio_index, 0);
if (IS_ERR_VALUE(set_direct_status)) {
pr_warn("set gpio direction output failed !\n");
goto test_gpiolib_api_failed;
}
pr_warn("step3: get gpio data value and check.\n");
val = __gpio_get_value(gpio_index);
pr_warn(" gpio data value : %d\n", val);
if (val != 0) {
pr_warn("failed!DATA value not the same as expectation.\n");
goto test_gpiolib_api_failed;
}
gpio_free(gpio_index);
pr_warn("step4: gpio free.\n");
pr_warn("finish API(gpio_get_value)testing.\n");
pr_warn("-----------------------------------------------\n\n");
/*
* test gpio set value api
*/
pr_warn("4. test gpio set value api:\n");
pr_warn("step1: request gpio.\n");
req_status = gpio_request(gpio_index, NULL);
if (req_status != 0) {
pr_warn("gpio request failed!\n");
return -EINVAL;
}
pr_warn("step2: set gpio direction output(set data value 0).\n");
set_direct_status = gpio_direction_output(gpio_index, 0);
if (IS_ERR_VALUE(set_direct_status)) {
pr_warn("set gpio direction output failed\n");
goto test_gpiolib_api_failed;
}
pr_warn("step3: get gpio data value,then set 1 and check.\n");
val = __gpio_get_value(gpio_index);
pr_warn(" get gpio data value : %d\n", val);
__gpio_set_value(gpio_index, 1);
pr_warn(" set gpio data value : 1\n");
val = __gpio_get_value(gpio_index);
pr_warn(" get gpio data value : %d\n", val);
if (val != 1) {
pr_warn("test gpio set dat value 1 failed !\n");
goto test_gpiolib_api_failed;
}
pr_warn("step4: get gpio data value,then set 0 and check.\n");
val = __gpio_get_value(gpio_index);
pr_warn(" get gpio data value : %d\n", val);
__gpio_set_value(gpio_index, 0);
pr_warn(" set gpio data value : 0\n");
val = __gpio_get_value(gpio_index);
pr_warn(" get gpio data value : %d\n", val);
if (val != 0) {
pr_warn("test gpio set dat value 0 failed!\n");
goto test_gpiolib_api_failed;
}
gpio_free(gpio_index);
pr_warn("step5: gpio free.\n");
pr_warn("finish API(gpio_set_value)testing.\n");
pr_warn("-----------------------------------------------\n");
pr_warn("test gpio gpiolib success!\n");
pr_warn("+++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
return 0;
test_gpiolib_api_failed:
pr_warn("-----------------------------------------------\n");
pr_warn("test gpio gpiolib failed!\n");
pr_warn("+++++++++++++++++++++++++++end++++++++++++++++++++++++++++\n\n");
gpio_free(gpio_index);
return -EINVAL;
}
static struct sunxi_pctrltest_case sunxi_ptest_case[] = {
{"pctrltest_request_all_resource", pctrltest_request_all_resource},
{"pctrltest_re_request_all_resource", pctrltest_re_request_all_resource},
{"pctrltest_request_gpio", pctrltest_request_gpio},
{"pctrltest_free_gpio", pctrltest_free_gpio},
{"pctrltest_lookup_state", pctrltest_lookup_state},
{"pctrltest_select_state", pctrltest_select_state},
{"pctrltest_get", pctrltest_get},
{"pctrltest_put", pctrltest_put},
{"pctrltest_devm_get_and_put", pctrltest_devm_get_and_put},
{"pctrltest_function_set", pctrltest_function_set},
{"pctrltest_data_set", pctrltest_data_set},
{"pctrltest_pull_set", pctrltest_pull_set},
{"pctrltest_dlevel_set", pctrltest_dlevel_set},
{"pctrltest_direction_input", pctrltest_direction_input},
{"pctrltest_direction_output", pctrltest_direction_output},
{"pctrltest_request_eint", pctrltest_request_eint},
{"pctrltest_re_request_eint", pctrltest_re_request_eint},
{"gpiotest_request_free", gpiotest_request_free},
{"gpiotest_re_request_free", gpiotest_re_request_free},
{"gpiotest_set_debounce", gpiotest_set_debounce},
{"gpiotest_gpiolib", gpiotest_gpiolib},
};
static ssize_t show_funcs(struct class *class, struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", sunxi_ptest_data->funcs);
}
static ssize_t show_data(struct class *class, struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", sunxi_ptest_data->data);
}
static ssize_t show_pull(struct class *class, struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", sunxi_ptest_data->pull);
}
static ssize_t show_dlevel(struct class *class, struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", sunxi_ptest_data->dlevel);
}
static ssize_t show_gpio_index(struct class *class, struct class_attribute *attr,
char *buf)
{
char pin_name[SUNXI_PIN_NAME_MAX_LEN];
sunxi_gpio_to_name(sunxi_ptest_data->gpio_index, pin_name);
return sprintf(buf, "%s\n", pin_name);
}
static ssize_t show_dev_name(struct class *class, struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", sunxi_ptest_data->dev_name);
}
static ssize_t show_result(struct class *class, struct class_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", sunxi_ptest_data->result);
}
static ssize_t show_exec(struct class *class, struct class_attribute *attr,
char *buf)
{
int i;
int total_len = 0;
struct sunxi_pctrltest_case *p = sunxi_ptest_case;
for (i = 0; i < ARRAY_SIZE(sunxi_ptest_case); i++, p++) {
total_len += snprintf(buf + total_len, SUNXI_FUNC_NAME_MAX_LEN,
"%s\n", p->name);
if (total_len > PAGE_SIZE - SUNXI_FUNC_NAME_MAX_LEN) {
pr_warn("can't show so many exec funcs.\n");
return -EINVAL;
}
}
return total_len;
}
static int get_parameter(const char *buf, int *data, size_t size)
{
char *after;
size_t count;
int tmp;
tmp = simple_strtoul(buf, &after, 10);
count = after - buf;
if (isspace(*after))
count++;
if (count == size) {
*data = tmp;
return size;
}
return -EINVAL;
}
static int get_exec_number(void)
{
int i;
struct sunxi_pctrltest_case *p = sunxi_ptest_case;
for (i = 0; i < ARRAY_SIZE(sunxi_ptest_case); i++, p++) {
if (strcmp(p->name, sunxi_ptest_data->exec) == 0)
return i;
}
return -1;
}
static ssize_t store_funcs(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
return get_parameter(buf, &sunxi_ptest_data->funcs, count);
}
static ssize_t store_data(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
return get_parameter(buf, &sunxi_ptest_data->data, count);
}
static ssize_t store_pull(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
return get_parameter(buf, &sunxi_ptest_data->pull, count);
}
static ssize_t store_dlevel(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
return get_parameter(buf, &sunxi_ptest_data->dlevel, count);
}
static ssize_t store_gpio_index(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
return get_parameter(buf, &sunxi_ptest_data->gpio_index, count);
}
static ssize_t store_dev_name(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
if (count > SUNXI_DEV_NAME_MAX_LEN) {
pr_warn("sunxi dev name max len less than 20 char.\n");
return -EINVAL;
}
ret = strlcpy(sunxi_ptest_data->dev_name, buf, count);
return ret;
}
static ssize_t store_result(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
return get_parameter(buf, &sunxi_ptest_data->result, count);
}
static ssize_t store_exec(struct class *class, struct class_attribute *attr,
const char *buf, size_t count)
{
int ret;
int number;
if (count > SUNXI_FUNC_NAME_MAX_LEN) {
pr_warn("sunxi func name max len less than 80 char.\n");
return -EINVAL;
}
ret = strlcpy(sunxi_ptest_data->exec, buf, count);
number = get_exec_number();
if (number < 0) {
pr_warn("can't find exec number.\n");
return -EINVAL;
}
sunxi_ptest_data->result = sunxi_ptest_case[number].func();
return ret;
}
static struct class_attribute sunxi_pctrltest_attrs[] = {
__ATTR(data, S_IRUGO | S_IWUSR, show_data, store_data),
__ATTR(dlevel, S_IRUGO | S_IWUSR, show_dlevel, store_dlevel),
__ATTR(funcs, S_IRUGO | S_IWUSR, show_funcs, store_funcs),
__ATTR(pull, S_IRUGO | S_IWUSR, show_pull, store_pull),
__ATTR(gpio_index, S_IRUGO | S_IWUSR, show_gpio_index, store_gpio_index),
__ATTR(dev_name, S_IRUGO | S_IWUSR, show_dev_name, store_dev_name),
__ATTR(exec, S_IRUGO | S_IWUSR, show_exec, store_exec),
__ATTR(result, S_IRUGO, show_result, store_result),
__ATTR_NULL,
};
static struct class sunxi_pctrltest_class = {
.name = "sunxi_pinctrl_test",
.owner = THIS_MODULE,
.class_attrs = sunxi_pctrltest_attrs,
};
static int sunxi_pctrltest_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct gpio_config config;
int gpio;
int ret;
if (np == NULL) {
pr_err("Vdevice failed to get of_node\n");
return -ENODEV;
}
gpio = of_get_named_gpio_flags(np, "test-gpios", 0,
(enum of_gpio_flags *)&config);
if (!gpio_is_valid(gpio)) {
pr_err("Vdevice failed to get test-gpios\n");
return -ENODEV;
}
sunxi_ptest_data = devm_kzalloc(&pdev->dev,
sizeof(struct sunxi_pctrltest_data),
GFP_KERNEL);
if (!sunxi_ptest_data)
return -ENOMEM;
ret = class_register(&sunxi_pctrltest_class);
if (ret < 0) {
pr_err("register sunxi pinctrl test class failed: %d\n", ret);
return -EBUSY;
}
pdev->dev.class = &sunxi_pctrltest_class;
dev_set_name(&pdev->dev, "Vdevice");
platform_set_drvdata(pdev, sunxi_ptest_data);
/* Set default parameters */
strlcpy(sunxi_ptest_data->dev_name, "Vdevice", SUNXI_DEV_NAME_MAX_LEN);
sunxi_ptest_data->result = -1;
sunxi_ptest_data->gpio_index = config.gpio;
sunxi_ptest_data->funcs = config.mul_sel;
sunxi_ptest_data->pull = config.pull;
sunxi_ptest_data->dlevel = config.drv_level;
sunxi_ptest_data->data = config.data;
init_completion(&sunxi_ptest_data->done);
return ret;
}
static int sunxi_pctrltest_remove(struct platform_device *pdev)
{
class_unregister(&sunxi_pctrltest_class);
return 0;
}
static const struct of_device_id sunxi_pctrltest_match[] = {
{ .compatible = "allwinner,sun8i-vdevice"},
{ .compatible = "allwinner,sun50i-vdevice"},
{}
};
static struct platform_driver sunxi_pctrltest_driver = {
.probe = sunxi_pctrltest_probe,
.remove = sunxi_pctrltest_remove,
.driver = {
.name = "Vdevice",
.owner = THIS_MODULE,
.of_match_table = sunxi_pctrltest_match,
},
};
static int __init sunxi_pctrltest_init(void)
{
int ret;
ret = platform_driver_register(&sunxi_pctrltest_driver);
if (IS_ERR_VALUE(ret)) {
pr_warn("register sunxi pinctrl platform driver failed\n");
return -EINVAL;
}
return 0;
}
static void __exit sunxi_pctrltest_exit(void)
{
platform_driver_unregister(&sunxi_pctrltest_driver);
}
module_init(sunxi_pctrltest_init);
module_exit(sunxi_pctrltest_exit);
MODULE_AUTHOR("Wim Hwang<huangwei@allwinnertech.com");
MODULE_AUTHOR("Huangshr<huangshr@allwinnertech.com");
MODULE_DESCRIPTION("Allwinner SUNXI Pinctrl driver test");
MODULE_LICENSE("GPL");