Files
android_kernel_motorola_sm6225/kernel/power/user_sysfs_private.c
T
yangjq f62b4fa286 power: suspend: Save snapshot of gpio, vreg when suspend
Add system node /sys/private/tlmm_before_sleep etc.
Used to check and change the gpio before suspend.
This won't save and change gpio's config only after a read of the node.
Use tlmm_tz to skip those gpios locked by TZ such as 111, 126.

Change-Id: I99810d8659ab8ea4a59029a9cea326f93becefd2
Signed-off-by: yangjq <yangjq@lenovo.com>
Reviewed-on: https://gerrit.mot.com/960741
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver <sltawvr@motorola.com>
Tested-by: Jira Key <jirakey@motorola.com>
Reviewed-by: Igor Kovalenko <igork@motorola.com>
Submit-Approved: Jira Key <jirakey@motorola.com>
Reviewed-on: https://gerrit.mot.com/1172239
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Guobin Zhang <zhanggb@motorola.com>
Submit-Approved: Jira Key
Reviewed-on: https://gerrit.mot.com/1340934
Reviewed-by: Jianqi Yang <yangj@motorola.com>
Reviewed-on: https://gerrit.mot.com/1362061
Reviewed-on: https://gerrit.mot.com/1453714
Reviewed-on: https://gerrit.mot.com/1509727
Reviewed-by: Wang Wang <wangwang1@lenovo.com>
2023-06-01 00:47:05 -03:00

831 lines
20 KiB
C

