aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/nvec/nvec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/nvec/nvec.c')
-rw-r--r--drivers/staging/nvec/nvec.c99
1 files changed, 52 insertions, 47 deletions
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 4ae44a5168f9..9fda136b8e05 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -14,8 +14,6 @@
*
*/
-/* #define DEBUG */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/atomic.h>
@@ -40,18 +38,18 @@
#include "nvec.h"
#define I2C_CNFG 0x00
-#define I2C_CNFG_PACKET_MODE_EN (1 << 10)
-#define I2C_CNFG_NEW_MASTER_SFM (1 << 11)
+#define I2C_CNFG_PACKET_MODE_EN BIT(10)
+#define I2C_CNFG_NEW_MASTER_SFM BIT(11)
#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12
#define I2C_SL_CNFG 0x20
-#define I2C_SL_NEWSL (1 << 2)
-#define I2C_SL_NACK (1 << 1)
-#define I2C_SL_RESP (1 << 0)
-#define I2C_SL_IRQ (1 << 3)
-#define END_TRANS (1 << 4)
-#define RCVD (1 << 2)
-#define RNW (1 << 1)
+#define I2C_SL_NEWSL BIT(2)
+#define I2C_SL_NACK BIT(1)
+#define I2C_SL_RESP BIT(0)
+#define I2C_SL_IRQ BIT(3)
+#define END_TRANS BIT(4)
+#define RCVD BIT(2)
+#define RNW BIT(1)
#define I2C_SL_RCVD 0x24
#define I2C_SL_STATUS 0x28
@@ -143,14 +141,14 @@ static int nvec_status_notifier(struct notifier_block *nb,
{
struct nvec_chip *nvec = container_of(nb, struct nvec_chip,
nvec_status_notifier);
- unsigned char *msg = (unsigned char *)data;
+ unsigned char *msg = data;
if (event_type != NVEC_CNTL)
return NOTIFY_DONE;
dev_warn(nvec->dev, "unhandled msg type %ld\n", event_type);
print_hex_dump(KERN_WARNING, "payload: ", DUMP_PREFIX_NONE, 16, 1,
- msg, msg[1] + 2, true);
+ msg, msg[1] + 2, true);
return NOTIFY_OK;
}
@@ -259,7 +257,7 @@ static void nvec_gpio_set_value(struct nvec_chip *nvec, int value)
* occurred, the nvec driver may print an error.
*/
int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
- short size)
+ short size)
{
struct nvec_msg *msg;
unsigned long flags;
@@ -288,46 +286,49 @@ EXPORT_SYMBOL(nvec_write_async);
* @nvec: An &struct nvec_chip
* @data: The data to write
* @size: The size of @data
+ * @msg: The response message received
*
* This is similar to nvec_write_async(), but waits for the
* request to be answered before returning. This function
* uses a mutex and can thus not be called from e.g.
* interrupt handlers.
*
- * Returns: A pointer to the response message on success,
- * %NULL on failure. Free with nvec_msg_free() once no longer
- * used.
+ * Returns: 0 on success, a negative error code on failure.
+ * The response message is returned in @msg. Shall be freed with
+ * with nvec_msg_free() once no longer used.
+ *
*/
-struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
- const unsigned char *data, short size)
+int nvec_write_sync(struct nvec_chip *nvec,
+ const unsigned char *data, short size,
+ struct nvec_msg **msg)
{
- struct nvec_msg *msg;
-
mutex_lock(&nvec->sync_write_mutex);
+ *msg = NULL;
nvec->sync_write_pending = (data[1] << 8) + data[0];
if (nvec_write_async(nvec, data, size) < 0) {
mutex_unlock(&nvec->sync_write_mutex);
- return NULL;
+ return -ENOMEM;
}
dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n",
- nvec->sync_write_pending);
+ nvec->sync_write_pending);
if (!(wait_for_completion_timeout(&nvec->sync_write,
- msecs_to_jiffies(2000)))) {
- dev_warn(nvec->dev, "timeout waiting for sync write to complete\n");
+ msecs_to_jiffies(2000)))) {
+ dev_warn(nvec->dev,
+ "timeout waiting for sync write to complete\n");
mutex_unlock(&nvec->sync_write_mutex);
- return NULL;
+ return -ETIMEDOUT;
}
dev_dbg(nvec->dev, "nvec_sync_write: pong!\n");
- msg = nvec->last_sync_msg;
+ *msg = nvec->last_sync_msg;
mutex_unlock(&nvec->sync_write_mutex);
- return msg;
+ return 0;
}
EXPORT_SYMBOL(nvec_write_sync);
@@ -422,8 +423,8 @@ static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg)
if ((msg->data[0] >> 7) == 1 && (msg->data[0] & 0x0f) == 5)
print_hex_dump(KERN_WARNING, "ec system event ",
- DUMP_PREFIX_NONE, 16, 1, msg->data,
- msg->data[1] + 2, true);
+ DUMP_PREFIX_NONE, 16, 1, msg->data,
+ msg->data[1] + 2, true);
atomic_notifier_call_chain(&nvec->notifier_list, msg->data[0] & 0x8f,
msg->data);
@@ -493,8 +494,8 @@ static void nvec_rx_completed(struct nvec_chip *nvec)
{
if (nvec->rx->pos != nvec_msg_size(nvec->rx)) {
dev_err(nvec->dev, "RX incomplete: Expected %u bytes, got %u\n",
- (uint) nvec_msg_size(nvec->rx),
- (uint) nvec->rx->pos);
+ (uint)nvec_msg_size(nvec->rx),
+ (uint)nvec->rx->pos);
nvec_msg_free(nvec, nvec->rx);
nvec->state = 0;
@@ -508,8 +509,10 @@ static void nvec_rx_completed(struct nvec_chip *nvec)
spin_lock(&nvec->rx_lock);
- /* add the received data to the work list
- and move the ring buffer pointer to the next entry */
+ /*
+ * Add the received data to the work list and move the ring buffer
+ * pointer to the next entry.
+ */
list_add_tail(&nvec->rx->node, &nvec->rx_data);
spin_unlock(&nvec->rx_lock);
@@ -638,11 +641,9 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
nvec_msg_free(nvec, nvec->rx);
nvec->state = 3;
nvec_tx_set(nvec);
- BUG_ON(nvec->tx->size < 1);
to_send = nvec->tx->data[0];
nvec->tx->pos = 1;
} else if (status == (I2C_SL_IRQ)) {
- BUG_ON(nvec->rx == NULL);
nvec->rx->data[1] = received;
nvec->rx->pos = 2;
nvec->state = 4;
@@ -686,8 +687,8 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
if ((status & (RCVD | RNW)) == RCVD) {
if (received != nvec->i2c_addr)
dev_err(nvec->dev,
- "received address 0x%02x, expected 0x%02x\n",
- received, nvec->i2c_addr);
+ "received address 0x%02x, expected 0x%02x\n",
+ received, nvec->i2c_addr);
nvec->state = 1;
}
@@ -776,7 +777,7 @@ static int nvec_i2c_parse_dt_pdata(struct nvec_chip *nvec)
}
if (of_property_read_u32(nvec->dev->of_node, "slave-addr",
- &nvec->i2c_addr)) {
+ &nvec->i2c_addr)) {
dev_err(nvec->dev, "no i2c address specified");
return -ENODEV;
}
@@ -852,14 +853,14 @@ static int tegra_nvec_probe(struct platform_device *pdev)
INIT_WORK(&nvec->tx_work, nvec_request_master);
err = devm_gpio_request_one(&pdev->dev, nvec->gpio, GPIOF_OUT_INIT_HIGH,
- "nvec gpio");
+ "nvec gpio");
if (err < 0) {
dev_err(nvec->dev, "couldn't request gpio\n");
return -ENODEV;
}
err = devm_request_irq(&pdev->dev, nvec->irq, nvec_interrupt, 0,
- "nvec", nvec);
+ "nvec", nvec);
if (err) {
dev_err(nvec->dev, "couldn't request irq\n");
return -ENODEV;
@@ -878,11 +879,13 @@ static int tegra_nvec_probe(struct platform_device *pdev)
pm_power_off = nvec_power_off;
/* Get Firmware Version */
- msg = nvec_write_sync(nvec, get_firmware_version, 2);
+ err = nvec_write_sync(nvec, get_firmware_version, 2, &msg);
- if (msg) {
- dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n",
- msg->data[4], msg->data[5], msg->data[6], msg->data[7]);
+ if (!err) {
+ dev_warn(nvec->dev,
+ "ec firmware version %02x.%02x.%02x / %02x\n",
+ msg->data[4], msg->data[5],
+ msg->data[6], msg->data[7]);
nvec_msg_free(nvec, msg);
}
@@ -924,6 +927,7 @@ static int tegra_nvec_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int nvec_suspend(struct device *dev)
{
+ int err;
struct platform_device *pdev = to_platform_device(dev);
struct nvec_chip *nvec = platform_get_drvdata(pdev);
struct nvec_msg *msg;
@@ -934,8 +938,9 @@ static int nvec_suspend(struct device *dev)
/* keep these sync or you'll break suspend */
nvec_toggle_global_events(nvec, false);
- msg = nvec_write_sync(nvec, ap_suspend, sizeof(ap_suspend));
- nvec_msg_free(nvec, msg);
+ err = nvec_write_sync(nvec, ap_suspend, sizeof(ap_suspend), &msg);
+ if (!err)
+ nvec_msg_free(nvec, msg);
nvec_disable_i2c_slave(nvec);