18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2010 Trusted Logic S.A. 48c2ecf20Sopenharmony_ci * modifications copyright (C) 2015 NXP B.V. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include <linux/kernel.h> 78c2ecf20Sopenharmony_ci#include <linux/module.h> 88c2ecf20Sopenharmony_ci#include <linux/fs.h> 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/list.h> 128c2ecf20Sopenharmony_ci#include <linux/i2c.h> 138c2ecf20Sopenharmony_ci#include <linux/irq.h> 148c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 158c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 188c2ecf20Sopenharmony_ci#include <linux/io.h> 198c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 208c2ecf20Sopenharmony_ci#include <linux/gpio.h> 218c2ecf20Sopenharmony_ci#include <linux/miscdevice.h> 228c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 238c2ecf20Sopenharmony_ci#include "pn5xx_i2c.h" 248c2ecf20Sopenharmony_ci#include <linux/of_gpio.h> 258c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 268c2ecf20Sopenharmony_ci#include <linux/of.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define MAX_BUFFER_SIZE 512 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define MODE_OFF 0 318c2ecf20Sopenharmony_ci#define MODE_RUN 1 328c2ecf20Sopenharmony_ci#define MODE_FW 2 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* Only pn548, pn547 and pn544 are supported */ 358c2ecf20Sopenharmony_ci#define CHIP "pn544" 368c2ecf20Sopenharmony_ci#define DRIVER_CARD "PN54x NFC" 378c2ecf20Sopenharmony_ci#define DRIVER_DESC "NFC driver for PN54x Family" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#ifndef CONFIG_OF 408c2ecf20Sopenharmony_ci#define CONFIG_OF 418c2ecf20Sopenharmony_ci#endif 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistruct pn54x_dev { 448c2ecf20Sopenharmony_ci wait_queue_head_t read_wq; 458c2ecf20Sopenharmony_ci struct mutex read_mutex; 468c2ecf20Sopenharmony_ci struct i2c_client *client; 478c2ecf20Sopenharmony_ci struct miscdevice pn54x_device; 488c2ecf20Sopenharmony_ci int ven_gpio; 498c2ecf20Sopenharmony_ci int firm_gpio; 508c2ecf20Sopenharmony_ci int irq_gpio; 518c2ecf20Sopenharmony_ci int clkreq_gpio; 528c2ecf20Sopenharmony_ci struct regulator *pvdd_reg; 538c2ecf20Sopenharmony_ci struct regulator *vbat_reg; 548c2ecf20Sopenharmony_ci struct regulator *pmuvcc_reg; 558c2ecf20Sopenharmony_ci struct regulator *sevdd_reg; 568c2ecf20Sopenharmony_ci bool irq_enabled; 578c2ecf20Sopenharmony_ci spinlock_t irq_enabled_lock; 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/********************************************************** 618c2ecf20Sopenharmony_ci * Interrupt control and handler 628c2ecf20Sopenharmony_ci **********************************************************/ 638c2ecf20Sopenharmony_cistatic void pn54x_disable_irq(struct pn54x_dev *pn54x_dev) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci unsigned long flags; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci spin_lock_irqsave(&pn54x_dev->irq_enabled_lock, flags); 688c2ecf20Sopenharmony_ci if (pn54x_dev->irq_enabled) { 698c2ecf20Sopenharmony_ci disable_irq_nosync(pn54x_dev->client->irq); 708c2ecf20Sopenharmony_ci pn54x_dev->irq_enabled = false; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&pn54x_dev->irq_enabled_lock, flags); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic irqreturn_t pn54x_dev_irq_handler(int irq, void *dev_id) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev = dev_id; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci pn54x_disable_irq(pn54x_dev); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* Wake up waiting readers */ 828c2ecf20Sopenharmony_ci wake_up(&pn54x_dev->read_wq); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci return IRQ_HANDLED; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/********************************************************** 888c2ecf20Sopenharmony_ci * private functions 898c2ecf20Sopenharmony_ci **********************************************************/ 908c2ecf20Sopenharmony_cistatic int pn544_enable(struct pn54x_dev *dev, int mode) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci int r; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* turn on the regulators */ 958c2ecf20Sopenharmony_ci /* -- if the regulators were specified, they're required */ 968c2ecf20Sopenharmony_ci if (dev->pvdd_reg) { 978c2ecf20Sopenharmony_ci r = regulator_enable(dev->pvdd_reg); 988c2ecf20Sopenharmony_ci if (r < 0) { 998c2ecf20Sopenharmony_ci pr_err("%s: not able to enable pvdd\n", __func__); 1008c2ecf20Sopenharmony_ci return r; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci if (dev->vbat_reg != NULL) { 1048c2ecf20Sopenharmony_ci r = regulator_enable(dev->vbat_reg); 1058c2ecf20Sopenharmony_ci if (r < 0) { 1068c2ecf20Sopenharmony_ci pr_err("%s: not able to enable vbat\n", __func__); 1078c2ecf20Sopenharmony_ci goto enable_exit0; 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci if (dev->pmuvcc_reg != NULL) { 1118c2ecf20Sopenharmony_ci r = regulator_enable(dev->pmuvcc_reg); 1128c2ecf20Sopenharmony_ci if (r < 0) { 1138c2ecf20Sopenharmony_ci pr_err("%s: not able to enable pmuvcc\n", __func__); 1148c2ecf20Sopenharmony_ci goto enable_exit1; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci if (dev->sevdd_reg != NULL) { 1188c2ecf20Sopenharmony_ci r = regulator_enable(dev->sevdd_reg); 1198c2ecf20Sopenharmony_ci if (r < 0) { 1208c2ecf20Sopenharmony_ci pr_err("%s: not able to enable sevdd\n", __func__); 1218c2ecf20Sopenharmony_ci goto enable_exit2; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (mode == MODE_RUN) { 1268c2ecf20Sopenharmony_ci if (gpio_is_valid(dev->firm_gpio)) 1278c2ecf20Sopenharmony_ci gpio_set_value_cansleep(dev->firm_gpio, 0); 1288c2ecf20Sopenharmony_ci gpio_set_value_cansleep(dev->ven_gpio, 1); 1298c2ecf20Sopenharmony_ci msleep(100); 1308c2ecf20Sopenharmony_ci } else if (mode == MODE_FW) { 1318c2ecf20Sopenharmony_ci /* power on with firmware download (requires hw reset) 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci gpio_set_value(dev->ven_gpio, 1); 1348c2ecf20Sopenharmony_ci msleep(20); 1358c2ecf20Sopenharmony_ci if (gpio_is_valid(dev->firm_gpio)) { 1368c2ecf20Sopenharmony_ci gpio_set_value(dev->firm_gpio, 1); 1378c2ecf20Sopenharmony_ci } else { 1388c2ecf20Sopenharmony_ci pr_err("%s Unused Firm GPIO %d\n", __func__, mode); 1398c2ecf20Sopenharmony_ci return GPIO_UNUSED; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci msleep(20); 1428c2ecf20Sopenharmony_ci gpio_set_value(dev->ven_gpio, 0); 1438c2ecf20Sopenharmony_ci msleep(100); 1448c2ecf20Sopenharmony_ci gpio_set_value(dev->ven_gpio, 1); 1458c2ecf20Sopenharmony_ci msleep(20); 1468c2ecf20Sopenharmony_ci } else { 1478c2ecf20Sopenharmony_ci pr_err("%s bad arg %d\n", __func__, mode); 1488c2ecf20Sopenharmony_ci return -EINVAL; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return 0; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cienable_exit2: 1548c2ecf20Sopenharmony_ci if (dev->pmuvcc_reg) 1558c2ecf20Sopenharmony_ci regulator_disable(dev->pmuvcc_reg); 1568c2ecf20Sopenharmony_cienable_exit1: 1578c2ecf20Sopenharmony_ci if (dev->vbat_reg) 1588c2ecf20Sopenharmony_ci regulator_disable(dev->vbat_reg); 1598c2ecf20Sopenharmony_cienable_exit0: 1608c2ecf20Sopenharmony_ci if (dev->pvdd_reg) 1618c2ecf20Sopenharmony_ci regulator_disable(dev->pvdd_reg); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci return r; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic void pn544_disable(struct pn54x_dev *dev) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci /* power off */ 1698c2ecf20Sopenharmony_ci if (gpio_is_valid(dev->firm_gpio)) 1708c2ecf20Sopenharmony_ci gpio_set_value_cansleep(dev->firm_gpio, 0); 1718c2ecf20Sopenharmony_ci gpio_set_value_cansleep(dev->ven_gpio, 0); 1728c2ecf20Sopenharmony_ci msleep(100); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci if (dev->sevdd_reg) 1758c2ecf20Sopenharmony_ci regulator_disable(dev->sevdd_reg); 1768c2ecf20Sopenharmony_ci if (dev->pmuvcc_reg) 1778c2ecf20Sopenharmony_ci regulator_disable(dev->pmuvcc_reg); 1788c2ecf20Sopenharmony_ci if (dev->vbat_reg) 1798c2ecf20Sopenharmony_ci regulator_disable(dev->vbat_reg); 1808c2ecf20Sopenharmony_ci if (dev->pvdd_reg) 1818c2ecf20Sopenharmony_ci regulator_disable(dev->pvdd_reg); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci/********************************************************** 1868c2ecf20Sopenharmony_ci * driver functions 1878c2ecf20Sopenharmony_ci **********************************************************/ 1888c2ecf20Sopenharmony_cistatic ssize_t pn54x_dev_read(struct file *filp, char __user *buf, 1898c2ecf20Sopenharmony_ci size_t count, loff_t *offset) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev = filp->private_data; 1928c2ecf20Sopenharmony_ci char tmp[MAX_BUFFER_SIZE]; 1938c2ecf20Sopenharmony_ci int ret; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (count > MAX_BUFFER_SIZE) 1968c2ecf20Sopenharmony_ci count = MAX_BUFFER_SIZE; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci pr_debug("%s : reading %zu bytes.\n", __func__, count); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci mutex_lock(&pn54x_dev->read_mutex); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (!gpio_get_value(pn54x_dev->irq_gpio)) { 2038c2ecf20Sopenharmony_ci if (filp->f_flags & O_NONBLOCK) { 2048c2ecf20Sopenharmony_ci ret = -EAGAIN; 2058c2ecf20Sopenharmony_ci goto fail; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci while (1) { 2098c2ecf20Sopenharmony_ci pn54x_dev->irq_enabled = true; 2108c2ecf20Sopenharmony_ci enable_irq(pn54x_dev->client->irq); 2118c2ecf20Sopenharmony_ci ret = wait_event_interruptible( 2128c2ecf20Sopenharmony_ci pn54x_dev->read_wq, 2138c2ecf20Sopenharmony_ci !pn54x_dev->irq_enabled); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci pn54x_disable_irq(pn54x_dev); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (ret) 2188c2ecf20Sopenharmony_ci goto fail; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (gpio_get_value(pn54x_dev->irq_gpio)) 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci pr_warning("%s: spurious interrupt detected\n", __func__); 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Read data */ 2288c2ecf20Sopenharmony_ci ret = i2c_master_recv(pn54x_dev->client, tmp, count); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci mutex_unlock(&pn54x_dev->read_mutex); 2318c2ecf20Sopenharmony_ci udelay(1000); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (ret < 0) { 2348c2ecf20Sopenharmony_ci pr_err("%s: i2c_master_recv returned %d\n", __func__, ret); 2358c2ecf20Sopenharmony_ci return ret; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci if (ret > count) { 2388c2ecf20Sopenharmony_ci pr_err("%s: received too many bytes from i2c (%d)\n", 2398c2ecf20Sopenharmony_ci __func__, ret); 2408c2ecf20Sopenharmony_ci return -EIO; 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci if (copy_to_user(buf, tmp, ret)) { 2438c2ecf20Sopenharmony_ci pr_warning("%s : failed to copy to user space\n", __func__); 2448c2ecf20Sopenharmony_ci return -EFAULT; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci return ret; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cifail: 2498c2ecf20Sopenharmony_ci mutex_unlock(&pn54x_dev->read_mutex); 2508c2ecf20Sopenharmony_ci return ret; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic ssize_t pn54x_dev_write(struct file *filp, const char __user *buf, 2548c2ecf20Sopenharmony_ci size_t count, loff_t *offset) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev; 2578c2ecf20Sopenharmony_ci char tmp[MAX_BUFFER_SIZE]; 2588c2ecf20Sopenharmony_ci int ret; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci pn54x_dev = filp->private_data; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (count > MAX_BUFFER_SIZE) 2638c2ecf20Sopenharmony_ci count = MAX_BUFFER_SIZE; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (copy_from_user(tmp, buf, count)) { 2668c2ecf20Sopenharmony_ci pr_err("%s : failed to copy from user space\n", __func__); 2678c2ecf20Sopenharmony_ci return -EFAULT; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci pr_debug("%s : writing %zu bytes.\n", __func__, count); 2718c2ecf20Sopenharmony_ci /* Write data */ 2728c2ecf20Sopenharmony_ci ret = i2c_master_send(pn54x_dev->client, tmp, count); 2738c2ecf20Sopenharmony_ci if (ret != count) { 2748c2ecf20Sopenharmony_ci pr_err("%s : i2c_master_send returned %d\n", __func__, ret); 2758c2ecf20Sopenharmony_ci ret = -EIO; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci udelay(1000); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci return ret; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic int pn54x_dev_open(struct inode *inode, struct file *filp) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev = container_of(filp->private_data, 2868c2ecf20Sopenharmony_ci struct pn54x_dev, pn54x_device); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci filp->private_data = pn54x_dev; 2898c2ecf20Sopenharmony_ci pn544_enable(pn54x_dev, MODE_RUN); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci return 0; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic int pn54x_dev_release(struct inode *inode, struct file *filp) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev = filp->private_data; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci pn544_disable(pn54x_dev); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return 0; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic long pn54x_dev_ioctl(struct file *filp, unsigned int cmd, 3048c2ecf20Sopenharmony_ci unsigned long arg) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev = filp->private_data; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci switch (cmd) { 3098c2ecf20Sopenharmony_ci case PN544_SET_PWR: 3108c2ecf20Sopenharmony_ci if (arg == 2) { 3118c2ecf20Sopenharmony_ci /* power on w/FW */ 3128c2ecf20Sopenharmony_ci if (pn544_enable(pn54x_dev, arg) == GPIO_UNUSED) 3138c2ecf20Sopenharmony_ci return GPIO_UNUSED; 3148c2ecf20Sopenharmony_ci } else if (arg == 1) { 3158c2ecf20Sopenharmony_ci /* power on */ 3168c2ecf20Sopenharmony_ci pn544_enable(pn54x_dev, arg); 3178c2ecf20Sopenharmony_ci } else if (arg == 0) { 3188c2ecf20Sopenharmony_ci /* power off */ 3198c2ecf20Sopenharmony_ci pn544_disable(pn54x_dev); 3208c2ecf20Sopenharmony_ci } else { 3218c2ecf20Sopenharmony_ci pr_err("%s bad SET_PWR arg %lu\n", __func__, arg); 3228c2ecf20Sopenharmony_ci return -EINVAL; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci break; 3258c2ecf20Sopenharmony_ci case PN54X_CLK_REQ: 3268c2ecf20Sopenharmony_ci if (arg == 1) { 3278c2ecf20Sopenharmony_ci if (gpio_is_valid(pn54x_dev->clkreq_gpio)) { 3288c2ecf20Sopenharmony_ci gpio_set_value(pn54x_dev->clkreq_gpio, 1); 3298c2ecf20Sopenharmony_ci } else { 3308c2ecf20Sopenharmony_ci pr_err("%s Unused Clkreq GPIO %lu\n", __func__, arg); 3318c2ecf20Sopenharmony_ci return GPIO_UNUSED; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci } else if (arg == 0) { 3348c2ecf20Sopenharmony_ci if (gpio_is_valid(pn54x_dev->clkreq_gpio)) { 3358c2ecf20Sopenharmony_ci gpio_set_value(pn54x_dev->clkreq_gpio, 0); 3368c2ecf20Sopenharmony_ci } else { 3378c2ecf20Sopenharmony_ci pr_err("%s Unused Clkreq GPIO %lu\n", __func__, arg); 3388c2ecf20Sopenharmony_ci return GPIO_UNUSED; 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci } else { 3418c2ecf20Sopenharmony_ci pr_err("%s bad CLK_REQ arg %lu\n", __func__, arg); 3428c2ecf20Sopenharmony_ci return -EINVAL; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci break; 3458c2ecf20Sopenharmony_ci default: 3468c2ecf20Sopenharmony_ci pr_err("%s bad ioctl %u\n", __func__, cmd); 3478c2ecf20Sopenharmony_ci return -EINVAL; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return 0; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic const struct file_operations pn54x_dev_fops = { 3548c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3558c2ecf20Sopenharmony_ci .llseek = no_llseek, 3568c2ecf20Sopenharmony_ci .read = pn54x_dev_read, 3578c2ecf20Sopenharmony_ci .write = pn54x_dev_write, 3588c2ecf20Sopenharmony_ci .open = pn54x_dev_open, 3598c2ecf20Sopenharmony_ci .release = pn54x_dev_release, 3608c2ecf20Sopenharmony_ci .unlocked_ioctl = pn54x_dev_ioctl, 3618c2ecf20Sopenharmony_ci}; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci/* 3658c2ecf20Sopenharmony_ci * Handlers for alternative sources of platform_data 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 3688c2ecf20Sopenharmony_ci/* 3698c2ecf20Sopenharmony_ci * Translate OpenFirmware node properties into platform_data 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_cistatic int pn54x_get_pdata(struct device *dev, struct pn544_i2c_platform_data *pdata) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci struct device_node *node; 3748c2ecf20Sopenharmony_ci u32 flags; 3758c2ecf20Sopenharmony_ci int val; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci /* make sure there is actually a device tree node */ 3788c2ecf20Sopenharmony_ci node = dev->of_node; 3798c2ecf20Sopenharmony_ci if (!node) 3808c2ecf20Sopenharmony_ci return -ENODEV; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci memset(pdata, 0, sizeof(*pdata)); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci /* read the dev tree data */ 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci /* ven pin - enable's power to the chip - REQUIRED */ 3878c2ecf20Sopenharmony_ci val = of_get_named_gpio_flags(node, "enable-gpios", 0, &flags); 3888c2ecf20Sopenharmony_ci if (val < 0) { 3898c2ecf20Sopenharmony_ci dev_err(dev, "VEN GPIO error getting from OF node\n"); 3908c2ecf20Sopenharmony_ci return val; 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci pdata->ven_gpio = val; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* firm pin - controls firmware download - OPTIONAL */ 3958c2ecf20Sopenharmony_ci val = of_get_named_gpio_flags(node, "firmware-gpios", 0, &flags); 3968c2ecf20Sopenharmony_ci if (val < 0) { 3978c2ecf20Sopenharmony_ci dev_err(dev, "VEN GPIO error getting from OF node\n"); 3988c2ecf20Sopenharmony_ci return val; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci pdata->firm_gpio = val; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* irq pin - data available irq - REQUIRED */ 4038c2ecf20Sopenharmony_ci val = of_get_named_gpio_flags(node, "interrupt-gpios", 0, &flags); 4048c2ecf20Sopenharmony_ci if (val < 0) { 4058c2ecf20Sopenharmony_ci dev_err(dev, "VEN GPIO error getting from OF node\n"); 4068c2ecf20Sopenharmony_ci return val; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci pdata->irq_gpio = val; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* clkreq pin - controls the clock to the PN547 - OPTIONAL */ 4118c2ecf20Sopenharmony_ci val = of_get_named_gpio_flags(node, "nxp,pn54x-clkreq", 0, &flags); 4128c2ecf20Sopenharmony_ci if (val < 0) { 4138c2ecf20Sopenharmony_ci dev_err(dev, "VEN GPIO error getting from OF node\n"); 4148c2ecf20Sopenharmony_ci return val; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci pdata->clkreq_gpio = val; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci /* handle the regulator lines - these are optional 4198c2ecf20Sopenharmony_ci * PVdd - pad Vdd (544, 547) 4208c2ecf20Sopenharmony_ci * Vbat - Battery (544, 547) 4218c2ecf20Sopenharmony_ci * PMUVcc - UICC Power (544, 547) 4228c2ecf20Sopenharmony_ci * SEVdd - SE Power (544) 4238c2ecf20Sopenharmony_ci * 4248c2ecf20Sopenharmony_ci * Will attempt to load a matching Regulator Resource for each 4258c2ecf20Sopenharmony_ci * If no resource is provided, then the input will not be controlled 4268c2ecf20Sopenharmony_ci * Example: if only PVdd is provided, it is the only one that will be 4278c2ecf20Sopenharmony_ci * turned on/off. 4288c2ecf20Sopenharmony_ci */ 4298c2ecf20Sopenharmony_ci pdata->pvdd_reg = regulator_get(dev, "nxp,pn54x-pvdd"); 4308c2ecf20Sopenharmony_ci if (IS_ERR(pdata->pvdd_reg)) { 4318c2ecf20Sopenharmony_ci pr_err("%s: could not get nxp,pn54x-pvdd, rc=%ld\n", __func__, PTR_ERR(pdata->pvdd_reg)); 4328c2ecf20Sopenharmony_ci pdata->pvdd_reg = NULL; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci pdata->vbat_reg = regulator_get(dev, "nxp,pn54x-vbat"); 4368c2ecf20Sopenharmony_ci if (IS_ERR(pdata->vbat_reg)) { 4378c2ecf20Sopenharmony_ci pr_err("%s: could not get nxp,pn54x-vbat, rc=%ld\n", __func__, PTR_ERR(pdata->vbat_reg)); 4388c2ecf20Sopenharmony_ci pdata->vbat_reg = NULL; 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci pdata->pmuvcc_reg = regulator_get(dev, "nxp,pn54x-pmuvcc"); 4428c2ecf20Sopenharmony_ci if (IS_ERR(pdata->pmuvcc_reg)) { 4438c2ecf20Sopenharmony_ci pr_err("%s: could not get nxp,pn54x-pmuvcc, rc=%ld\n", __func__, PTR_ERR(pdata->pmuvcc_reg)); 4448c2ecf20Sopenharmony_ci pdata->pmuvcc_reg = NULL; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci pdata->sevdd_reg = regulator_get(dev, "nxp,pn54x-sevdd"); 4488c2ecf20Sopenharmony_ci if (IS_ERR(pdata->sevdd_reg)) { 4498c2ecf20Sopenharmony_ci pr_err("%s: could not get nxp,pn54x-sevdd, rc=%ld\n", __func__, PTR_ERR(pdata->sevdd_reg)); 4508c2ecf20Sopenharmony_ci pdata->sevdd_reg = NULL; 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci return 0; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci#else 4568c2ecf20Sopenharmony_cistatic int pn54x_get_pdata(struct device *dev, struct pn544_i2c_platform_data *pdata) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci pdata = dev->platform_data; 4598c2ecf20Sopenharmony_ci return 0; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci#endif 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci/* 4658c2ecf20Sopenharmony_ci * pn54x_probe 4668c2ecf20Sopenharmony_ci */ 4678c2ecf20Sopenharmony_cistatic int pn54x_probe(struct i2c_client *client, 4688c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci int ret; 4718c2ecf20Sopenharmony_ci struct pn544_i2c_platform_data *pdata; // gpio values, from board file or DT 4728c2ecf20Sopenharmony_ci struct pn544_i2c_platform_data tmp_pdata; 4738c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev; // internal device specific data 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci /* ---- retrieve the platform data ---- */ 4768c2ecf20Sopenharmony_ci /* If the dev.platform_data is NULL, then */ 4778c2ecf20Sopenharmony_ci /* attempt to read from the device tree */ 4788c2ecf20Sopenharmony_ci if (!client->dev.platform_data) { 4798c2ecf20Sopenharmony_ci ret = pn54x_get_pdata(&(client->dev), &tmp_pdata); 4808c2ecf20Sopenharmony_ci if (ret) 4818c2ecf20Sopenharmony_ci return ret; 4828c2ecf20Sopenharmony_ci pdata = &tmp_pdata; 4838c2ecf20Sopenharmony_ci } else { 4848c2ecf20Sopenharmony_ci pdata = client->dev.platform_data; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (pdata == NULL) { 4888c2ecf20Sopenharmony_ci pr_err("%s : nfc probe fail\n", __func__); 4898c2ecf20Sopenharmony_ci return -ENODEV; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci /* validate the adapter has basic I2C functionality */ 4938c2ecf20Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 4948c2ecf20Sopenharmony_ci pr_err("%s : need I2C_FUNC_I2C\n", __func__); 4958c2ecf20Sopenharmony_ci return -ENODEV; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci /* reserve the GPIO pins */ 4998c2ecf20Sopenharmony_ci ret = gpio_request(pdata->irq_gpio, "nfc_int"); 5008c2ecf20Sopenharmony_ci if (ret) { 5018c2ecf20Sopenharmony_ci pr_err("%s :not able to get GPIO irq_gpio\n", __func__); 5028c2ecf20Sopenharmony_ci return -ENODEV; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci ret = gpio_to_irq(pdata->irq_gpio); 5058c2ecf20Sopenharmony_ci if (ret < 0) { 5068c2ecf20Sopenharmony_ci pr_err("%s :not able to map GPIO irq_gpio to an IRQ\n", __func__); 5078c2ecf20Sopenharmony_ci goto err_ven; 5088c2ecf20Sopenharmony_ci } else { 5098c2ecf20Sopenharmony_ci client->irq = ret; 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci ret = gpio_request(pdata->ven_gpio, "nfc_ven"); 5138c2ecf20Sopenharmony_ci if (ret) { 5148c2ecf20Sopenharmony_ci pr_err("%s :not able to get GPIO ven_gpio\n", __func__); 5158c2ecf20Sopenharmony_ci goto err_ven; 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci if (gpio_is_valid(pdata->firm_gpio)) { 5198c2ecf20Sopenharmony_ci ret = gpio_request(pdata->firm_gpio, "nfc_firm"); 5208c2ecf20Sopenharmony_ci if (ret) { 5218c2ecf20Sopenharmony_ci pr_err("%s :not able to get GPIO firm_gpio\n", __func__); 5228c2ecf20Sopenharmony_ci goto err_firm; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci if (gpio_is_valid(pdata->clkreq_gpio)) { 5278c2ecf20Sopenharmony_ci ret = gpio_request(pdata->clkreq_gpio, "nfc_clkreq"); 5288c2ecf20Sopenharmony_ci if (ret) { 5298c2ecf20Sopenharmony_ci pr_err("%s :not able to get GPIO clkreq_gpio\n", __func__); 5308c2ecf20Sopenharmony_ci goto err_clkreq; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci /* allocate the pn54x driver information structure */ 5358c2ecf20Sopenharmony_ci pn54x_dev = kzalloc(sizeof(*pn54x_dev), GFP_KERNEL); 5368c2ecf20Sopenharmony_ci if (pn54x_dev == NULL) { 5378c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to allocate memory for module data\n"); 5388c2ecf20Sopenharmony_ci ret = -ENOMEM; 5398c2ecf20Sopenharmony_ci goto err_exit; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci /* store the platform data in the driver info struct */ 5438c2ecf20Sopenharmony_ci pn54x_dev->irq_gpio = pdata->irq_gpio; 5448c2ecf20Sopenharmony_ci pn54x_dev->ven_gpio = pdata->ven_gpio; 5458c2ecf20Sopenharmony_ci pn54x_dev->firm_gpio = pdata->firm_gpio; 5468c2ecf20Sopenharmony_ci pn54x_dev->clkreq_gpio = pdata->clkreq_gpio; 5478c2ecf20Sopenharmony_ci pn54x_dev->pvdd_reg = pdata->pvdd_reg; 5488c2ecf20Sopenharmony_ci pn54x_dev->vbat_reg = pdata->vbat_reg; 5498c2ecf20Sopenharmony_ci pn54x_dev->pmuvcc_reg = pdata->pmuvcc_reg; 5508c2ecf20Sopenharmony_ci pn54x_dev->sevdd_reg = pdata->sevdd_reg; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci pn54x_dev->client = client; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* finish configuring the I/O */ 5558c2ecf20Sopenharmony_ci ret = gpio_direction_input(pn54x_dev->irq_gpio); 5568c2ecf20Sopenharmony_ci if (ret < 0) { 5578c2ecf20Sopenharmony_ci pr_err("%s :not able to set irq_gpio as input\n", __func__); 5588c2ecf20Sopenharmony_ci goto err_free; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci ret = gpio_direction_output(pn54x_dev->ven_gpio, 0); 5628c2ecf20Sopenharmony_ci if (ret < 0) { 5638c2ecf20Sopenharmony_ci pr_err("%s : not able to set ven_gpio as output\n", __func__); 5648c2ecf20Sopenharmony_ci goto err_exit; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci if (gpio_is_valid(pn54x_dev->firm_gpio)) { 5688c2ecf20Sopenharmony_ci ret = gpio_direction_output(pn54x_dev->firm_gpio, 0); 5698c2ecf20Sopenharmony_ci if (ret < 0) { 5708c2ecf20Sopenharmony_ci pr_err("%s : not able to set firm_gpio as output\n", 5718c2ecf20Sopenharmony_ci __func__); 5728c2ecf20Sopenharmony_ci goto err_exit; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (gpio_is_valid(pn54x_dev->clkreq_gpio)) { 5778c2ecf20Sopenharmony_ci ret = gpio_direction_output(pn54x_dev->clkreq_gpio, 0); 5788c2ecf20Sopenharmony_ci if (ret < 0) { 5798c2ecf20Sopenharmony_ci pr_err("%s : not able to set clkreq_gpio as output\n", 5808c2ecf20Sopenharmony_ci __func__); 5818c2ecf20Sopenharmony_ci goto err_exit; 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci /* init mutex and queues */ 5868c2ecf20Sopenharmony_ci init_waitqueue_head(&pn54x_dev->read_wq); 5878c2ecf20Sopenharmony_ci mutex_init(&pn54x_dev->read_mutex); 5888c2ecf20Sopenharmony_ci spin_lock_init(&pn54x_dev->irq_enabled_lock); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci /* register as a misc device - character based with one entry point */ 5918c2ecf20Sopenharmony_ci pn54x_dev->pn54x_device.minor = MISC_DYNAMIC_MINOR; 5928c2ecf20Sopenharmony_ci pn54x_dev->pn54x_device.name = CHIP; 5938c2ecf20Sopenharmony_ci pn54x_dev->pn54x_device.fops = &pn54x_dev_fops; 5948c2ecf20Sopenharmony_ci ret = misc_register(&pn54x_dev->pn54x_device); 5958c2ecf20Sopenharmony_ci if (ret) { 5968c2ecf20Sopenharmony_ci pr_err("%s : misc_register failed\n", __FILE__); 5978c2ecf20Sopenharmony_ci goto err_misc_register; 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci /* request irq. the irq is set whenever the chip has data available 6018c2ecf20Sopenharmony_ci * for reading. it is cleared when all data has been read. 6028c2ecf20Sopenharmony_ci */ 6038c2ecf20Sopenharmony_ci pn54x_dev->irq_enabled = true; 6048c2ecf20Sopenharmony_ci ret = request_irq(client->irq, pn54x_dev_irq_handler, 6058c2ecf20Sopenharmony_ci IRQF_TRIGGER_HIGH, client->name, pn54x_dev); 6068c2ecf20Sopenharmony_ci if (ret) { 6078c2ecf20Sopenharmony_ci dev_err(&client->dev, "request_irq failed\n"); 6088c2ecf20Sopenharmony_ci goto err_request_irq_failed; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci pn54x_disable_irq(pn54x_dev); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci i2c_set_clientdata(client, pn54x_dev); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci return 0; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_cierr_request_irq_failed: 6178c2ecf20Sopenharmony_ci misc_deregister(&pn54x_dev->pn54x_device); 6188c2ecf20Sopenharmony_cierr_misc_register: 6198c2ecf20Sopenharmony_cierr_free: 6208c2ecf20Sopenharmony_ci kfree(pn54x_dev); 6218c2ecf20Sopenharmony_cierr_exit: 6228c2ecf20Sopenharmony_ci if (gpio_is_valid(pdata->clkreq_gpio)) 6238c2ecf20Sopenharmony_ci gpio_free(pdata->clkreq_gpio); 6248c2ecf20Sopenharmony_cierr_clkreq: 6258c2ecf20Sopenharmony_ci if (gpio_is_valid(pdata->firm_gpio)) 6268c2ecf20Sopenharmony_ci gpio_free(pdata->firm_gpio); 6278c2ecf20Sopenharmony_cierr_firm: 6288c2ecf20Sopenharmony_ci gpio_free(pdata->ven_gpio); 6298c2ecf20Sopenharmony_cierr_ven: 6308c2ecf20Sopenharmony_ci gpio_free(pdata->irq_gpio); 6318c2ecf20Sopenharmony_ci return ret; 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_cistatic int pn54x_remove(struct i2c_client *client) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci struct pn54x_dev *pn54x_dev; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci pn54x_dev = i2c_get_clientdata(client); 6398c2ecf20Sopenharmony_ci free_irq(client->irq, pn54x_dev); 6408c2ecf20Sopenharmony_ci misc_deregister(&pn54x_dev->pn54x_device); 6418c2ecf20Sopenharmony_ci mutex_destroy(&pn54x_dev->read_mutex); 6428c2ecf20Sopenharmony_ci gpio_free(pn54x_dev->irq_gpio); 6438c2ecf20Sopenharmony_ci gpio_free(pn54x_dev->ven_gpio); 6448c2ecf20Sopenharmony_ci if (gpio_is_valid(pn54x_dev->firm_gpio)) 6458c2ecf20Sopenharmony_ci gpio_free(pn54x_dev->firm_gpio); 6468c2ecf20Sopenharmony_ci if (gpio_is_valid(pn54x_dev->clkreq_gpio)) 6478c2ecf20Sopenharmony_ci gpio_free(pn54x_dev->clkreq_gpio); 6488c2ecf20Sopenharmony_ci regulator_put(pn54x_dev->pvdd_reg); 6498c2ecf20Sopenharmony_ci regulator_put(pn54x_dev->vbat_reg); 6508c2ecf20Sopenharmony_ci regulator_put(pn54x_dev->pmuvcc_reg); 6518c2ecf20Sopenharmony_ci regulator_put(pn54x_dev->sevdd_reg); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci kfree(pn54x_dev); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci return 0; 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci/* 6598c2ecf20Sopenharmony_ci * 6608c2ecf20Sopenharmony_ci */ 6618c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 6628c2ecf20Sopenharmony_cistatic struct of_device_id pn54x_dt_match[] = { 6638c2ecf20Sopenharmony_ci { .compatible = "nxp,pn547", }, 6648c2ecf20Sopenharmony_ci { .compatible = "nxp,pn544", }, 6658c2ecf20Sopenharmony_ci { .compatible = "nxp,pn7150", }, 6668c2ecf20Sopenharmony_ci {}, 6678c2ecf20Sopenharmony_ci}; 6688c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pn54x_dt_match); 6698c2ecf20Sopenharmony_ci#endif 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic const struct i2c_device_id pn54x_id[] = { 6728c2ecf20Sopenharmony_ci { "pn547", 0 }, 6738c2ecf20Sopenharmony_ci { }, 6748c2ecf20Sopenharmony_ci}; 6758c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pn54x_id); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_cistatic struct i2c_driver pn54x_driver = { 6788c2ecf20Sopenharmony_ci .id_table = pn54x_id, 6798c2ecf20Sopenharmony_ci .probe = pn54x_probe, 6808c2ecf20Sopenharmony_ci .remove = pn54x_remove, 6818c2ecf20Sopenharmony_ci .driver = { 6828c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6838c2ecf20Sopenharmony_ci .name = "pn544", 6848c2ecf20Sopenharmony_ci .of_match_table = pn54x_dt_match, 6858c2ecf20Sopenharmony_ci }, 6868c2ecf20Sopenharmony_ci}; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci/* 6898c2ecf20Sopenharmony_ci * module load/unload record keeping 6908c2ecf20Sopenharmony_ci */ 6918c2ecf20Sopenharmony_cimodule_i2c_driver(pn54x_driver); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sylvain Fonteneau"); 6948c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 6958c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 696