Commit 74923441 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'nfc-pn533-add-uart-phy-driver'



Lars Poeschel says:

====================
nfc: pn533: add uart phy driver

The purpose of this patch series is to add a uart phy driver to the
pn533 nfc driver.
It first changes the dt strings and docs. The dt compatible strings
need to change, because I would add "pn532-uart" to the already
existing "pn533-i2c" one. These two are now unified into just
"pn532". Then the neccessary changes to the pn533 core driver are
made. Then the uart phy is added.
As the pn532 chip supports a autopoll, I wanted to use this instead
of the software poll loop in the pn533 core driver. It is added and
activated by the last to patches.
The way to add the autopoll later in seperate patches is chosen, to
show, that the uart phy driver can also work with the software poll
loop, if someone needs that for some reason.
In v11 of this patchseries I address a byte ordering issue reported
by kbuild test robot in patch 5/7.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9014fc31 e4a5dc18
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
* NXP Semiconductors PN532 NFC Controller

Required properties:
- compatible: Should be "nxp,pn532-i2c" or "nxp,pn533-i2c".
- compatible: Should be
    - "nxp,pn532" Place a node with this inside the devicetree node of the bus
                  where the NFC chip is connected to.
                  Currently the kernel has phy bindings for uart and i2c.
    - "nxp,pn532-i2c" (DEPRECATED) only works for the i2c binding.
    - "nxp,pn533-i2c" (DEPRECATED) only works for the i2c binding.

Required properties if connected on i2c:
- clock-frequency: I²C work frequency.
- reg: address on the bus
- reg: for the I²C bus address. This is fixed at 0x24 for the PN532.
- interrupts: GPIO interrupt to which the chip is connected

