Skip to content

Commit

Permalink
Merge branch 'nfc-next'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 29, 2019
2 parents d24b6c6 + 8f6920a commit e9e1dcd
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 129 deletions.
1 change: 0 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions drivers/nfc/nxp-nci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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.
2 changes: 0 additions & 2 deletions drivers/nfc/nxp-nci/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down
134 changes: 34 additions & 100 deletions drivers/nfc/nxp-nci/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,13 @@
* 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>
#include <linux/interrupt.h>
#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>
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}

Expand All @@ -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
Expand All @@ -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,
Expand Down
1 change: 0 additions & 1 deletion drivers/nfc/nxp-nci/nxp-nci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down
19 changes: 0 additions & 19 deletions include/linux/platform_data/nxp-nci.h

This file was deleted.

6 changes: 4 additions & 2 deletions net/nfc/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down Expand Up @@ -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]);
Expand Down

0 comments on commit e9e1dcd

Please sign in to comment.