/*
* Copyright (C) 2012 lenovo, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ctype.h>
#include <linux/uaccess.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/err.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_wakeup.h>
#ifdef CONFIG_PINCTRL_MSM
#include "../../drivers/pinctrl/qcom/pinctrl-msm.h"
#endif
#include "user_sysfs_private.h"
#define GPIO_CFG(gpio, func, dir, pull, drvstr) \
((((gpio) & 0x3FF) << 4) | \
((func) & 0xf) | \
(((dir) & 0x1) << 14) | \
(((pull) & 0x3) << 15) | \
(((drvstr) & 0xF) << 17))
/**
* extract GPIO pin from bit-field used for gpio_tlmm_config
*/
#define GPIO_PIN(gpio_cfg) (((gpio_cfg) >> 4) & 0x3ff)
#define GPIO_FUNC(gpio_cfg) (((gpio_cfg) >> 0) & 0xf)
#define GPIO_DIR(gpio_cfg) (((gpio_cfg) >> 14) & 0x1)
#define GPIO_PULL(gpio_cfg) (((gpio_cfg) >> 15) & 0x3)
#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf)
#define TLMM_NUM_GPIO 150
#define HAL_OUTPUT_VAL(config) (((config)&0x40000000)>>30)
static int before_sleep_fetched;
module_param(before_sleep_fetched, int, 0644);
static unsigned before_sleep_configs[TLMM_NUM_GPIO];
static int before_sleep_table_enabled;
module_param(before_sleep_table_enabled, int, 0644);
static unsigned before_sleep_table_configs[TLMM_NUM_GPIO];
static unsigned tz_configs[TLMM_NUM_GPIO];
#ifndef CONFIG_PINCTRL_MSM
int tlmm_get_inout(unsigned gpio)
{
return 0;
}
int tlmm_set_inout(unsigned gpio, unsigned value)
{
return 0;
}
int tlmm_get_config(unsigned gpio, unsigned *cfg)
{
return -EINVAL;
}
int tlmm_set_config(unsigned config)
{
return -EINVAL;
}
#endif
static int tlmm_dump_cfg(char *buf, int size,
unsigned gpio, unsigned cfg, int output_val)
{
/* mA */
static const char * const drvstr_str[] = {
"2", "4", "6", "8", "10", "12", "14", "16" };
/* "NO_PULL", "PULL_DOWN", "KEEPER", "PULL_UP" */
static const char * const pull_str[] = { "N", "D", "K", "U" };
/* "Input", "Output" */
static const char * const dir_str[] = { "I", "O" };
char func_str[20];
char *p = buf;
int drvstr = GPIO_DRVSTR(cfg);
int pull = GPIO_PULL(cfg);
int dir = GPIO_DIR(cfg);
int func = GPIO_FUNC(cfg);
/* pr_debug("%s(), drvstr=%d, pull=%d, dir=%d, func=%d\n", */
/* __func__, drvstr, pull, dir, func); */
snprintf(func_str, sizeof(func_str), "%d", func);
p += snprintf(p, size - (p - buf), "%d: %s%s%s%s", gpio, func_str,
pull_str[pull], dir_str[dir], drvstr_str[drvstr]);
p += snprintf(p, size - (p - buf), " = %d", output_val);
p += snprintf(p, size - (p - buf), "\n");
return p - buf;
}
static int tlmm_dump_header(char *buf, int size)
{
char *p = buf;
p += snprintf(p, size - (p - buf),
"0:GPIO\n");
p += snprintf(p, size - (p - buf),
"N:NO_PULL D:PULL_DOWN K:KEEPER U:PULL_UP\n");
p += snprintf(p, size - (p - buf),
"I:Input O:Output\n");
p += snprintf(p, size - (p - buf),
"2:2, 4, 6, 8, 10, 12, 14, 16 mA (driver strength)\n\n");
return p - buf;
}
int tlmm_dump_info(char *buf, int size, int tlmm_num, int tlmm_count)
{
unsigned i;
char *p = buf;
unsigned cfg;
int output_val = 0;
int ret;
if (tlmm_num < 0 || tlmm_num >= TLMM_NUM_GPIO)
return p - buf;
if (tlmm_count == 1) {
if (tz_configs[tlmm_num])
return p - buf;
ret = tlmm_get_config(tlmm_num, &cfg);
if (ret == 0) {
output_val = tlmm_get_inout(tlmm_num);
p += tlmm_dump_cfg(p, size - (p - buf),
tlmm_num, cfg, output_val);
}
} else {
p += tlmm_dump_header(p, size - (p - buf));
p += snprintf(p, size - (p - buf),
"Format: gpio func pull dir strength [output]\n");
p += snprintf(p, size - (p - buf),
"Shortcut: gpio output\n");
p += snprintf(p, size - (p - buf),
"echo 20 0 D O 2 1, Config tlmm 20 and output 1\n");
p += snprintf(p, size - (p - buf),
"echo 20 1, Set tlmm 20 to output 1\n");
for (i = tlmm_num; i < tlmm_num + tlmm_count; ++i) {
if (i >= TLMM_NUM_GPIO)
break;
if (tz_configs[i])
continue;
ret = tlmm_get_config(i, &cfg);
if (ret == 0) {
output_val = tlmm_get_inout(i);
p += tlmm_dump_cfg(p, size - (p - buf),
i, cfg, output_val);
}
}
pr_debug("%s(), %d\n", __func__, __LINE__);
p += snprintf(p, size - (p - buf), "(%d)\n", (int)(p - buf));
}
return p - buf;
}
/* save tlmm config before sleep */
void tlmm_before_sleep_save_configs(void)
{
unsigned i;
int ret;
/* only save tlmm configs when it has been fetched */
if (!before_sleep_fetched)
return;
pr_debug("%s(), Save tlmms before suspend!\n", __func__);
before_sleep_fetched = false;
for (i = 0; i < TLMM_NUM_GPIO; ++i) {
unsigned cfg;
int output_val = 0;
if (tz_configs[i])
continue;
ret = tlmm_get_config(i, &cfg);
if (ret < 0)
break;
output_val = tlmm_get_inout(i);
before_sleep_configs[i] = cfg | (output_val << 30);
}
}
int tlmm_before_sleep_dump_info(char *buf, int size)
{
unsigned i;
char *p = buf;
p += snprintf(p, size - (p - buf), "tlmm_before_sleep:\n");
if (!before_sleep_fetched) {
before_sleep_fetched = true;
p += tlmm_dump_header(p, size - (p - buf));
for (i = 0; i < TLMM_NUM_GPIO; ++i) {
unsigned cfg;
int output_val = 0;
if (tz_configs[i])
continue;
cfg = before_sleep_configs[i];
output_val = HAL_OUTPUT_VAL(cfg);
/* cfg &= ~0x40000000; */
p += tlmm_dump_cfg(p, size - (p - buf),
i, cfg, output_val);
}
p += snprintf(p, size - (p - buf), "(%d)\n", (int)(p - buf));
}
return p - buf;
}
/* set tlmms config before sleep */
void tlmm_before_sleep_set_configs(void)
{
int res;
unsigned i;
/* only set tlmms before sleep when it's enabled */
if (!before_sleep_table_enabled)
return;
pr_debug("%s(), Set tlmms before suspend!\n", __func__);
for (i = 0; i < TLMM_NUM_GPIO; ++i) {
unsigned cfg;
int gpio;
int dir;
int func;
int output_val = 0;
if (tz_configs[i])
continue;
cfg = before_sleep_table_configs[i];
gpio = GPIO_PIN(cfg);
if (gpio != i)
continue;
output_val = HAL_OUTPUT_VAL(cfg);
dir = GPIO_DIR(cfg);
func = GPIO_FUNC(cfg);
pr_debug("%s(), [%d]: 0x%x\n", __func__, i, cfg);
if (gpio < TLMM_NUM_GPIO)
res = tlmm_set_config(cfg & ~0x40000000);
if (res < 0) {
pr_debug("Error: Config failed.\n");
break;
}
if ((func == 0) && (dir == 1))
tlmm_set_inout(i, output_val);
}
}
int tlmm_tz_dump_info(char *buf, int size)
{
unsigned i;
char *p = buf;
p += snprintf(p, size - (p - buf),
"Format: gpio skip\n");
p += snprintf(p, size - (p - buf),
"Skip tlmms that locked by TZ.\n");
for (i = 0; i < TLMM_NUM_GPIO; ++i) {
p += snprintf(p, size - (p - buf), "%d: ", i);
p += snprintf(p, size - (p - buf), "%d\n", tz_configs[i]);
}
p += snprintf(p, size - (p - buf), "(%d)\n", (int)(p - buf));
return p - buf;
}
int tlmm_before_sleep_table_set_cfg(unsigned gpio, unsigned cfg)
{
if (gpio >= TLMM_NUM_GPIO && gpio != 255 && gpio != 256) {
pr_debug("gpio >= TLMM_NUM_GPIO && gpio != 255 && gpio != 256!\n");
return -EINVAL;
}
if (gpio < TLMM_NUM_GPIO) {
before_sleep_table_configs[gpio] = cfg;
before_sleep_table_enabled = true;
} else if (gpio == 255)
before_sleep_table_enabled = true;
else if (gpio == 256)
before_sleep_table_enabled = false;
return 0;
}
int tlmm_before_sleep_table_dump_info(char *buf, int size)
{
unsigned i;
char *p = buf;
p += tlmm_dump_header(p, size - (p - buf));
p += snprintf(p, size - (p - buf),
"Format: gpio function pull direction strength [output]\n");
p += snprintf(p, size - (p - buf),
"Set tlmm before suspend.\n");
p += snprintf(p, size - (p - buf),
"echo 20 0 D O 2 1, tlmm 20 output 1\n");
p += snprintf(p, size - (p - buf),
"echo 20, Disable tlmm 20's setting\n");
p += snprintf(p, size - (p - buf),
"echo 255, Enable the setting\n");
p += snprintf(p, size - (p - buf),
"echo 256, Disable the setting\n");
for (i = 0; i < TLMM_NUM_GPIO; ++i) {
unsigned cfg;
int output_val = 0;
if (tz_configs[i])
continue;
cfg = before_sleep_table_configs[i];
output_val = HAL_OUTPUT_VAL(cfg);
/* cfg &= ~0x40000000; */
p += tlmm_dump_cfg(p, size - (p - buf), i, cfg, output_val);
}
p += snprintf(p, size - (p - buf), "(%d)\n", (int)(p - buf));
return p - buf;
}
#define private_attr(_name) \
static struct kobj_attribute _name##_attr = { \
.attr = { \
.name = __stringify(_name), \
.mode = 0644, \
}, \
.show = _name##_show, \
.store = _name##_store, \
}
static int tlmm_num;
static ssize_t tlmm_num_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *p = buf;
p += snprintf(p, PAGE_SIZE, "Start gpio to check by cat tlmm\n");
p += snprintf(p, PAGE_SIZE - (p - buf), "0~%d\n", TLMM_NUM_GPIO - 1);
p += snprintf(p, PAGE_SIZE - (p - buf), "%d\n", tlmm_num);
return p - buf;
}
static ssize_t tlmm_num_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
int gpio;
int res;
res = kstrtoint(buf, 10, &gpio);
pr_debug("res=%d. %d\n", res, gpio);
if (res != 0)
goto tlmm_num_store_wrong_para;
if (gpio >= TLMM_NUM_GPIO)
goto tlmm_num_store_wrong_para;
tlmm_num = gpio;
pr_debug("tlmm_num: %d\n", tlmm_num);
goto tlmm_num_store_ok;
tlmm_num_store_wrong_para:
pr_debug("Wrong Input.\n");
pr_debug("Format: tlmm_num\n");
pr_debug(" tlmm_num: 0~%d\n", TLMM_NUM_GPIO - 1);
tlmm_num_store_ok:
return n;
}
static int tlmm_count = TLMM_NUM_GPIO;
static ssize_t tlmm_count_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *p = buf;
p += snprintf(p, PAGE_SIZE, "Number of gpios to check by cat tlmm\n");
p += snprintf(p, PAGE_SIZE - (p - buf), "0~%d\n", TLMM_NUM_GPIO);
p += snprintf(p, PAGE_SIZE - (p - buf), "%d\n", tlmm_count);
return p - buf;
}
static ssize_t tlmm_count_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t n)
{
int gpio;
int res;
res = kstrtoint(buf, 10, &gpio);
pr_debug("res=%d. %d\n", res, gpio);
if (res != 0)
goto tlmm_count_store_wrong_para;
if (gpio >= TLMM_NUM_GPIO)
goto tlmm_count_store_wrong_para;
tlmm_count = gpio;
pr_debug("tlmm_count: %d\n", tlmm_count);
goto tlmm_count_store_ok;
tlmm_count_store_wrong_para:
pr_debug("Wrong Input.\n");
pr_debug("Format: tlmm_count\n");
pr_debug(" tlmm_count: 0~%d\n", TLMM_NUM_GPIO);
tlmm_count_store_ok:
return n;
}
static ssize_t tlmm_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
char *p = buf;
p += tlmm_dump_info(buf, PAGE_SIZE, tlmm_num, tlmm_count);
return p - buf;
}
static ssize_t tlmm_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
char pull_c, dir_c;
int gpio, func, pull, dir, drvstr, output_val;
unsigned cfg;
int res;
res = sscanf(buf, "%d %d %c %c %d %d",
&gpio, &func, &pull_c, &dir_c, &drvstr, &output_val);
pr_debug("res=%d. %d %d %c %c %d %d\n",
res, gpio, func, pull_c, dir_c, drvstr, output_val);
/* Add a shortcut wrting format to change an output gpio's value */
if (res == 2 && gpio < TLMM_NUM_GPIO && (func == 0 || func == 1)) {
output_val = func;
goto tlmm_store_only_output_val;
}
if ((res != 5) && (res != 6))
goto tlmm_store_wrong_para;
if (gpio >= TLMM_NUM_GPIO)
goto tlmm_store_wrong_para;
if ('N' == pull_c)
pull = 0;
else if ('D' == pull_c)
pull = 1;
else if ('K' == pull_c)
pull = 2;
else if ('U' == pull_c)
pull = 3;
else
goto tlmm_store_wrong_para;
if ('I' == dir_c)
dir = 0;
else if ('O' == dir_c)
dir = 1;
else
goto tlmm_store_wrong_para;
drvstr = drvstr/2 - 1; /* 2mA -> 0, 4mA -> 1, 6mA -> 2, ... */
if (drvstr > 7)
goto tlmm_store_wrong_para;
if (output_val > 1)
goto tlmm_store_wrong_para;
pr_debug("final set: %d %d %d %d %d %d\n",
gpio, func, pull, dir, drvstr, output_val);
cfg = GPIO_CFG(gpio, func, dir, pull, drvstr);
if (gpio < TLMM_NUM_GPIO) {
if (tz_configs[gpio])
res = -1;
else
res = tlmm_set_config(cfg);
if (res < 0) {
pr_debug("Error: Config failed.\n");
goto tlmm_store_wrong_para;
}
}
pr_debug("final set: %d %d %d %d %d %d\n",
gpio, func, pull, dir, drvstr, output_val);
if ((func == 0) && (dir == 1)) /* gpio output */
tlmm_store_only_output_val:
tlmm_set_inout(gpio, output_val);
goto tlmm_store_ok;
tlmm_store_wrong_para:
pr_debug("Wrong Input or gpio is locked by TZ.\n");
pr_debug("Standard Format: gpio_num function pull direction strength [output_value]\n");
pr_debug("Shortcut Format: gpio_num output_value\n");
pr_debug(" gpio_num: 0 ~ 145\n");
pr_debug(" function: number, where 0 is GPIO\n");
pr_debug(" pull: 'N': NO_PULL, 'D':PULL_DOWN, 'K':KEEPER, 'U': PULL_UP\n");
pr_debug(" direction: 'I': Input, 'O': Output\n");
pr_debug(" strength: 2, 4, 6, 8, 10, 12, 14, 16\n");
pr_debug(" output_value: Optional. 0 or 1. valid if GPIO output\n");
pr_debug(" e.g. 'echo 20 0 D I 2' ==> set pin 20 as GPIO input\n");
pr_debug(" e.g. 'echo 20 0 D O 2 1' ==> set pin 20 as GPIO output and the output = 1\n");
pr_debug(" e.g. 'echo 20 1' ==> set output gpio pin 20 output = 1\n");
tlmm_store_ok:
return n;
}
static ssize_t tlmm_tz_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *p = buf;
p += tlmm_tz_dump_info(buf, PAGE_SIZE);
return p - buf;
}
static ssize_t tlmm_tz_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t n)
{
int gpio, func = 0;
int res;
res = sscanf(buf, "%d %d", &gpio, &func);
pr_debug("res=%d. %d %d\n", res, gpio, func);
if (res == 1)
func = 1;
pr_debug("final set: %d %d\n", gpio, func);
if (gpio >= TLMM_NUM_GPIO)
goto tlmm_tz_store_wrong_para;
tz_configs[gpio] = func;
goto tlmm_tz_store_ok;
tlmm_tz_store_wrong_para:
pr_debug("Wrong Input.\n");
pr_debug("Format: gpio [0|1]\n");
tlmm_tz_store_ok:
return n;
}
/* Set GPIO's sleep config from sysfs */
static ssize_t tlmm_before_sleep_table_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *p = buf;
p += tlmm_before_sleep_table_dump_info(buf, PAGE_SIZE);
return p - buf;
}
static ssize_t tlmm_before_sleep_table_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t n)
{
char pull_c, dir_c;
int gpio, func = 0, pull = 0, dir = 0, drvstr = 0, output_val = 0;
int ignore;
unsigned cfg;
int res;
res = sscanf(buf, "%d %d %c %c %d %d",
&gpio, &func, &pull_c, &dir_c, &drvstr, &output_val);
pr_debug("res=%d. %d %d %c %c %d %d\n",
res, gpio, func, pull_c, dir_c, drvstr, output_val);
/* if only gpio, means ignore(disable) the gpio's sleep config */
if (res == 1) {
ignore = 1;
pr_debug("final set: to disable gpio %d sleep config\n", gpio);
} else {
ignore = 0;
if ((res != 5) && (res != 6))
goto tlmm_before_sleep_table_store_wrong_para;
if (gpio >= TLMM_NUM_GPIO)
goto tlmm_before_sleep_table_store_wrong_para;
if ('N' == pull_c)
pull = 0;
else if ('D' == pull_c)
pull = 1;
else if ('K' == pull_c)
pull = 2;
else if ('U' == pull_c)
pull = 3;
else
goto tlmm_before_sleep_table_store_wrong_para;
if ('I' == dir_c)
dir = 0;
else if ('O' == dir_c)
dir = 1;
else
goto tlmm_before_sleep_table_store_wrong_para;
drvstr = drvstr/2 - 1; /* 2mA -> 0, 4mA -> 1, 6mA -> 2, ... */
if (drvstr > 7)
goto tlmm_before_sleep_table_store_wrong_para;
pr_debug("final set: %d %d %d %d %d\n",
gpio, func, pull, dir, drvstr);
}
cfg = GPIO_CFG(ignore ? 0xff : gpio, func, dir, pull, drvstr);
res = tlmm_before_sleep_table_set_cfg(gpio, cfg | (output_val << 30));
if (res < 0) {
pr_debug("Error: Config failed.\n");
goto tlmm_before_sleep_table_store_wrong_para;
}
goto tlmm_before_sleep_table_store_ok;
tlmm_before_sleep_table_store_wrong_para:
pr_debug("Wrong Input.\n");
pr_debug("Format: refer to tlmm's format except 'echo gpio_num > xxx' to disable the gpio's setting\n");
tlmm_before_sleep_table_store_ok:
return n;
}
static ssize_t tlmm_before_sleep_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *p = buf;
p += tlmm_before_sleep_dump_info(buf, PAGE_SIZE);
return p - buf;
}
static ssize_t tlmm_before_sleep_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t n)
{
pr_err("%s: no support.\n", __func__);
return n;
}
static ssize_t vreg_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
char *p = buf;
p += vreg_dump_info(buf);
return p - buf;
}
static ssize_t vreg_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t n)
{
pr_err("%s: no support.\n", __func__);
return n;
}
static ssize_t vreg_before_sleep_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
char *p = buf;
p += vreg_before_sleep_dump_info(buf);
return p - buf;
}
static ssize_t vreg_before_sleep_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t n)
{
pr_err("%s: no support.\n", __func__);
return n;
}
static ssize_t wake_lock_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
char *s = buf;
s += wakelock_dump_active_info(s, PAGE_SIZE - (s - buf));
return (s - buf);
}
static ssize_t wake_lock_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t n)
{
pr_err("%s: no support yet.\n", __func__);
return -EPERM;
}
private_attr(tlmm_num);
private_attr(tlmm_count);
private_attr(tlmm);
private_attr(tlmm_tz);
private_attr(tlmm_before_sleep_table);
private_attr(tlmm_before_sleep);
private_attr(vreg_before_sleep);
private_attr(vreg);
private_attr(wake_lock);
static struct attribute *g_private_attr[] = {
&tlmm_num_attr.attr,
&tlmm_count_attr.attr,
&tlmm_attr.attr,
&tlmm_tz_attr.attr,
&tlmm_before_sleep_table_attr.attr,
&tlmm_before_sleep_attr.attr,
&vreg_attr.attr,
&vreg_before_sleep_attr.attr,
&wake_lock_attr.attr,
NULL,
};
static struct attribute_group private_attr_group = {
.attrs = g_private_attr,
};
static struct kobject *sysfs_private_kobj;
static const struct of_device_id msm_tz_gpio_match_table[] = {
{.compatible = "qcom,tz_gpio"},
{},
};
static int tlmm_tz_init(void)
{
struct device_node *node;
const __be32 *list;
int size;
int result = 0;
node = of_find_matching_node(NULL, msm_tz_gpio_match_table);
pr_debug("%s(), %d, node=%p\n", __func__, __LINE__, node);
if (!node)
return -ENODEV;
list = of_get_property(node, "tlmm-tz", &size);
pr_debug("%s(), %d, size=%d\n", __func__, __LINE__, size);
if (!list || !size)
return -ENODEV;
/*
* Size is in bytes. Convert to size of uint32_t
*/
size /= sizeof(*list);
while (size) {
unsigned long gpio = be32_to_cpup(list++);
pr_debug("%s(), %d, gpio=%ld\n", __func__, __LINE__, gpio);
if (gpio < TLMM_NUM_GPIO)
tz_configs[gpio] = 1;
size--;
}
return result;
}
static int __init sysfs_private_init(void)
{
int result;
pr_debug("%s(), %d\n", __func__, __LINE__);
sysfs_private_kobj = kobject_create_and_add("private", NULL);
if (!sysfs_private_kobj)
return -ENOMEM;
result = sysfs_create_group(sysfs_private_kobj, &private_attr_group);
pr_debug("%s(), %d, result=%d\n", __func__, __LINE__, result);
result = tlmm_tz_init();
pr_debug("%s(), %d, result=%d\n", __func__, __LINE__, result);
return result;
}
static void __exit sysfs_private_exit(void)
{
pr_debug("%s(), %d\n", __func__, __LINE__);
sysfs_remove_group(sysfs_private_kobj, &private_attr_group);
kobject_put(sysfs_private_kobj);
}
module_init(sysfs_private_init);
module_exit(sysfs_private_exit);