Optional SoC Specific Properties:
@@ -15,9 +22,9 @@ Example (for ARM-based BeagleBone with PN532 on I2C2):
&i2c2 {


	pn532: pn532@24 {
	pn532: nfc@24 {

		compatible = "nxp,pn532-i2c";
		compatible = "nxp,pn532";

		reg = <0x24>;
		clock-frequency = <400000>;
@@ -27,3 +34,13 @@ Example (for ARM-based BeagleBone with PN532 on I2C2):

	};
};

Example (for PN532 connected via uart):

uart4: serial@49042000 {
        compatible = "ti,omap3-uart";

        pn532: nfc {
                compatible = "nxp,pn532";
        };
};
+11 −0
Original line number Diff line number Diff line
@@ -26,3 +26,14 @@ config NFC_PN533_I2C

	  If you choose to build a module, it'll be called pn533_i2c.
	  Say N if unsure.

config NFC_PN532_UART
	tristate "NFC PN532 device support (UART)"
	depends on SERIAL_DEV_BUS
	select NFC_PN533
	---help---
	  This module adds support for the NXP pn532 UART interface.
	  Select this if your platform is using the UART bus.

	  If you choose to build a module, it'll be called pn532_uart.
	  Say N if unsure.
+2 −0
Original line number Diff line number Diff line
@@ -4,7 +4,9 @@
#
pn533_usb-objs  = usb.o
pn533_i2c-objs  = i2c.o
pn532_uart-objs  = uart.o

obj-$(CONFIG_NFC_PN533)     += pn533.o
obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o
obj-$(CONFIG_NFC_PN533_I2C) += pn533_i2c.o
obj-$(CONFIG_NFC_PN532_UART) += pn532_uart.o
+23 −9
Original line number Diff line number Diff line
@@ -193,12 +193,10 @@ static int pn533_i2c_probe(struct i2c_client *client,
	phy->i2c_dev = client;
	i2c_set_clientdata(client, phy);

	priv = pn533_register_device(PN533_DEVICE_PN532,
				     PN533_NO_TYPE_B_PROTOCOLS,
	priv = pn53x_common_init(PN533_DEVICE_PN532,
				PN533_PROTO_REQ_ACK_RESP,
				phy, &i2c_phy_ops, NULL,
				     &phy->i2c_dev->dev,
				     &client->dev);
				&phy->i2c_dev->dev);

	if (IS_ERR(priv)) {
		r = PTR_ERR(priv);
@@ -206,6 +204,9 @@ static int pn533_i2c_probe(struct i2c_client *client,
	}

	phy->priv = priv;
	r = pn532_i2c_nfc_alloc(priv, PN533_NO_TYPE_B_PROTOCOLS, &client->dev);
	if (r)
		goto nfc_alloc_err;

	r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn,
				IRQF_TRIGGER_FALLING |
@@ -220,13 +221,20 @@ static int pn533_i2c_probe(struct i2c_client *client,
	if (r)
		goto fn_setup_err;

	return 0;
	r = nfc_register_device(priv->nfc_dev);
	if (r)
		goto fn_setup_err;

	return r;

fn_setup_err:
	free_irq(client->irq, phy);

irq_rqst_err:
	pn533_unregister_device(phy->priv);
	nfc_free_device(priv->nfc_dev);

nfc_alloc_err:
	pn53x_common_clean(phy->priv);

	return r;
}
@@ -239,12 +247,18 @@ static int pn533_i2c_remove(struct i2c_client *client)

	free_irq(client->irq, phy);

	pn533_unregister_device(phy->priv);
	pn53x_unregister_nfc(phy->priv);
	pn53x_common_clean(phy->priv);

	return 0;
}

static const struct of_device_id of_pn533_i2c_match[] = {
	{ .compatible = "nxp,pn532", },
	/*
	 * NOTE: The use of the compatibles with the trailing "...-i2c" is
	 * deprecated and will be removed.
	 */
	{ .compatible = "nxp,pn533-i2c", },
	{ .compatible = "nxp,pn532-i2c", },
	{},
+246 −35
Original line number Diff line number Diff line
@@ -185,6 +185,32 @@ struct pn533_cmd_jump_dep_response {
	u8 gt[];
} __packed;

struct pn532_autopoll_resp {
	u8 type;
	u8 ln;
	u8 tg;
	u8 tgdata[];
};

/* PN532_CMD_IN_AUTOPOLL */
#define PN532_AUTOPOLL_POLLNR_INFINITE	0xff
#define PN532_AUTOPOLL_PERIOD		0x03 /* in units of 150 ms */

#define PN532_AUTOPOLL_TYPE_GENERIC_106		0x00
#define PN532_AUTOPOLL_TYPE_GENERIC_212		0x01
#define PN532_AUTOPOLL_TYPE_GENERIC_424		0x02
#define PN532_AUTOPOLL_TYPE_JEWEL		0x04
#define PN532_AUTOPOLL_TYPE_MIFARE		0x10
#define PN532_AUTOPOLL_TYPE_FELICA212		0x11
#define PN532_AUTOPOLL_TYPE_FELICA424		0x12
#define PN532_AUTOPOLL_TYPE_ISOA		0x20
#define PN532_AUTOPOLL_TYPE_ISOB		0x23
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106	0x40
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212	0x41
#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424	0x42
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106	0x80
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212	0x81
#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424	0x82

/* PN533_TG_INIT_AS_TARGET */
#define PN533_INIT_TARGET_PASSIVE 0x1
@@ -1389,6 +1415,101 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev)
	return rc;
}

static int pn533_autopoll_complete(struct pn533 *dev, void *arg,
			       struct sk_buff *resp)
{
	struct pn532_autopoll_resp *apr;
	struct nfc_target nfc_tgt;
	u8 nbtg;
	int rc;

	if (IS_ERR(resp)) {
		rc = PTR_ERR(resp);

		nfc_err(dev->dev, "%s  autopoll complete error %d\n",
			__func__, rc);

		if (rc == -ENOENT) {
			if (dev->poll_mod_count != 0)
				return rc;
			goto stop_poll;
		} else if (rc < 0) {
			nfc_err(dev->dev,
				"Error %d when running autopoll\n", rc);
			goto stop_poll;
		}
	}

	nbtg = resp->data[0];
	if ((nbtg > 2) || (nbtg <= 0))
		return -EAGAIN;

	apr = (struct pn532_autopoll_resp *)&resp->data[1];
	while (nbtg--) {
		memset(&nfc_tgt, 0, sizeof(struct nfc_target));
		switch (apr->type) {
		case PN532_AUTOPOLL_TYPE_ISOA:
			dev_dbg(dev->dev, "ISOA\n");
			rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
						       apr->ln - 1);
			break;
		case PN532_AUTOPOLL_TYPE_FELICA212:
		case PN532_AUTOPOLL_TYPE_FELICA424:
			dev_dbg(dev->dev, "FELICA\n");
			rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata,
						       apr->ln - 1);
			break;
		case PN532_AUTOPOLL_TYPE_JEWEL:
			dev_dbg(dev->dev, "JEWEL\n");
			rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata,
						      apr->ln - 1);
			break;
		case PN532_AUTOPOLL_TYPE_ISOB:
			dev_dbg(dev->dev, "ISOB\n");
			rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata,
						       apr->ln - 1);
			break;
		case PN532_AUTOPOLL_TYPE_MIFARE:
			dev_dbg(dev->dev, "Mifare\n");
			rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
						       apr->ln - 1);
			break;
		default:
			nfc_err(dev->dev,
				    "Unknown current poll modulation\n");
			rc = -EPROTO;
		}

		if (rc)
			goto done;

		if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
			nfc_err(dev->dev,
				    "The Tg found doesn't have the desired protocol\n");
			rc = -EAGAIN;
			goto done;
		}

		dev->tgt_available_prots = nfc_tgt.supported_protocols;
		apr = (struct pn532_autopoll_resp *)
			(apr->tgdata + (apr->ln - 1));
	}

	pn533_poll_reset_mod_list(dev);
	nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);

