Commit e9e1dcda authored by David S. Miller's avatar David S. Miller

Merge branch 'nfc-next'

Andy Shevchenko says:

====================
NFC: nxp-nci: clean up and new device support

Few people reported that some laptops are coming with new ACPI ID for the
devices should be supported by nxp-nci driver.

This series adds new ID (patch 2), cleans up the driver from legacy platform
data and unifies GPIO request for Device Tree and ACPI (patches 3-6), removes
dead or unneeded code (patches 7, 9, 11), constifies ID table (patch 8),
removes comma in terminator line for better maintenance (patch 10) and
rectifies Kconfig entry (patches 12-14).

It also contains a fix for NFC subsystem as suggested by Sedat.

Series has been tested by Sedat.

Changelog v4:
- rebased on top of latest linux-next
- appended cover letter
- elaborated removal of pr_fmt() in the patch 11 (David)
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d24b6c62 8f6920ac
......@@ -11327,7 +11327,6 @@ F: include/net/nfc/
F: include/uapi/linux/nfc.h
F: drivers/nfc/
F: include/linux/platform_data/nfcmrvl.h
F: include/linux/platform_data/nxp-nci.h
F: Documentation/devicetree/bindings/net/nfc/
NFS, SUNRPC, AND LOCKD CLIENTS
......
......@@ -2,10 +2,9 @@
config NFC_NXP_NCI
tristate "NXP-NCI NFC driver"
depends on NFC_NCI
default n
---help---
Generic core driver for NXP NCI chips such as the NPC100
or PN7150 families.
Generic core driver for NXP NCI chips such as the NPC100 (PN547),
NPC300 (PN548) or PN7150 families.
This is a driver based on the NCI NFC kernel layers and
will thus not work with NXP libnfc library.
......@@ -23,4 +22,4 @@ config NFC_NXP_NCI_I2C
To compile this driver as a module, choose m here. The module will
be called nxp_nci_i2c.
Say Y if unsure.
Say N if unsure.
......@@ -11,10 +11,8 @@
*/
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/nfc.h>
#include <linux/platform_data/nxp-nci.h>
#include <net/nfc/nci_core.h>
......
......@@ -12,8 +12,6 @@
* Copyright (C) 2012 Intel Corporation. All rights reserved.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/i2c.h>
......@@ -21,9 +19,6 @@
#include <linux/module.h>
#include <linux/nfc.h>
#include <linux/gpio/consumer.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/platform_data/nxp-nci.h>
#include <asm/unaligned.h>
#include <net/nfc/nfc.h>
......@@ -38,8 +33,8 @@ struct nxp_nci_i2c_phy {
struct i2c_client *i2c_dev;
struct nci_dev *ndev;
unsigned int gpio_en;
unsigned int gpio_fw;
struct gpio_desc *gpiod_en;
struct gpio_desc *gpiod_fw;
int hard_fault; /*
* < 0 if hardware error occurred (e.g. i2c err)
......@@ -52,8 +47,8 @@ static int nxp_nci_i2c_set_mode(void *phy_id,
{
struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id;
gpio_set_value(phy->gpio_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0);
gpio_set_value(phy->gpio_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0);
gpiod_set_value(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0);
gpiod_set_value(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0);
usleep_range(10000, 15000);
if (mode == NXP_NCI_MODE_COLD)
......@@ -250,116 +245,55 @@ static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
return IRQ_NONE;
}
static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
{
struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client);
struct device_node *pp;
int r;
pp = client->dev.of_node;
if (!pp)
return -ENODEV;
r = of_get_named_gpio(pp, "enable-gpios", 0);
if (r == -EPROBE_DEFER)
r = of_get_named_gpio(pp, "enable-gpios", 0);
if (r < 0) {
nfc_err(&client->dev, "Failed to get EN gpio, error: %d\n", r);
return r;
}
phy->gpio_en = r;
r = of_get_named_gpio(pp, "firmware-gpios", 0);
if (r == -EPROBE_DEFER)
r = of_get_named_gpio(pp, "firmware-gpios", 0);
if (r < 0) {
nfc_err(&client->dev, "Failed to get FW gpio, error: %d\n", r);
return r;
}
phy->gpio_fw = r;
return 0;
}
static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy)
{
struct i2c_client *client = phy->i2c_dev;
struct gpio_desc *gpiod_en, *gpiod_fw;
static const struct acpi_gpio_params firmware_gpios = { 1, 0, false };
static const struct acpi_gpio_params enable_gpios = { 2, 0, false };
gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW);
gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW);
if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw)) {
nfc_err(&client->dev, "No GPIOs\n");
return -EINVAL;
}
phy->gpio_en = desc_to_gpio(gpiod_en);
phy->gpio_fw = desc_to_gpio(gpiod_fw);
return 0;
}
static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = {
{ "enable-gpios", &enable_gpios, 1 },
{ "firmware-gpios", &firmware_gpios, 1 },
{ }
};
static int nxp_nci_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct nxp_nci_i2c_phy *phy;
struct nxp_nci_nfc_platform_data *pdata;
int r;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
r = -ENODEV;
goto probe_exit;
return -ENODEV;
}
phy = devm_kzalloc(&client->dev, sizeof(struct nxp_nci_i2c_phy),
GFP_KERNEL);
if (!phy) {
r = -ENOMEM;
goto probe_exit;
}
if (!phy)
return -ENOMEM;
phy->i2c_dev = client;
i2c_set_clientdata(client, phy);
pdata = client->dev.platform_data;
if (!pdata && client->dev.of_node) {
r = nxp_nci_i2c_parse_devtree(client);
if (r < 0) {
nfc_err(&client->dev, "Failed to get DT data\n");
goto probe_exit;
}
} else if (pdata) {
phy->gpio_en = pdata->gpio_en;
phy->gpio_fw = pdata->gpio_fw;
} else if (ACPI_HANDLE(&client->dev)) {
r = nxp_nci_i2c_acpi_config(phy);
if (r < 0)
goto probe_exit;
goto nci_probe;
} else {
nfc_err(&client->dev, "No platform data\n");
r = -EINVAL;
goto probe_exit;
}
r = devm_acpi_dev_add_driver_gpios(dev, acpi_nxp_nci_gpios);
if (r)
return r;
r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en,
GPIOF_OUT_INIT_LOW, "nxp_nci_en");
if (r < 0)
goto probe_exit;
phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(phy->gpiod_en)) {
nfc_err(dev, "Failed to get EN gpio\n");
return PTR_ERR(phy->gpiod_en);
}
r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw,
GPIOF_OUT_INIT_LOW, "nxp_nci_fw");
if (r < 0)
goto probe_exit;
phy->gpiod_fw = devm_gpiod_get(dev, "firmware", GPIOD_OUT_LOW);
if (IS_ERR(phy->gpiod_fw)) {
nfc_err(dev, "Failed to get FW gpio\n");
return PTR_ERR(phy->gpiod_fw);
}
nci_probe:
r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops,
NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev);
if (r < 0)
goto probe_exit;
return r;
r = request_threaded_irq(client->irq, NULL,
nxp_nci_i2c_irq_thread_fn,
......@@ -368,7 +302,6 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
if (r < 0)
nfc_err(&client->dev, "Unable to register IRQ handler\n");
probe_exit:
return r;
}
......@@ -390,14 +323,15 @@ MODULE_DEVICE_TABLE(i2c, nxp_nci_i2c_id_table);
static const struct of_device_id of_nxp_nci_i2c_match[] = {
{ .compatible = "nxp,nxp-nci-i2c", },
{},
{}
};
MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match);
#ifdef CONFIG_ACPI
static struct acpi_device_id acpi_id[] = {
static const struct acpi_device_id acpi_id[] = {
{ "NXP1001" },
{ "NXP7471" },
{ },
{ }
};
MODULE_DEVICE_TABLE(acpi, acpi_id);
#endif
......@@ -406,7 +340,7 @@ static struct i2c_driver nxp_nci_i2c_driver = {
.driver = {
.name = NXP_NCI_I2C_DRIVER_NAME,
.acpi_match_table = ACPI_PTR(acpi_id),
.of_match_table = of_match_ptr(of_nxp_nci_i2c_match),
.of_match_table = of_nxp_nci_i2c_match,
},
.probe = nxp_nci_i2c_probe,
.id_table = nxp_nci_i2c_id_table,
......
......@@ -14,7 +14,6 @@
#include <linux/completion.h>
#include <linux/firmware.h>
#include <linux/nfc.h>
#include <linux/platform_data/nxp-nci.h>
#include <net/nfc/nci_core.h>
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Generic platform data for the NXP NCI NFC chips.
*
* Copyright (C) 2014 NXP Semiconductors All rights reserved.
*
* Authors: Clément Perrochaud <clement.perrochaud@nxp.com>
*/
#ifndef _NXP_NCI_H_
#define _NXP_NCI_H_
struct nxp_nci_nfc_platform_data {
unsigned int gpio_en;
unsigned int gpio_fw;
unsigned int irq;
};
#endif /* _NXP_NCI_H_ */
......@@ -970,7 +970,8 @@ static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info)
int rc;
u32 idx;
if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
!info->attrs[NFC_ATTR_TARGET_INDEX])
return -EINVAL;
idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
......@@ -1018,7 +1019,8 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
struct sk_buff *msg = NULL;
u32 idx;
if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
!info->attrs[NFC_ATTR_FIRMWARE_NAME])
return -EINVAL;
idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment