mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
85baa390bf
* Samsung Package Version: G800HXXU1CRJ1 * CAF Tag: LA.BF.1.1.3-00110-8x26.0
5494 lines
137 KiB
C
5494 lines
137 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifdef CONFIG_FELICA
|
|
#include "felica.h"
|
|
#include <linux/init.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/device.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/termios.h>
|
|
#include <linux/serial_core.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#ifdef F_WAKE_LOCK
|
|
#include <linux/wakelock.h>
|
|
#endif
|
|
|
|
#include <linux/types.h>
|
|
|
|
/* jmodel */
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
#include <mach/smc.h>
|
|
#elif defined(CONFIG_ARCH_APQ8064) || defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#include <mach/scm.h>
|
|
#endif
|
|
|
|
#include <asm/system_info.h>
|
|
#include <linux/of_gpio.h>
|
|
#include <linux/mfd/pm8xxx/gpio.h>
|
|
|
|
|
|
/******************************************************************************
|
|
* log
|
|
******************************************************************************/
|
|
#include <mach/sec_debug.h>
|
|
#define NO_CHECK_TAMPER
|
|
#define SRIB_DIAG_ENABLED
|
|
|
|
/******************************************************************************
|
|
* Board configuration
|
|
******************************************************************************/
|
|
/* jmodel */
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
#define FELICA_UART1RX EXYNOS5410_GPA0(4)
|
|
#endif
|
|
|
|
/* Hmodel */
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if !defined(CONFIG_MACH_KLTE_KDI) && !defined(CONFIG_MACH_KLTE_DCM) && !defined(CONFIG_MACH_KLTE_SBM)
|
|
static int gfelica_irq_int_pin = -1;
|
|
#endif
|
|
static struct platform_device *felica_gpio_pdev;
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
static int g_uicc_initrev = 7; //HW Rev 0.9
|
|
static int gfelica_sps_pin = 130; //Select Power Supply
|
|
static int gfelica_hsel_pin = GPIO_PINID_NFC_HSEL;
|
|
#define HW_REV09_OR_10 7 // to fix hltedcm i2c h/w issue in REV 09/10.
|
|
extern void of_sii8240_hw_poweron(bool enable); // to fix hltedcm i2c h/w issue in REV 09/10. Defined in driver/video/msm/mhl_v2/sii8240.c
|
|
/* K MODEL */
|
|
#elif defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
static int gfelica_sps_pin = -1; //Select Power Supply
|
|
static int gfelica_pon_pin = GPIO_FELICA_PON_REV06; // PON
|
|
static int gfelica_hsel_pin = -1;
|
|
static int g_uicc_initrev = 0;
|
|
//#define NO_CHECK_TAMPER
|
|
//#define SRIB_DIAG_ENABLED
|
|
#elif defined(CONFIG_MACH_KLTE_KDI)
|
|
static int gfelica_pon_pin = GPIO_FELICA_PON_REV06; // PON
|
|
static int gfelica_hsel_pin = -1;
|
|
static int gfelica_sps_pin = -1;
|
|
static int g_uicc_initrev = 0;
|
|
static int gfelica_uim_mon = 0;
|
|
//#define NO_CHECK_TAMPER
|
|
//#define SRIB_DIAG_ENABLED
|
|
#elif defined(CONFIG_MACH_HLTEKDI)
|
|
static int g_uicc_initrev = 4;
|
|
static int gfelica_sps_pin = -1;
|
|
static int gfelica_hsel_pin = GPIO_PINID_NFC_HSEL;
|
|
#elif defined(CONFIG_MACH_JS01LTEDCM)
|
|
static int g_uicc_initrev = 8; // HW Rev 0.4
|
|
static int gfelica_sps_pin = 130; // Select Power Supply
|
|
static int gfelica_hsel_pin = GPIO_PINID_NFC_HSEL;
|
|
#endif
|
|
#endif /* CONFIG_ARCH_MSM8974 */
|
|
|
|
/******************************************************************************
|
|
* global variable
|
|
******************************************************************************/
|
|
static struct class *felica_class;
|
|
|
|
#ifdef F_WAKE_LOCK
|
|
struct wake_lock felica_wake_1;
|
|
struct wake_lock felica_wake_2;
|
|
static int tmout_1 = 3*1000; // wake lock timeout for INT irq.
|
|
#endif
|
|
|
|
/* storages for communicate to netlink */
|
|
static int gfa_open_cnt;
|
|
static int gfa_pid;
|
|
static int gfa_connect_flag;
|
|
static struct sock *gfanl_sk;
|
|
static char gfa_send_str[FELICA_NL_MSG_SIZE];
|
|
static char gfa_rcv_str[FELICA_NL_MSG_SIZE];
|
|
static int gfa_wait_flag;
|
|
|
|
/* R/W functions availability information storage */
|
|
static char gfelica_rw_status;
|
|
|
|
/* IRQ data storage for INT terminal monitoring */
|
|
struct felica_int_irqdata {
|
|
struct delayed_work work;
|
|
wait_queue_head_t read_wait;
|
|
int irq_done;
|
|
int open_flag;
|
|
};
|
|
static struct felica_int_irqdata gint_irq;
|
|
static struct felica_int_irqdata *pgint_irq = &gint_irq;
|
|
|
|
/* storages for access restriction */
|
|
static uid_t gmfc_uid = -1;
|
|
static uid_t gmfl_uid = -1;
|
|
static uid_t grwm_uid = -1;
|
|
static uid_t gdiag_uid = -1;
|
|
#ifdef CONFIG_NFC_FELICA
|
|
static uid_t gnfc_uid = -1;
|
|
struct file *pg_tty;
|
|
static int gnfc_open_cnt;
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
/* package name's storage for access restriction */
|
|
static char gdiag_name[DIAG_NAME_MAXSIZE + 1];
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
static char gproc_name[PROC_NAME_MAXSIZE + 1];
|
|
#endif
|
|
static uid_t gant_uid = -1;
|
|
static int gi2c_address;
|
|
static char gi2c_antaddress;
|
|
static char gi2c_lockaddress;
|
|
static struct i2c_msg gread_msgs[] = {
|
|
{
|
|
.addr = 0,
|
|
.flags = 0,
|
|
.len = 0,
|
|
.buf = NULL,
|
|
},
|
|
{
|
|
.addr = 0,
|
|
.flags = 0,
|
|
.len = 0,
|
|
.buf = NULL,
|
|
},
|
|
};
|
|
|
|
static struct i2c_msg gwrite_msgs[] = {
|
|
{
|
|
.addr = 0,
|
|
.flags = 0,
|
|
.len = 0,
|
|
.buf = NULL,
|
|
},
|
|
};
|
|
|
|
#ifdef CONFIG_NFC_FELICA
|
|
/******************************************************************************
|
|
* Add global variable
|
|
******************************************************************************/
|
|
struct icc_poll_data {
|
|
wait_queue_head_t read_wait;
|
|
wait_queue_head_t rsp_wait;
|
|
wait_queue_head_t dummy_wait;
|
|
|
|
int handler_done;
|
|
int rsp_done;
|
|
struct delayed_work work;
|
|
int device_status;
|
|
int read_error;
|
|
int open_flag;
|
|
int available_flag;
|
|
};
|
|
|
|
struct poll_data {
|
|
wait_queue_head_t read_wait;
|
|
int irq_handler_done;
|
|
struct delayed_work work;
|
|
int device_status;
|
|
int read_error;
|
|
int open_flag;
|
|
};
|
|
|
|
static struct icc_poll_data gfelica_poll_data;
|
|
static struct icc_poll_data g_available_data;
|
|
static struct icc_poll_data *available_d = &g_available_data;
|
|
|
|
static int guartcc_start_req = UARTCC_NFC_START_ENDPROC;
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
static int guartcc_felica_status = UARTCC_FELICA_STATAUS_IN_INIT;
|
|
#else
|
|
static int guartcc_felica_status = UARTCC_FELICA_STATAUS_IDLE;
|
|
#endif
|
|
static int g_cen_sts = 0;
|
|
static int g_rfs_sts = 0;
|
|
static char g_uicc_sts = 0x00; // permissive mode issue
|
|
|
|
static int felica_varying_gpio_intu;
|
|
#ifdef P2P_FPGA_ALWAYS_ON
|
|
extern void set_fpga_felica_flag(int on);
|
|
#endif /* P2P_FPGA_ALWAYS_ON */
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/felica
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static int felica_uart_port;
|
|
|
|
static dev_t devid_felica_uart;
|
|
static struct cdev cdev_felica_uart;
|
|
static const struct file_operations fops_felica_uart = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_uart_open,
|
|
.release = felica_uart_close,
|
|
.read = felica_uart_read,
|
|
.write = felica_uart_write,
|
|
.fsync = felica_uart_sync,
|
|
.unlocked_ioctl = felica_uart_ioctl,
|
|
};
|
|
struct felica_sem_data {
|
|
struct semaphore felica_sem;
|
|
};
|
|
static struct felica_sem_data *dev_sem;
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void felica_uart_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_uart;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_uart = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_uart, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_UART_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_uart, &fops_felica_uart);
|
|
ret =
|
|
cdev_add(&cdev_felica_uart, devid_felica_uart, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_uart, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_uart =
|
|
device_create(felica_class, NULL, devid_felica_uart, NULL,
|
|
FELICA_UART_NAME);
|
|
if (IS_ERR(device_felica_uart)) {
|
|
cdev_del(&cdev_felica_uart);
|
|
unregister_chrdev_region(devid_felica_uart, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
dev_sem = kmalloc(sizeof(struct felica_sem_data), GFP_KERNEL);
|
|
if (!dev_sem) {
|
|
cdev_del(&cdev_felica_uart);
|
|
unregister_chrdev_region(devid_felica_uart, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(dev_sem malloc)", __func__);
|
|
return;
|
|
}
|
|
sema_init(&dev_sem->felica_sem, 1);
|
|
|
|
#ifdef CONFIG_NFC_FELICA
|
|
memset((void *)&gfelica_poll_data, 0x00, sizeof(struct icc_poll_data));
|
|
init_waitqueue_head(&gfelica_poll_data.rsp_wait);
|
|
gfelica_poll_data.rsp_done = 0;
|
|
gfelica_poll_data.open_flag = 0;
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_felica_uart), MINOR(devid_felica_uart));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void felica_uart_exit(void)
|
|
{
|
|
kfree(dev_sem);
|
|
device_destroy(felica_class, devid_felica_uart);
|
|
cdev_del(&cdev_felica_uart);
|
|
unregister_chrdev_region(devid_felica_uart, FELICA_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_uart_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
int ret;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
|
|
uid = __task_cred(current)->uid;
|
|
if ((uid != gmfc_uid) && (uid != gdiag_uid) && (uid != gant_uid)) {
|
|
FELICA_PR_ERR
|
|
(" %s END -EACCESS, uid=[%d], gmfc_uid=[%d], gdiag_uid=[%d]",
|
|
__func__, uid, gmfc_uid, gdiag_uid);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(" %s ERROR(down_interruptible)", \
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
if (gfa_open_cnt == 0) {
|
|
#ifdef CONFIG_NFC_FELICA
|
|
switch (guartcc_start_req) {
|
|
case UARTCC_NFC_START_AUTOPOLLING: /* AutoPoiing */
|
|
{
|
|
/* felica open-waiting for nfc autopolling */
|
|
ret = felica_uart_open_wait_for_polling();
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR( \
|
|
" %s open-waiting fail= [%d]\n " \
|
|
, __func__, ret);
|
|
return ret;
|
|
}
|
|
FELICA_PR_INFO( \
|
|
" %s open wait release\n", \
|
|
__func__);
|
|
}
|
|
break;
|
|
case UARTCC_NFC_START_ENDPROC: /* Unused NFC */
|
|
/* set felica status -> in use */
|
|
uartcc_set_felica_status(UARTCC_FELICA_STATAUS_IN_USE);
|
|
FELICA_PR_INFO( \
|
|
" %s started using FeliCa=[%d]\n", \
|
|
__func__, guartcc_start_req);
|
|
break;
|
|
default: /* NFC in use */
|
|
FELICA_PR_ERR(" -EFAULT %s NFC in use=[%d]\n", \
|
|
__func__, guartcc_start_req);
|
|
/* reset felica status -> idle */
|
|
uartcc_set_felica_status(
|
|
UARTCC_FELICA_STATAUS_IDLE);
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
break;
|
|
}
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
memset(gfa_send_str, 0, FELICA_NL_MSG_SIZE);
|
|
memset(gfa_rcv_str, 0, FELICA_NL_MSG_SIZE);
|
|
gfa_send_str[0] = FELICA_NL_REQ_OPEN;
|
|
gfa_send_str[1] = felica_uart_port;
|
|
|
|
ret = felica_nl_send_msg(2);
|
|
|
|
if (ret == 0) {
|
|
felica_nl_wait_ret_msg();
|
|
if (gfa_rcv_str[1] == FELICA_NL_EFAILED) {
|
|
FELICA_PR_ERR(" %s Open Fail", __func__);
|
|
#ifdef CONFIG_NFC_FELICA
|
|
/* reset felica status -> idle */
|
|
uartcc_set_felica_status(
|
|
UARTCC_FELICA_STATAUS_IDLE);
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
} else {
|
|
FELICA_PR_ERR(" %s felica_nl_send_msg Fail", \
|
|
__func__);
|
|
#ifdef CONFIG_NFC_FELICA
|
|
/* reset felica status -> idle */
|
|
uartcc_set_felica_status(
|
|
UARTCC_FELICA_STATAUS_IDLE);
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
#ifdef F_WAKE_LOCK
|
|
wake_lock(&felica_wake_2);
|
|
FELICA_PR_INFO(" %s Wake Lock(2)", __func__);
|
|
#endif
|
|
}
|
|
gfa_open_cnt++;
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_NFC_FELICA
|
|
/*
|
|
* felica open-waiting for nfc autopolling
|
|
*/
|
|
static int felica_uart_open_wait_for_polling(void)
|
|
{
|
|
int ret = 0;
|
|
struct icc_poll_data *felica_poll = &gfelica_poll_data;
|
|
|
|
FELICA_PR_DBG(" %s START\n", __func__);
|
|
|
|
/* set felica status -> wait polling */
|
|
uartcc_set_felica_status(UARTCC_FELICA_STATAUS_WAIT_POLLING);
|
|
up(&dev_sem->felica_sem);
|
|
ret = wait_event_interruptible(felica_poll->rsp_wait,
|
|
felica_poll->rsp_done == 1);
|
|
|
|
if (ret < 0) {
|
|
/* reset felica status -> idle */
|
|
uartcc_set_felica_status(UARTCC_FELICA_STATAUS_IDLE);
|
|
FELICA_PR_ERR
|
|
(" %s ERROR(wait_event_interruptible), ret=[%d]\n", \
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
/* reset felica status -> idle */
|
|
uartcc_set_felica_status(UARTCC_FELICA_STATAUS_IDLE);
|
|
FELICA_PR_ERR(" %s ERROR(down_interruptible)\n", \
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
/* set felica status -> in use */
|
|
uartcc_set_felica_status(UARTCC_FELICA_STATAUS_IN_USE);
|
|
felica_poll->rsp_done = 0;
|
|
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_uart_close(struct inode *inode, struct file *file)
|
|
{
|
|
int ret;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(" %s ERROR(down_interruptible)", \
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
gfa_open_cnt--;
|
|
if (gfa_open_cnt == 0) {
|
|
memset(gfa_send_str, 0, FELICA_NL_MSG_SIZE);
|
|
memset(gfa_rcv_str, 0, FELICA_NL_MSG_SIZE);
|
|
gfa_send_str[0] = FELICA_NL_REQ_CLOSE;
|
|
ret = felica_nl_send_msg(1);
|
|
if (ret == 0) {
|
|
felica_nl_wait_ret_msg();
|
|
if (gfa_rcv_str[1] == FELICA_NL_EFAILED) {
|
|
FELICA_PR_ERR(" %s Close Fail",\
|
|
__func__);
|
|
gfa_open_cnt++;
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
#ifdef CONFIG_NFC_FELICA
|
|
/* set felica status -> idle */
|
|
uartcc_set_felica_status(UARTCC_FELICA_STATAUS_IDLE);
|
|
if (1 == available_d->available_flag) {
|
|
if (0 != g_cen_sts) {
|
|
if (GPIO_VALUE_LOW != g_rfs_sts) {
|
|
available_d->rsp_done = 1;
|
|
FELICA_PR_INFO(
|
|
" wake up available");
|
|
wake_up_interruptible(
|
|
&available_d->read_wait);
|
|
}
|
|
}
|
|
}
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
} else {
|
|
FELICA_PR_ERR(" %s felica_nl_send_msg Fail", \
|
|
__func__);
|
|
gfa_open_cnt++;
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
#ifdef F_WAKE_LOCK
|
|
wake_unlock(&felica_wake_2);
|
|
FELICA_PR_INFO(" %s Wake UnLock(2)", __func__);
|
|
#endif
|
|
}
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t felica_uart_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret = 0;
|
|
int nlret;
|
|
size_t wk_len = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(" %s ERROR(down_interruptible)", \
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
memset(gfa_send_str, 0, FELICA_NL_MSG_SIZE);
|
|
memset(gfa_rcv_str, 0, FELICA_NL_MSG_SIZE);
|
|
|
|
wk_len = len;
|
|
if (FELICA_NL_MSG_DATA_SIZE < wk_len) {
|
|
FELICA_PR_INFO(" %s read max size over [%d]", __func__,
|
|
wk_len);
|
|
wk_len = FELICA_NL_MSG_DATA_SIZE;
|
|
}
|
|
gfa_send_str[0] = FELICA_NL_REQ_READ;
|
|
gfa_send_str[1] = (char)(wk_len >> 8);
|
|
gfa_send_str[2] = (char)wk_len;
|
|
nlret = felica_nl_send_msg(3);
|
|
|
|
wk_len = 0;
|
|
if (nlret == 0) {
|
|
felica_nl_wait_ret_msg();
|
|
if (gfa_rcv_str[1] == FELICA_NL_SUCCESS) {
|
|
wk_len =
|
|
(((int)gfa_rcv_str[2] << 8) & 0xFF00) | \
|
|
(int)gfa_rcv_str[3];
|
|
FELICA_PR_DBG(" %s Rcv len [%d]", __func__, wk_len);
|
|
FELICA_PR_DBG(
|
|
" %s Rcv data [%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]",
|
|
__func__, gfa_rcv_str[4], gfa_rcv_str[5],
|
|
gfa_rcv_str[6], gfa_rcv_str[7],
|
|
gfa_rcv_str[8], gfa_rcv_str[9],
|
|
gfa_rcv_str[10], gfa_rcv_str[11],
|
|
gfa_rcv_str[12], gfa_rcv_str[13]);
|
|
FELICA_PR_DBG(
|
|
" %s Rcv data2 [%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]",
|
|
__func__, gfa_rcv_str[14], gfa_rcv_str[15],
|
|
gfa_rcv_str[16], gfa_rcv_str[17],
|
|
gfa_rcv_str[18], gfa_rcv_str[19],
|
|
gfa_rcv_str[20], gfa_rcv_str[21],
|
|
gfa_rcv_str[22], gfa_rcv_str[23]);
|
|
FELICA_PR_DBG(
|
|
" %s Rcv data3 [%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]",
|
|
__func__, gfa_rcv_str[24], gfa_rcv_str[25],
|
|
gfa_rcv_str[26], gfa_rcv_str[27],
|
|
gfa_rcv_str[28], gfa_rcv_str[29],
|
|
gfa_rcv_str[30], gfa_rcv_str[31],
|
|
gfa_rcv_str[32], gfa_rcv_str[33]);
|
|
ret = copy_to_user(buf, &gfa_rcv_str[4], wk_len);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR
|
|
("%s ERROR(copy_from_user), ret=[%d]",
|
|
__func__, ret);
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
*ppos = *ppos + wk_len;
|
|
} else {
|
|
FELICA_PR_ERR(" %s FAIL", __func__);
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
} else {
|
|
FELICA_PR_ERR(" %s FAIL", __func__);
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return (ssize_t) wk_len;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t felica_uart_write(struct file *file, const char __user *data,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret = 0;
|
|
int nlret;
|
|
size_t wk_len = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(" %s ERROR(down_interruptible)", \
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
memset(gfa_send_str, 0, FELICA_NL_MSG_SIZE);
|
|
memset(gfa_rcv_str, 0, FELICA_NL_MSG_SIZE);
|
|
|
|
wk_len = len;
|
|
if (FELICA_NL_MSG_DATA_SIZE < wk_len) {
|
|
FELICA_PR_INFO(" %s read max size over [%d]", __func__,
|
|
wk_len);
|
|
wk_len = FELICA_NL_MSG_DATA_SIZE;
|
|
}
|
|
gfa_send_str[0] = FELICA_NL_REQ_WRITE;
|
|
gfa_send_str[1] = (char)(wk_len >> 8);
|
|
gfa_send_str[2] = (char)wk_len;
|
|
ret = copy_from_user(&gfa_send_str[3], data, wk_len);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), ret=[%d]",
|
|
__func__, ret);
|
|
up(&dev_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
nlret = felica_nl_send_msg(3 + len);
|
|
if (nlret == 0) {
|
|
wk_len = 0;
|
|
felica_nl_wait_ret_msg();
|
|
wk_len = (((int)gfa_rcv_str[2] << 8) & 0xFF00) | \
|
|
(int)gfa_rcv_str[3];
|
|
if (gfa_rcv_str[1] == FELICA_NL_EFAILED) {
|
|
FELICA_PR_ERR(" %s Write Fail", __func__);
|
|
up(&dev_sem->felica_sem);
|
|
return -EINVAL;
|
|
}
|
|
} else {
|
|
FELICA_PR_ERR(" %s felica_nl_send_msg Fail", __func__);
|
|
up(&dev_sem->felica_sem);
|
|
return -EINVAL;
|
|
}
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return wk_len;
|
|
}
|
|
|
|
/*
|
|
* sync operation
|
|
*/
|
|
static int felica_uart_sync(struct file *file, loff_t start,
|
|
loff_t len, int datasync)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* available operation
|
|
*/
|
|
static long felica_uart_ioctl(struct file *file, unsigned int cmd,
|
|
unsigned long arg)
|
|
{
|
|
unsigned int ret_str = 0;
|
|
int ret;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
FELICA_PR_INFO(" %s cmd = [0x%x]", __func__, cmd);
|
|
|
|
/* Ignore [TCGETS:0x5401] and [TCSBRK:0x5409] */
|
|
if (TCGETS == cmd || TCSBRK == cmd) {
|
|
FELICA_PR_INFO(" %s cmd throw [0x%x]", __func__, cmd);
|
|
return 0;
|
|
}
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(" %s ERROR(down_interruptible)", \
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
memset(gfa_send_str, 0, FELICA_NL_MSG_SIZE);
|
|
memset(gfa_rcv_str, 0, FELICA_NL_MSG_SIZE);
|
|
|
|
gfa_send_str[0] = FELICA_NL_REQ_AVAIABLE;
|
|
ret = felica_nl_send_msg(1);
|
|
|
|
if (ret == 0) {
|
|
|
|
/* 20130216 add for APQ support -S- */
|
|
/* 1ms sleep */
|
|
usleep_range(1000, 1000);
|
|
/* 20130216 add for APQ support -E- */
|
|
|
|
felica_nl_wait_ret_msg();
|
|
if (gfa_rcv_str[1] == FELICA_NL_SUCCESS) {
|
|
/* create response data */
|
|
ret_str =
|
|
(((unsigned int)gfa_rcv_str[2] << 8) & 0xFF00) | \
|
|
(unsigned int)gfa_rcv_str[3];
|
|
FELICA_PR_INFO(" Available Success data size [%d]", \
|
|
ret_str);
|
|
} else {
|
|
FELICA_PR_ERR(" %s Available Fail", __func__);
|
|
up(&dev_sem->felica_sem);
|
|
return -EINVAL;
|
|
}
|
|
} else {
|
|
FELICA_PR_ERR(" %s felica_nl_send_msg Fail", __func__);
|
|
up(&dev_sem->felica_sem);
|
|
return -EINVAL;
|
|
}
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return put_user(ret_str, (unsigned int __user *)arg);
|
|
|
|
}
|
|
|
|
/*
|
|
* create netlink socket
|
|
*/
|
|
static void felica_nl_init(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
gfa_connect_flag = 0;
|
|
gfa_pid = 0;
|
|
gfa_wait_flag = 0;
|
|
memset(gfa_send_str, 0, FELICA_NL_MSG_SIZE);
|
|
memset(gfa_rcv_str, 0, FELICA_NL_MSG_SIZE);
|
|
|
|
gfanl_sk =
|
|
netlink_kernel_create(&init_net, FELICA_NL_NETLINK_USER, 0,
|
|
felica_nl_recv_msg, NULL, THIS_MODULE);
|
|
if (!gfanl_sk)
|
|
FELICA_PR_ERR(" Error creating socket. %s\n", __func__);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* release netlink socket
|
|
*/
|
|
static void felica_nl_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
netlink_kernel_release(gfanl_sk);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* send message to FeliCa-Serial-Connector
|
|
*/
|
|
static int felica_nl_send_msg(int len)
|
|
{
|
|
struct nlmsghdr *nlh;
|
|
struct sk_buff *skb_out;
|
|
int msg_size = 0;
|
|
FELICA_PR_DBG(" %s START len: %d", __func__,len);
|
|
|
|
if (!gfanl_sk) {
|
|
FELICA_PR_ERR("Error Not creating socket. %s\n",
|
|
__func__);
|
|
return 1;
|
|
}
|
|
if (gfa_pid == 0) {
|
|
FELICA_PR_ERR("Error Not Rcv Connect Msg %s\n",
|
|
__func__);
|
|
return 1;
|
|
}
|
|
|
|
msg_size = len;
|
|
skb_out = nlmsg_new(msg_size, 0);
|
|
|
|
if (!skb_out) {
|
|
FELICA_PR_ERR(" Failed to allocate new skb_out %s\n", __func__);
|
|
return 1;
|
|
}
|
|
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
|
|
NETLINK_CB(skb_out).dst_group = 0;
|
|
memcpy(NLMSG_DATA(nlh), gfa_send_str, msg_size);
|
|
|
|
/* "skb_out" will release by netlink.*/
|
|
nlmsg_unicast(gfanl_sk, skb_out, gfa_pid);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* receive message from FeliCa-Serial-Connector
|
|
*/
|
|
static void felica_nl_recv_msg(struct sk_buff *skb)
|
|
{
|
|
|
|
struct nlmsghdr *nlh;
|
|
struct sk_buff *wskb;
|
|
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
int init_flag = 0;
|
|
#endif
|
|
|
|
if (!skb) {
|
|
FELICA_PR_ERR(" %s ERROR(skb NULL)", __func__);
|
|
return;
|
|
}
|
|
|
|
wskb = skb_get(skb);
|
|
if (wskb && (wskb->len > NLMSG_SPACE(0))) {
|
|
nlh = nlmsg_hdr(wskb);
|
|
memcpy(gfa_rcv_str, NLMSG_DATA(nlh), sizeof(gfa_rcv_str));
|
|
FELICA_PR_DBG(" %s START gfa_rcv_str[0]: 0x%x", __func__,gfa_rcv_str[0]);
|
|
if ((gfa_rcv_str[0] == FELICA_NL_CONNECT_MSG)
|
|
&& (gfa_connect_flag == 0)) {
|
|
/* pid of sending process */
|
|
gfa_pid = nlh->nlmsg_pid;
|
|
|
|
if (felica_get_tamper_fuse_cmd() != 1)
|
|
{
|
|
/* jmodel */
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
s3c_gpio_cfgall_range(FELICA_UART1RX, 2,\
|
|
S3C_GPIO_SFN(2), S3C_GPIO_PULL_DOWN);
|
|
felica_uart_port = 1;
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
felica_uart_port = 2;
|
|
#elif defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_SBM)
|
|
felica_uart_port = 2;
|
|
#elif defined(CONFIG_MACH_HLTEDCM) || defined(CONFIG_MACH_HLTEKDI) || defined(CONFIG_MACH_JS01LTEDCM)
|
|
felica_uart_port = 1;
|
|
#endif
|
|
|
|
felica_set_felica_info();
|
|
felica_uart_init();
|
|
felica_pon_init();
|
|
felica_cen_init();
|
|
felica_rfs_init();
|
|
felica_rws_init();
|
|
felica_ant_init();
|
|
#ifdef CONFIG_NFC_FELICA
|
|
snfc_uart_init();
|
|
cxd2235power_init();
|
|
hsel_init();
|
|
snfc_rfs_init();
|
|
available_poll_init();
|
|
snfc_cen_init();
|
|
#endif
|
|
if (gdiag_name[0] != 0x00)
|
|
felica_uid_init();
|
|
}
|
|
|
|
gfa_connect_flag = 1;
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
init_flag = 1;
|
|
guartcc_felica_status = UARTCC_FELICA_STATAUS_IN_INIT;
|
|
FELICA_PR_INFO(" RCV MSG [%d]", gfa_rcv_str[0]);
|
|
#endif
|
|
} else if ((gfa_rcv_str[0] == FELICA_NL_RESPONCE)
|
|
&& (gfa_pid == nlh->nlmsg_pid)) {
|
|
/* wake up */
|
|
gfa_wait_flag = 1;
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
} else if ((gfa_rcv_str[0] == FELICA_INIT_UICC_END)
|
|
&& (gfa_pid == nlh->nlmsg_pid)) {
|
|
FELICA_PR_INFO("RCV MSG FELICA_INIT_UICC_END [%d]",
|
|
gfa_rcv_str[0]);
|
|
if (gfa_rcv_str[1] == FELICA_NL_SUCCESS)
|
|
FELICA_PR_INFO("UICC INIT END SUCCESS");
|
|
else
|
|
FELICA_PR_INFO("UICC INIT END FAIL");
|
|
|
|
guartcc_felica_status = UARTCC_FELICA_STATAUS_IDLE;
|
|
#endif
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(RCV Undefine MSG) RCV MSG [%d], rcv pid [%d], gfa_pid [%d]",
|
|
__func__, gfa_rcv_str[0],nlh->nlmsg_pid,gfa_pid);
|
|
}
|
|
}
|
|
kfree_skb(skb);
|
|
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
if (init_flag) {
|
|
FELICA_PR_INFO("UICC INIT START");
|
|
memset(gfa_send_str, 0, FELICA_NL_MSG_SIZE);
|
|
memset(gfa_rcv_str, 0, FELICA_NL_MSG_SIZE);
|
|
gfa_send_str[0] = FELICA_NL_INIT_END_RES;
|
|
felica_nl_send_msg(1);
|
|
}
|
|
#endif
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
static void felica_set_felica_info(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START ", __func__);
|
|
memset(gdiag_name, 0x00, DIAG_NAME_MAXSIZE + 1);
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
memset(gproc_name, 0x00, PROC_NAME_MAXSIZE + 1);
|
|
#endif
|
|
gread_msgs[0].flags = gfa_rcv_str[MSG_READ1_FLAGS_OFFSET];
|
|
gread_msgs[0].len = gfa_rcv_str[MSG_READ1_LEN_OFFSET];
|
|
gread_msgs[1].flags = gfa_rcv_str[MSG_READ2_FLAGS_OFFSET];
|
|
gread_msgs[1].len = gfa_rcv_str[MSG_READ2_LEN_OFFSET];
|
|
gwrite_msgs[0].flags = gfa_rcv_str[MSG_WRITE_FLAGS_OFFSET];
|
|
gwrite_msgs[0].len = gfa_rcv_str[MSG_WRITE_LEN_OFFSET];
|
|
gi2c_lockaddress = gfa_rcv_str[MSG_LOCK_ADDR_OFFSET];
|
|
gi2c_address = gfa_rcv_str[MSG_I2C_ADDR_OFFSET];
|
|
|
|
memcpy(gdiag_name, &gfa_rcv_str[MSG_DIAG_NAME_OFFSET],
|
|
DIAG_NAME_MAXSIZE);
|
|
|
|
gmfc_uid =
|
|
(((int)gfa_rcv_str[MSG_MFC_UID_FRONT_OFFSET] << 8) & 0xFF00) |
|
|
(int)gfa_rcv_str[MSG_MFC_UID_BACK_OFFSET];
|
|
|
|
gmfl_uid =
|
|
(((int)gfa_rcv_str[MSG_MFL_UID_FRONT_OFFSET] << 8) & 0xFF00) |
|
|
(int)gfa_rcv_str[MSG_MFL_UID_BACK_OFFSET];
|
|
|
|
gi2c_antaddress = gfa_rcv_str[MSG_ANT_ADDR_OFFSET];
|
|
gant_uid =
|
|
(((int)gfa_rcv_str[MSG_ANT_UID_FRONT_OFFSET] << 8) & 0xFF00) |
|
|
(int)gfa_rcv_str[MSG_ANT_UID_BACK_OFFSET];
|
|
|
|
#ifdef CONFIG_NFC_FELICA
|
|
gnfc_uid =
|
|
(((int)gfa_rcv_str[MSG_NFC_UID_FRONT_OFFSET] << 8) & 0xFF00) |
|
|
(int)gfa_rcv_str[MSG_NFC_UID_BACK_OFFSET];
|
|
|
|
snfc_cen_sts_init();
|
|
#endif
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
memcpy(gproc_name, &gfa_rcv_str[MSG_PROC_NAME_OFFSET],
|
|
PROC_NAME_MAXSIZE);
|
|
#endif
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* waiting to receive messages from FeliCa-Serial-Connector
|
|
*/
|
|
static void felica_nl_wait_ret_msg(void)
|
|
{
|
|
unsigned int cnt = 0;
|
|
FELICA_PR_DBG(" %s START ", __func__);
|
|
|
|
while (1) {
|
|
if (gfa_wait_flag == 1) {
|
|
FELICA_PR_DBG(" %s sleep cnt [%d]", __func__,
|
|
cnt);
|
|
break;
|
|
}
|
|
mdelay(1);
|
|
cnt++;
|
|
}
|
|
gfa_wait_flag = 0;
|
|
|
|
FELICA_PR_DBG(" %s END ", __func__);
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
static int felica_smc_read_oemflag(u32 ctrl_word, u32 *val)
|
|
{
|
|
register u32 reg0 __asm__("r0");
|
|
register u32 reg1 __asm__("r1");
|
|
register u32 reg2 __asm__("r2");
|
|
register u32 reg3 __asm__("r3");
|
|
u32 idx = 0;
|
|
|
|
for (idx = 0; reg2 != ctrl_word; idx++) {
|
|
reg0 = -202;
|
|
reg1 = 1;
|
|
reg2 = idx;
|
|
|
|
__asm__ volatile ("smc 0\n" : "+r" (reg0), "+r"(reg1),
|
|
"+r"(reg2), "+r"(reg3)
|
|
);
|
|
if (reg1)
|
|
return -1;
|
|
}
|
|
|
|
reg0 = -202;
|
|
reg1 = 1;
|
|
reg2 = idx;
|
|
|
|
__asm__ volatile ("smc 0\n" : "+r" (reg0), "+r"(reg1),
|
|
"+r"(reg2), "+r"(reg3)
|
|
);
|
|
if (reg1)
|
|
return -1;
|
|
|
|
*val = reg2;
|
|
return 0;
|
|
}
|
|
|
|
static int felica_Cpu0(void)
|
|
{
|
|
int ret = 0;
|
|
struct cpumask mask = CPU_MASK_CPU0;
|
|
|
|
FELICA_PR_INFO(" System has %d CPU's, we are on CPU #%d\n"
|
|
"\tBinding this process to CPU #0.\n"
|
|
"\tactive mask is %lx, setting it to mask=%lx\n",
|
|
nr_cpu_ids,
|
|
raw_smp_processor_id(), cpu_active_mask->bits[0], mask.bits[0]);
|
|
|
|
ret = set_cpus_allowed_ptr(current, &mask);
|
|
if (0 != ret)
|
|
FELICA_PR_INFO(" set_cpus_allowed_ptr=%d.\n", ret);
|
|
|
|
FELICA_PR_INFO(" And now we are on CPU #%d", raw_smp_processor_id());
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int felica_CpuAll(void)
|
|
{
|
|
int ret = 0;
|
|
struct cpumask mask = CPU_MASK_ALL;
|
|
|
|
FELICA_PR_INFO(" System has %d CPU's, we are on CPU #%d\n"
|
|
"\tBinding this process to CPU #0.\n"
|
|
"\tactive mask is %lx, setting it to mask=%lx\n",
|
|
nr_cpu_ids,
|
|
raw_smp_processor_id(), cpu_active_mask->bits[0], mask.bits[0]);
|
|
|
|
ret = set_cpus_allowed_ptr(current, &mask);
|
|
if (0 != ret)
|
|
FELICA_PR_INFO(" set_cpus_allowed_ptr=%d.\n", ret);
|
|
|
|
FELICA_PR_INFO(" And now we are on CPU #%d", raw_smp_processor_id());
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static uint8_t felica_get_tamper_fuse_cmd(void)
|
|
{
|
|
u32 fuse_id = 0;
|
|
int ret;
|
|
|
|
ret = felica_Cpu0();
|
|
if (0 != ret) {
|
|
FELICA_PR_ERR(" changing core failed!");
|
|
return -1;
|
|
}
|
|
|
|
FELICA_PR_INFO(" get_fuse");
|
|
|
|
if (felica_smc_read_oemflag(0x80010001, (u32 *)&fuse_id) < 0) {
|
|
FELICA_PR_ERR(" %s read flag error", __func__);
|
|
return -1;
|
|
}
|
|
FELICA_PR_INFO(" Kernel Status[%x]", fuse_id);
|
|
felica_CpuAll();
|
|
|
|
return (uint8_t)fuse_id;
|
|
}
|
|
|
|
#elif defined(CONFIG_ARCH_APQ8064) || defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
|
|
static uint8_t felica_get_tamper_fuse_cmd(void)
|
|
{
|
|
|
|
uint32_t fuse_id = FELICA_HLOS_IMG_TAMPER_FUSE;
|
|
void *cmd_buf;
|
|
size_t cmd_len;
|
|
size_t resp_len = 0;
|
|
uint8_t resp_buf;
|
|
|
|
FELICA_PR_DBG(" %s START ", __func__);
|
|
|
|
resp_len = sizeof(resp_buf);
|
|
cmd_buf = (void *)&fuse_id;
|
|
cmd_len = sizeof(fuse_id);
|
|
|
|
scm_call(FELICA_SCM_SVC_FUSE, FELICA_SCM_IS_SW_FUSE_BLOWN_ID, cmd_buf,
|
|
cmd_len, &resp_buf, resp_len);
|
|
FELICA_PR_DBG(" %s END resp_buf = %d\n",__func__, resp_buf);
|
|
|
|
#ifdef NO_CHECK_TAMPER
|
|
FELICA_PR_ERR(" No checking tampered kernel just for test!\n");
|
|
return 0;
|
|
#endif
|
|
|
|
return resp_buf;
|
|
}
|
|
#endif
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/felica_pon
|
|
*****************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_felica_pon;
|
|
static struct cdev cdev_felica_pon;
|
|
static const struct file_operations fops_felica_pon = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_pon_open,
|
|
.release = felica_pon_close,
|
|
.read = felica_pon_read,
|
|
.write = felica_pon_write,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void felica_pon_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_pon;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_pon = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_pon, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_PON_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_pon, &fops_felica_pon);
|
|
ret = cdev_add(&cdev_felica_pon, devid_felica_pon, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_pon, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_pon =
|
|
device_create(felica_class, NULL, devid_felica_pon, NULL,
|
|
FELICA_PON_NAME);
|
|
if (IS_ERR(device_felica_pon)) {
|
|
cdev_del(&cdev_felica_pon);
|
|
unregister_chrdev_region(devid_felica_pon, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_felica_pon), MINOR(devid_felica_pon));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void felica_pon_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_felica_pon);
|
|
cdev_del(&cdev_felica_pon);
|
|
unregister_chrdev_region(devid_felica_pon, FELICA_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_pon_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
int ret = 0;
|
|
char *cmdpos;
|
|
static char cmdline[1025];
|
|
static unsigned long start_adr, end_adr, leng;
|
|
#endif
|
|
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
start_adr = current->mm->arg_start;
|
|
end_adr = current->mm->arg_end;
|
|
leng = end_adr - start_adr;
|
|
|
|
if (1024 < leng)
|
|
leng = 1024;
|
|
cmdpos = (char *)(current->mm->arg_start);
|
|
ret = copy_from_user(cmdline, cmdpos, leng);
|
|
cmdline[leng] = '\0';
|
|
if(ret != 0)
|
|
{
|
|
FELICA_PR_ERR(" %s cmdline[%s] ret[%d]", __func__, cmdline, ret);
|
|
return -EFAULT;
|
|
}
|
|
#endif
|
|
uid = __task_cred(current)->uid;
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
if (((uid != gmfc_uid) && (uid != gdiag_uid)
|
|
&& (uid != gant_uid)) &&
|
|
(strncmp(cmdline,gproc_name, leng) != 0)) {
|
|
#else
|
|
if ((uid != gmfc_uid) && (uid != gdiag_uid)
|
|
&& (uid != gant_uid)) {
|
|
#endif
|
|
FELICA_PR_ERR
|
|
(" %s END -EACCES, uid=[%d], gmfc_uid=[%d], gdiag_uid=[%d]",
|
|
__func__, uid, gmfc_uid, gdiag_uid);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_pon_close(struct inode *inode, struct file *file)
|
|
{
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ice_gpiox_set(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
gpio_set_value(gfelica_pon_pin, GPIO_VALUE_LOW);
|
|
#else
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#endif // CONFIG_MACH_KLTE
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t felica_pon_read(struct file *file, char __user *buf, size_t len,
|
|
loff_t *ppos)
|
|
{
|
|
int ret;
|
|
char retparam;
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
ret = gpio_get_value(GPIO_PINID_FELICA_PON);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ret = ice_gpiox_get(GPIO_PINID_FELICA_PON);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
ret = gpio_get_value(gfelica_pon_pin);
|
|
#else
|
|
ret = gpio_get_value(GPIO_PINID_FELICA_PON);
|
|
#endif // CONFIG_MACH_KLTE
|
|
#endif
|
|
FELICA_PR_INFO(" %s GPIO Read value of GPIO_PINID_FELICA_PON -> ret=[%d]", __func__,ret);
|
|
|
|
if (ret == GPIO_VALUE_HIGH) {
|
|
retparam = FELICA_PON_WIRED;
|
|
FELICA_PR_INFO(" Wired interface Status is [%d][start]",
|
|
retparam);
|
|
} else if (ret == GPIO_VALUE_LOW) {
|
|
retparam = FELICA_PON_WIRELESS;
|
|
FELICA_PR_INFO(" Wired interface Status is [%d][standby]",
|
|
retparam);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(gpio_get_value), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = copy_to_user(buf, &retparam, FELICA_PON_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
return FELICA_PON_DATA_LEN;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t felica_pon_write(struct file *file, const char __user *data,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
char pon;
|
|
int ret;
|
|
int setparam;
|
|
|
|
ret = copy_from_user(&pon, data, FELICA_PON_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (pon == FELICA_PON_WIRED) {
|
|
setparam = GPIO_VALUE_HIGH;
|
|
FELICA_PR_INFO(" Set wired interface to [%d][start]",
|
|
setparam);
|
|
} else if (pon == FELICA_PON_WIRELESS) {
|
|
setparam = GPIO_VALUE_LOW;
|
|
FELICA_PR_INFO(" Set wired interface to [%d][standby]",
|
|
setparam);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), pon=[%d]",
|
|
__func__, pon);
|
|
return -EINVAL;
|
|
}
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, setparam);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ice_gpiox_set(GPIO_PINID_FELICA_PON, setparam);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI)
|
|
if(gfelica_uim_mon == 1) {
|
|
FELICA_PR_ERR(" %s gfelica_uim_mon=%d\n", __func__, gfelica_uim_mon);
|
|
gpio_set_value(gfelica_pon_pin, GPIO_VALUE_HIGH);
|
|
return FELICA_PON_DATA_LEN;
|
|
}
|
|
gpio_set_value(gfelica_pon_pin, setparam);
|
|
#elif defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
gpio_set_value(gfelica_pon_pin, setparam);
|
|
#else
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, setparam);
|
|
#endif // CONFIG_MACH_KLTE
|
|
#endif
|
|
|
|
return FELICA_PON_DATA_LEN;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* felica_i2c_driver
|
|
******************************************************************************/
|
|
static struct i2c_client *felica_i2c_client;
|
|
static const struct i2c_device_id felica_i2c_idtable[] =
|
|
{
|
|
{FELICA_I2C_NAME, 0},
|
|
{}
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(i2c, felica_i2c_idtable);
|
|
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
static struct of_device_id felica_i2c_match_table[] =
|
|
{
|
|
{ .compatible = "felica,felica-i2c",},
|
|
{},
|
|
};
|
|
#endif
|
|
|
|
|
|
static struct i2c_driver felica_i2c_driver =
|
|
{
|
|
.probe = felica_i2c_probe,
|
|
.remove = felica_i2c_remove,
|
|
.driver =
|
|
{
|
|
.name = FELICA_I2C_NAME,
|
|
.owner = THIS_MODULE,
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
.of_match_table = felica_i2c_match_table,
|
|
#endif
|
|
},
|
|
.id_table = felica_i2c_idtable,
|
|
};
|
|
|
|
/*
|
|
* felica_i2c_init
|
|
*/
|
|
static void felica_i2c_init(void)
|
|
{
|
|
int ret;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = i2c_add_driver(&felica_i2c_driver);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_add_driver), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* felica_i2c_exit
|
|
*/
|
|
static void felica_i2c_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
i2c_del_driver(&felica_i2c_driver);
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* probe device
|
|
*/
|
|
static int felica_i2c_probe(struct i2c_client *client,
|
|
const struct i2c_device_id *devid)
|
|
{
|
|
FELICA_PR_INFO(" %s START", __func__);
|
|
|
|
felica_i2c_client = client;
|
|
if (!felica_i2c_client) {
|
|
FELICA_PR_ERR(" %s ERROR(felica_i2c_client==NULL)", \
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
|
|
|
|
FELICA_PR_INFO(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* remove device
|
|
*/
|
|
static int felica_i2c_remove(struct i2c_client *client)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* /dev/felica_cen
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_felica_cen;
|
|
static struct cdev cdev_felica_cen;
|
|
static const struct file_operations fops_felica_cen = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_cen_open,
|
|
.release = felica_cen_close,
|
|
.read = felica_cen_read,
|
|
.write = felica_cen_write,
|
|
};
|
|
|
|
/*
|
|
* felica_cen_init
|
|
*/
|
|
static void felica_cen_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_cen;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_cen = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_cen, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_CEN_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_cen, &fops_felica_cen);
|
|
ret = cdev_add(&cdev_felica_cen, devid_felica_cen, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_cen, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_cen =
|
|
device_create(felica_class, NULL, devid_felica_cen, NULL,
|
|
FELICA_CEN_NAME);
|
|
if (IS_ERR(device_felica_cen)) {
|
|
cdev_del(&cdev_felica_cen);
|
|
unregister_chrdev_region(devid_felica_cen, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_felica_cen), MINOR(devid_felica_cen));
|
|
}
|
|
|
|
/*
|
|
* felica_cen_exit
|
|
*/
|
|
static void felica_cen_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_felica_cen);
|
|
cdev_del(&cdev_felica_cen);
|
|
unregister_chrdev_region(devid_felica_cen, FELICA_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_cen_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
int ret = 0;
|
|
char *cmdpos;
|
|
static char cmdline[1025];
|
|
static unsigned long start_adr, end_adr, leng;
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s START . system_rev=[%d]", __func__,system_rev);
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//high
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN HIGH", __func__);
|
|
of_sii8240_hw_poweron(FELICA_CEN_UNLOCK);
|
|
}
|
|
#endif
|
|
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
start_adr = current->mm->arg_start;
|
|
end_adr = current->mm->arg_end;
|
|
leng = end_adr - start_adr;
|
|
|
|
if (1024 < leng)
|
|
leng = 1024;
|
|
cmdpos = (char *)(current->mm->arg_start);
|
|
ret = copy_from_user(cmdline, cmdpos, leng);
|
|
cmdline[leng] = '\0';
|
|
if(ret != 0)
|
|
{
|
|
FELICA_PR_ERR(" %s cmdline[%s] ret[%d]", __func__, cmdline, ret);
|
|
return -EFAULT;
|
|
}
|
|
#endif
|
|
|
|
uid = __task_cred(current)->uid;
|
|
if (file->f_mode & FMODE_WRITE) {
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
if ((uid != gdiag_uid) && (uid != gmfl_uid)
|
|
&& (strncmp(cmdline,gproc_name, leng) != 0)) {
|
|
#else
|
|
if ((uid != gdiag_uid) && (uid != gmfl_uid)) {
|
|
#endif
|
|
FELICA_PR_ERR(" %s END -EACCES, uid=[%d], gmfc_uid=[%d], gdiag_uid=[%d], gmfl_uid=[%d]\n", __func__, uid,gmfc_uid,gdiag_uid,gmfl_uid);
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//low
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN LOW", __func__);
|
|
// of_sii8240_hw_poweron(FELICA_CEN_LOCK);
|
|
}
|
|
#endif
|
|
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
}
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_cen_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//low
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN LOW", __func__);
|
|
// of_sii8240_hw_poweron(FELICA_CEN_LOCK);
|
|
}
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END system_rev=[%d]", __func__,system_rev);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t felica_cen_read(struct file *file, char __user *buf, \
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret;
|
|
unsigned char address = gi2c_lockaddress;
|
|
unsigned char read_buff = 0;
|
|
struct i2c_msg read_msgs[2];
|
|
|
|
read_msgs[0].flags = gread_msgs[0].flags;
|
|
read_msgs[0].len = gread_msgs[0].len;
|
|
read_msgs[1].flags = gread_msgs[1].flags;
|
|
read_msgs[1].len = gread_msgs[1].len;
|
|
|
|
read_msgs[0].addr = gi2c_address;
|
|
read_msgs[0].buf = &address;
|
|
read_msgs[1].addr = gi2c_address;
|
|
read_msgs[1].buf = &read_buff;
|
|
|
|
if (felica_i2c_client == NULL) {
|
|
FELICA_PR_ERR(" felica_i2c_client is NULL %s -EIO",__func__);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[0], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[0]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[1], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[1]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
read_buff &= FELICA_CONTROL_LOCK_MASK;
|
|
|
|
#ifdef CONFIG_NFC_FELICA
|
|
g_cen_sts = read_buff;
|
|
#endif
|
|
|
|
FELICA_PR_INFO(" %s g_cen_sts=[%d]", __func__, g_cen_sts);
|
|
|
|
ret = copy_to_user(buf, &read_buff, FELICA_CEN_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
return FELICA_CEN_DATA_LEN;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t felica_cen_write(struct file *file, const char __user *data,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
char cen;
|
|
int ret;
|
|
unsigned char write_buff[2];
|
|
|
|
if (felica_i2c_client == NULL) {
|
|
FELICA_PR_ERR(" felica_i2c_client is NULL %s",__func__);
|
|
return -EIO;
|
|
}
|
|
|
|
gwrite_msgs[0].buf = &write_buff[0];
|
|
gwrite_msgs[0].addr = gi2c_address;
|
|
write_buff[0] = gi2c_lockaddress;
|
|
|
|
ret = copy_from_user(&cen, data, FELICA_CEN_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
if (cen == FELICA_CEN_UNLOCK) {
|
|
write_buff[1] = FELICA_CEN_SET_UNLOCK;
|
|
FELICA_PR_INFO(" Set FeliCa-Lock status to [%d][UnLock]",
|
|
write_buff[1]);
|
|
} else if (cen == FELICA_CEN_LOCK) {
|
|
write_buff[1] = FELICA_CEN_SET_LOCK;
|
|
FELICA_PR_INFO(" Set FeliCa-Lock status to [%d][Lock]",
|
|
write_buff[1]);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), cen=[%d]",
|
|
__func__, cen);
|
|
return -EINVAL;
|
|
}
|
|
ret = i2c_transfer(felica_i2c_client->adapter, gwrite_msgs, 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
#ifdef CONFIG_NFC_FELICA
|
|
g_cen_sts = cen;
|
|
if (1 == available_d->available_flag) {
|
|
if (0 != g_cen_sts) {
|
|
if (GPIO_VALUE_LOW != g_rfs_sts) {
|
|
if (0 == guartcc_felica_status) {
|
|
available_d->rsp_done = 1;
|
|
FELICA_PR_INFO(" wake up available");
|
|
wake_up_interruptible(
|
|
&available_d->read_wait);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
FELICA_PR_INFO(" %s END, g_cen_sts =%d, g_rfs_sts = %d", __func__, g_cen_sts, g_rfs_sts);
|
|
return FELICA_CEN_DATA_LEN;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* /dev/felica_rfs
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_felica_rfs;
|
|
static struct cdev cdev_felica_rfs;
|
|
static const struct file_operations fops_felica_rfs = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_rfs_open,
|
|
.release = felica_rfs_close,
|
|
.read = felica_rfs_read,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void felica_rfs_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_rfs;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_rfs = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_rfs, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_RFS_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_rfs, &fops_felica_rfs);
|
|
ret = cdev_add(&cdev_felica_rfs, devid_felica_rfs, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_rfs, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_rfs =
|
|
device_create(felica_class, NULL, devid_felica_rfs, NULL,
|
|
FELICA_RFS_NAME);
|
|
if (IS_ERR(device_felica_rfs)) {
|
|
cdev_del(&cdev_felica_rfs);
|
|
unregister_chrdev_region(devid_felica_rfs, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_felica_rfs), MINOR(devid_felica_rfs));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void felica_rfs_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_felica_rfs);
|
|
cdev_del(&cdev_felica_rfs);
|
|
unregister_chrdev_region(devid_felica_rfs, FELICA_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_rfs_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
|
|
uid = __task_cred(current)->uid;
|
|
|
|
if ((uid != gmfc_uid) && (uid != gdiag_uid)) {
|
|
FELICA_PR_ERR
|
|
(" %s -EACCESS, uid=[%d], gmfc_uid=[%d], gdiag_uid=[%d]",
|
|
__func__, uid, gmfc_uid, gdiag_uid);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, uid=[%d], gmfc_uid=[%d], gdiag_uid=[%d]", __func__, uid, gmfc_uid, gdiag_uid);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_rfs_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t felica_rfs_read(struct file *file, char __user *buf, \
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret;
|
|
char retparam;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = gpio_get_value(GPIO_PINID_FELICA_RFS);
|
|
|
|
if (ret == GPIO_VALUE_HIGH) {
|
|
retparam = FELICA_RFS_STANDBY;
|
|
FELICA_PR_INFO(" Carrier-Wave Status is [%d][standby]",
|
|
retparam);
|
|
} else if (ret == GPIO_VALUE_LOW) {
|
|
retparam = FELICA_RFS_DETECTED;
|
|
FELICA_PR_INFO(" Carrier-Wave Status is [%d][detected]",
|
|
retparam);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(gpio_get_value), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = copy_to_user(buf, &retparam, FELICA_RFS_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return FELICA_RFS_DATA_LEN;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* /dev/felica_rws
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_felica_rws;
|
|
static struct cdev cdev_felica_rws;
|
|
static const struct file_operations fops_felica_rws = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_rws_open,
|
|
.release = felica_rws_close,
|
|
.read = felica_rws_read,
|
|
.write = felica_rws_write,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void felica_rws_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_rws;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_rws = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_rws, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_RWS_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_rws, &fops_felica_rws);
|
|
ret = cdev_add(&cdev_felica_rws, devid_felica_rws, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_rws, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_rws =
|
|
device_create(felica_class, NULL, devid_felica_rws, NULL,
|
|
FELICA_RWS_NAME);
|
|
if (IS_ERR(device_felica_rws)) {
|
|
cdev_del(&cdev_felica_rws);
|
|
unregister_chrdev_region(devid_felica_rws, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
gfelica_rw_status = FELICA_RW_STATUS_INIT;
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_felica_rws), MINOR(devid_felica_rws));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void felica_rws_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_felica_rws);
|
|
cdev_del(&cdev_felica_rws);
|
|
unregister_chrdev_region(devid_felica_rws, FELICA_MINOR_COUNT);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_rws_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
uid = __task_cred(current)->uid;
|
|
if (file->f_mode & FMODE_WRITE) {
|
|
if (uid != grwm_uid) {
|
|
FELICA_PR_ERR(\
|
|
" %s END -EACCES, uid=[%d],gmfc_uid=[%d],gdiag_uid=[%d]",
|
|
__func__, uid, gmfc_uid, gdiag_uid);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
} else {
|
|
if ((uid != gmfc_uid) && (uid != grwm_uid)) {
|
|
FELICA_PR_ERR(\
|
|
" %s END -EACCES, uid=[%d],gmfc_uid=[%d],gdiag_uid=[%d]",
|
|
__func__, uid, gmfc_uid, gdiag_uid);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_rws_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t felica_rws_read(struct file *file, char __user *buf, size_t len,
|
|
loff_t *ppos)
|
|
{
|
|
int ret;
|
|
char retparam;
|
|
|
|
if (gfelica_rw_status == FELICA_RW_STATUS_ENABLE) {
|
|
retparam = FELICA_RW_STATUS_ENABLE;
|
|
FELICA_PR_INFO(" ReaderWriterFunction status is [%d][enabled] %s",
|
|
retparam,__func__);
|
|
} else if (gfelica_rw_status == FELICA_RW_STATUS_DISABLE) {
|
|
retparam = FELICA_RW_STATUS_DISABLE;
|
|
FELICA_PR_INFO
|
|
(" ReaderWriterFunction status is [%d][disabled] %s", retparam,__func__);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(gfelica_rw_status), RWM=[%d]",
|
|
__func__, gfelica_rw_status);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = copy_to_user(buf, &retparam, FELICA_RWS_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
return FELICA_RWS_DATA_LEN;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t felica_rws_write(struct file *file, const char __user *data,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
char work;
|
|
int ret;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = copy_from_user(&work, data, FELICA_RWS_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (work == FELICA_RW_STATUS_ENABLE) {
|
|
FELICA_PR_INFO
|
|
("Set ReaderWriterFunction status to [%d][enable]", work);
|
|
} else if (work == FELICA_RW_STATUS_DISABLE) {
|
|
FELICA_PR_INFO
|
|
("Set ReaderWriterFunction status to s[%d][disable]", work);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), work=[%d]",
|
|
__func__, work);
|
|
return -EINVAL;
|
|
}
|
|
|
|
gfelica_rw_status = work;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return FELICA_RWS_DATA_LEN;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* /dev/felica_int_poll
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_felica_int_poll;
|
|
static struct cdev cdev_felica_int_poll;
|
|
static const struct file_operations fops_felica_int_poll = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_int_poll_open,
|
|
.release = felica_int_poll_close,
|
|
.read = felica_int_poll_read,
|
|
.poll = felica_int_poll_poll,
|
|
};
|
|
/*
|
|
* top half of irq_handler
|
|
*/
|
|
static irqreturn_t felica_int_irq_handler(int irq, void *dev_id)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
disable_irq_nosync(gpio_to_irq(GPIO_PINID_FELICA_INT));
|
|
#else
|
|
disable_irq_nosync(gpio_to_irq(gfelica_irq_int_pin));
|
|
#endif
|
|
#else
|
|
disable_irq_nosync(gpio_to_irq(GPIO_PINID_FELICA_INT_REV03));
|
|
#endif /* CONFIG_ARCH_MSM8974 */
|
|
schedule_delayed_work(&pgint_irq->work,
|
|
msecs_to_jiffies(FELICA_INT_DELAY_TIME));
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
/*
|
|
* bottom half of irq_handler
|
|
*/
|
|
static void felica_int_irq_work(struct work_struct *work)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
enable_irq(gpio_to_irq(GPIO_PINID_FELICA_INT));
|
|
#else
|
|
enable_irq(gpio_to_irq(gfelica_irq_int_pin));
|
|
#endif // CONFIG_MACH_KLTE
|
|
#else
|
|
enable_irq(gpio_to_irq(GPIO_PINID_FELICA_INT_REV03));
|
|
#endif /* CONFIG_ARCH_MSM8974 */
|
|
|
|
pgint_irq->irq_done = 1;
|
|
|
|
#ifdef F_WAKE_LOCK
|
|
wake_lock_timeout(&felica_wake_1, msecs_to_jiffies(tmout_1));
|
|
FELICA_PR_INFO(" %s Wake Lock(1)[%d]", __func__, tmout_1);
|
|
#endif
|
|
wake_up_interruptible(&pgint_irq->read_wait);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void felica_int_poll_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_int_poll;
|
|
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if !defined(CONFIG_MACH_KLTE_KDI) && !defined(CONFIG_MACH_KLTE_DCM) && !defined(CONFIG_MACH_KLTE_SBM)
|
|
struct device *dev = &felica_gpio_pdev->dev;
|
|
struct device_node *np;
|
|
#endif // CONFIG_MACH_KLTE
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_int_poll = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_int_poll, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_INT_POLL_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_int_poll, &fops_felica_int_poll);
|
|
ret =
|
|
cdev_add(&cdev_felica_int_poll, devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_int_poll =
|
|
device_create(felica_class, NULL, devid_felica_int_poll, NULL,
|
|
FELICA_INT_POLL_NAME);
|
|
if (IS_ERR(device_felica_int_poll)) {
|
|
cdev_del(&cdev_felica_int_poll);
|
|
unregister_chrdev_region(devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
memset(pgint_irq, 0x00, sizeof(struct felica_int_irqdata));
|
|
INIT_DELAYED_WORK(&pgint_irq->work, felica_int_irq_work);
|
|
init_waitqueue_head(&pgint_irq->read_wait);
|
|
|
|
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if !defined(CONFIG_MACH_KLTE_KDI) && !defined(CONFIG_MACH_KLTE_DCM) && !defined(CONFIG_MACH_KLTE_SBM)
|
|
if (!dev) {
|
|
FELICA_PR_ERR(" %s ERROR NULL", __func__);
|
|
return;
|
|
}
|
|
np = dev->of_node;
|
|
gfelica_irq_int_pin = of_get_named_gpio(np, "felica,irq-gpio", 0);
|
|
FELICA_PR_INFO(" %s gfelica_irq_int_pin [%d]",
|
|
__func__, gfelica_irq_int_pin);
|
|
#endif // CONFIG_MACH_KLTE
|
|
|
|
#if defined(CONFIG_MACH_HLTEKDI)
|
|
gfelica_sps_pin = of_get_named_gpio(np, "felica,sps-gpio", 0);
|
|
if(gfelica_sps_pin < 0)
|
|
{
|
|
FELICA_PR_ERR(" %s ERROR(), ret=[%d]",__func__, gfelica_sps_pin);
|
|
return;
|
|
}
|
|
FELICA_PR_INFO(" %s gfelica_sps_pin [%d]",
|
|
__func__, gfelica_sps_pin);
|
|
ret = gpio_get_value(gfelica_sps_pin);
|
|
FELICA_PR_INFO(" %s gfelica_sps_pin [%d]",
|
|
__func__, ret);
|
|
#endif
|
|
#if defined(CONFIG_MACH_HLTEDCM) || defined(CONFIG_MACH_JS01LTEDCM)
|
|
if (system_rev >= g_uicc_initrev) {
|
|
gpio_tlmm_config(GPIO_CFG(gfelica_sps_pin, GPIOMUX_FUNC_GPIO,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
FELICA_PR_INFO(" %s gfelica_sps_pin dcm [%d]",
|
|
__func__, gfelica_sps_pin);
|
|
FELICA_PR_INFO(" %s gfelica_sps_pin dcm [%d]",
|
|
__func__, gpio_get_value(gfelica_sps_pin));
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
ret = request_threaded_irq(
|
|
gpio_to_irq(GPIO_PINID_FELICA_INT),
|
|
NULL,
|
|
felica_int_irq_handler,
|
|
IRQF_TRIGGER_FALLING,
|
|
FELICA_INT_POLL_NAME,
|
|
(void *)pgint_irq);
|
|
|
|
FELICA_PR_INFO(" %s INFO(request_irq)= %d GPIO=%d, ret=[%d]",
|
|
__func__, gpio_to_irq(GPIO_PINID_FELICA_INT),GPIO_PINID_FELICA_INT,ret);
|
|
#else
|
|
ret = request_threaded_irq(
|
|
gpio_to_irq(gfelica_irq_int_pin),
|
|
NULL,
|
|
felica_int_irq_handler,
|
|
IRQF_TRIGGER_FALLING,
|
|
FELICA_INT_POLL_NAME,
|
|
(void *)pgint_irq);
|
|
#endif // CONFIG_MACH_KLTE
|
|
#else
|
|
ret = request_irq(gpio_to_irq(GPIO_PINID_FELICA_INT_REV03),
|
|
felica_int_irq_handler,
|
|
IRQF_TRIGGER_FALLING,
|
|
FELICA_INT_POLL_NAME, (void *)pgint_irq);
|
|
#endif /* CONFIG_ARCH_MSM8974 */
|
|
|
|
if (ret != 0) {
|
|
device_destroy(felica_class, devid_felica_int_poll);
|
|
cdev_del(&cdev_felica_int_poll);
|
|
unregister_chrdev_region(devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(request_irq), ret=[%d]",
|
|
__func__,ret);
|
|
return;
|
|
}
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
ret = enable_irq_wake(gpio_to_irq(GPIO_PINID_FELICA_INT));
|
|
if (ret < 0) {
|
|
free_irq(gpio_to_irq(GPIO_PINID_FELICA_INT), (void *)pgint_irq);
|
|
device_destroy(felica_class, devid_felica_int_poll);
|
|
cdev_del(&cdev_felica_int_poll);
|
|
unregister_chrdev_region(devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(enable_irq_wake), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
#else
|
|
ret = enable_irq_wake(gpio_to_irq(gfelica_irq_int_pin));
|
|
if (ret < 0) {
|
|
free_irq(gpio_to_irq(gfelica_irq_int_pin), (void *)pgint_irq);
|
|
device_destroy(felica_class, devid_felica_int_poll);
|
|
cdev_del(&cdev_felica_int_poll);
|
|
unregister_chrdev_region(devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(enable_irq_wake), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
#endif // CONFIG_MACH_KLTE
|
|
#else
|
|
ret = enable_irq_wake(gpio_to_irq(GPIO_PINID_FELICA_INT_REV03));
|
|
if (ret < 0) {
|
|
free_irq(gpio_to_irq(
|
|
GPIO_PINID_FELICA_INT_REV03),
|
|
(void *)pgint_irq);
|
|
device_destroy(felica_class, devid_felica_int_poll);
|
|
cdev_del(&cdev_felica_int_poll);
|
|
unregister_chrdev_region(devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(enable_irq_wake), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
#endif /* CONFIG_ARCH_MSM8974 */
|
|
pgint_irq->irq_done = 0;
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__, \
|
|
MAJOR(devid_felica_int_poll),
|
|
MINOR(devid_felica_int_poll));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void felica_int_poll_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
disable_irq(gpio_to_irq(GPIO_PINID_FELICA_INT));
|
|
free_irq(gpio_to_irq(
|
|
GPIO_PINID_FELICA_INT),
|
|
(void *)pgint_irq);
|
|
#else
|
|
disable_irq(gpio_to_irq(gfelica_irq_int_pin));
|
|
free_irq(gpio_to_irq(
|
|
gfelica_irq_int_pin),
|
|
(void *)pgint_irq);
|
|
#endif // CONFIG_MACH_KLTE
|
|
#else
|
|
disable_irq(gpio_to_irq(GPIO_PINID_FELICA_INT_REV03));
|
|
free_irq(gpio_to_irq(
|
|
GPIO_PINID_FELICA_INT_REV03),
|
|
(void *)pgint_irq);
|
|
#endif
|
|
device_destroy(felica_class, devid_felica_int_poll);
|
|
cdev_del(&cdev_felica_int_poll);
|
|
unregister_chrdev_region(
|
|
devid_felica_int_poll,
|
|
FELICA_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_int_poll_open(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_int_poll_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t felica_int_poll_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret;
|
|
char retparam;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (!pgint_irq->irq_done) {
|
|
ret =
|
|
wait_event_interruptible(pgint_irq->read_wait,
|
|
pgint_irq->irq_done == 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR
|
|
(" %s ERROR(wait_event_interruptible),ret=[%d]",\
|
|
__func__, ret);
|
|
return -EINTR;
|
|
}
|
|
}
|
|
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
ret = gpio_get_value(GPIO_PINID_FELICA_INT);
|
|
#else
|
|
ret = gpio_get_value(gfelica_irq_int_pin);
|
|
#endif // CONFIG_MACH_KLTE
|
|
#else
|
|
ret = gpio_get_value(GPIO_PINID_FELICA_INT_REV03);
|
|
#endif
|
|
if (ret == GPIO_VALUE_HIGH) {
|
|
retparam = FELICA_INT_HIGH;
|
|
FELICA_PR_INFO(" INT-PIN value is [%d][HIGH]", retparam);
|
|
} else if (ret == GPIO_VALUE_LOW) {
|
|
retparam = FELICA_INT_LOW;
|
|
FELICA_PR_INFO(" INT-PIN value is [%d][LOW]", retparam);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(gpio_get_value), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = copy_to_user(buf, &retparam, FELICA_INT_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
pgint_irq->irq_done = 0;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return FELICA_INT_DATA_LEN;
|
|
}
|
|
|
|
/*
|
|
* poll operation
|
|
*/
|
|
static unsigned int felica_int_poll_poll(struct file *file, poll_table *wait)
|
|
{
|
|
unsigned int mask = 0;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
poll_wait(file, &pgint_irq->read_wait, wait);
|
|
if (pgint_irq->irq_done)
|
|
mask = POLLIN | POLLRDNORM;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return mask;
|
|
}
|
|
/******************************************************************************
|
|
* /dev/felica_uid
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_felica_uid;
|
|
static struct cdev cdev_felica_uid;
|
|
static const struct file_operations fops_felica_uid = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_uid_open,
|
|
.release = felica_uid_close,
|
|
.unlocked_ioctl = felica_uid_ioctl,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void felica_uid_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_uid;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_uid = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_uid, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_UID_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_uid, &fops_felica_uid);
|
|
ret = cdev_add(&cdev_felica_uid, devid_felica_uid, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_uid, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_uid =
|
|
device_create(felica_class, NULL, devid_felica_uid, NULL,
|
|
FELICA_UID_NAME);
|
|
if (IS_ERR(device_felica_uid)) {
|
|
cdev_del(&cdev_felica_uid);
|
|
unregister_chrdev_region(devid_felica_uid, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_felica_uid), MINOR(devid_felica_uid));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void felica_uid_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
if (gdiag_name[0] != 0x00) {
|
|
device_destroy(felica_class, devid_felica_uid);
|
|
cdev_del(&cdev_felica_uid);
|
|
unregister_chrdev_region(devid_felica_uid, \
|
|
FELICA_MINOR_COUNT);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_uid_open(struct inode *inode, struct file *file)
|
|
{
|
|
int ret = 0;
|
|
char *cmdpos;
|
|
static char cmdline[1025];
|
|
static unsigned long start_adr, end_adr, leng;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
start_adr = current->mm->arg_start;
|
|
end_adr = current->mm->arg_end;
|
|
leng = end_adr - start_adr;
|
|
|
|
if (1024 < leng)
|
|
leng = 1024;
|
|
|
|
cmdpos = (char *)(current->mm->arg_start);
|
|
ret = copy_from_user(cmdline, cmdpos, leng);
|
|
cmdline[leng] = '\0';
|
|
if(ret != 0)
|
|
{
|
|
FELICA_PR_ERR(" %s cmdline[%s] ret[%d]", __func__, cmdline, ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (strncmp(cmdline, gdiag_name, leng) != 0) {
|
|
FELICA_PR_INFO(" %s ERROR, %s gdiag %s", \
|
|
__func__, cmdline, gdiag_name);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_uid_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* uid registration
|
|
*/
|
|
static long felica_uid_ioctl(struct file *file, unsigned int cmd,
|
|
unsigned long arg)
|
|
{
|
|
FELICA_PR_DBG(" %s START, cmd=[%d]", __func__, cmd);
|
|
|
|
switch (cmd) {
|
|
case SET_FELICA_UID_DIAG:
|
|
gdiag_uid = *((int *)arg);
|
|
FELICA_PR_INFO("Set gdiag_uid to [%d]", gdiag_uid);
|
|
break;
|
|
default:
|
|
FELICA_PR_ERR(" %s ERROR(unknown command)", __func__);
|
|
break;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* /dev/felica_ant
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_felica_ant;
|
|
static struct cdev cdev_felica_ant;
|
|
static const struct file_operations fops_felica_ant = {
|
|
.owner = THIS_MODULE,
|
|
.open = felica_ant_open,
|
|
.release = felica_ant_close,
|
|
.read = felica_ant_read,
|
|
.write = felica_ant_write,
|
|
};
|
|
|
|
/*
|
|
* felica_ant_init
|
|
*/
|
|
static void felica_ant_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_felica_ant;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_felica_ant = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_felica_ant, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, FELICA_ANT_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_felica_ant, &fops_felica_ant);
|
|
ret = cdev_add(&cdev_felica_ant, devid_felica_ant, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_felica_ant, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_felica_ant =
|
|
device_create(felica_class, NULL, devid_felica_ant, NULL,
|
|
FELICA_ANT_NAME);
|
|
if (IS_ERR(device_felica_ant)) {
|
|
cdev_del(&cdev_felica_ant);
|
|
unregister_chrdev_region(devid_felica_ant, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_felica_ant), MINOR(devid_felica_ant));
|
|
}
|
|
|
|
/*
|
|
* felica_ant_exit
|
|
*/
|
|
static void felica_ant_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_felica_ant);
|
|
cdev_del(&cdev_felica_ant);
|
|
unregister_chrdev_region(devid_felica_ant, FELICA_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int felica_ant_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//high
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN HIGH", __func__);
|
|
of_sii8240_hw_poweron(FELICA_CEN_UNLOCK);
|
|
}
|
|
#endif
|
|
|
|
uid = __task_cred(current)->uid;
|
|
if ((uid != gant_uid) && (uid != gdiag_uid)) {
|
|
FELICA_PR_ERR(\
|
|
" %s END -EACCES, uid=[%d], gant_uid=[%d]\n", __func__, uid, gant_uid);
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//low
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN LOW", __func__);
|
|
// of_sii8240_hw_poweron(FELICA_CEN_LOCK);
|
|
}
|
|
#endif
|
|
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int felica_ant_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//low
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN LOW", __func__);
|
|
// of_sii8240_hw_poweron(FELICA_CEN_LOCK);
|
|
}
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END system_rev=[%d]", __func__,system_rev);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t felica_ant_read(struct file *file, char __user *buf, \
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret;
|
|
unsigned char address = gi2c_antaddress;
|
|
unsigned char read_buff = 0;
|
|
struct i2c_msg read_msgs[2];
|
|
|
|
read_msgs[0].flags = gread_msgs[0].flags;
|
|
read_msgs[0].len = gread_msgs[0].len;
|
|
read_msgs[1].flags = gread_msgs[1].flags;
|
|
read_msgs[1].len = gread_msgs[1].len;
|
|
|
|
read_msgs[0].addr = gi2c_address;
|
|
read_msgs[0].buf = &address;
|
|
read_msgs[1].addr = gi2c_address;
|
|
read_msgs[1].buf = &read_buff;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
if (felica_i2c_client == NULL) {
|
|
FELICA_PR_ERR(" %s -EIO felica_i2c_client is NULL", \
|
|
__func__);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[0], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[0]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[1], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[1]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
FELICA_PR_INFO(" %s read_buff=[%d]", __func__, read_buff);
|
|
|
|
ret = copy_to_user(buf, &read_buff, FELICA_ANT_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return FELICA_ANT_DATA_LEN;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t felica_ant_write(struct file *file, const char __user *data,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
char ant;
|
|
int ret;
|
|
unsigned char write_buff[2];
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (felica_i2c_client == NULL) {
|
|
FELICA_PR_ERR(" %s -EIO felica_i2c_client is NULL", \
|
|
__func__);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = copy_from_user(&ant, data, FELICA_ANT_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
write_buff[0] = gi2c_antaddress;
|
|
write_buff[1] = ant;
|
|
gwrite_msgs[0].buf = &write_buff[0];
|
|
gwrite_msgs[0].addr = gi2c_address;
|
|
|
|
ret = i2c_transfer(felica_i2c_client->adapter, gwrite_msgs, 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return FELICA_ANT_DATA_LEN;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Mobile FeliCa device driver initialization / termination function
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* to set initial value to each terminal
|
|
*/
|
|
static void felica_initialize_pin(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ice_gpiox_set(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if !defined(CONFIG_MACH_KLTE_KDI) && !defined(CONFIG_MACH_KLTE_DCM) && !defined(CONFIG_MACH_KLTE_SBM) // We are not doing the initialization here. felica_register_device() does it and sets up the initial pin value to LOW.
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#endif
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* to set final value to each terminal
|
|
*/
|
|
static void felica_finalize_pin(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ice_gpiox_set(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if !defined (CONFIG_MACH_KLTE_KDI) && !defined (CONFIG_MACH_KLTE_DCM) && !defined(CONFIG_MACH_KLTE_SBM) // We are not doing the initialization here. felica_register_device() does it and sets up the initial pin value to LOW.
|
|
gpio_set_value(GPIO_PINID_FELICA_PON, GPIO_VALUE_LOW);
|
|
#endif
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* device driver registration
|
|
*/
|
|
static void felica_register_device(void)
|
|
{
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
struct device *dev = &felica_gpio_pdev->dev;
|
|
struct device_node *np;
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
if (!dev)
|
|
{
|
|
FELICA_PR_ERR(" %s ERROR NULL", __func__);
|
|
return;
|
|
}
|
|
|
|
np = dev->of_node;
|
|
|
|
if(system_rev <=8)
|
|
{
|
|
gfelica_pon_pin = of_get_named_gpio(np, "felica,pon-gpio", 0);
|
|
if(gfelica_pon_pin < 0)
|
|
{
|
|
FELICA_PR_ERR(" %s ERROR(), gfelica_pon_pin=[%d]",__func__, gfelica_pon_pin);
|
|
return;
|
|
}
|
|
|
|
gpio_tlmm_config(GPIO_CFG(gfelica_pon_pin, GPIOMUX_FUNC_GPIO,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
FELICA_PR_INFO(" %s gfelica_pon_pin [%d]",__func__, gpio_get_value(gfelica_pon_pin));
|
|
}
|
|
|
|
gpio_set_value(gfelica_pon_pin, GPIO_VALUE_LOW);
|
|
|
|
gfelica_hsel_pin = of_get_named_gpio (np, "felica,hsel-gpio", 0);
|
|
if(gfelica_hsel_pin < 0)
|
|
{
|
|
FELICA_PR_ERR(" %s ERROR(), ret=[%d]",__func__, gfelica_hsel_pin);
|
|
return;
|
|
}
|
|
FELICA_PR_INFO(" %s gfelica_hsel_pin [%d]",__func__, gfelica_hsel_pin);
|
|
|
|
if (system_rev >= g_uicc_initrev)
|
|
{
|
|
gpio_tlmm_config(GPIO_CFG(gfelica_hsel_pin, GPIOMUX_FUNC_GPIO,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
FELICA_PR_INFO(" %s gfelica_hsel_pin [%d]",__func__, gpio_get_value(gfelica_hsel_pin));
|
|
}
|
|
|
|
gpio_set_value(gfelica_hsel_pin, GPIO_VALUE_LOW);
|
|
|
|
#if defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
|
|
gfelica_sps_pin = of_get_named_gpio(np, "felica,sps-gpio", 0);
|
|
if(gfelica_sps_pin < 0)
|
|
{
|
|
FELICA_PR_ERR(" %s ERROR(), ret=[%d]",__func__, gfelica_sps_pin);
|
|
return;
|
|
}
|
|
FELICA_PR_INFO(" %s gfelica_sps_pin [%d]",__func__, gfelica_sps_pin);
|
|
|
|
if (system_rev >= g_uicc_initrev)
|
|
{
|
|
gpio_tlmm_config(GPIO_CFG(gfelica_sps_pin, GPIOMUX_FUNC_GPIO,
|
|
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
|
|
GPIO_CFG_ENABLE);
|
|
FELICA_PR_INFO(" %s gfelica_sps_pin [%d]",__func__, gpio_get_value(gfelica_sps_pin));
|
|
}
|
|
|
|
#endif
|
|
#else
|
|
felica_int_poll_init();
|
|
#endif //CONFIG_MACH_KLTE
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* device driver deregistration
|
|
*/
|
|
static void felica_deregister_device(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
felica_uid_exit();
|
|
#if !defined(CONFIG_ARCH_MSM8974) && !defined(CONFIG_ARCH_MSM8974PRO)
|
|
felica_int_poll_exit();
|
|
#endif
|
|
|
|
felica_ant_exit();
|
|
felica_rws_exit();
|
|
felica_rfs_exit();
|
|
felica_cen_exit();
|
|
felica_pon_exit();
|
|
felica_uart_exit();
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
static struct of_device_id felica_of_match[] =
|
|
{
|
|
{ .compatible = "felica,gpio-table",
|
|
},
|
|
{}
|
|
};
|
|
static int __devexit felica_gpio_remove(struct platform_device *pdev)
|
|
{
|
|
felica_int_poll_exit();
|
|
return 0;
|
|
}
|
|
static struct platform_driver felica_of_driver =
|
|
{
|
|
.remove = __devexit_p(felica_gpio_remove),
|
|
.driver =
|
|
{
|
|
.name = FELICA_GPIO_DRIVER_NAME,
|
|
.owner = THIS_MODULE,
|
|
.of_match_table = felica_of_match,
|
|
},
|
|
};
|
|
|
|
static int __init felica_gpio_probe(struct platform_device *pdev)
|
|
{
|
|
felica_gpio_pdev = pdev;
|
|
if (felica_gpio_pdev == NULL) {
|
|
FELICA_PR_ERR(" %s -EIO felica_gpio_pdev is NULL", \
|
|
__func__);
|
|
return -EIO;
|
|
}
|
|
felica_register_device();
|
|
schedule_delayed_work(&pgint_irq->work, msecs_to_jiffies(10));
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* The entry point for initialization module
|
|
*/
|
|
static int __init felica_init(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
#ifdef F_WAKE_LOCK
|
|
wake_lock_init(&felica_wake_1, WAKE_LOCK_SUSPEND, "felica-int-1");
|
|
wake_lock_init(&felica_wake_2, WAKE_LOCK_SUSPEND, "felica-int-2");
|
|
#endif
|
|
felica_class = class_create(THIS_MODULE, "felica");
|
|
if (IS_ERR(felica_class)) {
|
|
FELICA_PR_ERR(" %s ERROR(class_create)", __func__);
|
|
return PTR_ERR(felica_class);
|
|
}
|
|
|
|
felica_initialize_pin();
|
|
#if !defined(CONFIG_ARCH_MSM8974) && !defined(CONFIG_ARCH_MSM8974PRO)
|
|
felica_register_device();
|
|
#endif
|
|
felica_nl_init();
|
|
felica_i2c_init();
|
|
uicc_init();
|
|
/* MFC UID registration */
|
|
#if !defined(CONFIG_ARCH_MSM8974) && !defined(CONFIG_ARCH_MSM8974PRO)
|
|
schedule_delayed_work(&pgint_irq->work, msecs_to_jiffies(10));
|
|
#endif
|
|
|
|
#ifdef CONFIG_NFC_FELICA
|
|
|
|
/* FELICA_INTU GPIO is changed Start*/
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
felica_varying_gpio_intu = GPIO_PINID_NFC_INTU;
|
|
#else
|
|
if (system_rev > 0 && system_rev < 15)
|
|
felica_varying_gpio_intu = GPIO_PINID_NFC_INTU_REV03;
|
|
else
|
|
felica_varying_gpio_intu = GPIO_PINID_NFC_INTU_REV06;
|
|
#endif
|
|
FELICA_PR_INFO(" %s , system_rev=[%d]", __func__, system_rev);
|
|
/* FELICA_INTU GPIO is changed End */
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
felica_int_poll_init();
|
|
#endif // CONFIG_MACH_KLTE
|
|
snfc_register_device();
|
|
uartcc_init();
|
|
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
return platform_driver_probe(&felica_of_driver, felica_gpio_probe);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* The entry point for the termination module
|
|
*/
|
|
static void __exit felica_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
#ifdef F_WAKE_LOCK
|
|
wake_lock_destroy(&felica_wake_1);
|
|
wake_lock_destroy(&felica_wake_2);
|
|
#endif
|
|
uicc_exit();
|
|
felica_i2c_exit();
|
|
felica_nl_exit();
|
|
felica_deregister_device();
|
|
#ifdef CONFIG_NFC_FELICA
|
|
snfc_deregister_device();
|
|
snfc_uart_exit();
|
|
uartcc_exit();
|
|
snfc_cen_exit();
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
felica_finalize_pin();
|
|
class_destroy(felica_class);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
*
|
|
*
|
|
*
|
|
* Add driver code for CXD2235AGG NFC/Felica combo IC
|
|
*
|
|
*
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
#ifdef CONFIG_NFC_FELICA
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_hsel
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_snfc_hsel;
|
|
static struct cdev hsel_cdev;
|
|
static const struct file_operations hsel_fileops = {
|
|
.owner = THIS_MODULE,
|
|
.read = hsel_read,
|
|
.write = hsel_write,
|
|
.open = hsel_open,
|
|
.release = hsel_release,
|
|
};
|
|
|
|
/* function prototype */
|
|
static int hsel_init(void)
|
|
{
|
|
int ret = 0;
|
|
struct device *class_dev;
|
|
devid_snfc_hsel = MKDEV(MISC_MAJOR, 0);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = alloc_chrdev_region(&devid_snfc_hsel, 0, HSEL_DEV_COUNT,
|
|
HSEL_DEV_NAME);
|
|
|
|
if (0 != ret) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
cdev_init(&hsel_cdev, &hsel_fileops);
|
|
hsel_cdev.owner = THIS_MODULE;
|
|
|
|
ret = cdev_add(&hsel_cdev, devid_snfc_hsel, HSEL_DEV_COUNT);
|
|
if (0 != ret) {
|
|
unregister_chrdev_region(devid_snfc_hsel, HSEL_DEV_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
class_dev = device_create(felica_class, NULL, devid_snfc_hsel,
|
|
NULL, HSEL_DEV_NAME);
|
|
if (0 != IS_ERR(class_dev)) {
|
|
cdev_del(&hsel_cdev);
|
|
unregister_chrdev_region(devid_snfc_hsel, HSEL_DEV_COUNT);
|
|
ret = PTR_ERR(class_dev);
|
|
FELICA_PR_ERR(" %s ERROR(device_create), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void hsel_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_snfc_hsel);
|
|
|
|
cdev_del(&hsel_cdev);
|
|
unregister_chrdev_region(devid_snfc_hsel, HSEL_DEV_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int hsel_open(struct inode *inode, struct file *file)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int hsel_release(struct inode *inode, struct file *file)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t hsel_read(struct file *file, char __user *buf, size_t len,
|
|
loff_t *ppos)
|
|
{
|
|
char hsel_val;
|
|
int ret = -EINVAL;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (NULL == buf) {
|
|
FELICA_PR_ERR(" %s hsel_read param err", __func__);
|
|
return -EIO;
|
|
}
|
|
|
|
if (1 > len) {
|
|
FELICA_PR_ERR(
|
|
" %s length check len = %d", __func__, len);
|
|
return -EIO;
|
|
}
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
ret = gpio_get_value(GPIO_PINID_NFC_HSEL);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ret = ice_gpiox_get(GPIO_PINID_NFC_HSEL);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
ret = gpio_get_value(gfelica_hsel_pin);
|
|
#endif
|
|
if (0 > ret) {
|
|
FELICA_PR_ERR(" %s ERROR(gpio_get_value), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
if (0 == ret)
|
|
hsel_val = 0;
|
|
else
|
|
hsel_val = 1;
|
|
|
|
if (copy_to_user(buf, &hsel_val, 1)) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user)", __func__);
|
|
return -EFAULT;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t hsel_write(struct file *file, const char __user *data,\
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
char hsel_val;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (NULL == data) {
|
|
FELICA_PR_ERR(" %s hsel_write param err", __func__);
|
|
return -EIO;
|
|
}
|
|
|
|
if (1 > len) {
|
|
FELICA_PR_ERR(
|
|
" %s length check len = %d",
|
|
__func__, len);
|
|
return -EIO;
|
|
}
|
|
|
|
if (copy_from_user(&hsel_val, data, 1)) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user)", __func__);
|
|
return -EFAULT;
|
|
}
|
|
if (0 == hsel_val) {
|
|
FELICA_PR_INFO(" %s HSEL = Low", __func__);
|
|
} else if (1 == hsel_val) {
|
|
FELICA_PR_INFO(" %s HSEL = High", __func__);
|
|
} else {
|
|
FELICA_PR_ERR(" param err = %d", hsel_val);
|
|
return -EIO;
|
|
}
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
gpio_set_value(GPIO_PINID_NFC_HSEL , hsel_val);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ice_gpiox_set(GPIO_PINID_NFC_HSEL , hsel_val);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
gpio_set_value(gfelica_hsel_pin , hsel_val);
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_intu_poll
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_snfc_intu_poll;
|
|
static struct cdev intu_poll_cdev;
|
|
static struct poll_data g_intu_data;
|
|
static struct poll_data *g_intu_d = &g_intu_data;
|
|
static const struct file_operations intu_poll_fileops = {
|
|
.owner = THIS_MODULE,
|
|
.read = intu_poll_read,
|
|
.open = intu_poll_open,
|
|
.release = intu_poll_release,
|
|
/* .poll = intu_poll_poll,*/
|
|
};
|
|
|
|
/*
|
|
* top half of irq_handler
|
|
*/
|
|
static irqreturn_t intu_poll_irq_handler(int irq, void *dev_id)
|
|
{
|
|
struct poll_data *intu_d = g_intu_d;
|
|
|
|
FELICA_PR_DBG(" %s START irq = %d", __func__, irq);
|
|
|
|
disable_irq_nosync(gpio_to_irq(felica_varying_gpio_intu));
|
|
|
|
schedule_delayed_work(&intu_d->work, 0);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
/*
|
|
* bottom half of irq_handler
|
|
*/
|
|
static void intu_poll_work_func(struct work_struct *work)
|
|
{
|
|
struct poll_data *intu_d = g_intu_d;
|
|
int read_value = 0;
|
|
int old_value = 0;
|
|
unsigned long irqflag = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
old_value = intu_d->device_status;
|
|
|
|
read_value = gpio_get_value(felica_varying_gpio_intu);
|
|
|
|
FELICA_PR_INFO(" %s read_value = %d old_value = %d",
|
|
__func__, read_value, old_value);
|
|
|
|
if (read_value < 0) {
|
|
intu_d->read_error = read_value;
|
|
} else if (read_value != old_value) {
|
|
intu_d->device_status = read_value;
|
|
intu_d->read_error = 0;
|
|
|
|
if (intu_d->device_status == INTU_POLL_DEV_LOW)
|
|
irqflag = IRQF_TRIGGER_HIGH | IRQF_SHARED;
|
|
else
|
|
irqflag = IRQF_TRIGGER_LOW | IRQF_SHARED;
|
|
|
|
if (irq_set_irq_type(gpio_to_irq(felica_varying_gpio_intu),
|
|
irqflag)) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(set_irq_type), irqflag=[%ld]",
|
|
__func__, irqflag);
|
|
}
|
|
}
|
|
|
|
enable_irq(gpio_to_irq(felica_varying_gpio_intu));
|
|
|
|
if (read_value != old_value || intu_d->read_error) {
|
|
intu_d->irq_handler_done = 1;
|
|
wake_up_interruptible(&intu_d->read_wait);
|
|
}
|
|
FELICA_PR_DBG(
|
|
" %s END read_value = %d, old_value = %d, intu_d->read_error = %d",
|
|
__func__, read_value, old_value, intu_d->read_error);
|
|
}
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static int intu_poll_init(void)
|
|
{
|
|
int ret = 0;
|
|
struct device *class_dev;
|
|
unsigned long irqflag = 0;
|
|
|
|
devid_snfc_intu_poll = MKDEV(MISC_MAJOR, 0);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = alloc_chrdev_region(&devid_snfc_intu_poll,
|
|
0, INTU_POLL_DEV_COUNT, INTU_POLL_DEV_NAME);
|
|
if (ret) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
cdev_init(&intu_poll_cdev, &intu_poll_fileops);
|
|
intu_poll_cdev.owner = THIS_MODULE;
|
|
|
|
ret = cdev_add(&intu_poll_cdev,
|
|
devid_snfc_intu_poll,
|
|
INTU_POLL_DEV_COUNT);
|
|
if (ret) {
|
|
unregister_chrdev_region(
|
|
devid_snfc_intu_poll,
|
|
INTU_POLL_DEV_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
class_dev = device_create(felica_class,
|
|
NULL, devid_snfc_intu_poll, NULL,
|
|
INTU_POLL_DEV_NAME);
|
|
if (IS_ERR(class_dev)) {
|
|
cdev_del(&intu_poll_cdev);
|
|
unregister_chrdev_region(
|
|
devid_snfc_intu_poll, INTU_POLL_DEV_COUNT);
|
|
ret = PTR_ERR(class_dev);
|
|
FELICA_PR_ERR(" %s ERROR(device_create), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
memset(g_intu_d, 0x00, sizeof(struct poll_data));
|
|
|
|
INIT_DELAYED_WORK(&g_intu_d->work, intu_poll_work_func);
|
|
|
|
init_waitqueue_head(&g_intu_d->read_wait);
|
|
|
|
g_intu_d->open_flag = 0;
|
|
|
|
if (g_intu_d->open_flag) {
|
|
FELICA_PR_ERR(" %s only one time", __func__);
|
|
return 0;
|
|
}
|
|
g_intu_d->open_flag = 1;
|
|
|
|
ret = gpio_get_value(felica_varying_gpio_intu);
|
|
if (ret < 0) {
|
|
g_intu_d->open_flag = 0;
|
|
FELICA_PR_ERR(" %s ERROR(gpio_get_value), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
g_intu_d->device_status = ret;
|
|
|
|
if (g_intu_d->device_status == INTU_POLL_DEV_LOW)
|
|
irqflag = IRQF_TRIGGER_HIGH | IRQF_SHARED;
|
|
else
|
|
irqflag = IRQF_TRIGGER_LOW | IRQF_SHARED;
|
|
|
|
if (request_irq(gpio_to_irq(felica_varying_gpio_intu),
|
|
intu_poll_irq_handler, irqflag, INTU_POLL_DEV_NAME,
|
|
(void *)g_intu_d)) {
|
|
g_intu_d->open_flag = 0;
|
|
FELICA_PR_ERR(" %s ERROR(request_irq), irqflag=[%ld]",
|
|
__func__, irqflag);
|
|
return -EIO;
|
|
}
|
|
g_intu_d->irq_handler_done = 0;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void intu_poll_exit(void)
|
|
{
|
|
struct poll_data *intu_d = g_intu_d;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
cancel_delayed_work(&intu_d->work);
|
|
free_irq(gpio_to_irq(felica_varying_gpio_intu), (void *)intu_d);
|
|
|
|
intu_d->open_flag = 0;
|
|
|
|
cdev_del(&intu_poll_cdev);
|
|
unregister_chrdev_region(devid_snfc_intu_poll, INTU_POLL_DEV_COUNT);
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int intu_poll_open(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int intu_poll_release(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t intu_poll_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
struct poll_data *intu_d = g_intu_d;
|
|
int ret;
|
|
char cret;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (len < 1) {
|
|
FELICA_PR_ERR(
|
|
" %s length check len = %d", __func__, len);
|
|
return -EIO;
|
|
}
|
|
|
|
if (!intu_d->irq_handler_done) {
|
|
if (file->f_flags & O_NONBLOCK) {
|
|
FELICA_PR_ERR(" NONBLOCK");
|
|
return -EAGAIN;
|
|
}
|
|
FELICA_PR_INFO(" NFC intu_poll wait irq");
|
|
ret = wait_event_interruptible(intu_d->read_wait,
|
|
intu_d->irq_handler_done == 1);
|
|
if (-ERESTARTSYS == ret) {
|
|
FELICA_PR_ERR(
|
|
" %s -EINTR wait_event_interruptible ret = %d",
|
|
__func__, ret);
|
|
return -EINTR;
|
|
}
|
|
}
|
|
|
|
if (intu_d->read_error) {
|
|
intu_d->irq_handler_done = 0;
|
|
intu_d->read_error = 0;
|
|
FELICA_PR_ERR(" %s intu_d->read_error = %d",
|
|
__func__, intu_d->read_error);
|
|
return -EIO;
|
|
}
|
|
|
|
if (intu_d->device_status == INTU_POLL_DEV_HIGH)
|
|
cret = 1;
|
|
else
|
|
cret = 0;
|
|
|
|
len = 1;
|
|
|
|
if (copy_to_user(buf, &cret, len)) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user)", __func__);
|
|
return -EFAULT;
|
|
}
|
|
intu_d->irq_handler_done = 0;
|
|
|
|
FELICA_PR_DBG(
|
|
" %s END len = %d, cret = %d", __func__, len, cret);
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_available_poll
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_snfc_abailable_poll;
|
|
static struct cdev available_poll_cdev;
|
|
static const struct file_operations available_poll_fileops = {
|
|
.owner = THIS_MODULE,
|
|
.unlocked_ioctl = available_poll_ioctl,
|
|
.read = available_poll_read,
|
|
.open = available_poll_open,
|
|
.release = available_poll_release,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static int available_poll_init(void)
|
|
{
|
|
int ret = 0;
|
|
struct device *class_dev;
|
|
|
|
devid_snfc_abailable_poll = MKDEV(MISC_MAJOR, 0);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = alloc_chrdev_region(&devid_snfc_abailable_poll, 0,
|
|
AVAILABLE_POLL_DEV_COUNT, AVAILABLE_POLL_DEV_NAME);
|
|
if (ret) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
cdev_init(&available_poll_cdev, &available_poll_fileops);
|
|
available_poll_cdev.owner = THIS_MODULE;
|
|
|
|
ret = cdev_add(&available_poll_cdev, devid_snfc_abailable_poll,
|
|
AVAILABLE_POLL_DEV_COUNT);
|
|
if (ret) {
|
|
unregister_chrdev_region(devid_snfc_abailable_poll,
|
|
AVAILABLE_POLL_DEV_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
class_dev = device_create(felica_class, NULL, devid_snfc_abailable_poll,
|
|
NULL, AVAILABLE_POLL_DEV_NAME);
|
|
|
|
if (IS_ERR(class_dev)) {
|
|
cdev_del(&available_poll_cdev);
|
|
unregister_chrdev_region(devid_snfc_abailable_poll,
|
|
AVAILABLE_POLL_DEV_COUNT);
|
|
ret = PTR_ERR(class_dev);
|
|
FELICA_PR_ERR(" %s ERROR(device_create), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
memset((void *)&g_available_data, 0x00, sizeof(struct icc_poll_data));
|
|
|
|
init_waitqueue_head(&g_available_data.read_wait);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void available_poll_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_snfc_abailable_poll);
|
|
|
|
cdev_del(&available_poll_cdev);
|
|
unregister_chrdev_region(devid_snfc_abailable_poll,
|
|
AVAILABLE_POLL_DEV_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int available_poll_open(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int available_poll_release(struct inode *inode, struct file *file)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
if (g_available_data.available_flag == 1) {
|
|
g_available_data.rsp_done = 1;
|
|
wake_up_interruptible(&g_available_data.read_wait);
|
|
}
|
|
g_available_data.rsp_done = 0;
|
|
g_available_data.available_flag = 0;
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t available_poll_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
char type = 0;
|
|
int nRet = -1;
|
|
struct icc_poll_data *available_d = &g_available_data;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if ((!uartcc_is_idle_status()) ||
|
|
(0 == g_cen_sts) ||
|
|
(GPIO_VALUE_LOW == g_rfs_sts)) {
|
|
|
|
available_d->available_flag = 1;
|
|
nRet = wait_event_interruptible(available_d->read_wait,
|
|
available_d->rsp_done == 1);
|
|
if (nRet < 0) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(wait_event_interruptible), ret=[%d]"
|
|
, __func__, nRet);
|
|
return -EIO;
|
|
}
|
|
type = 0x01;
|
|
available_d->rsp_done = 0;
|
|
available_d->available_flag = 0;
|
|
} else {
|
|
type = 0x01;
|
|
}
|
|
|
|
if (copy_to_user(buf, &type, len)) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user)", __func__);
|
|
return -EFAULT;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END read size = %d ", __func__, len);
|
|
|
|
return len;
|
|
}
|
|
|
|
/*
|
|
* available operation
|
|
*/
|
|
static long available_poll_ioctl(struct file *file, unsigned int cmd,
|
|
unsigned long arg)
|
|
{
|
|
long nRet = -EIO;
|
|
|
|
FELICA_PR_DBG(" %s START cmd = %x", __func__, cmd);
|
|
switch (cmd) {
|
|
case AVAILABLE_POLL_DEV_SET_PRE_LOCK:
|
|
g_cen_sts = 0;
|
|
nRet = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
FELICA_PR_DBG(" %s END cmd = %x", __func__, cmd);
|
|
return nRet;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_rfs_poll
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_snfc_rfs_poll;
|
|
static struct cdev rfs_poll_cdev;
|
|
static struct poll_data g_rfs_data;
|
|
static struct poll_data *g_rfs_d = &g_rfs_data;
|
|
static const struct file_operations rfs_poll_fileops = {
|
|
.owner = THIS_MODULE,
|
|
.read = rfs_poll_read,
|
|
.open = rfs_poll_open,
|
|
.release = rfs_poll_release,
|
|
.poll = rfs_poll_poll,
|
|
};
|
|
|
|
/*
|
|
* top half of irq_handler
|
|
*/
|
|
static irqreturn_t rfs_poll_irq_handler(int irq, void *dev_id)
|
|
{
|
|
struct poll_data *rfs_d = g_rfs_d;
|
|
|
|
FELICA_PR_DBG(" %s START irq = %d", __func__, irq);
|
|
|
|
disable_irq_nosync(gpio_to_irq(GPIO_PINID_NFC_RFS_POLL));
|
|
|
|
schedule_delayed_work(&rfs_d->work, msecs_to_jiffies(RFS_POLL_DELAY));
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
/*
|
|
* bottom half of irq_handler
|
|
*/
|
|
static void rfs_poll_work_func(struct work_struct *work)
|
|
{
|
|
struct poll_data *rfs_d = g_rfs_d;
|
|
int read_value = 0;
|
|
int old_value = 0;
|
|
unsigned long irqflag = 0;
|
|
struct icc_poll_data *available_d = &g_available_data;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
old_value = rfs_d->device_status;
|
|
|
|
read_value = gpio_get_value(GPIO_PINID_NFC_RFS_POLL);
|
|
|
|
FELICA_PR_INFO(" %s read_value = %d old_value = %d",
|
|
__func__ , read_value, old_value);
|
|
|
|
if (read_value < 0) {
|
|
rfs_d->read_error = read_value;
|
|
} else if (read_value != old_value) {
|
|
g_rfs_sts = read_value;
|
|
if (1 == available_d->available_flag) {
|
|
if (0 != g_cen_sts) {
|
|
if (GPIO_VALUE_LOW != g_rfs_sts) {
|
|
if (uartcc_is_idle_status()) {
|
|
FELICA_PR_INFO(
|
|
" %s wake up available",
|
|
__func__);
|
|
available_d->rsp_done = 1;
|
|
wake_up_interruptible(
|
|
&available_d->read_wait);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
rfs_d->device_status = read_value;
|
|
rfs_d->read_error = 0;
|
|
|
|
if (rfs_d->device_status == RFS_POLL_DEV_LOW)
|
|
irqflag = IRQF_TRIGGER_HIGH | IRQF_SHARED;
|
|
else
|
|
irqflag = IRQF_TRIGGER_LOW | IRQF_SHARED;
|
|
|
|
if (irq_set_irq_type(
|
|
gpio_to_irq(GPIO_PINID_NFC_RFS_POLL), irqflag)) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(set_irq_type), irqflag=[%ld]",
|
|
__func__, irqflag);
|
|
}
|
|
}
|
|
|
|
enable_irq(gpio_to_irq(GPIO_PINID_NFC_RFS_POLL));
|
|
|
|
if (read_value != old_value || rfs_d->read_error) {
|
|
rfs_d->irq_handler_done = 1;
|
|
wake_up_interruptible(&rfs_d->read_wait);
|
|
}
|
|
|
|
FELICA_PR_INFO(
|
|
" %s END read_value = %d,old_value = %d,rfs_d->read_error = %d",
|
|
__func__, read_value, old_value, rfs_d->read_error);
|
|
}
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static int rfs_poll_init(void)
|
|
{
|
|
int ret = 0;
|
|
struct device *class_dev;
|
|
unsigned long irqflag = 0;
|
|
|
|
devid_snfc_rfs_poll = MKDEV(MISC_MAJOR, 0);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = alloc_chrdev_region(&devid_snfc_rfs_poll , 0 , RFS_POLL_DEV_COUNT,
|
|
RFS_POLL_DEV_NAME);
|
|
if (ret) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region) ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
cdev_init(&rfs_poll_cdev, &rfs_poll_fileops);
|
|
rfs_poll_cdev.owner = THIS_MODULE;
|
|
|
|
ret = cdev_add(&rfs_poll_cdev, devid_snfc_rfs_poll, RFS_POLL_DEV_COUNT);
|
|
if (ret) {
|
|
unregister_chrdev_region(
|
|
devid_snfc_rfs_poll, RFS_POLL_DEV_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
class_dev = device_create(felica_class, NULL, devid_snfc_rfs_poll, NULL,
|
|
RFS_POLL_DEV_NAME);
|
|
|
|
if (IS_ERR(class_dev)) {
|
|
cdev_del(&rfs_poll_cdev);
|
|
unregister_chrdev_region(
|
|
devid_snfc_rfs_poll, RFS_POLL_DEV_COUNT);
|
|
ret = PTR_ERR(class_dev);
|
|
FELICA_PR_ERR(" %s ERROR(device_create), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
memset(g_rfs_d, 0x00, sizeof(struct poll_data));
|
|
|
|
INIT_DELAYED_WORK(&g_rfs_d->work, rfs_poll_work_func);
|
|
|
|
init_waitqueue_head(&g_rfs_d->read_wait);
|
|
|
|
g_rfs_d->open_flag = 0;
|
|
|
|
if (g_rfs_d->open_flag) {
|
|
FELICA_PR_ERR(" %s only one time", __func__);
|
|
return -EBUSY;
|
|
}
|
|
g_rfs_d->open_flag = 1;
|
|
|
|
ret = gpio_get_value(GPIO_PINID_NFC_RFS_POLL);
|
|
if (ret < 0) {
|
|
g_rfs_d->open_flag = 0;
|
|
FELICA_PR_ERR(" %s ERROR(gpio_get_value), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
g_rfs_d->device_status = ret;
|
|
g_rfs_sts = ret;
|
|
|
|
if (g_rfs_d->device_status == RFS_POLL_DEV_LOW)
|
|
irqflag = IRQF_TRIGGER_HIGH | IRQF_SHARED;
|
|
else
|
|
irqflag = IRQF_TRIGGER_LOW | IRQF_SHARED;
|
|
|
|
if (request_irq(gpio_to_irq(
|
|
GPIO_PINID_NFC_RFS_POLL), rfs_poll_irq_handler,
|
|
irqflag, RFS_POLL_DEV_NAME, (void *)g_rfs_d)) {
|
|
g_rfs_d->open_flag = 0;
|
|
FELICA_PR_ERR(" %s ERROR(request_irq), irqflag=[%ld]",
|
|
__func__, irqflag);
|
|
return -EIO;
|
|
}
|
|
g_rfs_d->irq_handler_done = 0;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void rfs_poll_exit(void)
|
|
{
|
|
struct poll_data *rfs_d = g_rfs_d;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
cancel_delayed_work(&rfs_d->work);
|
|
free_irq(gpio_to_irq(GPIO_PINID_NFC_RFS_POLL), (void *)rfs_d);
|
|
|
|
rfs_d->open_flag = 0;
|
|
|
|
cdev_del(&rfs_poll_cdev);
|
|
unregister_chrdev_region(
|
|
devid_snfc_rfs_poll, RFS_POLL_DEV_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open operation
|
|
*/
|
|
static int rfs_poll_open(struct inode *inode, struct file *file)
|
|
{
|
|
int uid_ret = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
uid_ret = snfc_uid_check();
|
|
if (uid_ret < 0) {
|
|
FELICA_PR_ERR
|
|
(" %s open fail=[%d]", __func__, uid_ret);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close operation
|
|
*/
|
|
static int rfs_poll_release(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* poll operation
|
|
*/
|
|
static unsigned int rfs_poll_poll(struct file *file, poll_table *wait)
|
|
{
|
|
struct poll_data *rfs_d = g_rfs_d;
|
|
unsigned int mask = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
poll_wait(file, &rfs_d->read_wait, wait);
|
|
if (rfs_d->irq_handler_done)
|
|
mask = POLLIN | POLLRDNORM;
|
|
|
|
FELICA_PR_DBG(" %s END mask = %d", __func__, mask);
|
|
|
|
return mask;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t rfs_poll_read(struct file *file, char __user *buf, size_t len,
|
|
loff_t *ppos)
|
|
{
|
|
struct poll_data *rfs_d = g_rfs_d;
|
|
int ret;
|
|
char cret;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (len < 1) {
|
|
FELICA_PR_ERR(
|
|
" %s length check len = %d", __func__, len);
|
|
return -EIO;
|
|
}
|
|
|
|
if (!rfs_d->irq_handler_done) {
|
|
if (file->f_flags & O_NONBLOCK) {
|
|
FELICA_PR_ERR(" %s NONBLOCK", __func__);
|
|
return -EAGAIN;
|
|
}
|
|
FELICA_PR_INFO(
|
|
" %s FeliCa rfs_poll wait irq", __func__);
|
|
ret = wait_event_interruptible(rfs_d->read_wait,
|
|
rfs_d->irq_handler_done == 1);
|
|
if (-ERESTARTSYS == ret) {
|
|
FELICA_PR_ERR(
|
|
" %s -EINTR wait_event_interruptible ret=[%d]",
|
|
__func__, ret);
|
|
return -EINTR;
|
|
}
|
|
}
|
|
|
|
if (rfs_d->read_error) {
|
|
rfs_d->irq_handler_done = 0;
|
|
rfs_d->read_error = 0;
|
|
FELICA_PR_ERR(" %s rfs_d->read_error = %d",
|
|
__func__, rfs_d->read_error);
|
|
return -EIO;
|
|
}
|
|
|
|
if (rfs_d->device_status == RFS_POLL_DEV_HIGH)
|
|
cret = RFS_POLL_RET_STS_HIGH;
|
|
else
|
|
cret = RFS_POLL_RET_STS_LOW;
|
|
|
|
len = 1;
|
|
|
|
if (copy_to_user(buf, &cret, len)) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user)", __func__);
|
|
return -EFAULT;
|
|
}
|
|
rfs_d->irq_handler_done = 0;
|
|
|
|
FELICA_PR_DBG(
|
|
" %s END len = %d, cret = %d",
|
|
__func__, len, cret);
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_pon
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_snfc_pon;
|
|
static struct cdev cxd2235power_cdev;
|
|
static const struct file_operations cxd2235power_fileops = {
|
|
.owner = THIS_MODULE,
|
|
.write = cxd2235power_write,
|
|
.open = cxd2235power_open,
|
|
.release = cxd2235power_release,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static int cxd2235power_init(void)
|
|
{
|
|
int ret = 0;
|
|
struct device *class_dev;
|
|
|
|
devid_snfc_pon = MKDEV(MISC_MAJOR, 0);
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = alloc_chrdev_region(&devid_snfc_pon , 0 , CXD2235_POWER_DEV_COUNT,
|
|
CXD2235_POWER_DEV_NAME);
|
|
if (ret) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
cdev_init(&cxd2235power_cdev, &cxd2235power_fileops);
|
|
cxd2235power_cdev.owner = THIS_MODULE;
|
|
|
|
ret = cdev_add(&cxd2235power_cdev, devid_snfc_pon,
|
|
CXD2235_POWER_DEV_COUNT);
|
|
if (ret) {
|
|
unregister_chrdev_region(
|
|
devid_snfc_pon, CXD2235_POWER_DEV_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
class_dev = device_create(felica_class, NULL, devid_snfc_pon, NULL,
|
|
CXD2235_POWER_DEV_NAME);
|
|
if (IS_ERR(class_dev)) {
|
|
cdev_del(&cxd2235power_cdev);
|
|
unregister_chrdev_region(
|
|
devid_snfc_pon, CXD2235_POWER_DEV_COUNT);
|
|
ret = PTR_ERR(class_dev);
|
|
FELICA_PR_ERR(" %s ERROR(device_create), ret=[%d]",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void cxd2235power_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_snfc_pon);
|
|
cdev_del(&cxd2235power_cdev);
|
|
unregister_chrdev_region(devid_snfc_pon, CXD2235_POWER_DEV_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open operation
|
|
*/
|
|
static int cxd2235power_open(struct inode *inode, struct file *file)
|
|
{
|
|
int uid_ret = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
uid_ret = snfc_uid_check();
|
|
if (uid_ret < 0) {
|
|
FELICA_PR_ERR
|
|
(" %s open fail=[%d]", __func__, uid_ret);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close operation
|
|
*/
|
|
static int cxd2235power_release(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t cxd2235power_write(struct file *file, const char __user *data,
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
char on;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (len < 1) {
|
|
FELICA_PR_ERR(
|
|
" %s length check len = %d", __func__, len);
|
|
return -EIO;
|
|
}
|
|
len = 1;
|
|
if (copy_from_user(&on, data, len)) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_from_user)", __func__);
|
|
return -EFAULT;
|
|
}
|
|
|
|
#if defined(CONFIG_ARCH_EXYNOS)
|
|
gpio_set_value(GPIO_PINID_NFC_PON , on);
|
|
#elif defined(CONFIG_ARCH_APQ8064)
|
|
ice_gpiox_set(GPIO_PINID_NFC_PON, on);
|
|
#elif defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM8974PRO)
|
|
#if defined(CONFIG_MACH_KLTE_KDI) || defined(CONFIG_MACH_KLTE_DCM) || defined(CONFIG_MACH_KLTE_SBM)
|
|
gpio_set_value(gfelica_pon_pin , on); // PON is same for FELICA and NFC.
|
|
#else
|
|
gpio_set_value(GPIO_PINID_NFC_PON , on);
|
|
#endif // CONFIG_MACH_KLTE
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END on = %d", __func__, on);
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_rfs
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_snfc_rfs;
|
|
static struct cdev cdev_snfc_rfs;
|
|
static const struct file_operations fops_snfc_rfs = {
|
|
.owner = THIS_MODULE,
|
|
.open = snfc_rfs_open,
|
|
.release = snfc_rfs_close,
|
|
.read = snfc_rfs_read,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void snfc_rfs_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_snfc_rfs;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_snfc_rfs = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_snfc_rfs, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, SNFC_RFS_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_snfc_rfs, &fops_snfc_rfs);
|
|
ret = cdev_add(&cdev_snfc_rfs, devid_snfc_rfs, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_snfc_rfs, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_snfc_rfs =
|
|
device_create(felica_class, NULL, devid_snfc_rfs, NULL,
|
|
SNFC_RFS_NAME);
|
|
if (IS_ERR(device_snfc_rfs)) {
|
|
cdev_del(&cdev_snfc_rfs);
|
|
unregister_chrdev_region(devid_snfc_rfs, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_snfc_rfs), MINOR(devid_snfc_rfs));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void snfc_rfs_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_snfc_rfs);
|
|
cdev_del(&cdev_snfc_rfs);
|
|
unregister_chrdev_region(devid_snfc_rfs, FELICA_MINOR_COUNT);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int snfc_rfs_open(struct inode *inode, struct file *file)
|
|
{
|
|
int uid_ret = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
uid_ret = snfc_uid_check();
|
|
if (uid_ret < 0) {
|
|
FELICA_PR_ERR
|
|
(" %s open fail=[%d]", __func__, uid_ret);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int snfc_rfs_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t snfc_rfs_read(struct file *file, char __user *buf, \
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret;
|
|
char retparam;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
ret = gpio_get_value(GPIO_PINID_SNFC_RFS);
|
|
|
|
if (ret == GPIO_VALUE_HIGH) {
|
|
retparam = SNFC_RFS_STANDBY;
|
|
FELICA_PR_INFO(" Carrier-Wave Status is [%d][standby]",
|
|
retparam);
|
|
} else if (ret == GPIO_VALUE_LOW) {
|
|
retparam = SNFC_RFS_DETECTED;
|
|
FELICA_PR_INFO(" Carrier-Wave Status is [%d][detected]",
|
|
retparam);
|
|
} else {
|
|
FELICA_PR_ERR(" %s ERROR(gpio_get_value), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = copy_to_user(buf, &retparam, SNFC_RFS_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return SNFC_RFS_DATA_LEN;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_uart
|
|
******************************************************************************/
|
|
/* character device definition */
|
|
static dev_t devid_snfc;
|
|
static struct cdev cdev_snfc;
|
|
static const struct file_operations fops_snfc = {
|
|
.owner = THIS_MODULE,
|
|
.open = snfc_uart_open,
|
|
.release = snfc_uart_close,
|
|
.read = snfc_uart_read,
|
|
.write = snfc_uart_write,
|
|
.unlocked_ioctl = snfc_uart_ioctl,
|
|
.poll = snfc_uart_poll,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void snfc_uart_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_snfc;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_snfc = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret = alloc_chrdev_region(&devid_snfc, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, SNFC_UART_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_snfc, &fops_snfc);
|
|
ret = cdev_add(&cdev_snfc, devid_snfc, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_snfc, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_snfc = device_create(felica_class, NULL, devid_snfc, NULL,
|
|
SNFC_UART_NAME);
|
|
if (IS_ERR(device_snfc)) {
|
|
cdev_del(&cdev_snfc);
|
|
unregister_chrdev_region(devid_snfc, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_snfc), MINOR(devid_snfc));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void snfc_uart_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_snfc);
|
|
cdev_del(&cdev_snfc);
|
|
unregister_chrdev_region(devid_snfc, FELICA_MINOR_COUNT);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int snfc_uart_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
/* struct termios termios;*/
|
|
struct file *tty;
|
|
int ret = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
/* check NFC uid */
|
|
uid = __task_cred(current)->uid;
|
|
if (uid != gnfc_uid) {
|
|
FELICA_PR_ERR(\
|
|
" %s END -EACCES, uid=[%d], gnfc_uid=[%d]\n", __func__, uid,gnfc_uid);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
|
|
file->private_data = dev_sem;
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(\
|
|
" %s END, ERR[ERESTARTSYS]\n", __func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
if (pg_tty != NULL) {
|
|
FELICA_PR_ERR(
|
|
" %s multi open result=%d", __func__, ret);
|
|
gnfc_open_cnt++;
|
|
up(&dev_sem->felica_sem);
|
|
return ret;
|
|
}
|
|
|
|
tty = filp_open(UART_DEV_NAME, O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
|
|
|
|
if (IS_ERR(tty)) {
|
|
pg_tty = NULL;
|
|
ret = PTR_ERR(tty);
|
|
up(&dev_sem->felica_sem);
|
|
FELICA_PR_ERR(
|
|
" %s filp_open result = %d", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
pg_tty = tty;
|
|
gnfc_open_cnt++;
|
|
ret = 0;
|
|
up(&dev_sem->felica_sem);
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int snfc_uart_close(struct inode *inode, struct file *file)
|
|
{
|
|
struct file *tty;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(\
|
|
" %s END, ERR[ERESTARTSYS]\n", __func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
gnfc_open_cnt--;
|
|
tty = NULL;
|
|
if (gnfc_open_cnt == 0) {
|
|
tty = pg_tty;
|
|
if (tty) {
|
|
filp_close(tty, 0);
|
|
pg_tty = NULL;
|
|
}
|
|
}
|
|
|
|
up(&dev_sem->felica_sem);
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t snfc_uart_read(struct file *file, char __user *buf,\
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
struct file *tty;
|
|
ssize_t ret = -ENOSYS;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(\
|
|
" %s END, ERR[ERESTARTSYS]\n", __func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
tty = pg_tty;
|
|
if (tty && tty->f_op->read)
|
|
ret = tty->f_op->read(tty, buf, len, ppos);
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* write operation
|
|
*/
|
|
static ssize_t snfc_uart_write(struct file *file, const char __user *data, \
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
struct file *tty;
|
|
ssize_t ret = -ENOSYS;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(\
|
|
" %s END, ERR[ERESTARTSYS]\n", __func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
tty = pg_tty;
|
|
if (tty && tty->f_op->write)
|
|
ret = tty->f_op->write(tty, data, len, ppos);
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* ioctl operation
|
|
*/
|
|
static long snfc_uart_ioctl(struct file *file, unsigned int cmd, \
|
|
unsigned long arg)
|
|
{
|
|
struct file *tty;
|
|
ssize_t ret = -ENOSYS;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem)) {
|
|
FELICA_PR_ERR(\
|
|
" %s END, ERR[ERESTARTSYS]\n", __func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
tty = pg_tty;
|
|
if (tty && tty->f_op->unlocked_ioctl)
|
|
ret = tty->f_op->unlocked_ioctl(tty, cmd, arg);
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* poll operation
|
|
*/
|
|
static unsigned int snfc_uart_poll(struct file *file,
|
|
struct poll_table_struct *poll_table)
|
|
{
|
|
struct file *tty;
|
|
unsigned int ret = 0;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
if (down_interruptible(&dev_sem->felica_sem))
|
|
return 0;
|
|
|
|
|
|
tty = pg_tty;
|
|
if (tty && tty->f_op->poll)
|
|
ret = tty->f_op->poll(tty, poll_table);
|
|
|
|
up(&dev_sem->felica_sem);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* /dev/uartcc
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static struct felica_sem_data *guartcc_sem;
|
|
static dev_t devid_uartcc;
|
|
static struct cdev cdev_uartcc;
|
|
static const struct file_operations fops_uartcc = {
|
|
.owner = THIS_MODULE,
|
|
.open = uartcc_open,
|
|
.release = uartcc_close,
|
|
.unlocked_ioctl = uartcc_ioctl,
|
|
};
|
|
|
|
/*
|
|
* uartcc_init
|
|
*/
|
|
static void uartcc_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_uartcc;
|
|
|
|
FELICA_PR_DBG(" %s START\n", __func__);
|
|
|
|
devid_uartcc = MKDEV(UARTCC_MAJOR, UARTCC_MINOR);
|
|
|
|
ret =
|
|
alloc_chrdev_region(&devid_uartcc, UARTCC_BASEMINOR,
|
|
UARTCC_MINOR_COUNT, UARTCC_NAME);
|
|
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(alloc_chrdev_region), ret=[%d]\n",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_uartcc, &fops_uartcc);
|
|
ret = cdev_add(&cdev_uartcc, devid_uartcc, UARTCC_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_uartcc, UARTCC_MINOR_COUNT);
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(cdev_add), ret=[%d]\n", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_uartcc =
|
|
device_create(felica_class, NULL, devid_uartcc, NULL,
|
|
UARTCC_NAME);
|
|
if (IS_ERR(device_uartcc)) {
|
|
cdev_del(&cdev_uartcc);
|
|
unregister_chrdev_region(devid_uartcc, UARTCC_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)\n", __func__);
|
|
return;
|
|
}
|
|
|
|
guartcc_sem = kmalloc(sizeof(struct felica_sem_data), GFP_KERNEL);
|
|
if (!guartcc_sem) {
|
|
cdev_del(&cdev_uartcc);
|
|
unregister_chrdev_region(devid_uartcc, UARTCC_MINOR_COUNT);
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(guartcc_sem malloc)\n", __func__);
|
|
return;
|
|
}
|
|
sema_init(&guartcc_sem->felica_sem, 1);
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]\n", __func__, \
|
|
MAJOR(devid_uartcc), MINOR(devid_uartcc));
|
|
}
|
|
|
|
/*
|
|
* uartcc_exit
|
|
*/
|
|
static void uartcc_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START\n", __func__);
|
|
|
|
kfree(guartcc_sem);
|
|
device_destroy(felica_class, devid_uartcc);
|
|
cdev_del(&cdev_uartcc);
|
|
unregister_chrdev_region(devid_uartcc, UARTCC_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int uartcc_open(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int uartcc_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* available operation
|
|
*/
|
|
static long uartcc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
{
|
|
int ret = 0;
|
|
int user_buf = 0;
|
|
|
|
FELICA_PR_DBG(" %s START, cmd=[%d]\n", __func__, cmd);
|
|
|
|
switch (cmd) {
|
|
case UARTCC_SET_NFC_START_REQ:
|
|
if (down_interruptible(&guartcc_sem->felica_sem)) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(down_interruptible)\n",
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
ret = copy_from_user(
|
|
&user_buf, (void __user *)arg, sizeof(user_buf));
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR
|
|
(" %s ERROR(copy_from_user), ret=[%d]\n",
|
|
__func__, ret);
|
|
up(&guartcc_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
|
|
guartcc_start_req = user_buf;
|
|
/* felica start request */
|
|
uartcc_felica_start_request();
|
|
FELICA_PR_INFO(" %s Set nfc start request=[%d]\n",
|
|
__func__, guartcc_start_req);
|
|
|
|
#ifdef P2P_FPGA_ALWAYS_ON
|
|
switch (guartcc_start_req) {
|
|
case SNFC_START_TARGET:
|
|
case SNFC_START_INTU:
|
|
set_fpga_felica_flag(1);
|
|
break;
|
|
case UARTCC_NFC_START_ENDPROC:
|
|
break;
|
|
default:
|
|
set_fpga_felica_flag(0);
|
|
break;
|
|
}
|
|
FELICA_PR_INFO(" %s [fpga]felica_status=[%d]\n",
|
|
__func__, felica_status);
|
|
#endif /* P2P_FPGA_ALWAYS_ON */
|
|
up(&guartcc_sem->felica_sem);
|
|
break;
|
|
case UARTCC_GET_FELICA_STATUS:
|
|
if (down_interruptible(&guartcc_sem->felica_sem)) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(down_interruptible)\n", \
|
|
__func__);
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
user_buf = uartcc_get_felica_status();
|
|
ret = copy_to_user(
|
|
(int __user *)arg, &user_buf, sizeof(user_buf));
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR
|
|
(" %s ERROR(copy_to_user), ret=[%d]\n", \
|
|
__func__, ret);
|
|
up(&guartcc_sem->felica_sem);
|
|
return -EFAULT;
|
|
}
|
|
FELICA_PR_INFO(" %s Get felica status=[%d]\n", \
|
|
__func__, guartcc_felica_status);
|
|
up(&guartcc_sem->felica_sem);
|
|
break;
|
|
case UARTCC_SET_FELICA_STATUS:
|
|
case UARTCC_GET_NFC_START_REQ:
|
|
FELICA_PR_INFO(" %s No operation cmd\n", __func__);
|
|
break;
|
|
default:
|
|
FELICA_PR_ERR(" %s ERROR(unknown command)\n", __func__);
|
|
ret = -EIO;
|
|
break;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* felica start request
|
|
*/
|
|
static void uartcc_felica_start_request(void)
|
|
{
|
|
struct icc_poll_data *felica_poll = &gfelica_poll_data;
|
|
|
|
FELICA_PR_DBG(" %s START\n", __func__);
|
|
FELICA_PR_INFO(" %s start_req=[%d], felica_status=[%d]\n", \
|
|
__func__, guartcc_start_req, guartcc_felica_status);
|
|
|
|
/* wake up condition
|
|
* - nfc star req is ENDPROC
|
|
* - felica usage is waiting AutoPolling
|
|
*/
|
|
if ((guartcc_start_req == UARTCC_NFC_START_ENDPROC) &&
|
|
(uartcc_get_felica_status() ==
|
|
UARTCC_FELICA_STATAUS_WAIT_POLLING)) {
|
|
felica_poll->rsp_done = 1;
|
|
wake_up_interruptible(&felica_poll->rsp_wait);
|
|
FELICA_PR_INFO(
|
|
" %s wake up felica start event\n", __func__);
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
}
|
|
|
|
/*
|
|
* set felica status
|
|
*/
|
|
static void uartcc_set_felica_status(int status)
|
|
{
|
|
FELICA_PR_DBG(" %s START, status=[%d]\n", __func__, status);
|
|
|
|
guartcc_felica_status = status;
|
|
|
|
FELICA_PR_INFO(" %s guartcc_felica_status=[%d]\n",
|
|
__func__, guartcc_felica_status);
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
}
|
|
|
|
/*
|
|
* get felica status
|
|
*/
|
|
static int uartcc_get_felica_status(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START, guartcc_felica_status=[%d]\n", \
|
|
__func__, guartcc_felica_status);
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
#if defined(CONFIG_MACH_KLTE_KDI)
|
|
if(gfelica_uim_mon == 1) {
|
|
FELICA_PR_ERR(" %s gfelica_uim_mon=%d\n", __func__, gfelica_uim_mon);
|
|
return UARTCC_FELICA_STATAUS_IN_INIT;
|
|
}
|
|
return guartcc_felica_status;
|
|
#else
|
|
return guartcc_felica_status;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* check for idle state felica
|
|
*/
|
|
static unsigned int uartcc_is_idle_status(void)
|
|
{
|
|
int ret = 0;
|
|
int flc_cts = 0;
|
|
|
|
FELICA_PR_DBG(" %s START\n", __func__);
|
|
|
|
flc_cts = uartcc_get_felica_status();
|
|
|
|
if (!flc_cts) { /* idle */
|
|
FELICA_PR_INFO(" %s felica status is idle\n", __func__);
|
|
ret = 1;
|
|
} else { /* else state */
|
|
FELICA_PR_INFO(" %s felica status isn't idle=[%d]\n", \
|
|
__func__, flc_cts);
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return ret;
|
|
}
|
|
/******************************************************************************
|
|
* /dev/felica_uicc
|
|
******************************************************************************/
|
|
|
|
/* character device definition */
|
|
static dev_t devid_uicc;
|
|
static struct cdev cdev_uicc;
|
|
static const struct file_operations fops_uicc = {
|
|
.owner = THIS_MODULE,
|
|
.open = uicc_open,
|
|
.release = uicc_close,
|
|
.read = uicc_read, // permissive mode issue
|
|
.unlocked_ioctl = uicc_ioctl,
|
|
};
|
|
|
|
/*
|
|
* uartcc_init
|
|
*/
|
|
static void uicc_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_uicc;
|
|
|
|
FELICA_PR_DBG(" %s START\n", __func__);
|
|
|
|
devid_uicc = MKDEV(UICC_MAJOR, UICC_MINOR);
|
|
|
|
ret =
|
|
alloc_chrdev_region(&devid_uicc, UICC_BASEMINOR,
|
|
UICC_MINOR_COUNT, UICC_NAME);
|
|
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(alloc_chrdev_region), ret=[%d]\n",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_uicc, &fops_uicc);
|
|
ret = cdev_add(&cdev_uicc, devid_uicc, UICC_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_uicc, UICC_MINOR_COUNT);
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(cdev_add), ret=[%d]\n", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_uicc =
|
|
device_create(felica_class, NULL, devid_uicc, NULL,
|
|
UICC_NAME);
|
|
if (IS_ERR(device_uicc)) {
|
|
cdev_del(&cdev_uicc);
|
|
unregister_chrdev_region(devid_uicc, UICC_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)\n", __func__);
|
|
return;
|
|
}
|
|
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]\n", __func__, \
|
|
MAJOR(devid_uicc), MINOR(devid_uicc));
|
|
}
|
|
|
|
/*
|
|
* uicc_exit
|
|
*/
|
|
static void uicc_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START\n", __func__);
|
|
|
|
device_destroy(felica_class, devid_uicc);
|
|
cdev_del(&cdev_uicc);
|
|
unregister_chrdev_region(devid_uicc, UICC_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int uicc_open(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int uicc_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation // permissive mode issue
|
|
*/
|
|
static ssize_t uicc_read(struct file *file, char __user *buf, \
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret;
|
|
char read_buff = 0;
|
|
|
|
read_buff = g_uicc_sts;
|
|
|
|
ret = copy_to_user(buf, &read_buff, FELICA_UICC_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return FELICA_UICC_DATA_LEN;
|
|
}
|
|
|
|
/*
|
|
* available operation
|
|
*/
|
|
static long uicc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
{
|
|
int ret = 0;
|
|
|
|
struct regulator *reg_l9;
|
|
|
|
FELICA_PR_DBG(" %s START, cmd=[%d]\n", __func__, cmd);
|
|
FELICA_PR_INFO(" %s START, system_rev=[%d] UICC_rev[%d]\n",
|
|
__func__, system_rev,g_uicc_initrev);
|
|
|
|
switch (cmd) {
|
|
case UICC_POWER_ON:
|
|
if(system_rev < g_uicc_initrev)
|
|
{
|
|
reg_l9 = regulator_get(NULL, "8941_l9");
|
|
if (IS_ERR(reg_l9)) {
|
|
FELICA_PR_ERR(" %s 2 could not get 8917_l9, rc = %ld\n",
|
|
__func__, PTR_ERR(reg_l9));
|
|
return UICC_ERROR;
|
|
}
|
|
FELICA_PR_INFO(" %s regulator_get, reg_l9 OK]", __func__);
|
|
|
|
ret = regulator_set_voltage(reg_l9, 1800000, 1800000);
|
|
if (ret) {
|
|
FELICA_PR_ERR(
|
|
" %s ERROR(regulator_set_voltage 1.8V~1.8V), ret=[%d]"
|
|
, __func__, ret);
|
|
return UICC_ERROR;
|
|
}
|
|
FELICA_PR_INFO(
|
|
" %s regulator_set_voltage(1.8v~1.8v), ret=[%d]"
|
|
, __func__, ret);
|
|
|
|
if (regulator_is_enabled(reg_l9)) {
|
|
FELICA_PR_INFO(
|
|
" %s L9(0V) is enabled. No need to do anything\n"
|
|
, __func__);
|
|
} else {
|
|
ret = regulator_enable(reg_l9);
|
|
if (ret) {
|
|
FELICA_PR_ERR(
|
|
" %s regulator_enable l9 failed, rc=%d\n"
|
|
, __func__, ret);
|
|
return UICC_ERROR;
|
|
}
|
|
}
|
|
FELICA_PR_INFO(
|
|
" %s regulator_enable, ret=[%d]", __func__, ret);
|
|
}
|
|
break;
|
|
|
|
case UICC_POWER_OFF:
|
|
if(system_rev < g_uicc_initrev)
|
|
{
|
|
reg_l9 = regulator_get(NULL, "8941_l9");
|
|
if (IS_ERR(reg_l9)) {
|
|
FELICA_PR_ERR(" %s could not get 8917_l9, rc = %ld\n",
|
|
__func__, PTR_ERR(reg_l9));
|
|
return UICC_ERROR;
|
|
}
|
|
|
|
FELICA_PR_INFO(" %s regulator_get, reg_l9 OK]", __func__);
|
|
|
|
if (regulator_is_enabled(reg_l9)) {
|
|
FELICA_PR_INFO(
|
|
" %s L9(0V) is enabled already\n",__func__);
|
|
if (regulator_disable(reg_l9)) {
|
|
FELICA_PR_ERR
|
|
(" %s disable l9 failed\n", __func__);
|
|
return UICC_ERROR;
|
|
}
|
|
} else {
|
|
FELICA_PR_ERR
|
|
(" %s regulator l9 already disabled", __func__);
|
|
return UICC_ERROR;
|
|
}
|
|
}
|
|
break;
|
|
case UICC_POWER_SPS_PMIC:
|
|
g_uicc_sts = 0x01; // permissive mode issue
|
|
if(system_rev >= g_uicc_initrev)
|
|
{
|
|
#if defined(CONFIG_MACH_KLTE_KDI)
|
|
FELICA_PR_ERR(" %s Select Power Supply control is missing in K-KDDI! This makes kernel panic! gfelica_sps_pin=%d\n", __func__, gfelica_sps_pin);
|
|
#else
|
|
gpio_set_value(gfelica_sps_pin, GPIO_VALUE_HIGH);
|
|
FELICA_PR_INFO(
|
|
" %s Select Power Supply -> HI [%d][%d]\n", __func__,
|
|
gfelica_sps_pin, gpio_get_value(gfelica_sps_pin));
|
|
#endif
|
|
}
|
|
|
|
break;
|
|
|
|
case UICC_POWER_UIM_MON:
|
|
#if defined(CONFIG_MACH_KLTE_KDI)
|
|
FELICA_PR_INFO(" %s UICC_POWER_UIM_MON! make PON always high!\n", __func__);
|
|
gfelica_uim_mon = 1;
|
|
gpio_set_value(gfelica_pon_pin, GPIO_VALUE_HIGH);
|
|
#else
|
|
FELICA_PR_ERR(" %s UICC_POWER_UIM_MON! this is only for K-KDDI\n", __func__);
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
FELICA_PR_ERR(" %s Undefine Paramater [%d]", __func__, cmd);
|
|
return UICC_ERROR;
|
|
break;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END\n", __func__);
|
|
return UICC_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* common
|
|
******************************************************************************/
|
|
/*
|
|
* add CXD2235 additional pin registration
|
|
*/
|
|
static void snfc_register_device(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
intu_poll_init();
|
|
schedule_delayed_work(&g_intu_d->work, msecs_to_jiffies(10));
|
|
rfs_poll_init();
|
|
schedule_delayed_work(&g_rfs_d->work, msecs_to_jiffies(10));
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* add CXD2235 additional pin unregistration
|
|
*/
|
|
static void snfc_deregister_device(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
available_poll_exit();
|
|
intu_poll_exit();
|
|
snfc_rfs_exit();
|
|
rfs_poll_exit();
|
|
hsel_exit();
|
|
cxd2235power_exit();
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* add read and store CEN status for snfc_available_poll device
|
|
*/
|
|
static ssize_t snfc_cen_sts_init(void)
|
|
{
|
|
int ret;
|
|
unsigned char address = gi2c_lockaddress;
|
|
unsigned char read_buff = 0;
|
|
struct i2c_msg read_msgs[2];
|
|
|
|
read_msgs[0].flags = gread_msgs[0].flags;
|
|
read_msgs[0].len = gread_msgs[0].len;
|
|
read_msgs[1].flags = gread_msgs[1].flags;
|
|
read_msgs[1].len = gread_msgs[1].len;
|
|
|
|
read_msgs[0].addr = gi2c_address;
|
|
read_msgs[0].buf = &address;
|
|
read_msgs[1].addr = gi2c_address;
|
|
read_msgs[1].buf = &read_buff;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
if (felica_i2c_client == NULL) {
|
|
FELICA_PR_ERR(" felica_i2c_client is NULL");
|
|
return -EIO;
|
|
}
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//high
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN HIGH", __func__);
|
|
of_sii8240_hw_poweron(FELICA_CEN_UNLOCK);
|
|
}
|
|
#endif
|
|
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[0], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[0]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[1], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[1]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
FELICA_PR_INFO(" %s read_buff=[%d]", __func__, read_buff);
|
|
read_buff &= FELICA_CONTROL_LOCK_MASK;
|
|
FELICA_PR_INFO(" %s read_buff=[%d]", __func__, read_buff);
|
|
g_cen_sts = read_buff;
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//low
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN LOW", __func__);
|
|
// of_sii8240_hw_poweron(FELICA_CEN_LOCK);
|
|
}
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return FELICA_CEN_DATA_LEN;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* /dev/snfc_cen
|
|
******************************************************************************/
|
|
/* character device definition */
|
|
static dev_t devid_snfca_cen;
|
|
static struct cdev cdev_snfc_cen;
|
|
static const struct file_operations fops_snfc_cen = {
|
|
.owner = THIS_MODULE,
|
|
.open = snfc_cen_open,
|
|
.release = snfc_cen_close,
|
|
.read = snfc_cen_read,
|
|
};
|
|
|
|
/*
|
|
* initialize device
|
|
*/
|
|
static void snfc_cen_init(void)
|
|
{
|
|
int ret;
|
|
struct device *device_snfc_cen;
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
devid_snfca_cen = MKDEV(FELICA_MAJOR, FELICA_MINOR);
|
|
ret =
|
|
alloc_chrdev_region(&devid_snfca_cen, FELICA_BASEMINOR,
|
|
FELICA_MINOR_COUNT, SNFC_CEN_NAME);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(alloc_chrdev_region), ret=[%d]",
|
|
__func__, ret);
|
|
return;
|
|
}
|
|
|
|
cdev_init(&cdev_snfc_cen, &fops_snfc_cen);
|
|
ret = cdev_add(&cdev_snfc_cen, devid_snfca_cen, FELICA_MINOR_COUNT);
|
|
if (ret < 0) {
|
|
unregister_chrdev_region(devid_snfca_cen, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(cdev_add), ret=[%d]", __func__,
|
|
ret);
|
|
return;
|
|
}
|
|
|
|
device_snfc_cen =
|
|
device_create(felica_class, NULL, devid_snfca_cen, NULL,
|
|
SNFC_CEN_NAME);
|
|
if (IS_ERR(device_snfc_cen)) {
|
|
cdev_del(&cdev_snfc_cen);
|
|
unregister_chrdev_region(devid_snfca_cen, FELICA_MINOR_COUNT);
|
|
FELICA_PR_ERR(" %s ERROR(device_create)", __func__);
|
|
return;
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END, major=[%d], minor=[%d]", __func__,
|
|
MAJOR(devid_snfca_cen), MINOR(devid_snfca_cen));
|
|
}
|
|
|
|
/*
|
|
* finalize device
|
|
*/
|
|
static void snfc_cen_exit(void)
|
|
{
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
|
|
device_destroy(felica_class, devid_snfca_cen);
|
|
cdev_del(&cdev_snfc_cen);
|
|
unregister_chrdev_region(devid_snfca_cen, FELICA_MINOR_COUNT);
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
}
|
|
|
|
/*
|
|
* open device
|
|
*/
|
|
static int snfc_cen_open(struct inode *inode, struct file *file)
|
|
{
|
|
uid_t uid;
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
int ret = 0;
|
|
char *cmdpos;
|
|
static char cmdline[1025];
|
|
static unsigned long start_adr, end_adr, leng;
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s START . system_rev=[%d]", __func__,system_rev);
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//high
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN HIGH", __func__);
|
|
of_sii8240_hw_poweron(SNFC_CEN_UNLOCK);
|
|
}
|
|
#endif
|
|
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
start_adr = current->mm->arg_start;
|
|
end_adr = current->mm->arg_end;
|
|
leng = end_adr - start_adr;
|
|
|
|
if (1024 < leng)
|
|
leng = 1024;
|
|
cmdpos = (char *)(current->mm->arg_start);
|
|
ret = copy_from_user(cmdline, cmdpos, leng);
|
|
cmdline[leng] = '\0';
|
|
if(ret != 0)
|
|
{
|
|
FELICA_PR_ERR(" %s cmdline[%s] ret[%d]", __func__, cmdline, ret);
|
|
return -EFAULT;
|
|
}
|
|
#endif
|
|
|
|
uid = __task_cred(current)->uid;
|
|
if (file->f_mode & FMODE_WRITE) {
|
|
#ifdef FELICA_UICC_FUNCTION
|
|
if ((uid != gdiag_uid) && (uid != gmfl_uid)
|
|
&& (strncmp(cmdline,gproc_name, leng) != 0)) {
|
|
#else
|
|
if ((uid != gdiag_uid) && (uid != gmfl_uid)) {
|
|
#endif
|
|
FELICA_PR_ERR(" %s END -EACCES, uid=[%d], gmfc_uid=[%d], gdiag_uid=[%d], gmfl_uid=[%d]\n", __func__, uid,gmfc_uid,gdiag_uid,gmfl_uid);
|
|
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//low
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN LOW", __func__);
|
|
// of_sii8240_hw_poweron(SNFC_CEN_LOCK);
|
|
}
|
|
#endif
|
|
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -EACCES;
|
|
#endif
|
|
}
|
|
}
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* close device
|
|
*/
|
|
static int snfc_cen_close(struct inode *inode, struct file *file)
|
|
{
|
|
/* no operation */
|
|
#if defined(CONFIG_MACH_HLTEDCM)
|
|
//low
|
|
if (system_rev == HW_REV09_OR_10)
|
|
{
|
|
FELICA_PR_INFO(" %s Making MHL_EN LOW", __func__);
|
|
// of_sii8240_hw_poweron(SNFC_CEN_LOCK);
|
|
}
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s END system_rev=[%d]", __func__,system_rev);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* read operation
|
|
*/
|
|
static ssize_t snfc_cen_read(struct file *file, char __user *buf, \
|
|
size_t len, loff_t *ppos)
|
|
{
|
|
int ret;
|
|
unsigned char address = gi2c_lockaddress;
|
|
unsigned char read_buff = 0;
|
|
struct i2c_msg read_msgs[2];
|
|
|
|
read_msgs[0].flags = gread_msgs[0].flags;
|
|
read_msgs[0].len = gread_msgs[0].len;
|
|
read_msgs[1].flags = gread_msgs[1].flags;
|
|
read_msgs[1].len = gread_msgs[1].len;
|
|
|
|
read_msgs[0].addr = gi2c_address;
|
|
read_msgs[0].buf = &address;
|
|
read_msgs[1].addr = gi2c_address;
|
|
read_msgs[1].buf = &read_buff;
|
|
|
|
if (felica_i2c_client == NULL) {
|
|
FELICA_PR_ERR(" felica_i2c_client is NULL %s -EIO",__func__);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[0], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[0]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
ret = i2c_transfer(felica_i2c_client->adapter, &read_msgs[1], 1);
|
|
if (ret < 0) {
|
|
FELICA_PR_ERR(" %s ERROR(i2c_transfer[1]), ret=[%d]",
|
|
__func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
read_buff &= SNFC_CONTROL_LOCK_MASK;
|
|
|
|
#ifdef CONFIG_NFC_FELICA
|
|
g_cen_sts = read_buff;
|
|
#endif
|
|
|
|
FELICA_PR_DBG(" %s g_cen_sts=[%d]", __func__, g_cen_sts);
|
|
|
|
ret = copy_to_user(buf, &read_buff, SNFC_CEN_DATA_LEN);
|
|
if (ret != 0) {
|
|
FELICA_PR_ERR(" %s ERROR(copy_to_user), ret=[%d]",
|
|
__func__, ret);
|
|
return -EFAULT;
|
|
}
|
|
*ppos += 1;
|
|
|
|
return SNFC_CEN_DATA_LEN;
|
|
}
|
|
|
|
/*
|
|
* uid check
|
|
*/
|
|
static int snfc_uid_check(void)
|
|
{
|
|
uid_t uid;
|
|
uid = __task_cred(current)->uid;
|
|
|
|
FELICA_PR_DBG(" %s START", __func__);
|
|
FELICA_PR_INFO(" %s gnfc_uid=[%d]", __func__, (int)gnfc_uid);
|
|
|
|
if ((uid != gnfc_uid) && (uid != gdiag_uid)) {
|
|
FELICA_PR_ERR
|
|
(" %s END, uid=[%d], gnfc_uid=[%d], gdiag_uid=[%d]", \
|
|
__func__, uid, gnfc_uid, gdiag_uid);
|
|
#ifdef SRIB_DIAG_ENABLED
|
|
FELICA_PR_ERR(" SRIB-Diag enabled just for test\n");
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
FELICA_PR_DBG(" %s END", __func__);
|
|
return 0;
|
|
}
|
|
|
|
#endif /* CONFIG_NFC_FELICA */
|
|
module_init(felica_init);
|
|
module_exit(felica_exit);
|
|
MODULE_DESCRIPTION("felica_dd");
|
|
MODULE_LICENSE("GPL v2");
|
|
#endif /* CONFIG_FELICA */
|