Add samsung specific changes
This commit is contained in:
@@ -124,4 +124,16 @@ config PINCTRL_SM8550_LPASS_LPI
|
||||
(Low Power Island) found on the Qualcomm Technologies Inc SM8550
|
||||
platform.
|
||||
|
||||
config SEC_GPIO_DVS
|
||||
tristate "setting Samsung GPIO debugging and verification system"
|
||||
help
|
||||
To verify gpio configurations of devices, set this feature.
|
||||
This feature should be enabled for user-debug mode.
|
||||
|
||||
config SEC_GPIO_DUMP
|
||||
bool "Help to check GPIO configuration"
|
||||
help
|
||||
To debug gpio state, set this feature.
|
||||
This feature can be enabled for all modes.
|
||||
|
||||
endif
|
||||
|
@@ -1,6 +1,76 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
if PINCTRL_MSM
|
||||
|
||||
config PINCTRL_KERA
|
||||
tristate "Qualcomm Technologies, Inc. KERA pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc KERA platform.
|
||||
Say Y here to compile statically, or M here to compile it as a
|
||||
module. If unsure, say N.
|
||||
|
||||
config PINCTRL_TUNA
|
||||
tristate "Qualcomm Technologies, Inc. TUNA pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc TUNA platform.
|
||||
Say Y here to compile statically, or M here to compile it as a
|
||||
module. If unsure, say N.
|
||||
|
||||
config PINCTRL_SUN
|
||||
tristate "Qualcomm Technologies, Inc. SUN pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc SUN platform.
|
||||
Say Y here to compile statically, or M here to compile it as a
|
||||
module. If unsure, say N.
|
||||
|
||||
config PINCTRL_PINEAPPLE
|
||||
tristate "Qualcomm Technologies, Inc. Pineapple pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc PINEAPPLE platform.
|
||||
Say Y here to compile statically, or M here to compile it as a
|
||||
module. If unsure, say N.
|
||||
|
||||
config PINCTRL_PARROT
|
||||
tristate "Qualcomm Technologies Inc PARROT pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc PARROT platform.
|
||||
Say Y here to compile statically, or M here to compile it as a module.
|
||||
If unsure, say N.
|
||||
|
||||
config PINCTRL_RAVELIN
|
||||
tristate "Qualcomm Technologies Inc RAVELIN pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc RAVELIN platform.
|
||||
Say Y here to compile statically, or M here to compile it as a module.
|
||||
If unsure, say N.
|
||||
|
||||
config PINCTRL_MONACO
|
||||
tristate "Qualcomm Technologies, Inc MONACO pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc MONACO platform.
|
||||
Say Y here to compile statically, or M here to compile it as a
|
||||
module. If unsure, say N.
|
||||
|
||||
config PINCTRL_APQ8064
|
||||
tristate "Qualcomm APQ8064 pin controller driver"
|
||||
depends on ARM || COMPILE_TEST
|
||||
@@ -366,4 +436,13 @@ config PINCTRL_SM8550
|
||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||
Technologies Inc SM8550 platform.
|
||||
|
||||
config PINCTRL_X1E80100
|
||||
tristate "Qualcomm Technologies Inc X1E80100 pin controller driver"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc Top Level Mode Multiplexer block (TLMM)
|
||||
block found on the Qualcomm Technologies Inc X1E80100 platform.
|
||||
Say Y here to compile statically, or M here to compile it as a module.
|
||||
If unsure, say N.
|
||||
endif
|
||||
|
@@ -1,6 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Qualcomm pin control drivers
|
||||
obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o
|
||||
obj-$(CONFIG_PINCTRL_TUNA) += pinctrl-tuna.o
|
||||
obj-$(CONFIG_PINCTRL_KERA) += pinctrl-kera.o
|
||||
obj-$(CONFIG_PINCTRL_SUN) += pinctrl-sun.o
|
||||
obj-$(CONFIG_PINCTRL_RAVELIN) += pinctrl-ravelin.o
|
||||
obj-$(CONFIG_PINCTRL_PINEAPPLE) += pinctrl-pineapple.o
|
||||
obj-$(CONFIG_PINCTRL_PARROT) += pinctrl-parrot.o
|
||||
obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o
|
||||
obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o
|
||||
obj-$(CONFIG_PINCTRL_IPQ4019) += pinctrl-ipq4019.o
|
||||
@@ -60,3 +66,8 @@ obj-$(CONFIG_PINCTRL_SM8550) += pinctrl-sm8550.o
|
||||
obj-$(CONFIG_PINCTRL_SM8550_LPASS_LPI) += pinctrl-sm8550-lpass-lpi.o
|
||||
obj-$(CONFIG_PINCTRL_SC8280XP_LPASS_LPI) += pinctrl-sc8280xp-lpass-lpi.o
|
||||
obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o
|
||||
obj-$(CONFIG_PINCTRL_X1E80100) += pinctrl-x1e80100.o
|
||||
obj-$(CONFIG_PINCTRL_MONACO) += pinctrl-monaco.o
|
||||
|
||||
# Debug and verify gpio configurations.
|
||||
obj-$(CONFIG_SEC_GPIO_DVS) += secgpio_dvs.o
|
||||
|
2304
drivers/pinctrl/qcom/pinctrl-kera.c
Normal file
2304
drivers/pinctrl/qcom/pinctrl-kera.c
Normal file
File diff suppressed because it is too large
Load Diff
1717
drivers/pinctrl/qcom/pinctrl-monaco.c
Normal file
1717
drivers/pinctrl/qcom/pinctrl-monaco.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2013, Sony Mobile Communications AB.
|
||||
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
@@ -24,8 +25,9 @@
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
||||
#include <linux/soc/qcom/irq.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include "../core.h"
|
||||
#include "../pinconf.h"
|
||||
@@ -33,9 +35,16 @@
|
||||
|
||||
#include "pinctrl-msm.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_GPIO_DVS)
|
||||
#include "secgpio_dvs.h"
|
||||
#endif
|
||||
|
||||
#define MAX_NR_GPIO 300
|
||||
#define MAX_NR_TILES 4
|
||||
#define DEFAULT_REG_SIZE_4K 1
|
||||
#define PS_HOLD_OFFSET 0x820
|
||||
#define QUP_MASK GENMASK(5, 0)
|
||||
#define SPARE_MASK GENMASK(15, 8)
|
||||
|
||||
/**
|
||||
* struct msm_pinctrl - state for a pinctrl-msm device
|
||||
@@ -82,6 +91,39 @@ struct msm_pinctrl {
|
||||
u32 phys_base[MAX_NR_TILES];
|
||||
};
|
||||
|
||||
static struct msm_pinctrl *msm_pinctrl_data;
|
||||
static bool pinctrl_msm_log_mask;
|
||||
|
||||
#define EGPIO_PRESENT 11
|
||||
#define EGPIO_ENABLE 12
|
||||
#define I2C_PULL 13
|
||||
#define MSM_APPS_OWNER 1
|
||||
#define MSM_REMOTE_OWNER 0
|
||||
|
||||
/* custom pinconf parameters for msm pinictrl*/
|
||||
#define MSM_PIN_CONFIG_APPS (PIN_CONFIG_END + 1)
|
||||
#define MSM_PIN_CONFIG_REMOTE (PIN_CONFIG_END + 2)
|
||||
#define MSM_PIN_CONFIG_I2C_PULL (PIN_CONFIG_END + 3)
|
||||
|
||||
static const struct pinconf_generic_params msm_gpio_bindings[] = {
|
||||
{"qcom,apps", MSM_PIN_CONFIG_APPS, 0},
|
||||
{"qcom,remote", MSM_PIN_CONFIG_REMOTE, 0},
|
||||
{"qcom,i2c_pull", MSM_PIN_CONFIG_I2C_PULL, 0},
|
||||
};
|
||||
|
||||
static const char * const pulls_keeper[] = {
|
||||
"no pull",
|
||||
"pull down",
|
||||
"keeper",
|
||||
"pull up"
|
||||
};
|
||||
|
||||
static const char * const pulls_no_keeper[] = {
|
||||
"no pull",
|
||||
"pull down",
|
||||
"pull up",
|
||||
};
|
||||
|
||||
#define MSM_ACCESSOR(name) \
|
||||
static u32 msm_readl_##name(struct msm_pinctrl *pctrl, \
|
||||
const struct msm_pingroup *g) \
|
||||
@@ -326,6 +368,15 @@ static int msm_config_reg(struct msm_pinctrl *pctrl,
|
||||
*bit = g->oe_bit;
|
||||
*mask = 1;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_APPS:
|
||||
case MSM_PIN_CONFIG_REMOTE:
|
||||
*bit = EGPIO_ENABLE;
|
||||
*mask = 1;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_I2C_PULL:
|
||||
*bit = I2C_PULL;
|
||||
*mask = 1;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
@@ -418,6 +469,23 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev,
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_APPS:
|
||||
/* Pin do not support egpio or remote owner */
|
||||
if (!(val & BIT(EGPIO_PRESENT)) || !arg)
|
||||
return -EINVAL;
|
||||
|
||||
arg = 1;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_REMOTE:
|
||||
/* Pin do not support epgio or APPS owner */
|
||||
if (!(val & BIT(EGPIO_PRESENT)) || arg)
|
||||
return -EINVAL;
|
||||
|
||||
arg = 1;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_I2C_PULL:
|
||||
arg = 1;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
@@ -439,6 +507,7 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
|
||||
unsigned mask;
|
||||
unsigned arg;
|
||||
unsigned bit;
|
||||
u32 owner_bit, owner_update = 0;
|
||||
int ret;
|
||||
u32 val;
|
||||
int i;
|
||||
@@ -527,6 +596,17 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
|
||||
*/
|
||||
arg = 0;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_APPS:
|
||||
owner_update = 1;
|
||||
owner_bit = MSM_APPS_OWNER;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_REMOTE:
|
||||
owner_update = 1;
|
||||
owner_bit = MSM_REMOTE_OWNER;
|
||||
break;
|
||||
case MSM_PIN_CONFIG_I2C_PULL:
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
arg = !!arg;
|
||||
break;
|
||||
@@ -541,6 +621,9 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
|
||||
dev_err(pctrl->dev, "config %x: %x is invalid\n", param, arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Update the owner bits as final config update */
|
||||
if (param == MSM_PIN_CONFIG_APPS || param == MSM_PIN_CONFIG_REMOTE)
|
||||
continue;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
@@ -550,6 +633,22 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
if (owner_update) {
|
||||
ret = msm_config_reg(pctrl, g,
|
||||
MSM_PIN_CONFIG_APPS, &mask, &bit);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
if (val & BIT(EGPIO_PRESENT)) {
|
||||
val &= ~(mask << bit);
|
||||
val |= owner_bit << bit;
|
||||
msm_writel_ctl(val, pctrl, g);
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -653,6 +752,229 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
static void msm_gpio_pin_status_get(struct msm_pinctrl *pctrl, const struct msm_pingroup *g,
|
||||
unsigned int offset, int *is_out, unsigned int *func,
|
||||
int *drive, int *pull, int *egpio_enable, int *val)
|
||||
{
|
||||
u32 ctl_reg, io_reg;
|
||||
|
||||
ctl_reg = msm_readl_ctl(pctrl, g);
|
||||
io_reg = msm_readl_io(pctrl, g);
|
||||
|
||||
*is_out = !!(ctl_reg & BIT(g->oe_bit));
|
||||
*func = (ctl_reg >> g->mux_bit) & 7;
|
||||
*drive = (ctl_reg >> g->drv_bit) & 7;
|
||||
*pull = (ctl_reg >> g->pull_bit) & 3;
|
||||
*egpio_enable = 0;
|
||||
if (pctrl->soc->egpio_func && ctl_reg & BIT(g->egpio_present))
|
||||
*egpio_enable = !(ctl_reg & BIT(g->egpio_enable));
|
||||
|
||||
if (*is_out)
|
||||
*val = !!(io_reg & BIT(g->out_bit));
|
||||
else
|
||||
*val = !!(io_reg & BIT(g->in_bit));
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_GPIO_DVS) || IS_ENABLED(CONFIG_SEC_GPIO_DUMP)
|
||||
#define AP_GPIO_MAX 215
|
||||
|
||||
#define IN_OUT_MASK 0xF0
|
||||
#define PUPD_MASK 0xE
|
||||
#define DATA_MASK 0x1
|
||||
|
||||
#define GET_RESULT_GPIO(a, b, c) \
|
||||
((a<<4 & IN_OUT_MASK) | (b<<1 & PUPD_MASK) | (c & DATA_MASK))
|
||||
|
||||
struct gpiomux_setting {
|
||||
int func;
|
||||
int drv;
|
||||
int pull;
|
||||
int is_out;
|
||||
int val;
|
||||
};
|
||||
|
||||
static void msm_gp_get_all(struct gpio_chip *chip, u32 pin_no, struct gpiomux_setting *set)
|
||||
{
|
||||
const struct msm_pingroup *g;
|
||||
struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
u32 ctl_reg, io_reg;
|
||||
int drive;
|
||||
|
||||
g = &pctrl->soc->groups[pin_no];
|
||||
|
||||
ctl_reg = msm_readl_ctl(pctrl, g);
|
||||
io_reg = msm_readl_io(pctrl, g);
|
||||
|
||||
set->is_out = !!(ctl_reg & BIT(g->oe_bit));
|
||||
set->func = (ctl_reg >> g->mux_bit) & 7;
|
||||
drive = (ctl_reg >> g->drv_bit) & 7;
|
||||
set->drv = msm_regval_to_drive(drive);
|
||||
set->pull = (ctl_reg >> g->pull_bit) & 3;
|
||||
|
||||
if (set->is_out)
|
||||
set->val = !!(io_reg & BIT(g->out_bit));
|
||||
else
|
||||
set->val = !!(io_reg & BIT(g->in_bit));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_GPIO_DVS)
|
||||
/****************************************************************/
|
||||
/* Pre-defined variables. (DO NOT CHANGE THIS!!) */
|
||||
static unsigned char checkgpiomap_result[GDVS_PHONE_STATUS_MAX][AP_GPIO_MAX];
|
||||
static struct gpiomap_result gpiomap_result = {
|
||||
.init = checkgpiomap_result[PHONE_INIT],
|
||||
.sleep = checkgpiomap_result[PHONE_SLEEP]
|
||||
};
|
||||
|
||||
static void msm_check_gpio_status(unsigned char phonestate)
|
||||
{
|
||||
struct gpio_chip *gp;
|
||||
struct gpiomux_setting set;
|
||||
int i;
|
||||
u8 temp_io = 0, temp_pdpu = 0, temp_lh = 0;
|
||||
|
||||
if (!msm_pinctrl_data) {
|
||||
pr_err("pinctrl data is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gp = &msm_pinctrl_data->chip;
|
||||
|
||||
pr_info("[dvs_%s] state : %s\n", __func__,
|
||||
(phonestate == PHONE_INIT) ? "init" : "sleep");
|
||||
|
||||
for (i = 0; i < AP_GPIO_MAX; i++) {
|
||||
/* If it is not valid gpio or secure, Shows IN/PD/L */
|
||||
if (!gpiochip_line_is_valid(gp, i)) {
|
||||
checkgpiomap_result[phonestate][i] =
|
||||
GET_RESULT_GPIO(0x1, 0x1, 0x0);
|
||||
continue;
|
||||
}
|
||||
|
||||
msm_gp_get_all(gp, i, &set);
|
||||
|
||||
if (set.func == 0) {
|
||||
if (set.is_out)
|
||||
temp_io = 0x02; /* GPIO_OUT */
|
||||
else
|
||||
temp_io = 0x01; /* GPIO_IN */
|
||||
} else
|
||||
temp_io = 0x0; /* FUNC */
|
||||
|
||||
switch (set.pull) {
|
||||
case MSM_NO_PULL:
|
||||
temp_pdpu = 0x00;
|
||||
break;
|
||||
case MSM_PULL_DOWN:
|
||||
temp_pdpu = 0x01;
|
||||
break;
|
||||
/*
|
||||
* gpiodvs is only for samsung,
|
||||
* so pull definition could be different from original value.
|
||||
* gpiodvs definition: PU(0x2), KEEPER(0x3)
|
||||
*/
|
||||
case MSM_PULL_UP:
|
||||
temp_pdpu = 0x02;
|
||||
break;
|
||||
case MSM_KEEPER:
|
||||
temp_pdpu = 0x03;
|
||||
break;
|
||||
default:
|
||||
temp_pdpu = 0x07;
|
||||
break;
|
||||
}
|
||||
|
||||
temp_lh = set.val;
|
||||
|
||||
checkgpiomap_result[phonestate][i] =
|
||||
GET_RESULT_GPIO(temp_io, temp_pdpu, temp_lh);
|
||||
}
|
||||
|
||||
pr_info("[dvs_%s]-\n", __func__);
|
||||
}
|
||||
|
||||
static struct gpio_dvs_t msm_gpio_dvs = {
|
||||
.result = &gpiomap_result,
|
||||
.check_gpio_status = msm_check_gpio_status,
|
||||
.count = AP_GPIO_MAX,
|
||||
.check_sleep = false,
|
||||
};
|
||||
|
||||
const struct secgpio_dvs_data msm_gpio_dvs_data = {
|
||||
.gpio_dvs = &msm_gpio_dvs,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(msm_gpio_dvs_data);
|
||||
#endif /* CONFIG_SEC_GPIO_DVS */
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_GPIO_DUMP)
|
||||
static const char * const gpiomux_func_str[] = {
|
||||
"GPIO",
|
||||
"Func_1",
|
||||
"Func_2",
|
||||
"Func_3",
|
||||
"Func_4",
|
||||
"Func_5",
|
||||
"Func_6",
|
||||
"Func_7",
|
||||
"Func_8",
|
||||
"Func_9",
|
||||
"Func_a",
|
||||
"Func_b",
|
||||
"Func_c",
|
||||
"Func_d",
|
||||
"Func_e",
|
||||
"Func_f",
|
||||
};
|
||||
|
||||
static const char * const gpiomux_pull_str[] = {
|
||||
"PULL_NONE",
|
||||
"PULL_DOWN",
|
||||
"PULL_KEEPER",
|
||||
"PULL_UP",
|
||||
};
|
||||
|
||||
static const char * const gpiomux_dir_str[] = {
|
||||
"IN",
|
||||
"OUT",
|
||||
};
|
||||
|
||||
static const char * const gpiomux_val_str[] = {
|
||||
"LOW",
|
||||
"HIGH",
|
||||
};
|
||||
|
||||
void sec_ap_gpio_debug_print(void)
|
||||
{
|
||||
struct gpio_chip *gp;
|
||||
struct gpiomux_setting set = {0,};
|
||||
int i;
|
||||
|
||||
if (!msm_pinctrl_data) {
|
||||
pr_err("pinctrl data is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gp = &msm_pinctrl_data->chip;
|
||||
|
||||
for (i = 0; i < AP_GPIO_MAX; i++) {
|
||||
if (!gpiochip_line_is_valid(gp, i))
|
||||
continue;
|
||||
|
||||
msm_gp_get_all(gp, i, &set);
|
||||
|
||||
pr_info("GPIO[%u] %10s %10s %13s DRV_%dmA %10s\n",
|
||||
i,
|
||||
gpiomux_func_str[set.func],
|
||||
gpiomux_dir_str[set.is_out],
|
||||
gpiomux_pull_str[set.pull],
|
||||
set.drv,
|
||||
gpiomux_val_str[set.val]);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(sec_ap_gpio_debug_print);
|
||||
#endif /* CONFIG_SEC_GPIO_DUMP */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static void msm_gpio_dbg_show_one(struct seq_file *s,
|
||||
@@ -669,40 +991,13 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
|
||||
int pull;
|
||||
int val;
|
||||
int egpio_enable;
|
||||
u32 ctl_reg, io_reg;
|
||||
|
||||
static const char * const pulls_keeper[] = {
|
||||
"no pull",
|
||||
"pull down",
|
||||
"keeper",
|
||||
"pull up"
|
||||
};
|
||||
|
||||
static const char * const pulls_no_keeper[] = {
|
||||
"no pull",
|
||||
"pull down",
|
||||
"pull up",
|
||||
};
|
||||
|
||||
if (!gpiochip_line_is_valid(chip, offset))
|
||||
return;
|
||||
|
||||
g = &pctrl->soc->groups[offset];
|
||||
ctl_reg = msm_readl_ctl(pctrl, g);
|
||||
io_reg = msm_readl_io(pctrl, g);
|
||||
|
||||
is_out = !!(ctl_reg & BIT(g->oe_bit));
|
||||
func = (ctl_reg >> g->mux_bit) & 7;
|
||||
drive = (ctl_reg >> g->drv_bit) & 7;
|
||||
pull = (ctl_reg >> g->pull_bit) & 3;
|
||||
egpio_enable = 0;
|
||||
if (pctrl->soc->egpio_func && ctl_reg & BIT(g->egpio_present))
|
||||
egpio_enable = !(ctl_reg & BIT(g->egpio_enable));
|
||||
|
||||
if (is_out)
|
||||
val = !!(io_reg & BIT(g->out_bit));
|
||||
else
|
||||
val = !!(io_reg & BIT(g->in_bit));
|
||||
msm_gpio_pin_status_get(pctrl, g, offset, &is_out, &func,
|
||||
&drive, &pull, &egpio_enable, &val);
|
||||
|
||||
if (egpio_enable) {
|
||||
seq_printf(s, " %-8s: egpio\n", g->grp.name);
|
||||
@@ -732,6 +1027,39 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
#define msm_gpio_dbg_show NULL
|
||||
#endif
|
||||
|
||||
static void msm_gpio_log_pin_status(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
const struct msm_pingroup *g;
|
||||
struct msm_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
unsigned int func;
|
||||
int is_out;
|
||||
int drive;
|
||||
int pull;
|
||||
int val;
|
||||
int egpio_enable;
|
||||
|
||||
if (!gpiochip_line_is_valid(chip, offset))
|
||||
return;
|
||||
|
||||
g = &pctrl->soc->groups[offset];
|
||||
msm_gpio_pin_status_get(pctrl, g, offset, &is_out, &func,
|
||||
&drive, &pull, &egpio_enable, &val);
|
||||
|
||||
printk_deferred("%s: %s, %s, func%d, %dmA, %s\n",
|
||||
g->grp.name, is_out ? "out" : "in",
|
||||
val ? "high" : "low", func,
|
||||
msm_regval_to_drive(drive),
|
||||
pctrl->soc->pull_no_keeper ? pulls_no_keeper[pull] : pulls_keeper[pull]);
|
||||
}
|
||||
|
||||
static void msm_gpios_status(struct gpio_chip *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++)
|
||||
msm_gpio_log_pin_status(chip, i);
|
||||
}
|
||||
|
||||
static int msm_gpio_init_valid_mask(struct gpio_chip *gc,
|
||||
unsigned long *valid_mask,
|
||||
unsigned int ngpios)
|
||||
@@ -740,6 +1068,8 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *gc,
|
||||
int ret;
|
||||
unsigned int len, i;
|
||||
const int *reserved = pctrl->soc->reserved_gpios;
|
||||
struct property *prop;
|
||||
const __be32 *p;
|
||||
u16 *tmp;
|
||||
|
||||
/* Remove driver-provided reserved GPIOs from valid_mask */
|
||||
@@ -755,6 +1085,17 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *gc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (of_property_count_u32_elems(pctrl->dev->of_node, "qcom,gpios-reserved") > 0) {
|
||||
bitmap_fill(valid_mask, ngpios);
|
||||
of_property_for_each_u32(pctrl->dev->of_node, "qcom,gpios-reserved", prop, p, i) {
|
||||
if (i >= ngpios) {
|
||||
dev_err(pctrl->dev, "invalid list of reserved GPIOs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
clear_bit(i, valid_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* The number of GPIOs in the ACPI tables */
|
||||
len = ret = device_property_count_u16(pctrl->dev, "gpios");
|
||||
if (ret < 0)
|
||||
@@ -1298,6 +1639,8 @@ static int msm_gpio_wakeirq(struct gpio_chip *gc,
|
||||
{
|
||||
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
const struct msm_gpio_wakeirq_map *map;
|
||||
const struct msm_pingroup *g;
|
||||
u32 intr_cfg;
|
||||
int i;
|
||||
|
||||
*parent = GPIO_NO_WAKE_IRQ;
|
||||
@@ -1311,15 +1654,40 @@ static int msm_gpio_wakeirq(struct gpio_chip *gc,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Additionally set intr_wakeup_enable_bit for the GPIOs Routed
|
||||
* to parent irqchip depending on intr_wakeup_present_bit.
|
||||
*/
|
||||
if (*parent != GPIO_NO_WAKE_IRQ) {
|
||||
g = &pctrl->soc->groups[child];
|
||||
|
||||
if (!g->intr_wakeup_present_bit)
|
||||
return 0;
|
||||
|
||||
intr_cfg = msm_readl_intr_cfg(pctrl, g);
|
||||
if (intr_cfg & BIT(g->intr_wakeup_present_bit)) {
|
||||
intr_cfg |= BIT(g->intr_wakeup_enable_bit);
|
||||
msm_writel_intr_cfg(intr_cfg, pctrl, g);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
|
||||
{
|
||||
bool have_reserved, have_gpios;
|
||||
|
||||
if (pctrl->soc->reserved_gpios)
|
||||
return true;
|
||||
|
||||
return device_property_count_u16(pctrl->dev, "gpios") > 0;
|
||||
have_reserved = of_property_count_u32_elems(pctrl->dev->of_node, "qcom,gpios-reserved") > 0;
|
||||
have_gpios = device_property_count_u16(pctrl->dev, "gpios") > 0;
|
||||
|
||||
if (have_reserved && have_gpios)
|
||||
dev_warn(pctrl->dev, "qcom,gpios-reserved and gpios are both defined. Only one should be used.\n");
|
||||
|
||||
return have_reserved || have_gpios;
|
||||
}
|
||||
|
||||
static const struct irq_chip msm_gpio_irq_chip = {
|
||||
@@ -1478,6 +1846,203 @@ SIMPLE_DEV_PM_OPS(msm_pinctrl_dev_pm_ops, msm_pinctrl_suspend,
|
||||
|
||||
EXPORT_SYMBOL(msm_pinctrl_dev_pm_ops);
|
||||
|
||||
void debug_pintctrl_msm_enable(void)
|
||||
{
|
||||
pinctrl_msm_log_mask = true;
|
||||
}
|
||||
EXPORT_SYMBOL(debug_pintctrl_msm_enable);
|
||||
|
||||
void debug_pintctrl_msm_disable(void)
|
||||
{
|
||||
pinctrl_msm_log_mask = false;
|
||||
}
|
||||
EXPORT_SYMBOL(debug_pintctrl_msm_disable);
|
||||
|
||||
static __maybe_unused int noirq_msm_pinctrl_suspend(struct device *dev)
|
||||
{
|
||||
struct msm_pinctrl *pctrl = dev_get_drvdata(dev);
|
||||
|
||||
if (pinctrl_msm_log_mask) {
|
||||
printk_deferred("%s\n", pctrl->chip.label);
|
||||
msm_gpios_status(&pctrl->chip);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dev_pm_ops noirq_msm_pinctrl_dev_pm_ops = {
|
||||
.suspend_noirq = noirq_msm_pinctrl_suspend,
|
||||
};
|
||||
EXPORT_SYMBOL(noirq_msm_pinctrl_dev_pm_ops);
|
||||
|
||||
/*
|
||||
* msm_gpio_mpm_wake_set - API to make interrupt wakeup capable
|
||||
* @dev: Device corrsponding to pinctrl
|
||||
* @gpio: Gpio number to make interrupt wakeup capable
|
||||
* @enable: Enable/Disable wakeup capability
|
||||
*/
|
||||
int msm_gpio_mpm_wake_set(unsigned int gpio, bool enable)
|
||||
{
|
||||
const struct msm_pingroup *g;
|
||||
unsigned long flags;
|
||||
u32 val, intr_cfg;
|
||||
|
||||
g = &msm_pinctrl_data->soc->groups[gpio];
|
||||
if (g->wake_bit == -1 && !g->intr_wakeup_present_bit)
|
||||
return -ENOENT;
|
||||
|
||||
raw_spin_lock_irqsave(&msm_pinctrl_data->lock, flags);
|
||||
|
||||
intr_cfg = msm_readl_intr_cfg(msm_pinctrl_data, g);
|
||||
if (intr_cfg & BIT(g->intr_wakeup_present_bit)) {
|
||||
if (enable)
|
||||
intr_cfg |= BIT(g->intr_wakeup_enable_bit);
|
||||
else
|
||||
intr_cfg &= ~BIT(g->intr_wakeup_enable_bit);
|
||||
|
||||
msm_writel_intr_cfg(intr_cfg, msm_pinctrl_data, g);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
val = readl_relaxed(msm_pinctrl_data->regs[g->tile] + g->wake_reg);
|
||||
if (enable)
|
||||
val |= BIT(g->wake_bit);
|
||||
else
|
||||
val &= ~BIT(g->wake_bit);
|
||||
|
||||
writel_relaxed(val, msm_pinctrl_data->regs[g->tile] + g->wake_reg);
|
||||
|
||||
exit:
|
||||
raw_spin_unlock_irqrestore(&msm_pinctrl_data->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpio_mpm_wake_set);
|
||||
|
||||
/*
|
||||
* msm_gpio_get_pin_address - API to get GPIO physical address range
|
||||
* @gpio_num: global GPIO num, as returned from gpio apis - desc_to_gpio().
|
||||
* @res: Out param. Resource struct with start/end addr populated.
|
||||
* @ret: true if the pin is valid, false otherwise.
|
||||
*/
|
||||
bool msm_gpio_get_pin_address(unsigned int gpio_num, struct resource *res)
|
||||
{
|
||||
struct gpio_chip *chip;
|
||||
const struct msm_pingroup *g;
|
||||
struct resource *tile_res;
|
||||
struct platform_device *pdev;
|
||||
unsigned int gpio;
|
||||
|
||||
if (!msm_pinctrl_data) {
|
||||
pr_err("pinctrl data is not available\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
chip = &msm_pinctrl_data->chip;
|
||||
pdev = to_platform_device(msm_pinctrl_data->dev);
|
||||
gpio = gpio_num - chip->base;
|
||||
|
||||
if (!gpiochip_line_is_valid(chip, gpio))
|
||||
return false;
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
g = &msm_pinctrl_data->soc->groups[gpio];
|
||||
if (msm_pinctrl_data->soc->tiles)
|
||||
tile_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
msm_pinctrl_data->soc->tiles[g->tile]);
|
||||
else
|
||||
tile_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!tile_res) {
|
||||
dev_err(&pdev->dev, "failed to get resource\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
res->start = tile_res->start + g->ctl_reg;
|
||||
res->end = res->start + (g->reg_size_4k ? : DEFAULT_REG_SIZE_4K) * SZ_4K - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpio_get_pin_address);
|
||||
|
||||
int msm_qup_write(u32 mode, u32 val)
|
||||
{
|
||||
int i;
|
||||
struct pinctrl_qup *regs = msm_pinctrl_data->soc->qup_regs;
|
||||
int num_regs = msm_pinctrl_data->soc->nqup_regs;
|
||||
|
||||
/*Iterate over modes*/
|
||||
for (i = 0; i < num_regs; i++) {
|
||||
if (regs[i].mode == mode) {
|
||||
writel_relaxed(val & QUP_MASK,
|
||||
msm_pinctrl_data->regs[0] + regs[i].offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_qup_write);
|
||||
|
||||
int msm_qup_read(unsigned int mode)
|
||||
{
|
||||
int i, val;
|
||||
struct pinctrl_qup *regs = msm_pinctrl_data->soc->qup_regs;
|
||||
int num_regs = msm_pinctrl_data->soc->nqup_regs;
|
||||
|
||||
/*Iterate over modes*/
|
||||
for (i = 0; i < num_regs; i++) {
|
||||
if (regs[i].mode == mode) {
|
||||
val = readl_relaxed(msm_pinctrl_data->regs[0] +
|
||||
regs[i].offset);
|
||||
return val & QUP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_qup_read);
|
||||
|
||||
int msm_spare_write(int spare_reg, u32 val)
|
||||
{
|
||||
u32 offset;
|
||||
const struct msm_spare_tlmm *regs = msm_pinctrl_data->soc->spare_regs;
|
||||
int num_regs = msm_pinctrl_data->soc->nspare_regs;
|
||||
|
||||
if (!regs || spare_reg >= num_regs)
|
||||
return -ENOENT;
|
||||
|
||||
offset = regs[spare_reg].offset;
|
||||
if (offset != 0) {
|
||||
writel_relaxed(val & SPARE_MASK,
|
||||
msm_pinctrl_data->regs[0] + offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(msm_spare_write);
|
||||
|
||||
int msm_spare_read(int spare_reg)
|
||||
{
|
||||
u32 offset, val;
|
||||
const struct msm_spare_tlmm *regs = msm_pinctrl_data->soc->spare_regs;
|
||||
int num_regs = msm_pinctrl_data->soc->nspare_regs;
|
||||
|
||||
if (!regs || spare_reg >= num_regs)
|
||||
return -ENOENT;
|
||||
|
||||
offset = regs[spare_reg].offset;
|
||||
if (offset != 0) {
|
||||
val = readl_relaxed(msm_pinctrl_data->regs[0] + offset);
|
||||
return val & SPARE_MASK;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(msm_spare_read);
|
||||
|
||||
int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
const struct msm_pinctrl_soc_data *soc_data)
|
||||
{
|
||||
@@ -1486,7 +2051,7 @@ int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
|
||||
msm_pinctrl_data = pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
|
||||
if (!pctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1528,6 +2093,8 @@ int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
pctrl->desc.name = dev_name(&pdev->dev);
|
||||
pctrl->desc.pins = pctrl->soc->pins;
|
||||
pctrl->desc.npins = pctrl->soc->npins;
|
||||
pctrl->desc.num_custom_params = ARRAY_SIZE(msm_gpio_bindings);
|
||||
pctrl->desc.custom_params = msm_gpio_bindings;
|
||||
|
||||
pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
|
||||
if (IS_ERR(pctrl->pctrl)) {
|
||||
@@ -1539,6 +2106,8 @@ int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pinctrl_msm_log_mask = false;
|
||||
|
||||
platform_set_drvdata(pdev, pctrl);
|
||||
|
||||
dev_dbg(&pdev->dev, "Probed Qualcomm pinctrl driver\n");
|
||||
@@ -1559,5 +2128,6 @@ int msm_pinctrl_remove(struct platform_device *pdev)
|
||||
}
|
||||
EXPORT_SYMBOL(msm_pinctrl_remove);
|
||||
|
||||
MODULE_SOFTDEP("pre: qcom-pdc");
|
||||
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. TLMM driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@@ -1,10 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2013, Sony Mobile Communications AB.
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef __PINCTRL_MSM_H__
|
||||
#define __PINCTRL_MSM_H__
|
||||
|
||||
#include <linux/pinctrl/qcom-pinctrl.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
@@ -48,6 +51,7 @@ struct pinctrl_pin_desc;
|
||||
* @intr_status_reg: Offset of the register holding the status bits for this group.
|
||||
* @intr_target_reg: Offset of the register specifying routing of the interrupts
|
||||
* from this group.
|
||||
* @reg_size_4k: Size of the group register space in 4k granularity.
|
||||
* @mux_bit: Offset in @ctl_reg for the pinmux function selection.
|
||||
* @pull_bit: Offset in @ctl_reg for the bias configuration.
|
||||
* @drv_bit: Offset in @ctl_reg for the drive strength configuration.
|
||||
@@ -68,6 +72,8 @@ struct pinctrl_pin_desc;
|
||||
* @intr_detection_width: Number of bits used for specifying interrupt type,
|
||||
* Should be 2 for SoCs that can detect both edges in hardware,
|
||||
* otherwise 1.
|
||||
* @wake_reg: Offset of the WAKEUP_INT_EN register from base tile
|
||||
* @wake_bit: Bit number for the corresponding gpio
|
||||
*/
|
||||
struct msm_pingroup {
|
||||
struct pingroup grp;
|
||||
@@ -80,6 +86,7 @@ struct msm_pingroup {
|
||||
u32 intr_cfg_reg;
|
||||
u32 intr_status_reg;
|
||||
u32 intr_target_reg;
|
||||
unsigned int reg_size_4k:5;
|
||||
|
||||
unsigned int tile:2;
|
||||
|
||||
@@ -101,12 +108,17 @@ struct msm_pingroup {
|
||||
unsigned intr_ack_high:1;
|
||||
|
||||
unsigned intr_target_bit:5;
|
||||
unsigned intr_wakeup_enable_bit:5;
|
||||
unsigned intr_wakeup_present_bit:5;
|
||||
unsigned intr_target_width:5;
|
||||
unsigned intr_target_kpss_val:5;
|
||||
unsigned intr_raw_status_bit:5;
|
||||
unsigned intr_polarity_bit:5;
|
||||
unsigned intr_detection_bit:5;
|
||||
unsigned intr_detection_width:5;
|
||||
|
||||
u32 wake_reg;
|
||||
unsigned int wake_bit;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -119,6 +131,26 @@ struct msm_gpio_wakeirq_map {
|
||||
unsigned int wakeirq;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct pinctrl_qup - Qup mode configuration
|
||||
* @mode: Qup i3c mode
|
||||
* @offset: Offset of the register
|
||||
*/
|
||||
struct pinctrl_qup {
|
||||
u32 mode;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct msm_spare_tlmm - TLMM spare registers config
|
||||
* @spare_reg: spare register number
|
||||
* @offset: Offset of spare register
|
||||
*/
|
||||
struct msm_spare_tlmm {
|
||||
int spare_reg;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration
|
||||
* @pins: An array describing all pins the pin controller affects.
|
||||
@@ -158,11 +190,16 @@ struct msm_pinctrl_soc_data {
|
||||
const struct msm_gpio_wakeirq_map *wakeirq_map;
|
||||
unsigned int nwakeirq_map;
|
||||
bool wakeirq_dual_edge_errata;
|
||||
struct pinctrl_qup *qup_regs;
|
||||
unsigned int nqup_regs;
|
||||
unsigned int gpio_func;
|
||||
unsigned int egpio_func;
|
||||
const struct msm_spare_tlmm *spare_regs;
|
||||
unsigned int nspare_regs;
|
||||
};
|
||||
|
||||
extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;
|
||||
extern const struct dev_pm_ops noirq_msm_pinctrl_dev_pm_ops;
|
||||
|
||||
int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
const struct msm_pinctrl_soc_data *soc_data);
|
||||
|
81
drivers/pinctrl/qcom/pinctrl-parrot.c
Normal file
81
drivers/pinctrl/qcom/pinctrl-parrot.c
Normal file
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022, 2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-msm.h"
|
||||
#include "pinctrl-parrot.h"
|
||||
|
||||
static const struct msm_pinctrl_soc_data parrot_tlmm = {
|
||||
.pins = parrot_pins,
|
||||
.npins = ARRAY_SIZE(parrot_pins),
|
||||
.functions = parrot_functions,
|
||||
.nfunctions = ARRAY_SIZE(parrot_functions),
|
||||
.groups = parrot_groups,
|
||||
.ngroups = ARRAY_SIZE(parrot_groups),
|
||||
.ngpios = 142,
|
||||
.wakeirq_map = parrot_pdc_map,
|
||||
.nwakeirq_map = ARRAY_SIZE(parrot_pdc_map),
|
||||
.egpio_func = 11,
|
||||
};
|
||||
|
||||
static const struct msm_pinctrl_soc_data parrot_vm_tlmm = {
|
||||
.pins = parrot_pins,
|
||||
.npins = ARRAY_SIZE(parrot_pins),
|
||||
.functions = parrot_functions,
|
||||
.nfunctions = ARRAY_SIZE(parrot_functions),
|
||||
.groups = parrot_groups,
|
||||
.ngroups = ARRAY_SIZE(parrot_groups),
|
||||
.ngpios = 142,
|
||||
.egpio_func = 11,
|
||||
};
|
||||
|
||||
static int parrot_tlmm_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct msm_pinctrl_soc_data *pinctrl_data;
|
||||
|
||||
pinctrl_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!pinctrl_data)
|
||||
return -EINVAL;
|
||||
|
||||
return msm_pinctrl_probe(pdev, pinctrl_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id parrot_tlmm_of_match[] = {
|
||||
{ .compatible = "qcom,parrot-tlmm", .data = &parrot_tlmm},
|
||||
{ .compatible = "qcom,parrot-vm-tlmm", .data = &parrot_vm_tlmm},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver parrot_tlmm_driver = {
|
||||
.driver = {
|
||||
.name = "parrot-pinctrl",
|
||||
.of_match_table = parrot_tlmm_of_match,
|
||||
},
|
||||
.probe = parrot_tlmm_probe,
|
||||
.remove = msm_pinctrl_remove,
|
||||
};
|
||||
|
||||
static int __init parrot_tlmm_init(void)
|
||||
{
|
||||
return platform_driver_register(&parrot_tlmm_driver);
|
||||
}
|
||||
arch_initcall(parrot_tlmm_init);
|
||||
|
||||
static void __exit parrot_tlmm_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&parrot_tlmm_driver);
|
||||
}
|
||||
module_exit(parrot_tlmm_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QTI parrot TLMM driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(of, parrot_tlmm_of_match);
|
||||
MODULE_SOFTDEP("pre: qcom_tlmm_vm_irqchip");
|
1804
drivers/pinctrl/qcom/pinctrl-parrot.h
Normal file
1804
drivers/pinctrl/qcom/pinctrl-parrot.h
Normal file
File diff suppressed because it is too large
Load Diff
2550
drivers/pinctrl/qcom/pinctrl-pineapple.c
Normal file
2550
drivers/pinctrl/qcom/pinctrl-pineapple.c
Normal file
File diff suppressed because it is too large
Load Diff
78
drivers/pinctrl/qcom/pinctrl-ravelin.c
Normal file
78
drivers/pinctrl/qcom/pinctrl-ravelin.c
Normal file
@@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-msm.h"
|
||||
#include "pinctrl-ravelin.h"
|
||||
|
||||
static const struct msm_pinctrl_soc_data ravelin_tlmm = {
|
||||
.pins = ravelin_pins,
|
||||
.npins = ARRAY_SIZE(ravelin_pins),
|
||||
.functions = ravelin_functions,
|
||||
.nfunctions = ARRAY_SIZE(ravelin_functions),
|
||||
.groups = ravelin_groups,
|
||||
.ngroups = ARRAY_SIZE(ravelin_groups),
|
||||
.ngpios = 137,
|
||||
.wakeirq_map = ravelin_pdc_map,
|
||||
.nwakeirq_map = ARRAY_SIZE(ravelin_pdc_map),
|
||||
};
|
||||
|
||||
static const struct msm_pinctrl_soc_data ravelin_vm_tlmm = {
|
||||
.pins = ravelin_pins,
|
||||
.npins = ARRAY_SIZE(ravelin_pins),
|
||||
.functions = ravelin_functions,
|
||||
.nfunctions = ARRAY_SIZE(ravelin_functions),
|
||||
.groups = ravelin_groups,
|
||||
.ngroups = ARRAY_SIZE(ravelin_groups),
|
||||
.ngpios = 137,
|
||||
};
|
||||
|
||||
static int ravelin_tlmm_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct msm_pinctrl_soc_data *pinctrl_data;
|
||||
|
||||
pinctrl_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!pinctrl_data)
|
||||
return -EINVAL;
|
||||
|
||||
return msm_pinctrl_probe(pdev, pinctrl_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id ravelin_tlmm_of_match[] = {
|
||||
{ .compatible = "qcom,ravelin-tlmm", .data = &ravelin_tlmm},
|
||||
{ .compatible = "qcom,ravelin-vm-tlmm", .data = &ravelin_vm_tlmm},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver ravelin_tlmm_driver = {
|
||||
.driver = {
|
||||
.name = "ravelin-tlmm",
|
||||
.of_match_table = ravelin_tlmm_of_match,
|
||||
},
|
||||
.probe = ravelin_tlmm_probe,
|
||||
.remove = msm_pinctrl_remove,
|
||||
};
|
||||
|
||||
static int __init ravelin_tlmm_init(void)
|
||||
{
|
||||
return platform_driver_register(&ravelin_tlmm_driver);
|
||||
}
|
||||
arch_initcall(ravelin_tlmm_init);
|
||||
|
||||
static void __exit ravelin_tlmm_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ravelin_tlmm_driver);
|
||||
}
|
||||
module_exit(ravelin_tlmm_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QTI ravelin tlmm driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(of, ravelin_tlmm_of_match);
|
||||
MODULE_SOFTDEP("pre: qcom_tlmm_vm_irqchip");
|
1632
drivers/pinctrl/qcom/pinctrl-ravelin.h
Normal file
1632
drivers/pinctrl/qcom/pinctrl-ravelin.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2014, 2016-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
@@ -139,6 +139,7 @@ enum pmic_gpio_func_index {
|
||||
* struct pmic_gpio_pad - keep current GPIO settings
|
||||
* @base: Address base in SPMI device.
|
||||
* @is_enabled: Set to false when GPIO should be put in high Z state.
|
||||
* @is_configured: Set to true if the GPIO is configured
|
||||
* @out_value: Cached pin output value
|
||||
* @have_buffer: Set to true if GPIO output could be configured in push-pull,
|
||||
* open-drain or open-source mode.
|
||||
@@ -158,6 +159,7 @@ enum pmic_gpio_func_index {
|
||||
struct pmic_gpio_pad {
|
||||
u16 base;
|
||||
bool is_enabled;
|
||||
bool is_configured;
|
||||
bool out_value;
|
||||
bool have_buffer;
|
||||
bool output_enabled;
|
||||
@@ -329,6 +331,7 @@ static int pmic_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
||||
}
|
||||
|
||||
pad->function = function;
|
||||
pad->is_configured = true;
|
||||
|
||||
if (pad->analog_pass)
|
||||
val = PMIC_GPIO_MODE_ANALOG_PASS_THRU;
|
||||
@@ -485,6 +488,7 @@ static int pmic_gpio_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
pad = pctldev->desc->pins[pin].drv_data;
|
||||
|
||||
pad->is_enabled = true;
|
||||
pad->is_configured = true;
|
||||
for (i = 0; i < nconfs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
@@ -713,6 +717,90 @@ static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_GPIO_DUMP)
|
||||
#define MAX_PMIC 32
|
||||
static int pmic_count;
|
||||
static struct gpio_chip *pmic_gpio_chip[MAX_PMIC];
|
||||
|
||||
static void pmic_gpio_sec_dbg_print(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct pmic_gpio_pad *pad;
|
||||
int val, ret, function;
|
||||
int index;
|
||||
|
||||
static const char *const biases[] = {
|
||||
"pull-up 30uA", "pull-up 1.5uA", "pull-up 31.5uA",
|
||||
"pull-up 1.5uA + 30uA boost", "pull-down 10uA", "no pull"
|
||||
};
|
||||
static const char *const buffer_types[] = {
|
||||
"push-pull", "open-drain", "open-source"
|
||||
};
|
||||
static const char *const strengths[] = {
|
||||
"no", "high", "medium", "low"
|
||||
};
|
||||
|
||||
pr_info("%s: chip.label:%s\n", __func__, state->chip.label);
|
||||
|
||||
for (index = 0; index < state->chip.ngpio; index++) {
|
||||
pad = pctldev->desc->pins[index].drv_data;
|
||||
val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_EN_CTL);
|
||||
|
||||
if (val < 0 || !(val >> PMIC_GPIO_REG_MASTER_EN_SHIFT)) {
|
||||
pr_info(" gpio%-2d: ---\n", index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pad->input_enabled) {
|
||||
ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
|
||||
pad->out_value = ret;
|
||||
}
|
||||
|
||||
if (!pad->lv_mv_type &&
|
||||
pad->function >= PMIC_GPIO_FUNC_INDEX_FUNC3) {
|
||||
function = pad->function + (PMIC_GPIO_FUNC_INDEX_DTEST1 -
|
||||
PMIC_GPIO_FUNC_INDEX_FUNC3);
|
||||
} else {
|
||||
function = pad->function;
|
||||
}
|
||||
|
||||
pr_info(" gpio%-2d: %-7s %-4s vin-%d %-27s %-10s %-2s %-7s atest-%d dtest-%d\n",
|
||||
index,
|
||||
pmic_gpio_functions[function],
|
||||
pad->output_enabled ? "OUT" : "IN",
|
||||
pad->power_source,
|
||||
biases[pad->pullup],
|
||||
buffer_types[pad->buffer_type],
|
||||
pad->out_value ? "H" : "L",
|
||||
strengths[pad->strength],
|
||||
pad->atest,
|
||||
pad->dtest_buffer);
|
||||
}
|
||||
|
||||
pr_info("\n");
|
||||
}
|
||||
|
||||
static void pmic_gpio_sec_dbg_show(struct gpio_chip *chip)
|
||||
{
|
||||
struct pmic_gpio_state *state = gpiochip_get_data(chip);
|
||||
|
||||
pmic_gpio_sec_dbg_print(state->ctrl);
|
||||
}
|
||||
|
||||
void sec_pmic_gpio_debug_print(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < pmic_count; i++)
|
||||
pmic_gpio_sec_dbg_show(pmic_gpio_chip[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sec_pmic_gpio_debug_print);
|
||||
#endif /* CONFIG_SEC_GPIO_DUMP */
|
||||
|
||||
static const struct pinconf_ops pmic_gpio_pinconf_ops = {
|
||||
.is_generic = true,
|
||||
.pin_config_group_get = pmic_gpio_config_get,
|
||||
@@ -808,6 +896,33 @@ static const struct gpio_chip pmic_gpio_gpio_template = {
|
||||
.dbg_show = pmic_gpio_dbg_show,
|
||||
};
|
||||
|
||||
static int __maybe_unused pmic_gpio_restore(struct device *dev)
|
||||
{
|
||||
struct pmic_gpio_state *state = dev_get_drvdata(dev);
|
||||
struct pinctrl_dev *ctrl = state->ctrl;
|
||||
struct pmic_gpio_pad *pad;
|
||||
unsigned int i, npins = ctrl->desc->npins;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < npins; i++) {
|
||||
pad = ctrl->desc->pins[i].drv_data;
|
||||
if (pad->is_configured) {
|
||||
ret = pmic_gpio_config_set(ctrl, i, NULL, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(state->dev, "Failed to restore pin %s[%d] ret=%d\n",
|
||||
ctrl->desc->pins[i].name, i, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops __maybe_unused pmic_gpio_pm_ops = {
|
||||
.restore = pm_ptr(pmic_gpio_restore),
|
||||
};
|
||||
|
||||
static int pmic_gpio_populate(struct pmic_gpio_state *state,
|
||||
struct pmic_gpio_pad *pad)
|
||||
{
|
||||
@@ -961,6 +1076,7 @@ static int pmic_gpio_populate(struct pmic_gpio_state *state,
|
||||
|
||||
/* Pin could be disabled with PIN_CONFIG_BIAS_HIGH_IMPEDANCE */
|
||||
pad->is_enabled = true;
|
||||
pad->is_configured = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1129,6 +1245,11 @@ static int pmic_gpio_probe(struct platform_device *pdev)
|
||||
state->chip.of_gpio_n_cells = 2;
|
||||
state->chip.can_sleep = false;
|
||||
|
||||
#if IS_ENABLED(CONFIG_SEC_GPIO_DUMP)
|
||||
pr_info("%s: [%d]chip.label:%s\n", __func__, pmic_count, state->chip.label);
|
||||
pmic_gpio_chip[pmic_count++] = &(state->chip);
|
||||
#endif
|
||||
|
||||
state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
|
||||
if (IS_ERR(state->ctrl))
|
||||
return PTR_ERR(state->ctrl);
|
||||
@@ -1203,6 +1324,7 @@ static const struct of_device_id pmic_gpio_of_match[] = {
|
||||
{ .compatible = "qcom,pm6150-gpio", .data = (void *) 10 },
|
||||
{ .compatible = "qcom,pm6150l-gpio", .data = (void *) 12 },
|
||||
{ .compatible = "qcom,pm6350-gpio", .data = (void *) 9 },
|
||||
{ .compatible = "qcom,pm6450-gpio", .data = (void *) 9 },
|
||||
{ .compatible = "qcom,pm7250b-gpio", .data = (void *) 12 },
|
||||
{ .compatible = "qcom,pm7325-gpio", .data = (void *) 10 },
|
||||
{ .compatible = "qcom,pm7550ba-gpio", .data = (void *) 8},
|
||||
@@ -1235,10 +1357,13 @@ static const struct of_device_id pmic_gpio_of_match[] = {
|
||||
{ .compatible = "qcom,pm8994-gpio", .data = (void *) 22 },
|
||||
{ .compatible = "qcom,pm8998-gpio", .data = (void *) 26 },
|
||||
{ .compatible = "qcom,pma8084-gpio", .data = (void *) 22 },
|
||||
{ .compatible = "qcom,pmd802x-gpio", .data = (void *) 4 },
|
||||
{ .compatible = "qcom,pmi632-gpio", .data = (void *) 8 },
|
||||
{ .compatible = "qcom,pmi8950-gpio", .data = (void *) 2 },
|
||||
{ .compatible = "qcom,pmi8994-gpio", .data = (void *) 10 },
|
||||
{ .compatible = "qcom,pmi8998-gpio", .data = (void *) 14 },
|
||||
{ .compatible = "qcom,pmih010x-gpio", .data = (void *) 18 },
|
||||
{ .compatible = "qcom,pmiv0108-gpio", .data = (void *) 10 },
|
||||
{ .compatible = "qcom,pmk8350-gpio", .data = (void *) 4 },
|
||||
{ .compatible = "qcom,pmk8550-gpio", .data = (void *) 6 },
|
||||
{ .compatible = "qcom,pmm8155au-gpio", .data = (void *) 10 },
|
||||
@@ -1254,6 +1379,8 @@ static const struct of_device_id pmic_gpio_of_match[] = {
|
||||
{ .compatible = "qcom,pmx55-gpio", .data = (void *) 11 },
|
||||
{ .compatible = "qcom,pmx65-gpio", .data = (void *) 16 },
|
||||
{ .compatible = "qcom,pmx75-gpio", .data = (void *) 16 },
|
||||
{ .compatible = "qcom,pmxr2230-gpio", .data = (void *) 12 },
|
||||
{ .compatible = "qcom,pm5100-gpio", .data = (void *) 16 },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -1263,6 +1390,7 @@ static struct platform_driver pmic_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "qcom-spmi-gpio",
|
||||
.of_match_table = pmic_gpio_of_match,
|
||||
.pm = pm_ptr(&pmic_gpio_pm_ops),
|
||||
},
|
||||
.probe = pmic_gpio_probe,
|
||||
.remove = pmic_gpio_remove,
|
||||
|
2607
drivers/pinctrl/qcom/pinctrl-sun.c
Normal file
2607
drivers/pinctrl/qcom/pinctrl-sun.c
Normal file
File diff suppressed because it is too large
Load Diff
2338
drivers/pinctrl/qcom/pinctrl-tuna.c
Normal file
2338
drivers/pinctrl/qcom/pinctrl-tuna.c
Normal file
File diff suppressed because it is too large
Load Diff
2379
drivers/pinctrl/qcom/pinctrl-x1e80100.c
Normal file
2379
drivers/pinctrl/qcom/pinctrl-x1e80100.c
Normal file
File diff suppressed because it is too large
Load Diff
331
drivers/pinctrl/qcom/secgpio_dvs.c
Normal file
331
drivers/pinctrl/qcom/secgpio_dvs.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Samsung Mobile VE Group.
|
||||
*
|
||||
* drivers/gpio/secgpio_dvs.c
|
||||
*
|
||||
* Drivers for samsung gpio debugging & verification.
|
||||
*
|
||||
* Copyright (C) 2013, Samsung Electronics.
|
||||
*
|
||||
* This program is free software. You can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "secgpio_dvs.h"
|
||||
#include <trace/events/power.h>
|
||||
|
||||
/*sys fs*/
|
||||
struct class *secgpio_dvs_class;
|
||||
EXPORT_SYMBOL(secgpio_dvs_class);
|
||||
|
||||
struct device *secgpio_dotest;
|
||||
EXPORT_SYMBOL(secgpio_dotest);
|
||||
|
||||
/* extern GPIOMAP_RESULT GpioMap_result; */
|
||||
static struct gpio_dvs_t *gdvs_info;
|
||||
|
||||
static ssize_t checked_secgpio_file_read(
|
||||
struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t checked_sleep_secgpio_file_read(
|
||||
struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t checked_secgpio_init_read_details(
|
||||
struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t checked_secgpio_sleep_read_details(
|
||||
struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t secgpio_checked_sleepgpio_read(
|
||||
struct device *dev, struct device_attribute *attr, char *buf);
|
||||
static ssize_t checked_secgpio_init_call(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len);
|
||||
|
||||
static DEVICE_ATTR(gpioinit_check, 0664,
|
||||
checked_secgpio_file_read, NULL);
|
||||
static DEVICE_ATTR(gpiosleep_check, 0664,
|
||||
checked_sleep_secgpio_file_read, NULL);
|
||||
static DEVICE_ATTR(check_init_detail, 0664,
|
||||
checked_secgpio_init_read_details, NULL);
|
||||
static DEVICE_ATTR(check_sleep_detail, 0664,
|
||||
checked_secgpio_sleep_read_details, NULL);
|
||||
static DEVICE_ATTR(checked_sleepGPIO, 0664,
|
||||
secgpio_checked_sleepgpio_read, NULL);
|
||||
static DEVICE_ATTR(gpioinit_call, 0664,
|
||||
NULL, checked_secgpio_init_call);
|
||||
|
||||
static struct attribute *secgpio_dvs_attributes[] = {
|
||||
&dev_attr_gpioinit_check.attr,
|
||||
&dev_attr_gpiosleep_check.attr,
|
||||
&dev_attr_check_init_detail.attr,
|
||||
&dev_attr_check_sleep_detail.attr,
|
||||
&dev_attr_checked_sleepGPIO.attr,
|
||||
&dev_attr_gpioinit_call.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group secgpio_dvs_attr_group = {
|
||||
.attrs = secgpio_dvs_attributes,
|
||||
};
|
||||
|
||||
static ssize_t checked_secgpio_file_read(
|
||||
struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
char temp_buf[20];
|
||||
struct gpio_dvs_t *gdvs = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < gdvs->count; i++) {
|
||||
memset(temp_buf, 0, sizeof(char)*20);
|
||||
snprintf(temp_buf, 20, "%x ", gdvs->result->init[i]);
|
||||
strlcat(buf, temp_buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t checked_sleep_secgpio_file_read(
|
||||
struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
char temp_buf[20];
|
||||
struct gpio_dvs_t *gdvs = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < gdvs->count; i++) {
|
||||
memset(temp_buf, 0, sizeof(char)*20);
|
||||
snprintf(temp_buf, 20, "%x ", gdvs->result->sleep[i]);
|
||||
strlcat(buf, temp_buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t checked_secgpio_init_read_details(
|
||||
struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
char temp_buf[20];
|
||||
struct gpio_dvs_t *gdvs = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < gdvs->count; i++) {
|
||||
memset(temp_buf, 0, sizeof(char)*20);
|
||||
snprintf(temp_buf, 20, "GI[%d] - %x\n ",
|
||||
i, gdvs->result->init[i]);
|
||||
strlcat(buf, temp_buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
static ssize_t checked_secgpio_sleep_read_details(
|
||||
struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
char temp_buf[20];
|
||||
struct gpio_dvs_t *gdvs = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < gdvs->count; i++) {
|
||||
memset(temp_buf, 0, sizeof(char)*20);
|
||||
snprintf(temp_buf, 20, "GS[%d] - %x\n ",
|
||||
i, gdvs->result->sleep[i]);
|
||||
strlcat(buf, temp_buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return strlen(buf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static ssize_t secgpio_checked_sleepgpio_read(
|
||||
struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gpio_dvs_t *gdvs = dev_get_drvdata(dev);
|
||||
|
||||
if (gdvs->check_sleep)
|
||||
return snprintf(buf, PAGE_SIZE, "1");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "0");
|
||||
}
|
||||
|
||||
static ssize_t checked_secgpio_init_call(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
/* Check init gpio status */
|
||||
gpio_dvs_check_initgpio();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void gpio_dvs_check_initgpio(void)
|
||||
{
|
||||
if (gdvs_info && gdvs_info->check_gpio_status)
|
||||
gdvs_info->check_gpio_status(PHONE_INIT);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_dvs_check_initgpio);
|
||||
|
||||
void gpio_dvs_check_sleepgpio(void)
|
||||
{
|
||||
if (unlikely(gdvs_info && !gdvs_info->check_sleep)) {
|
||||
gdvs_info->check_gpio_status(PHONE_SLEEP);
|
||||
gdvs_info->check_sleep = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id secgpio_dvs_dt_match[] = {
|
||||
{ .compatible = "samsung,secgpio-dvs",
|
||||
.data = (void *)&msm_gpio_dvs_data },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, secgpio_dvs_dt_match);
|
||||
|
||||
static struct secgpio_dvs_data *secgpio_dvs_get_soc_data(
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct secgpio_dvs_data *data;
|
||||
|
||||
match = of_match_node(secgpio_dvs_dt_match, node);
|
||||
if (!match) {
|
||||
dev_err(&pdev->dev, "failed to get SoC node\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (struct secgpio_dvs_data *)match->data;
|
||||
if (!data) {
|
||||
dev_err(&pdev->dev, "failed to get SoC data\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
#else
|
||||
static struct gpio_dvs_t *secgpio_dvs_get_soc_data(struct platform_device *pdev)
|
||||
{
|
||||
return dev_get_platdata(&pdev->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int secgpio_dvs_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct class *secgpio_dvs_class;
|
||||
struct device *secgpio_dotest;
|
||||
struct secgpio_dvs_data *data = secgpio_dvs_get_soc_data(pdev);
|
||||
struct gpio_dvs_t *gdvs;
|
||||
|
||||
pr_info("[secgpio_dvs] %s has been created!!!\n", __func__);
|
||||
|
||||
if (!data)
|
||||
return -ENODEV;
|
||||
|
||||
gdvs = data->gpio_dvs;
|
||||
|
||||
secgpio_dvs_class = class_create("secgpio_check");
|
||||
if (IS_ERR(secgpio_dvs_class)) {
|
||||
ret = PTR_ERR(secgpio_dvs_class);
|
||||
pr_err("Failed to create class(secgpio_check_all)");
|
||||
goto fail_out;
|
||||
}
|
||||
|
||||
secgpio_dotest = device_create(secgpio_dvs_class,
|
||||
NULL, 0, NULL, "secgpio_check_all");
|
||||
if (IS_ERR(secgpio_dotest)) {
|
||||
ret = PTR_ERR(secgpio_dotest);
|
||||
pr_err("Failed to create device(secgpio_check_all)");
|
||||
goto fail1;
|
||||
}
|
||||
dev_set_drvdata(secgpio_dotest, gdvs);
|
||||
gdvs_info = gdvs;
|
||||
|
||||
ret = sysfs_create_group(&secgpio_dotest->kobj,
|
||||
&secgpio_dvs_attr_group);
|
||||
if (ret) {
|
||||
pr_err("Failed to create sysfs group");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
fail2:
|
||||
device_destroy(secgpio_dvs_class, 0);
|
||||
fail1:
|
||||
class_destroy(secgpio_dvs_class);
|
||||
fail_out:
|
||||
if (ret)
|
||||
pr_err(" (err = %d)!\n", ret);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int secgpio_dvs_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver secgpio_dvs = {
|
||||
.probe = secgpio_dvs_probe,
|
||||
.remove = secgpio_dvs_remove,
|
||||
.driver = {
|
||||
.name = "secgpio_dvs",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_OF
|
||||
.of_match_table = of_match_ptr(secgpio_dvs_dt_match),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
static void gpio_debug_suspend_trace_probe(void *unused,
|
||||
const char *action, int val, bool start)
|
||||
{
|
||||
if (start && val > 0 && !strcmp("machine_suspend", action)) {
|
||||
gpio_dvs_check_sleepgpio();
|
||||
}
|
||||
}
|
||||
|
||||
static int __init secgpio_dvs_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&secgpio_dvs);
|
||||
pr_info("[secgpio_dvs] %s has been initialized!!!, ret=%d\n", __func__, ret);
|
||||
|
||||
/* Register callback for cheking sleep gpio status */
|
||||
ret = register_trace_suspend_resume(
|
||||
gpio_debug_suspend_trace_probe, NULL);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to register suspend trace callback, ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit secgpio_dvs_exit(void)
|
||||
{
|
||||
unregister_trace_suspend_resume(
|
||||
gpio_debug_suspend_trace_probe, NULL);
|
||||
|
||||
platform_driver_unregister(&secgpio_dvs);
|
||||
}
|
||||
|
||||
module_init(secgpio_dvs_init);
|
||||
module_exit(secgpio_dvs_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Samsung GPIO debugging and verification");
|
||||
MODULE_LICENSE("GPL v2");
|
50
drivers/pinctrl/qcom/secgpio_dvs.h
Normal file
50
drivers/pinctrl/qcom/secgpio_dvs.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* secgpio_dvs.h -- Samsung GPIO debugging and verification system
|
||||
*/
|
||||
|
||||
#ifndef __SECGPIO_DVS_H
|
||||
#define __SECGPIO_DVS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum gdvs_phone_status {
|
||||
PHONE_INIT = 0,
|
||||
PHONE_SLEEP,
|
||||
GDVS_PHONE_STATUS_MAX
|
||||
};
|
||||
|
||||
enum gdvs_io_value {
|
||||
GDVS_IO_FUNC = 0x00,
|
||||
GDVS_IO_IN,
|
||||
GDVS_IO_OUT,
|
||||
};
|
||||
|
||||
enum gdvs_pupd_value {
|
||||
GDVS_PUPD_NP = 0x00,
|
||||
GDVS_PUPD_PD,
|
||||
GDVS_PUPD_PU,
|
||||
GDVS_PUPD_KEEPER,
|
||||
GDVS_PUPD_ERR = 0x3F
|
||||
};
|
||||
|
||||
struct gpiomap_result {
|
||||
unsigned char *init;
|
||||
unsigned char *sleep;
|
||||
};
|
||||
|
||||
struct gpio_dvs_t {
|
||||
struct gpiomap_result *result;
|
||||
unsigned int count;
|
||||
bool check_sleep;
|
||||
void (*check_gpio_status)(unsigned char phonestate);
|
||||
};
|
||||
|
||||
struct secgpio_dvs_data {
|
||||
struct gpio_dvs_t *gpio_dvs;
|
||||
};
|
||||
|
||||
void gpio_dvs_check_initgpio(void);
|
||||
void gpio_dvs_check_sleepgpio(void);
|
||||
|
||||
extern const struct secgpio_dvs_data msm_gpio_dvs_data;
|
||||
#endif /* __SECGPIO_DVS_H */
|
Reference in New Issue
Block a user