done:
	dev_kfree_skb(resp);
	return rc;

stop_poll:
	nfc_err(dev->dev, "autopoll operation has been stopped\n");

	pn533_poll_reset_mod_list(dev);
	dev->poll_protocols = 0;
	return rc;
}

static int pn533_poll_complete(struct pn533 *dev, void *arg,
			       struct sk_buff *resp)
{
@@ -1532,6 +1653,7 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
{
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
	struct pn533_poll_modulations *cur_mod;
	struct sk_buff *skb;
	u8 rand_mod;
	int rc;

@@ -1557,9 +1679,73 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
			tm_protocols = 0;
	}

	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
	dev->poll_protocols = im_protocols;
	dev->listen_protocols = tm_protocols;
	if (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL) {
		skb = pn533_alloc_skb(dev, 4 + 6);
		if (!skb)
			return -ENOMEM;

		*((u8 *)skb_put(skb, sizeof(u8))) =
			PN532_AUTOPOLL_POLLNR_INFINITE;
		*((u8 *)skb_put(skb, sizeof(u8))) = PN532_AUTOPOLL_PERIOD;

		if ((im_protocols & NFC_PROTO_MIFARE_MASK) &&
				(im_protocols & NFC_PROTO_ISO14443_MASK) &&
				(im_protocols & NFC_PROTO_NFC_DEP_MASK))
			*((u8 *)skb_put(skb, sizeof(u8))) =
				PN532_AUTOPOLL_TYPE_GENERIC_106;
		else {
			if (im_protocols & NFC_PROTO_MIFARE_MASK)
				*((u8 *)skb_put(skb, sizeof(u8))) =
					PN532_AUTOPOLL_TYPE_MIFARE;

			if (im_protocols & NFC_PROTO_ISO14443_MASK)
				*((u8 *)skb_put(skb, sizeof(u8))) =
					PN532_AUTOPOLL_TYPE_ISOA;

			if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
				*((u8 *)skb_put(skb, sizeof(u8))) =
					PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106;
				*((u8 *)skb_put(skb, sizeof(u8))) =
					PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212;
				*((u8 *)skb_put(skb, sizeof(u8))) =
					PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424;
			}
		}

		if (im_protocols & NFC_PROTO_FELICA_MASK ||
				im_protocols & NFC_PROTO_NFC_DEP_MASK) {
			*((u8 *)skb_put(skb, sizeof(u8))) =
				PN532_AUTOPOLL_TYPE_FELICA212;
			*((u8 *)skb_put(skb, sizeof(u8))) =
				PN532_AUTOPOLL_TYPE_FELICA424;
		}

		if (im_protocols & NFC_PROTO_JEWEL_MASK)
			*((u8 *)skb_put(skb, sizeof(u8))) =
				PN532_AUTOPOLL_TYPE_JEWEL;

		if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
			*((u8 *)skb_put(skb, sizeof(u8))) =
				PN532_AUTOPOLL_TYPE_ISOB;

		if (tm_protocols)
			*((u8 *)skb_put(skb, sizeof(u8))) =
				PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106;

		rc = pn533_send_cmd_async(dev, PN533_CMD_IN_AUTOPOLL, skb,
				pn533_autopoll_complete, NULL);

		if (rc < 0)
			dev_kfree_skb(skb);
		else
			dev->poll_mod_count++;

		return rc;
	}

	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);

	/* Do not always start polling from the same modulation */
	get_random_bytes(&rand_mod, sizeof(rand_mod));
