mirror of
https://github.com/physwizz/a155-U-u1.git
synced 2024-11-19 13:27:49 +00:00
562 lines
14 KiB
C
562 lines
14 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2021 MediaTek Inc.
|
|
*
|
|
* Author: Light Hsieh <light.hsieh@mediatek.com>
|
|
*
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <dt-bindings/pinctrl/mt65xx.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <../../gpio/gpiolib.h>
|
|
#include <asm-generic/gpio.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/seq_file.h>
|
|
#include "pinctrl-paris.h"
|
|
|
|
#define PULL_DELAY 50 /* in ms */
|
|
#define FUN_3STATE "gpio_get_value_tristate"
|
|
|
|
static const char *pinctrl_paris_modname = MTK_PINCTRL_DEV;
|
|
static struct mtk_pinctrl *g_hw;
|
|
|
|
static void mtk_gpio_find_mtk_pinctrl_dev(void)
|
|
{
|
|
unsigned int pin = ARCH_NR_GPIOS - 1;
|
|
struct gpio_desc *gdesc;
|
|
struct mtk_pinctrl *hw;
|
|
|
|
do {
|
|
gdesc = gpio_to_desc(pin);
|
|
if (gdesc
|
|
&& !strncmp(pinctrl_paris_modname,
|
|
gdesc->gdev->chip->label,
|
|
strlen(pinctrl_paris_modname))) {
|
|
hw = gpiochip_get_data(gdesc->gdev->chip);
|
|
if (!strcmp(hw->dev->parent->kobj.name, "soc") ||
|
|
!strcmp(hw->dev->parent->kobj.name, "platform")) {
|
|
if (hw->soc->bias_get_combo &&
|
|
hw->soc->bias_set_combo) {
|
|
g_hw = hw;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (gdesc)
|
|
pin = gdesc->gdev->chip->base - 1;
|
|
if (pin == 0 || !gdesc)
|
|
break;
|
|
} while (1);
|
|
|
|
pr_notice("[pinctrl]cannot find %s gpiochip\n", pinctrl_paris_modname);
|
|
}
|
|
|
|
int gpio_get_tristate_input(unsigned int pin)
|
|
{
|
|
struct mtk_pinctrl *hw = NULL;
|
|
const struct mtk_pin_desc *desc;
|
|
int val, val_up, val_down, ret, pullup, pullen, pull_type;
|
|
|
|
if (!g_hw)
|
|
mtk_gpio_find_mtk_pinctrl_dev();
|
|
if (!g_hw)
|
|
return -ENOTSUPP;
|
|
hw = g_hw;
|
|
|
|
if (!hw->soc) {
|
|
pr_notice("invalid gpio chip\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (pin < hw->chip.base) {
|
|
pr_notice(FUN_3STATE ": please use virtual pin number\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (pin - hw->chip.base >= hw->soc->npins) {
|
|
pr_notice(FUN_3STATE ": invalid pin number: %u\n",
|
|
pin);
|
|
return -EINVAL;
|
|
}
|
|
|
|
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin - hw->chip.base];
|
|
|
|
ret = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_MODE, &val);
|
|
if (ret)
|
|
return ret;
|
|
if (val != 0) {
|
|
pr_notice(FUN_3STATE ":GPIO%d in mode %d, not GPIO mode\n",
|
|
pin, val);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = hw->soc->bias_get_combo(hw, desc, &pullup, &pullen);
|
|
if (ret)
|
|
return ret;
|
|
if (pullen == 0 || pullen == MTK_PUPD_SET_R1R0_00) {
|
|
pr_notice(FUN_3STATE ":GPIO%d not pullen, skip floating test\n",
|
|
pin);
|
|
return gpio_get_value(pin);
|
|
}
|
|
if (pullen > MTK_PUPD_SET_R1R0_00)
|
|
pull_type = 1;
|
|
else
|
|
pull_type = 0;
|
|
|
|
/* set pullsel as pull-up and get input value */
|
|
pr_notice(FUN_3STATE ":pull up GPIO%d\n", pin);
|
|
ret = hw->soc->bias_set_combo(hw, desc, 1,
|
|
(pull_type ? MTK_PUPD_SET_R1R0_11 : MTK_ENABLE));
|
|
if (ret)
|
|
goto out;
|
|
mdelay(PULL_DELAY);
|
|
val_up = gpio_get_value(pin);
|
|
pr_notice(FUN_3STATE ":GPIO%d input %d\n", pin, val_up);
|
|
|
|
/* set pullsel as pull-down and get input value */
|
|
pr_notice(FUN_3STATE ":pull down GPIO%d\n", pin);
|
|
ret = hw->soc->bias_set_combo(hw, desc, 0,
|
|
(pull_type ? MTK_PUPD_SET_R1R0_11 : MTK_ENABLE));
|
|
if (ret)
|
|
goto out;
|
|
mdelay(PULL_DELAY);
|
|
val_down = gpio_get_value(pin);
|
|
pr_notice(FUN_3STATE ":GPIO%d input %d\n", pin, val_down);
|
|
|
|
if (val_up && val_down)
|
|
ret = 1;
|
|
else if (!val_up && !val_down)
|
|
ret = 0;
|
|
else if (val_up && !val_down)
|
|
ret = 2;
|
|
else {
|
|
pr_notice(FUN_3STATE ":GPIO%d pull HW is abnormal\n", pin);
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
out:
|
|
/* restore pullsel */
|
|
hw->soc->bias_set_combo(hw, desc, pullup, pullen);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int mtk_hw_set_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio,
|
|
int value, int field)
|
|
{
|
|
const struct mtk_pin_desc *desc;
|
|
|
|
if (gpio > hw->soc->npins)
|
|
return -EINVAL;
|
|
|
|
if (!strncmp(hw->dev->kobj.name, "mt63", strlen("mt63")))
|
|
return mt63xx_hw_set_value(hw, gpio, field, value);
|
|
|
|
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
|
return mtk_hw_set_value(hw, desc, field, value);
|
|
}
|
|
|
|
#define mtk_pctrl_set_pinmux(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_MODE)
|
|
|
|
/* MTK HW use 0 as input, 1 for output
|
|
* This interface is for set direct register value,
|
|
* so don't reverse
|
|
*/
|
|
#define mtk_pctrl_set_direction(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_DIR)
|
|
|
|
#define mtk_pctrl_set_out(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_DO)
|
|
|
|
#define mtk_pctrl_set_smt(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_SMT)
|
|
|
|
#define mtk_pctrl_set_ies(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_IES)
|
|
|
|
#define mtk_pctrl_set_drv(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_DRV)
|
|
|
|
#define mtk_pctrl_set_pullen(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_PULLEN)
|
|
|
|
#define mtk_pctrl_set_pullsel(hw, gpio, val) \
|
|
mtk_hw_set_value_wrap(hw, gpio, val, PINCTRL_PIN_REG_PULLSEL)
|
|
|
|
void gpio_dump_regs_range(int start, int end)
|
|
{
|
|
struct gpio_chip *chip = NULL;
|
|
struct mtk_pinctrl *hw;
|
|
char buf[96];
|
|
int i;
|
|
|
|
if (!g_hw)
|
|
mtk_gpio_find_mtk_pinctrl_dev();
|
|
if (!g_hw)
|
|
return;
|
|
|
|
hw = g_hw;
|
|
chip = &hw->chip;
|
|
|
|
if (start < 0) {
|
|
start = 0;
|
|
end = chip->ngpio - 1;
|
|
}
|
|
if (end < 0)
|
|
end = chip->ngpio - 1;
|
|
if (end > chip->ngpio - 1)
|
|
end = chip->ngpio - 1;
|
|
|
|
pr_notice("PIN: (MODE)(DIR)(DOUT)(DIN)(DRIVE)(SMT)(IES)(PULL_EN)(PULL_SEL)(R1 R0)\n");
|
|
|
|
for (i = start; i <= end; i++) {
|
|
(void)mtk_pctrl_show_one_pin(hw, i, buf, 96);
|
|
pr_notice("%s\n", buf);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(gpio_dump_regs_range);
|
|
|
|
void gpio_dump_regs(void)
|
|
{
|
|
gpio_dump_regs_range(-1, -1);
|
|
}
|
|
EXPORT_SYMBOL_GPL(gpio_dump_regs);
|
|
|
|
#define PIN_DBG_BUF_SZ 96
|
|
static int mtk_gpio_proc_show(struct seq_file *file, void *v)
|
|
{
|
|
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)file->private;
|
|
struct gpio_chip *chip;
|
|
unsigned int i = 0, start;
|
|
int mt63xx;
|
|
|
|
if (!hw) {
|
|
pr_debug("[pinctrl] Err: NULL pointer!\n");
|
|
return 0;
|
|
}
|
|
|
|
if (!strncmp(hw->dev->kobj.name, "mt63", strlen("mt63")))
|
|
mt63xx = 1;
|
|
else
|
|
mt63xx = 0;
|
|
|
|
chip = &hw->chip;
|
|
|
|
seq_printf(file, "pins base: %d\n", chip->base);
|
|
seq_puts(file, "PIN: (MODE)(DIR)(DOUT)(DIN)(DRIVE)(SMT)(IES)(PULL_EN)(PULL_SEL)(R1 R0)\n");
|
|
|
|
if (hw->soc->capability_flags & FLAG_GPIO_START_IDX_1)
|
|
start = 1;
|
|
else
|
|
start = 0;
|
|
for (i = start; i < chip->ngpio; i++) {
|
|
if (!mt63xx && mtk_is_virt_gpio(hw, i))
|
|
continue;
|
|
hw->pctrl->desc->pctlops->pin_dbg_show(hw->pctrl, file, i);
|
|
seq_puts(file, "\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t mtk_gpio_write(struct file *file, const char __user *ubuf,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
const struct mtk_pin_desc *desc;
|
|
struct mtk_pinctrl *hw;
|
|
struct gpio_chip *chip;
|
|
int i, gpio, val, val2, vals[12];
|
|
int pullup = 0, pullen = 0;
|
|
char attrs[12], buf[64];
|
|
int r1r0_en[4] = {MTK_PUPD_SET_R1R0_00, MTK_PUPD_SET_R1R0_01,
|
|
MTK_PUPD_SET_R1R0_10, MTK_PUPD_SET_R1R0_11};
|
|
int mt63xx;
|
|
|
|
hw = (struct mtk_pinctrl *)
|
|
(((struct seq_file *)file->private_data)->private);
|
|
|
|
if (!hw || !hw->soc) {
|
|
pr_notice("[pinctrl]cannot find %s device\n",
|
|
pinctrl_paris_modname);
|
|
return count;
|
|
}
|
|
|
|
if (!strncmp(hw->dev->kobj.name, "mt63", strlen("mt63")))
|
|
mt63xx = 1;
|
|
else
|
|
mt63xx = 0;
|
|
|
|
chip = &hw->chip;
|
|
|
|
if (count == 0)
|
|
return -1;
|
|
if (count > 63)
|
|
count = 63;
|
|
|
|
if (copy_from_user(buf, ubuf, count))
|
|
return -1;
|
|
|
|
if (!strncmp(buf, "mode", 4)
|
|
&& (sscanf(buf+4, "%d %d", &gpio, &val) == 2)) {
|
|
mtk_pctrl_set_pinmux(hw, gpio, val);
|
|
} else if (!strncmp(buf, "dir", 3)
|
|
&& (sscanf(buf+3, "%d %d", &gpio, &val) == 2)) {
|
|
mtk_pctrl_set_direction(hw, gpio, val);
|
|
} else if (!strncmp(buf, "out", 3)
|
|
&& (sscanf(buf+3, "%d %d", &gpio, &val) == 2)) {
|
|
mtk_pctrl_set_direction(hw, gpio, 1);
|
|
mtk_pctrl_set_out(hw, gpio, val);
|
|
} else if (!strncmp(buf, "pullen", 6)
|
|
&& (sscanf(buf+6, "%d %d", &gpio, &val) == 2)) {
|
|
if (gpio < 0 || gpio >= hw->soc->npins) {
|
|
pr_notice("invalid pin number\n");
|
|
goto out;
|
|
}
|
|
if (!mt63xx) {
|
|
desc = (const struct mtk_pin_desc *)
|
|
&hw->soc->pins[gpio];
|
|
hw->soc->bias_get_combo(hw, desc, &pullup, &pullen);
|
|
if (pullen < MTK_PUPD_SET_R1R0_00) {
|
|
pullen = !!val;
|
|
if (pullup == 2)
|
|
pullup = 0;
|
|
} else if (pullen >= MTK_PUPD_SET_R1R0_00 &&
|
|
pullen <= MTK_PUPD_SET_R1R0_11) {
|
|
if (val < 0)
|
|
val = 0;
|
|
else if (val > 3)
|
|
val = 3;
|
|
pullen = r1r0_en[val];
|
|
} else if (pullen >= MTK_PULL_SET_RSEL_000 &&
|
|
pullen <= MTK_PULL_SET_RSEL_MAX) {
|
|
/* don't support to change rsel via pullen */
|
|
pullen = !!val;
|
|
if (pullup == 2)
|
|
pullup = 0;
|
|
} else {
|
|
goto out;
|
|
}
|
|
hw->soc->bias_set_combo(hw, desc, pullup, pullen);
|
|
} else
|
|
mtk_pctrl_set_pullen(hw, gpio, !!val);
|
|
} else if ((!strncmp(buf, "pullsel", 7))
|
|
&& (sscanf(buf+7, "%d %d", &gpio, &val) == 2)) {
|
|
if (gpio < 0 || gpio >= hw->soc->npins) {
|
|
pr_notice("invalid pin number\n");
|
|
goto out;
|
|
}
|
|
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
|
if (!mt63xx) {
|
|
hw->soc->bias_get_combo(hw, desc, &pullup, &pullen);
|
|
if (pullen == 0)
|
|
pullen = 1;
|
|
hw->soc->bias_set_combo(hw, desc, !!val, pullen);
|
|
} else
|
|
mtk_pctrl_set_pullsel(hw, gpio, !!val);
|
|
} else if ((!strncmp(buf, "ies", 3))
|
|
&& (sscanf(buf+3, "%d %d", &gpio, &val) == 2)) {
|
|
mtk_pctrl_set_ies(hw, gpio, val);
|
|
} else if ((!strncmp(buf, "smt", 3))
|
|
&& (sscanf(buf+3, "%d %d", &gpio, &val) == 2)) {
|
|
mtk_pctrl_set_smt(hw, gpio, val);
|
|
} else if ((!strncmp(buf, "driving", 7))
|
|
&& (sscanf(buf+7, "%d %d", &gpio, &val) == 2)) {
|
|
if (hw->soc->drive_set) {
|
|
if (gpio < 0 || gpio >= hw->soc->npins) {
|
|
pr_notice("invalid pin number\n");
|
|
goto out;
|
|
}
|
|
desc = (const struct mtk_pin_desc *)
|
|
&hw->soc->pins[gpio];
|
|
hw->soc->drive_set(hw, desc, val);
|
|
} else
|
|
mtk_pctrl_set_drv(hw, gpio, val);
|
|
} else if ((!strncmp(buf, "r1r0", 4))
|
|
&& (sscanf(buf+4, "%d %d %d", &gpio, &val, &val2) == 3)) {
|
|
if (gpio < 0 || gpio >= hw->soc->npins) {
|
|
pr_notice("invalid pin number\n");
|
|
goto out;
|
|
}
|
|
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
|
if (mt63xx) {
|
|
pr_notice("[pinctrl] r1r0 not supported\n");
|
|
goto out;
|
|
}
|
|
hw->soc->bias_get_combo(hw, desc, &pullup, &pullen);
|
|
pullen = r1r0_en[(((!!val) << 1) + !!val2)];
|
|
hw->soc->bias_set_combo(hw, desc, pullup, pullen);
|
|
} else if ((!strncmp(buf, "rsel", 4))
|
|
&& (sscanf(buf+4, "%d %d", &gpio, &val) == 2)) {
|
|
if (gpio < 0 || gpio >= hw->soc->npins) {
|
|
pr_notice("invalid pin number\n");
|
|
goto out;
|
|
}
|
|
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
|
if (mt63xx) {
|
|
pr_notice("[pinctrl] rsel not supported\n");
|
|
goto out;
|
|
}
|
|
hw->soc->bias_get_combo(hw, desc, &pullup, &pullen);
|
|
hw->soc->bias_set_combo(hw, desc, pullup,
|
|
val + MTK_PULL_SET_RSEL_000);
|
|
} else if (!strncmp(buf, "set", 3)) {
|
|
if (!mt63xx) {
|
|
val = sscanf(buf+3, "%d %c%c%c%c%c%c%c%c%c%c %c%c",
|
|
&gpio,
|
|
&attrs[0], &attrs[1], &attrs[2], &attrs[3],
|
|
&attrs[4], &attrs[5], &attrs[6], &attrs[7],
|
|
&attrs[8], &attrs[9], &attrs[10], &attrs[11]);
|
|
if (val < 11) {
|
|
pr_notice("invalid input count %d\n", val);
|
|
goto out;
|
|
}
|
|
} else {
|
|
val = sscanf(buf+3, "%d %c%c%c%c%c%c%c%c%c",
|
|
&gpio,
|
|
&attrs[0], &attrs[1], &attrs[2], &attrs[3],
|
|
&attrs[4], &attrs[5], &attrs[6],
|
|
&attrs[8], &attrs[9]);
|
|
if (val < 10) {
|
|
pr_notice("invalid input count %d\n", val);
|
|
goto out;
|
|
}
|
|
}
|
|
for (i = 0; i < ARRAY_SIZE(attrs); i++) {
|
|
if ((attrs[i] >= '0') && (attrs[i] <= '9'))
|
|
vals[i] = attrs[i] - '0';
|
|
else
|
|
vals[i] = 0;
|
|
}
|
|
if (gpio < 0 || gpio >= hw->soc->npins) {
|
|
pr_notice("invalid pin number\n");
|
|
goto out;
|
|
}
|
|
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
|
/* MODE */
|
|
mtk_pctrl_set_pinmux(hw, gpio, vals[0]);
|
|
/* DIR */
|
|
mtk_pctrl_set_direction(hw, gpio, !!vals[1]);
|
|
/* DOUT */
|
|
if (vals[1])
|
|
mtk_pctrl_set_out(hw, gpio, !!vals[2]);
|
|
/* DRIVING */
|
|
if (hw->soc->drive_set)
|
|
hw->soc->drive_set(hw, desc, vals[4]*10 + vals[5]);
|
|
else
|
|
mtk_pctrl_set_drv(hw, gpio, vals[4]*10 + vals[5]);
|
|
/* SMT */
|
|
mtk_pctrl_set_smt(hw, gpio, vals[6]);
|
|
/* IES */
|
|
if (!mt63xx)
|
|
mtk_pctrl_set_ies(hw, gpio, vals[7]);
|
|
/* PULL */
|
|
if (!mt63xx) {
|
|
hw->soc->bias_get_combo(hw, desc, &pullup, &pullen);
|
|
if ((pullen < MTK_PUPD_SET_R1R0_00)
|
|
|| (pullen >= MTK_PULL_SET_RSEL_000 &&
|
|
pullen <= MTK_PULL_SET_RSEL_MAX)){
|
|
hw->soc->bias_set_combo(hw, desc, !!vals[9],
|
|
!!vals[8]);
|
|
} else if (pullen >= MTK_PUPD_SET_R1R0_00 &&
|
|
pullen <= MTK_PUPD_SET_R1R0_11) {
|
|
val = (((!!vals[10]) << 1) + !!vals[11]);
|
|
pullen = r1r0_en[val];
|
|
hw->soc->bias_set_combo(hw, desc, !!vals[9],
|
|
pullen);
|
|
}
|
|
} else {
|
|
mtk_pctrl_set_pullen(hw, gpio, !!vals[8]);
|
|
mtk_pctrl_set_pullsel(hw, gpio, !!vals[9]);
|
|
}
|
|
}
|
|
|
|
out:
|
|
return count;
|
|
}
|
|
|
|
static int mtk_gpio_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, mtk_gpio_proc_show, PDE_DATA(inode));
|
|
}
|
|
|
|
static const struct proc_ops mtk_gpio_fops = {
|
|
.proc_open = mtk_gpio_open,
|
|
.proc_read = seq_read,
|
|
.proc_lseek = seq_lseek,
|
|
.proc_release = seq_release,
|
|
.proc_write = mtk_gpio_write,
|
|
};
|
|
|
|
static struct proc_dir_entry *mtk_gpio_debug_root;
|
|
|
|
static int mtk_gpio_init_procfs(void)
|
|
{
|
|
struct proc_dir_entry *proc_entry;
|
|
struct mtk_pinctrl *hw = NULL;
|
|
struct gpio_desc *gdesc;
|
|
unsigned int pin = ARCH_NR_GPIOS - 1;
|
|
kuid_t uid;
|
|
kgid_t gid;
|
|
|
|
uid = make_kuid(&init_user_ns, 0);
|
|
gid = make_kgid(&init_user_ns, 1001);
|
|
|
|
mtk_gpio_debug_root = proc_mkdir("mtk_gpio", NULL);
|
|
|
|
do {
|
|
gdesc = gpio_to_desc(pin);
|
|
if (!gdesc)
|
|
break;
|
|
|
|
if (!strncmp(pinctrl_paris_modname,
|
|
gdesc->gdev->chip->label,
|
|
strlen(pinctrl_paris_modname))) {
|
|
hw = gpiochip_get_data(gdesc->gdev->chip);
|
|
if (!hw || !hw->soc || !hw->dev) {
|
|
pr_notice("invalid gpio chip\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!strcmp(hw->dev->parent->kobj.name, "soc") ||
|
|
!strcmp(hw->dev->parent->kobj.name, "platform")) {
|
|
if (hw->soc->bias_get_combo &&
|
|
hw->soc->bias_set_combo) {
|
|
proc_entry = proc_create_data("soc.pinctrl",
|
|
S_IFREG | 0444, mtk_gpio_debug_root,
|
|
&mtk_gpio_fops, hw);
|
|
}
|
|
} else
|
|
proc_entry = proc_create_data(hw->dev->kobj.name,
|
|
S_IFREG | 0444, mtk_gpio_debug_root,
|
|
&mtk_gpio_fops, hw);
|
|
|
|
if (proc_entry) {
|
|
proc_set_user(proc_entry, uid, gid);
|
|
} else {
|
|
pr_notice("[pinctrl]error create mtk_gpio\n");
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
pin = gdesc->gdev->chip->base - 1;
|
|
} while (pin > 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int __init pinctrl_mtk_debug_v2_init(void)
|
|
{
|
|
return mtk_gpio_init_procfs();
|
|
}
|
|
|
|
late_initcall(pinctrl_mtk_debug_v2_init);
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_DESCRIPTION("MediaTek Pinctrl DEBUG Driver");
|