mirror of https://github.com/OpenIPC/firmware.git
1744 lines
55 KiB
Diff
1744 lines
55 KiB
Diff
diff -drupN a/drivers/pinctrl/sunxi/pinctrl-sunxi-test.c b/drivers/pinctrl/sunxi/pinctrl-sunxi-test.c
|
|
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi-test.c 1970-01-01 03:00:00.000000000 +0300
|
|
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi-test.c 2022-06-12 05:28:14.000000000 +0300
|
|
@@ -0,0 +1,1739 @@
|
|
+/*
|
|
+ * 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;
|
|
+ int irq;
|
|
+};
|
|
+
|
|
+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);
|
|
+ val = 0;
|
|
+ }
|
|
+ (*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, 0xFFFFFF);
|
|
+ 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, 0xFFFFFF);
|
|
+ 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, 0xFFFFFF);
|
|
+ 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, 0xFFFFFF);
|
|
+ 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) for irq:%d.\n",
|
|
+ trigger == IRQF_TRIGGER_HIGH ? "high" : "low", virq);
|
|
+ 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_request_irq(void)
|
|
+{
|
|
+ int ret;
|
|
+ int virq = sunxi_ptest_data->irq;
|
|
+ int trigger = IRQF_TRIGGER_HIGH;
|
|
+
|
|
+ reinit_completion(&sunxi_ptest_data->done);
|
|
+
|
|
+ pr_warn("step1: request irq(%s level) for irq:%d.\n",
|
|
+ trigger == IRQF_TRIGGER_HIGH ? "high" : "low", virq);
|
|
+ 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("step2: 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, 0xFFFFFF);
|
|
+ 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, 0xFFFFFF);
|
|
+ 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, 0xFFFFFF);
|
|
+ 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, 0xFFFFFF);
|
|
+ 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_request_irq", pctrltest_request_irq},
|
|
+ {"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, irq;
|
|
+ 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;
|
|
+
|
|
+ irq = platform_get_irq(pdev, 0);
|
|
+ if (irq < 0) {
|
|
+ printk("Get irq error!\n");
|
|
+ return -EBUSY;
|
|
+ }
|
|
+ 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;
|
|
+ sunxi_ptest_data->irq = irq;
|
|
+ init_completion(&sunxi_ptest_data->done);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int sunxi_pctrltest_remove(struct platform_device *pdev)
|
|
+{
|
|
+ platform_set_drvdata(pdev, NULL);
|
|
+ pdev->dev.class = NULL;
|
|
+ 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");
|