@@ -2458,7 +2644,11 @@ static int pn533_dev_up(struct nfc_dev *nfc_dev)
{
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);

	if (dev->device_type == PN533_DEVICE_PN532) {
	if (dev->phy_ops->dev_up)
		dev->phy_ops->dev_up(dev);

	if ((dev->device_type == PN533_DEVICE_PN532) ||
		(dev->device_type == PN533_DEVICE_PN532_AUTOPOLL)) {
		int rc = pn532_sam_configuration(nfc_dev);

		if (rc)
@@ -2470,7 +2660,14 @@ static int pn533_dev_up(struct nfc_dev *nfc_dev)

static int pn533_dev_down(struct nfc_dev *nfc_dev)
{
	return pn533_rf_field(nfc_dev, 0);
	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
	int ret;

	ret = pn533_rf_field(nfc_dev, 0);
	if (dev->phy_ops->dev_down && !ret)
		dev->phy_ops->dev_down(dev);

	return ret;
}

static struct nfc_ops pn533_nfc_ops = {
@@ -2498,6 +2695,7 @@ static int pn533_setup(struct pn533 *dev)
	case PN533_DEVICE_PASORI:
	case PN533_DEVICE_ACR122U:
	case PN533_DEVICE_PN532:
	case PN533_DEVICE_PN532_AUTOPOLL:
		max_retries.mx_rty_atr = 0x2;
		max_retries.mx_rty_psl = 0x1;
		max_retries.mx_rty_passive_act =
@@ -2534,6 +2732,7 @@ static int pn533_setup(struct pn533 *dev)
	switch (dev->device_type) {
	case PN533_DEVICE_STD:
	case PN533_DEVICE_PN532:
	case PN533_DEVICE_PN532_AUTOPOLL:
		break;

	case PN533_DEVICE_PASORI:
@@ -2580,14 +2779,12 @@ int pn533_finalize_setup(struct pn533 *dev)
}
EXPORT_SYMBOL_GPL(pn533_finalize_setup);

struct pn533 *pn533_register_device(u32 device_type,
				u32 protocols,
struct pn533 *pn53x_common_init(u32 device_type,
				enum pn533_protocol_type protocol_type,
				void *phy,
				struct pn533_phy_ops *phy_ops,
				struct pn533_frame_ops *fops,
				struct device *dev,
				struct device *parent)
				struct device *dev)
{
	struct pn533 *priv;
	int rc = -ENOMEM;
@@ -2628,43 +2825,18 @@ struct pn533 *pn533_register_device(u32 device_type,
	skb_queue_head_init(&priv->fragment_skb);

	INIT_LIST_HEAD(&priv->cmd_queue);

	priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
					   priv->ops->tx_header_len +
					   PN533_CMD_DATAEXCH_HEAD_LEN,
					   priv->ops->tx_tail_len);
	if (!priv->nfc_dev) {
		rc = -ENOMEM;
		goto destroy_wq;
	}

	nfc_set_parent_dev(priv->nfc_dev, parent);
	nfc_set_drvdata(priv->nfc_dev, priv);

	rc = nfc_register_device(priv->nfc_dev);
	if (rc)
		goto free_nfc_dev;

	return priv;

free_nfc_dev:
	nfc_free_device(priv->nfc_dev);

destroy_wq:
	destroy_workqueue(priv->wq);
error:
	kfree(priv);
	return ERR_PTR(rc);
}
EXPORT_SYMBOL_GPL(pn533_register_device);
EXPORT_SYMBOL_GPL(pn53x_common_init);

void pn533_unregister_device(struct pn533 *priv)
void pn53x_common_clean(struct pn533 *priv)
{
	struct pn533_cmd *cmd, *n;

	nfc_unregister_device(priv->nfc_dev);
	nfc_free_device(priv->nfc_dev);

	flush_delayed_work(&priv->poll_work);
	destroy_workqueue(priv->wq);

@@ -2679,8 +2851,47 @@ void pn533_unregister_device(struct pn533 *priv)

	kfree(priv);
}
EXPORT_SYMBOL_GPL(pn533_unregister_device);
EXPORT_SYMBOL_GPL(pn53x_common_clean);

int pn532_i2c_nfc_alloc(struct pn533 *priv, u32 protocols,
			struct device *parent)
{
	priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols,
					   priv->ops->tx_header_len +
					   PN533_CMD_DATAEXCH_HEAD_LEN,
					   priv->ops->tx_tail_len);
	if (!priv->nfc_dev)
		return -ENOMEM;

	nfc_set_parent_dev(priv->nfc_dev, parent);
	nfc_set_drvdata(priv->nfc_dev, priv);
	return 0;
}
EXPORT_SYMBOL_GPL(pn532_i2c_nfc_alloc);

int pn53x_register_nfc(struct pn533 *priv, u32 protocols,
			struct device *parent)
{
	int rc;

	rc = pn532_i2c_nfc_alloc(priv, protocols, parent);
	if (rc)
		return rc;

	rc = nfc_register_device(priv->nfc_dev);
	if (rc)
		nfc_free_device(priv->nfc_dev);

	return rc;
}
EXPORT_SYMBOL_GPL(pn53x_register_nfc);

void pn53x_unregister_nfc(struct pn533 *priv)
{
	nfc_unregister_device(priv->nfc_dev);
	nfc_free_device(priv->nfc_dev);
}
EXPORT_SYMBOL_GPL(pn53x_unregister_nfc);

MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
Loading