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 Inside Secure microread NFC Chip
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
128c2ecf20Sopenharmony_ci#include <linux/nfc.h>
138c2ecf20Sopenharmony_ci#include <net/nfc/hci.h>
148c2ecf20Sopenharmony_ci#include <net/nfc/llc.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "../mei_phy.h"
178c2ecf20Sopenharmony_ci#include "microread.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define MICROREAD_DRIVER_NAME "microread"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic int microread_mei_probe(struct mei_cl_device *cldev,
228c2ecf20Sopenharmony_ci			       const struct mei_cl_device_id *id)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	struct nfc_mei_phy *phy;
258c2ecf20Sopenharmony_ci	int r;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	pr_info("Probing NFC microread\n");
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	phy = nfc_mei_phy_alloc(cldev);
308c2ecf20Sopenharmony_ci	if (!phy) {
318c2ecf20Sopenharmony_ci		pr_err("Cannot allocate memory for microread mei phy.\n");
328c2ecf20Sopenharmony_ci		return -ENOMEM;
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	r = microread_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
368c2ecf20Sopenharmony_ci			    MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
378c2ecf20Sopenharmony_ci			    &phy->hdev);
388c2ecf20Sopenharmony_ci	if (r < 0) {
398c2ecf20Sopenharmony_ci		nfc_mei_phy_free(phy);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci		return r;
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	return 0;
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic int microread_mei_remove(struct mei_cl_device *cldev)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	microread_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 microread_mei_tbl[] = {
598c2ecf20Sopenharmony_ci	{ MICROREAD_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, microread_mei_tbl);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic struct mei_cl_driver microread_driver = {
678c2ecf20Sopenharmony_ci	.id_table = microread_mei_tbl,
688c2ecf20Sopenharmony_ci	.name = MICROREAD_DRIVER_NAME,
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	.probe = microread_mei_probe,
718c2ecf20Sopenharmony_ci	.remove = microread_mei_remove,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cimodule_mei_cl_driver(microread_driver);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
778c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC);
78