mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
input: ldc2114: add new features
Following features have been added to LDC2114 kernel driver: 1) DT configurable settings with versioning support 2) control of LPWM pin 3) reboot notification callback 4) conditional polling and DT config debug messages Change-Id: I828e73bc049961204f71fe5a41b40ab6af7a16cf Signed-off-by: Konstantin Makariev <hcv867@motorola.com> Reviewed-on: https://gerrit.mot.com/1123709 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Ryan Lattrel <ryanl@motorola.com> Reviewed-by: Konstantin Makariev <kmakariev@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
d36bb898a0
commit
35054c46d3
2 changed files with 285 additions and 43 deletions
|
|
@ -5,7 +5,8 @@ EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include -I$(TOP)/motorola/kerne
|
|||
ldc2114_keys-objs := ldc2114.o
|
||||
|
||||
ifeq ($(TARGET_BUILD_VARIANT),userdebug)
|
||||
EXTRA_CFLAGS += -DLDC2114_CHARDEV
|
||||
# Following line is in control of extra debug
|
||||
EXTRA_CFLAGS += -DLDC2114_CHARDEV -DLDC2114_POLL_DEBUG -DLDC2114_CFG_DEBUG
|
||||
ldc2114_keys-objs += ldc2114-cdev.o
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,16 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/memory.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include "ldc2114_cdev.h"
|
||||
|
||||
#define LDC2114_DRIVER_NAME "ldc2114"
|
||||
|
||||
#define LDC2114_SHORT_DELAY 50
|
||||
#define LDC2114_LONG_DELAY (LDC2114_SHORT_DELAY * 10)
|
||||
#define LDC2114_MAX_RETRIES 10
|
||||
|
||||
#define MAX_KEYS 4
|
||||
#define irq_to_gpio(irq) ((irq) - gpio_to_irq(0))
|
||||
|
||||
|
|
@ -215,6 +220,15 @@ static const struct reg_field ldc2114_reg_fields[] = {
|
|||
|
||||
#define SENSITIVITY_GAIN 0x3c
|
||||
|
||||
struct ldc2114_cfg_data {
|
||||
uint8_t address, value;
|
||||
};
|
||||
|
||||
struct ldc2114_config {
|
||||
int size;
|
||||
struct ldc2114_cfg_data data[0];
|
||||
};
|
||||
|
||||
static const uint8_t CONFIG_ADDR_DATA[] = {
|
||||
LDC2114_EN, 0xff, /* enable 4 buttons */
|
||||
LDC2114_NP_SCAN_RATE, 0x01, /* normal-power scan rate */
|
||||
|
|
@ -251,6 +265,7 @@ struct ldc2114_data {
|
|||
atomic_t poll_work_running;
|
||||
struct semaphore semaphore;
|
||||
int intb_gpio;
|
||||
int lpwm_gpio;
|
||||
int signal_gpio;
|
||||
int intb_polarity;
|
||||
int irq;
|
||||
|
|
@ -263,6 +278,10 @@ struct ldc2114_data {
|
|||
struct delayed_work irq_work;
|
||||
struct input_dev *input;
|
||||
struct notifier_block poll_nb;
|
||||
struct notifier_block reboot_nb;
|
||||
unsigned int verno;
|
||||
struct ldc2114_config *normal;
|
||||
struct ldc2114_config *lpm;
|
||||
};
|
||||
|
||||
struct ldc2114_attr {
|
||||
|
|
@ -388,6 +407,20 @@ static LDC2114_ATTR(ftf1, F_FTF1_2_FTF1);
|
|||
static LDC2114_ATTR(ftf2, F_FTF1_2_FTF2);
|
||||
static LDC2114_ATTR(ftf3, F_FTF3_FTF3);
|
||||
|
||||
static ssize_t ldc2114_verno_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ldc2114_data *ldc = i2c_get_clientdata(client);
|
||||
|
||||
return sprintf(buf, "%u\n", ldc->verno);
|
||||
}
|
||||
|
||||
static struct ldc2114_attr ldc2114_attr_verno = {
|
||||
.dev_attr = __ATTR(verno, S_IRUGO, ldc2114_verno_show, NULL),
|
||||
.field = 0,
|
||||
};
|
||||
|
||||
static struct attribute *ldc2114_attributes[] = {
|
||||
&ldc2114_attr_timout.dev_attr.attr,
|
||||
&ldc2114_attr_lc_wd.dev_attr.attr,
|
||||
|
|
@ -458,6 +491,7 @@ static struct attribute *ldc2114_attributes[] = {
|
|||
&ldc2114_attr_ftf1.dev_attr.attr,
|
||||
&ldc2114_attr_ftf2.dev_attr.attr,
|
||||
&ldc2114_attr_ftf3.dev_attr.attr,
|
||||
&ldc2114_attr_verno.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -749,9 +783,19 @@ static int ldc2114_input_device(struct ldc2114_data *ldc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void inline ldc2114_toggle(struct ldc2114_data *ldc)
|
||||
#if defined(LDC2114_POLL_DEBUG) || defined(LDC2114_CFG_DEBUG)
|
||||
static void ldc2114_toggle_gpio(struct ldc2114_data *ldc,
|
||||
int gpio)
|
||||
{
|
||||
gpio_set_value(ldc->signal_gpio, !gpio_get_value(ldc->signal_gpio));
|
||||
int value = gpio_get_value(gpio);
|
||||
dev_dbg(ldc->dev, "toggle gpio %d from state %d\n", gpio, value);
|
||||
gpio_set_value(gpio, !value);
|
||||
#else
|
||||
static void inline ldc2114_toggle_gpio(struct ldc2114_data *ldc,
|
||||
int gpio)
|
||||
{
|
||||
gpio_set_value(gpio, !gpio_get_value(gpio));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ldc2114_poll(struct ldc2114_data *ldc,
|
||||
|
|
@ -786,6 +830,27 @@ static int ldc2114_poll(struct ldc2114_data *ldc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LDC2114_POLL_DEBUG
|
||||
#define NANO_SEC 1000000000
|
||||
#define SEC_TO_MSEC 1000
|
||||
#define NANO_TO_MSEC 1000000
|
||||
|
||||
static inline unsigned long long timediff_ms(struct timespec start,
|
||||
struct timespec end)
|
||||
{
|
||||
struct timespec temp;
|
||||
|
||||
if ((end.tv_nsec - start.tv_nsec) < 0) {
|
||||
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
|
||||
temp.tv_nsec = NANO_SEC + end.tv_nsec - start.tv_nsec;
|
||||
} else {
|
||||
temp.tv_sec = end.tv_sec - start.tv_sec;
|
||||
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
|
||||
}
|
||||
return (temp.tv_sec * SEC_TO_MSEC) + (temp.tv_nsec / NANO_TO_MSEC);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ldc2114_polling_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dw =
|
||||
|
|
@ -809,6 +874,11 @@ static void ldc2114_polling_work(struct work_struct *work)
|
|||
msecs_to_jiffies(ldc->poll_interval));
|
||||
}
|
||||
|
||||
#ifdef LDC2114_POLL_DEBUG
|
||||
ktime_t start_polling_tm;
|
||||
int polling_counter;
|
||||
#endif
|
||||
|
||||
static void ldc2114_irq_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dw =
|
||||
|
|
@ -828,11 +898,6 @@ static void ldc2114_irq_work(struct work_struct *work)
|
|||
dev_info(ldc->dev, "STATUS bits 0x%x\n", status_reg);
|
||||
|
||||
ret = ldc2114_read_bulk(ldc->dev, LDC2114_OUT, &data, sizeof(data));
|
||||
#if 0
|
||||
dev_dbg(ldc->dev, "DATA_0=%d, DATA_1=%d, DATA_2=%d, DATA_3=%d\n",
|
||||
comp2_12b(&data.values[0]), comp2_12b(&data.values[1]),
|
||||
comp2_12b(&data.values[2]), comp2_12b(&data.values[3]));
|
||||
#endif
|
||||
if (data.out != output_bits) {
|
||||
output_bits = data.out;
|
||||
dev_dbg(ldc->dev, "OUTPUT bits 0x%x\n", output_bits);
|
||||
|
|
@ -855,9 +920,19 @@ static void ldc2114_irq_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
if (atomic_read(&ldc->irq_work_running)) {
|
||||
#ifdef LDC2114_POLL_DEBUG
|
||||
polling_counter++;
|
||||
#endif
|
||||
usleep_range(OUT_POLL_WAIT_LOW, OUT_POLL_WAIT_HIGH);
|
||||
up(&ldc->semaphore);
|
||||
} else {
|
||||
#ifdef LDC2114_POLL_DEBUG
|
||||
dev_info(ldc->dev, "polled %d times within %llums\n",
|
||||
polling_counter,
|
||||
timediff_ms(ktime_to_timespec(start_polling_tm),
|
||||
ktime_to_timespec(ktime_get())));
|
||||
polling_counter = 0;
|
||||
#endif
|
||||
/* TODO: make sure we never miss release :) */
|
||||
/* Work around missed release */
|
||||
for (i = 0, s = 0; i < MAX_KEYS; i++) {
|
||||
|
|
@ -892,6 +967,9 @@ static irqreturn_t ldc2114_irq(int irq, void *data)
|
|||
dev_dbg(ldc->dev, "starting work...\n");
|
||||
atomic_set(&ldc->irq_work_running, 1);
|
||||
up(&ldc->semaphore);
|
||||
#ifdef LDC2114_POLL_DEBUG
|
||||
start_polling_tm = ktime_get();
|
||||
#endif
|
||||
} else if (stop_irq_work) {
|
||||
dev_dbg(ldc->dev, "stopping work...\n");
|
||||
atomic_set(&ldc->irq_work_running, 0);
|
||||
|
|
@ -899,7 +977,7 @@ static irqreturn_t ldc2114_irq(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
|
||||
if (gpio_is_valid(ldc->signal_gpio))
|
||||
ldc2114_toggle(ldc);
|
||||
ldc2114_toggle_gpio(ldc, ldc->signal_gpio);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
@ -911,21 +989,92 @@ static const struct of_device_id ldc2114_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, ldc2114_of_match);
|
||||
|
||||
static struct ldc2114_config *read_config_data(struct ldc2114_data *ldc,
|
||||
struct device_node *parent, const char *suffix)
|
||||
{
|
||||
struct ldc2114_config *config = NULL;
|
||||
struct device_node *node;
|
||||
u32 length = 0;
|
||||
const char *data;
|
||||
char node_name[64];
|
||||
int npairs, i;
|
||||
|
||||
scnprintf(node_name, 63, "config-%s", suffix);
|
||||
node = of_find_node_by_name(parent, node_name);
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
data = of_get_property(node, "config-data", &length);
|
||||
if (!data) {
|
||||
#ifdef LDC2114_CFG_DEBUG
|
||||
dev_info(ldc->dev, "(config-%s) prop config-data not found\n", suffix);
|
||||
#endif
|
||||
goto out;
|
||||
}
|
||||
|
||||
npairs = length / 2;
|
||||
#ifdef LDC2114_CFG_DEBUG
|
||||
dev_info(ldc->dev, "(config-%s) array size %d\n", suffix, npairs);
|
||||
#endif
|
||||
config = devm_kzalloc(ldc->dev, sizeof(struct ldc2114_config) +
|
||||
sizeof(struct ldc2114_cfg_data) * npairs, GFP_KERNEL);
|
||||
if (!config)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < npairs; i++) {
|
||||
config->data[i].address = (uint8_t)*data++;
|
||||
config->data[i].value = (uint8_t)*data++;
|
||||
#ifdef LDC2114_CFG_DEBUG
|
||||
dev_info(ldc->dev, "[%d] addr=0x%02x, val=0x%02x\n",
|
||||
i, config->data[i].address, config->data[i].value);
|
||||
#endif
|
||||
}
|
||||
|
||||
config->size = npairs;
|
||||
|
||||
out:
|
||||
of_node_put(node);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static int ldc2114_of_init(struct i2c_client *client)
|
||||
{
|
||||
int ret;
|
||||
struct ldc2114_data *ldc = i2c_get_clientdata(client);
|
||||
struct device_node *np = client->dev.of_node;
|
||||
struct device_node *config;
|
||||
|
||||
ret = of_get_gpio(np, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(ldc->dev, "failed to get lwpm-gpio: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ldc->lpwm_gpio = ret;
|
||||
ret = devm_gpio_request(ldc->dev,
|
||||
ldc->lpwm_gpio, LDC2114_DRIVER_NAME "_lpwm");
|
||||
if (ret) {
|
||||
dev_err(ldc->dev, "failed to request lpwm-gpio %d\n", ldc->lpwm_gpio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_get_gpio(np, 1);
|
||||
if (ret < 0)
|
||||
ldc->signal_gpio = -EINVAL;
|
||||
else {
|
||||
ldc->signal_gpio = ret;
|
||||
dev_info(ldc->dev, "using gpio %d as a signal\n", ldc->signal_gpio);
|
||||
gpio_direction_output(ldc->signal_gpio, !gpio_get_value(ldc->signal_gpio));
|
||||
/* start with low */
|
||||
gpio_direction_output(ldc->signal_gpio, 0);
|
||||
/* then toggle */
|
||||
ldc2114_toggle_gpio(ldc, ldc->signal_gpio);
|
||||
}
|
||||
|
||||
/* Init LWPM gpio into LOW, since this is default power off state */
|
||||
/* Then toggle its state as part of apply configuration procedure */
|
||||
gpio_direction_output(ldc->lpwm_gpio, 0);
|
||||
|
||||
ret = of_irq_get(np, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(ldc->dev, "failed to get irq: %d\n", ret);
|
||||
|
|
@ -937,7 +1086,7 @@ static int ldc2114_of_init(struct i2c_client *client)
|
|||
ret = devm_gpio_request(ldc->dev,
|
||||
ldc->intb_gpio, LDC2114_DRIVER_NAME "_irq");
|
||||
if (ret) {
|
||||
dev_err(ldc->dev, "failed to request gpio %u\n", ldc->intb_gpio);
|
||||
dev_err(ldc->dev, "failed to request gpio %d\n", ldc->intb_gpio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -948,6 +1097,25 @@ static int ldc2114_of_init(struct i2c_client *client)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
config = of_find_node_by_name(np, "configs");
|
||||
if (!config) {
|
||||
dev_info(ldc->dev, "does not support configs\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
of_property_read_u32(config, "config-ver", &ldc->verno);
|
||||
dev_info(ldc->dev, "dt config Rev.%u\n", ldc->verno);
|
||||
|
||||
ldc->normal = read_config_data(ldc, config, "normal");
|
||||
if (ldc->normal)
|
||||
dev_info(ldc->dev, "has normal config\n");
|
||||
|
||||
ldc->lpm = read_config_data(ldc, config, "lpm");
|
||||
if (ldc->lpm)
|
||||
dev_info(ldc->dev, "has lpm config\n");
|
||||
|
||||
of_node_put(config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
|
@ -958,54 +1126,75 @@ static inline void ldc2114_of_init(struct i2c_client *client)
|
|||
|
||||
#define EXITIF_ERR(cmd) { \
|
||||
ret = cmd; \
|
||||
if (ret) \
|
||||
if (ret) { \
|
||||
dev_dbg(ldc->dev, "ret=%d; exiting...\n", ret); \
|
||||
return ret; \
|
||||
} \
|
||||
}
|
||||
|
||||
static int ldc2114_apply_config(struct ldc2114_data *ldc, struct ldc2114_config *cfg)
|
||||
{
|
||||
bool partial_fail = false;
|
||||
int i, ret;
|
||||
|
||||
/* now it's time to toggle LWPM pin */
|
||||
ldc2114_toggle_gpio(ldc, ldc->lpwm_gpio);
|
||||
|
||||
if (!cfg || !cfg->size)
|
||||
return 0;
|
||||
|
||||
EXITIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_FULL,
|
||||
LDC2114_REG_STATUS_CHIP_READY));
|
||||
EXITIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_CONFIG_MODE,
|
||||
LDC2114_REG_STATUS_RDY_TO_WRITE));
|
||||
|
||||
for (i = 0; i < cfg->size; i++) {
|
||||
ret = ldc2114_write_reg8(ldc->dev,
|
||||
cfg->data[i].address, cfg->data[i].value);
|
||||
if (ret) {
|
||||
partial_fail = true;
|
||||
dev_err(ldc->dev, "config failed at i=%d\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EXITIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_NONE,
|
||||
LDC2114_REG_STATUS_CHIP_READY));
|
||||
|
||||
return partial_fail ? -1 : 0;
|
||||
}
|
||||
|
||||
static int ldc2114_initialize(struct ldc2114_data *ldc)
|
||||
{
|
||||
struct ldc2114_16bit version;
|
||||
uint8_t value;
|
||||
bool full_reset_done = false;
|
||||
int i, ret;
|
||||
int ret, attempts = 0;
|
||||
|
||||
EXITIF_ERR(ldc2114_read_reg8(ldc->dev, LDC2114_STATUS, &value));
|
||||
do_again:
|
||||
|
||||
if (!(value & LDC2114_REG_STATUS_CHIP_READY)) {
|
||||
dev_info(ldc->dev, "invalid status; resetting...\n");
|
||||
EXITIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_FULL,
|
||||
LDC2114_REG_STATUS_CHIP_READY));
|
||||
full_reset_done = true;
|
||||
while (gpio_get_value(ldc->intb_gpio) == 0) {
|
||||
if (gpio_is_valid(ldc->signal_gpio))
|
||||
ldc2114_toggle_gpio(ldc, ldc->signal_gpio);
|
||||
|
||||
usleep_range(OUT_POLL_WAIT_LOW, OUT_POLL_WAIT_HIGH);
|
||||
|
||||
if (gpio_is_valid(ldc->signal_gpio))
|
||||
ldc2114_toggle_gpio(ldc, ldc->signal_gpio);
|
||||
}
|
||||
|
||||
EXITIF_ERR(ldc2114_read_reg8(ldc->dev, LDC2114_GAIN0, &value));
|
||||
if (SENSITIVITY_GAIN != value) {
|
||||
dev_info(ldc->dev, "invalid configuration\n");
|
||||
|
||||
if (!full_reset_done)
|
||||
EXITIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_FULL,
|
||||
LDC2114_REG_STATUS_CHIP_READY));
|
||||
|
||||
EXITIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_CONFIG_MODE,
|
||||
LDC2114_REG_STATUS_RDY_TO_WRITE));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(CONFIG_ADDR_DATA); i += 2) {
|
||||
ret = ldc2114_write_reg8(ldc->dev,
|
||||
CONFIG_ADDR_DATA[i], CONFIG_ADDR_DATA[i+1]);
|
||||
if (ret < 0) {
|
||||
dev_err(ldc->dev, "config failed: i=%d\n", i);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
EXITIF_ERR(ldc2114_reset(ldc->dev, LDC2114_REG_RESET_NONE,
|
||||
LDC2114_REG_STATUS_CHIP_READY));
|
||||
dev_info(ldc->dev, "applied fixup\n");
|
||||
ret = ldc2114_apply_config(ldc, ldc->normal);
|
||||
if (ret) {
|
||||
if (++attempts > LDC2114_MAX_RETRIES) {
|
||||
dev_err(ldc->dev, "failed NORMAL config %d times\n", attempts);
|
||||
return -EIO;
|
||||
}
|
||||
goto do_again;
|
||||
}
|
||||
|
||||
EXITIF_ERR(ldc2114_read_bulk(ldc->dev, LDC2114_DEVICE_ID_LSB,
|
||||
&version, sizeof(version)));
|
||||
dev_info(ldc->dev, "TI " LDC2114_DRIVER_NAME " 0x%x\n", (version.lsb | (version.msb << 8)));
|
||||
dev_info(ldc->dev, "TI " LDC2114_DRIVER_NAME " 0x%x\n",
|
||||
(version.lsb | (version.msb << 8)));
|
||||
|
||||
EXITIF_ERR(ldc2114_read_reg8(ldc->dev, LDC2114_INTPOL, &value));
|
||||
ldc->intb_polarity = value & BIT(3) ? 1 : 0;
|
||||
|
|
@ -1033,7 +1222,52 @@ static int ldc2114_poll_enable_cb(struct notifier_block *n,
|
|||
dev_dbg(ldc->dev, "polling resumed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ldc2114_reboot_cb(struct notifier_block *nb,
|
||||
unsigned long event, void *unused)
|
||||
{
|
||||
struct ldc2114_data *ldc =
|
||||
container_of(nb, struct ldc2114_data, reboot_nb);
|
||||
int ret, attempts;
|
||||
static int runaway;
|
||||
|
||||
if (runaway)
|
||||
goto out;
|
||||
|
||||
runaway++;
|
||||
attempts = 0;
|
||||
|
||||
/* Stop polling work if it's running */
|
||||
if (ldc->data_polling)
|
||||
cancel_delayed_work_sync(&ldc->polling_work);
|
||||
|
||||
do_again:
|
||||
|
||||
if (ldc->irq_enabled) {
|
||||
/* wait until active touch is cleared */
|
||||
while (atomic_read(&ldc->irq_work_running) == 1) {
|
||||
if (gpio_is_valid(ldc->signal_gpio))
|
||||
ldc2114_toggle_gpio(ldc, ldc->signal_gpio);
|
||||
|
||||
usleep_range(OUT_POLL_WAIT_LOW, OUT_POLL_WAIT_HIGH);
|
||||
|
||||
if (gpio_is_valid(ldc->signal_gpio))
|
||||
ldc2114_toggle_gpio(ldc, ldc->signal_gpio);
|
||||
}
|
||||
disable_irq(ldc->irq);
|
||||
}
|
||||
|
||||
ret = ldc2114_apply_config(ldc, ldc->lpm);
|
||||
if (ret) {
|
||||
if (++attempts <= LDC2114_MAX_RETRIES)
|
||||
goto do_again;
|
||||
dev_err(ldc->dev, "failed LPM config %d times\n", attempts);
|
||||
}
|
||||
|
||||
out:
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int ldc2114_probe(struct i2c_client *client,
|
||||
|
|
@ -1126,6 +1360,13 @@ static int ldc2114_probe(struct i2c_client *client,
|
|||
if (ret)
|
||||
dev_err(ldc->dev, "Unable to create sysfs group: %d\n", ret);
|
||||
|
||||
ldc->reboot_nb.notifier_call = ldc2114_reboot_cb;
|
||||
ldc->reboot_nb.next = NULL;
|
||||
ldc->reboot_nb.priority = 1;
|
||||
ret = register_reboot_notifier(&ldc->reboot_nb);
|
||||
if (ret)
|
||||
dev_err(ldc->dev, "register for reboot failed: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue