18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2013  Intel Corporation. All rights reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * HCI based Driver for NXP pn544 NFC Chip
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/module.h>
98c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
108c2ecf20Sopenharmony_ci#include <linux/nfc.h>
118c2ecf20Sopenharmony_ci#include <net/nfc/hci.h>
128c2ecf20Sopenharmony_ci#include <net/nfc/llc.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "../mei_phy.h"
158c2ecf20Sopenharmony_ci#include "pn544.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define PN544_DRIVER_NAME "pn544"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic int pn544_mei_probe(struct mei_cl_device *cldev,
208c2ecf20Sopenharmony_ci			       const struct mei_cl_device_id *id)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	struct nfc_mei_phy *phy;
238c2ecf20Sopenharmony_ci	int r;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	pr_info("Probing NFC pn544\n");
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	phy = nfc_mei_phy_alloc(cldev);
288c2ecf20Sopenharmony_ci	if (!phy) {
298c2ecf20Sopenharmony_ci		pr_err("Cannot allocate memory for pn544 mei phy.\n");
308c2ecf20Sopenharmony_ci		return -ENOMEM;
318c2ecf20Sopenharmony_ci	}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
348c2ecf20Sopenharmony_ci			    MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
358c2ecf20Sopenharmony_ci			    NULL, &phy->hdev);
368c2ecf20Sopenharmony_ci	if (r < 0) {
378c2ecf20Sopenharmony_ci		nfc_mei_phy_free(phy);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci		return r;
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	return 0;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic int pn544_mei_remove(struct mei_cl_device *cldev)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	pr_info("Removing pn544\n");
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	pn544_hci_remove(phy->hdev);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	nfc_mei_phy_free(phy);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	return 0;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic struct mei_cl_device_id pn544_mei_tbl[] = {
598c2ecf20Sopenharmony_ci	{ PN544_DRIVER_NAME, MEI_NFC_UUID, MEI_CL_VERSION_ANY},
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	/* required last entry */
628c2ecf20Sopenharmony_ci	{ }
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(mei, pn544_mei_tbl);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic struct mei_cl_driver pn544_driver = {
678c2ecf20Sopenharmony_ci	.id_table = pn544_mei_tbl,
688c2ecf20Sopenharmony_ci	.name = PN544_DRIVER_NAME,
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	.probe = pn544_mei_probe,
718c2ecf20Sopenharmony_ci	.remove = pn544_mei_remove,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cimodule_mei_cl_driver(pn544_driver);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
778c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC);
78