687 lines
18 KiB
C
Executable file
687 lines
18 KiB
C
Executable file
/*****************************************************************************************
|
|
* Copyright (c) 2021- 2022 TsingTeng MicroSystem Corp.Ltd.
|
|
* TMS_EDIT
|
|
* File : guide_driver.c
|
|
* Description: Source file for tms devices guide
|
|
* Version : 1.0
|
|
* Date : 2022/4/11
|
|
* Team : NFC Middleware
|
|
* Author : Guoliang Wu
|
|
* --------------------------------- Revision History: ---------------------------------
|
|
* <version> <date> < author > <desc>
|
|
*******************************************************************************************/
|
|
#include "guide_driver.h"
|
|
|
|
/*********** PART0: Global Variables Area ***********/
|
|
struct guide_dev *guidev = NULL;
|
|
static chip_t chip_type = TMS_THN31;
|
|
|
|
/*********** PART1: Function declarations Area ***********/
|
|
#if defined(CONFIG_TMS_ESE_DEVICE) || defined(CONFIG_TMS_ESE_DEVICE_MODULE)
|
|
extern int ese_driver_init(void);
|
|
extern void ese_driver_exit(void);
|
|
#endif
|
|
//extern int xxx_probe(struct i2c_client *client, const struct i2c_device_id *id);
|
|
//extern int xxx_remove(struct i2c_client *client);
|
|
//extern int xxx_suspend(struct device *device);
|
|
//extern int xxx_resume(struct device *device);
|
|
//extern int xxx_ese_dev_init(void);
|
|
//extern void xxx_ese_dev_exit(void);
|
|
|
|
/*********** PART2: Guidev Driver Start Area ***********/
|
|
static void guidev_resource_release(struct guide_dev *gdata)
|
|
{
|
|
gpio_free(gdata->hw_res.irq_gpio);
|
|
gpio_free(gdata->hw_res.ven_gpio);
|
|
gpio_free(gdata->hw_res.download_gpio);
|
|
TMS_DEBUG("Finished");
|
|
}
|
|
|
|
static void guidev_hw_reset(uint32_t mdelay)
|
|
{
|
|
if (!guidev->tms->set_ven) {
|
|
TMS_ERR("guidev->tms->set_ven is NULL");
|
|
return;
|
|
}
|
|
|
|
guidev->tms->set_ven(guidev->hw_res, OFF);
|
|
usleep_range(GPIO_VEN_SET_WAIT_TIME_US, (GPIO_VEN_SET_WAIT_TIME_US) + 100);
|
|
guidev->tms->set_ven(guidev->hw_res, ON);
|
|
|
|
if (mdelay) {
|
|
usleep_range(mdelay, (mdelay) + 100);
|
|
}
|
|
|
|
TMS_DEBUG("Finished");
|
|
}
|
|
|
|
static int guidev_probe_driver(struct i2c_client *client,
|
|
const struct i2c_device_id *id, chip_t chip_type)
|
|
{
|
|
int ret = SUCCESS;
|
|
guidev_resource_release(guidev);
|
|
|
|
switch (chip_type) {
|
|
case TMS_THN31:
|
|
TMS_INFO("TMS THN31 driver start probe\n");
|
|
ret = nfc_device_probe(client, id);
|
|
#if defined(CONFIG_TMS_ESE_DEVICE) || defined(CONFIG_TMS_ESE_DEVICE_MODULE)
|
|
ese_driver_init();
|
|
#endif
|
|
break;
|
|
|
|
case SAMPLE_DEV_1:
|
|
//TMS_INFO("XXX XXX driver start probe\n");
|
|
//ret = sample_dev_1_probe(client, id);
|
|
//sample_dev_1_ese_driver_init();
|
|
break;
|
|
|
|
case SAMPLE_DEV_2:
|
|
//TMS_INFO("XXX XXX driver start probe\n");
|
|
//ret = sample_dev_2_probe(client, id);
|
|
//sample_dev_2_ese_driver_init();
|
|
break;
|
|
|
|
default:
|
|
TMS_ERR("Unknow chip %s[%d]\n", guidev->tms->nfc_name, chip_type);
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int guidev_parse_dts(struct guide_dev *gdata)
|
|
{
|
|
int rc;
|
|
int ret = 0;
|
|
struct device_node *np;
|
|
TMS_INFO("Start+\n");
|
|
np = gdata->dev->of_node;
|
|
gdata->hw_res.irq_gpio = of_get_named_gpio(np, "tms,irq-gpio", 0);
|
|
|
|
if (gpio_is_valid(gdata->hw_res.irq_gpio)) {
|
|
rc = gpio_request(gdata->hw_res.irq_gpio, "guidev_int");
|
|
|
|
if (rc) {
|
|
TMS_WARN("unable to request gpio[%d] as irq\n", gdata->hw_res.irq_gpio);
|
|
}
|
|
} else {
|
|
TMS_ERR("irq gpio not specified in dts\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
gdata->hw_res.ven_gpio = of_get_named_gpio_flags(np, "tms,ven-gpio", 0,
|
|
&gdata->hw_res.ven_flag);
|
|
|
|
if (gpio_is_valid(gdata->hw_res.ven_gpio)) {
|
|
rc = gpio_request(gdata->hw_res.ven_gpio, "guidev_ven");
|
|
|
|
if (rc) {
|
|
TMS_WARN("unable to request gpio[%d] as ven\n", gdata->hw_res.ven_gpio);
|
|
}
|
|
} else {
|
|
TMS_ERR("ven gpio not specified in dts\n");
|
|
ret = -EINVAL;
|
|
goto err_ven;
|
|
}
|
|
|
|
gdata->hw_res.download_gpio = of_get_named_gpio_flags(np, "tms,download-gpio",
|
|
0,
|
|
&gdata->hw_res.download_flag);
|
|
|
|
if (gpio_is_valid(gdata->hw_res.download_gpio)) {
|
|
rc = gpio_request(gdata->hw_res.download_gpio, "guidev_fw_download");
|
|
|
|
if (rc) {
|
|
TMS_WARN("unable to request gpio[%d] as download\n",
|
|
gdata->hw_res.download_gpio);
|
|
}
|
|
} else {
|
|
TMS_ERR("fw-download gpio not specified in dts\n");
|
|
ret = -EINVAL;
|
|
goto err_fw_download;
|
|
}
|
|
|
|
TMS_DEBUG("irq_gpio = %d, ven_gpio = %d, dwnld_gpio = %d, error:%d\n",
|
|
gdata->hw_res.irq_gpio, gdata->hw_res.ven_gpio, gdata->hw_res.download_gpio,
|
|
ret);
|
|
TMS_INFO("Normal end-\n");
|
|
return SUCCESS;
|
|
err_fw_download:
|
|
gpio_free(gdata->hw_res.ven_gpio);
|
|
err_ven:
|
|
gpio_free(gdata->hw_res.irq_gpio);
|
|
TMS_ERR("Error end, ret = %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int guidev_gpio_configure(struct hw_resource hw_res)
|
|
{
|
|
int ret;
|
|
TMS_INFO("Start+\n");
|
|
|
|
if (gpio_is_valid(hw_res.irq_gpio)) {
|
|
ret = gpio_direction_input(hw_res.irq_gpio);
|
|
|
|
if (ret < 0) {
|
|
TMS_ERR("not able to set irq gpio as input\n");
|
|
return -ERROR;
|
|
}
|
|
|
|
TMS_INFO("set irq gpio as input\n");
|
|
}
|
|
|
|
if (gpio_is_valid(hw_res.ven_gpio)) {
|
|
ret = gpio_direction_output(hw_res.ven_gpio, hw_res.ven_flag);
|
|
|
|
if (ret < 0) {
|
|
TMS_ERR("not able to set ven gpio as output\n");
|
|
return -ERROR;
|
|
}
|
|
|
|
TMS_INFO("set ven gpio as output\n");
|
|
}
|
|
|
|
if (gpio_is_valid(hw_res.download_gpio)) {
|
|
ret = gpio_direction_output(hw_res.download_gpio, hw_res.download_flag);
|
|
|
|
if (ret < 0) {
|
|
TMS_ERR("not able to set dwnld gpio as output\n");
|
|
return -ERROR;
|
|
}
|
|
|
|
TMS_INFO("set dwnld gpio as output\n");
|
|
}
|
|
|
|
TMS_INFO("Normal end-\n");
|
|
return SUCCESS;
|
|
}
|
|
|
|
static int tms_chip_identification(struct match_info info, uint8_t *buf)
|
|
{
|
|
int ret, i;
|
|
int cmp_byte = 0;
|
|
TMS_INFO("Start+\n");
|
|
|
|
if (info.pattern == TMS_FW) {
|
|
cmp_byte = info.sum - TMS_FW_CMP_BYTE - info.check_sum;
|
|
} else if (info.pattern == TMS_BL) {
|
|
cmp_byte = info.sum - TMS_BL_CMP_BYTE - info.check_sum;
|
|
} else {
|
|
return -ERROR;
|
|
TMS_ERR("Chip identified fail\n");
|
|
}
|
|
|
|
TMS_INFO("Compare major version is %02x\n", buf[cmp_byte]);
|
|
|
|
for (i = 0; i < MAX_MAJOR_VERSION_NUM; i++) {
|
|
if ((buf[cmp_byte] & TMS_VERSION_MASK) == info.major_ver[i]) {
|
|
ret = SUCCESS;
|
|
TMS_DEBUG("Version matched\n");
|
|
break;
|
|
}
|
|
|
|
ret = -ERROR;
|
|
}
|
|
|
|
TMS_INFO("Normal end-\n");
|
|
return ret;
|
|
}
|
|
|
|
static int tms_receive_process(struct guide_dev *gdata, struct match_info *info,
|
|
uint8_t *buf)
|
|
{
|
|
int ret;
|
|
int retry;
|
|
int read_len = 0;
|
|
TMS_INFO("Start+\n");
|
|
retry = info->read_retry;
|
|
|
|
do {
|
|
msleep(5);
|
|
|
|
if (gpio_get_value(gdata->hw_res.irq_gpio)) {
|
|
read_len = TMS_CMD_HEAD_LEN;
|
|
ret = i2c_master_recv(gdata->client, buf, read_len);
|
|
|
|
if (ret == read_len) {
|
|
info->sum = ret;
|
|
} else {
|
|
TMS_ERR("Receive head error[%d]\n", ret);
|
|
return -ERROR;
|
|
}
|
|
|
|
read_len = buf[HEAD_PAYLOAD_BYTE];
|
|
|
|
if (read_len > (MAX_CMD_LEN - info->check_sum)) {
|
|
read_len = MAX_CMD_LEN - info->check_sum;
|
|
TMS_WARN("Receive payload is more than buf max\n");
|
|
}
|
|
|
|
ret = i2c_master_recv(gdata->client, buf + info->sum,
|
|
read_len + info->check_sum);
|
|
|
|
if (ret == (read_len + info->check_sum)) {
|
|
info->sum = info->sum + ret;
|
|
} else {
|
|
TMS_ERR("Receive payload error[%d]\n", ret);
|
|
return -ERROR;
|
|
}
|
|
|
|
ret = SUCCESS;
|
|
break;
|
|
}
|
|
|
|
TMS_ERR("detected interrupt again\n");
|
|
ret = -ERROR;
|
|
retry--;
|
|
} while (retry > 0);
|
|
|
|
if (ret != SUCCESS) {
|
|
TMS_ERR("No response is received\n");
|
|
return -ERROR;
|
|
}
|
|
|
|
tms_buffer_dump("Rx <-", buf, info->sum);
|
|
TMS_INFO("Normal end-\n");
|
|
return ret;
|
|
}
|
|
|
|
static int tms_check_chip_info(struct guide_dev *gdata, struct match_info info)
|
|
{
|
|
int ret;
|
|
int retry;
|
|
uint8_t read_buf[MAX_CMD_LEN];
|
|
TMS_INFO("Start+\n");
|
|
retry = info.write_retry;
|
|
|
|
if (info.pattern == TMS_FW) {
|
|
guidev_hw_reset(GPIO_VEN_SET_WAIT_TIME_US);
|
|
TMS_DEBUG("TMS chip FW match check...\n");
|
|
} else if (info.pattern == TMS_BL) {
|
|
if (!gdata->tms->set_download) {
|
|
TMS_ERR("gdata->tms->set_download is NULL");
|
|
return -ERROR;
|
|
}
|
|
gdata->tms->set_download(gdata->hw_res, ON);
|
|
guidev_hw_reset(GPIO_VEN_SET_WAIT_TIME_US);
|
|
TMS_DEBUG("TMS chip BL match check...\n");
|
|
} else {
|
|
TMS_ERR("TMS chip info error\n");
|
|
return -ERROR;
|
|
}
|
|
|
|
if (info.write_len > 0 && info.write_len < MAX_CMD_LEN) {
|
|
tms_buffer_dump("Tx ->", info.cmd, info.write_len);
|
|
} else {
|
|
TMS_WARN("Send Command too loog, set length is %d\n", MAX_CMD_LEN);
|
|
info.write_len = MAX_CMD_LEN;
|
|
}
|
|
|
|
while (retry > 0) {
|
|
ret = i2c_master_send(gdata->client, info.cmd, info.write_len);
|
|
|
|
if (ret == info.write_len) {
|
|
ret = tms_receive_process(gdata, &info, read_buf);
|
|
|
|
if (info.pattern == TMS_FW) {
|
|
/*if nci payload > 1, do not read + check_sum*/
|
|
info.check_sum = 0;
|
|
ret = tms_receive_process(gdata, &info, read_buf);
|
|
} else if (info.pattern == TMS_BL) {
|
|
gdata->tms->set_download(gdata->hw_res, OFF);
|
|
guidev_hw_reset(GPIO_VEN_SET_WAIT_TIME_US);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
TMS_DEBUG("Send Command error[%d]\n", ret);
|
|
retry--;
|
|
msleep(10);
|
|
ret = -ERROR;
|
|
};
|
|
|
|
if (ret != SUCCESS) {
|
|
TMS_ERR("Command transceive failed\n");
|
|
return -ERROR;
|
|
}
|
|
|
|
ret = tms_chip_identification(info, read_buf);
|
|
TMS_INFO("Normal end-\n");
|
|
return ret;
|
|
}
|
|
|
|
static int guidev_chip_match(struct guide_dev *gdata)
|
|
{
|
|
int ret = -ERROR;
|
|
int count = 0;
|
|
struct match_info info_list[] = {
|
|
{
|
|
.type = TMS_THN31,
|
|
.pattern = TMS_FW,
|
|
.name = "thn31",
|
|
.write_len = 4,
|
|
.write_retry = 3,
|
|
.read_retry = 10,
|
|
.check_sum = 1,
|
|
.major_ver = {0xC0, 0xD0},
|
|
.cmd = {0x20, 0x00, 0x01, 0x00},
|
|
},
|
|
{
|
|
.type = TMS_THN31,
|
|
.pattern = TMS_BL,
|
|
.name = "thn31",
|
|
.write_len = 9,
|
|
.write_retry = 3,
|
|
.read_retry = 10,
|
|
.check_sum = 1,
|
|
.major_ver = {0xB0},
|
|
.cmd = {0x5A, 0x00, 0x05, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x17},
|
|
},
|
|
{
|
|
.type = SAMPLE_DEV_1,
|
|
.pattern = SAMPLE_MATCH_1,
|
|
.name = "sample_match_1",
|
|
.write_len = 9,
|
|
.write_retry = 3,
|
|
.read_retry = 10,
|
|
.check_sum = 1,
|
|
.major_ver = {0xB0},
|
|
.cmd = {0x5A, 0x00, 0x05, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x17},
|
|
},
|
|
{
|
|
.type = SAMPLE_DEV_2,
|
|
.pattern = SAMPLE_MATCH_2,
|
|
.name = "sample_match_2",
|
|
.write_len = 9,
|
|
.write_retry = 3,
|
|
.read_retry = 10,
|
|
.check_sum = 1,
|
|
.major_ver = {0xB0},
|
|
.cmd = {0x5A, 0x00, 0x05, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x17},
|
|
},
|
|
};
|
|
TMS_INFO("Start+\n");
|
|
|
|
for (count = 0; count < ARRAY_SIZE(info_list); count++) {
|
|
TMS_DEBUG("Check chip info %d times\n", count + 1);
|
|
if (info_list[count].type == TMS_THN31) {
|
|
ret = tms_check_chip_info(gdata, info_list[count]);
|
|
} else if (info_list[count].type == SAMPLE_DEV_1) {
|
|
//ret = sample_dev_1_check_chip_info(gdata, info_list);
|
|
ret = -ERROR;
|
|
} else if (info_list[count].type == SAMPLE_DEV_2) {
|
|
//ret = sample_dev_2_check_chip_info(gdata, info_list);
|
|
ret = -ERROR;
|
|
}
|
|
|
|
if (ret == SUCCESS) {
|
|
chip_type = info_list[count].type;
|
|
gdata->tms->nfc_name = info_list[count].name;
|
|
TMS_INFO("Matched chip is %s\n", gdata->tms->nfc_name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
TMS_INFO("end-\n");
|
|
return ret;
|
|
}
|
|
|
|
static int guidev_dev_probe(struct i2c_client *client,
|
|
const struct i2c_device_id *id)
|
|
{
|
|
int ret;
|
|
TMS_INFO("Start+\n");
|
|
/* step1 : alloc data */
|
|
guidev = kzalloc(sizeof(struct guide_dev), GFP_KERNEL);
|
|
|
|
if (guidev == NULL) {
|
|
TMS_ERR("Guide info alloc memory error\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* step2 : binding tms common data */
|
|
guidev->tms = tms_common_data_binding();
|
|
|
|
if (guidev->tms == NULL) {
|
|
TMS_ERR("Get tms common info error\n");
|
|
ret = -ENOMEM;
|
|
goto err_free_guidev;
|
|
}
|
|
|
|
/* step3 : init and binding parameters for easy operate */
|
|
guidev->client = client;
|
|
guidev->dev = &client->dev;
|
|
|
|
/* step4 : dts parse */
|
|
ret = guidev_parse_dts(guidev);
|
|
|
|
if (ret) {
|
|
TMS_ERR("failed to parse dts\n");
|
|
goto err_free_guidev;
|
|
}
|
|
|
|
/* step5 : I2C function check */
|
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
|
TMS_ERR("need I2C_FUNC_I2C\n");
|
|
guidev_resource_release(guidev);
|
|
ret = -ENODEV;
|
|
goto err_free_guidev;
|
|
}
|
|
|
|
/* step6 : Set gpio */
|
|
ret = guidev_gpio_configure(guidev->hw_res);
|
|
|
|
if (ret) {
|
|
TMS_ERR("failed to configure\n");
|
|
guidev_resource_release(guidev);
|
|
goto err_free_guidev;
|
|
}
|
|
|
|
/* step7 : match nfc chip info */
|
|
ret = guidev_chip_match(guidev);
|
|
|
|
if (ret) {
|
|
TMS_ERR("Fail to match chip\n");
|
|
}
|
|
|
|
/* step8 : Probe driver */
|
|
ret = guidev_probe_driver(client, id, chip_type);
|
|
|
|
if (ret) {
|
|
TMS_ERR("failed to configure\n");
|
|
goto err_free_guidev;
|
|
}
|
|
|
|
/* step9 : Create system property node */
|
|
ret = nfc_create_sysfs_interfaces(&client->dev);
|
|
|
|
if (ret < 0) {
|
|
TMS_ERR("Create sysfs interface failed\n");
|
|
goto err_free_guidev;
|
|
}
|
|
|
|
ret = sysfs_create_link(NULL, &client->dev.kobj, "nfc");
|
|
|
|
if (ret < 0) {
|
|
TMS_ERR("create sysfs link failed\n");
|
|
goto err_remove_sysfs_interface;
|
|
}
|
|
|
|
TMS_INFO("probe finished\n");
|
|
return SUCCESS;
|
|
err_remove_sysfs_interface:
|
|
nfc_remove_sysfs_interfaces(&client->dev);
|
|
err_free_guidev:
|
|
kfree(guidev);
|
|
guidev = NULL;
|
|
TMS_ERR("probe failed, check hardware\n");
|
|
return ret;
|
|
}
|
|
|
|
static int guidev_dev_remove(struct i2c_client *client)
|
|
{
|
|
switch (chip_type) {
|
|
case TMS_THN31:
|
|
nfc_device_remove(client);
|
|
TMS_INFO("TMS THN31 nfc start removed\n");
|
|
break;
|
|
|
|
case SAMPLE_DEV_1:
|
|
//TMS_INFO("XXX XXX nfc start removed\n");
|
|
//sample_dev_1_remove(client);
|
|
break;
|
|
|
|
case SAMPLE_DEV_2:
|
|
//TMS_INFO("XXX XXX nfc start removed\n");
|
|
//sample_dev_2_remove(client);
|
|
break;
|
|
|
|
default:
|
|
TMS_ERR("No chip to remove %d\n", chip_type);
|
|
break;
|
|
}
|
|
|
|
nfc_remove_sysfs_interfaces(&client->dev);
|
|
kfree(guidev);
|
|
guidev = NULL;
|
|
return SUCCESS;
|
|
}
|
|
|
|
void guidev_dev_shutdown(struct i2c_client *client)
|
|
{
|
|
if (!guidev || !guidev->tms || !guidev->tms->set_ven) {
|
|
TMS_ERR("set_ven is NULL");
|
|
return;
|
|
}
|
|
|
|
guidev->tms->set_ven(guidev->hw_res, OFF);
|
|
msleep(20); // hard reset guard time
|
|
}
|
|
|
|
static int guide_suspend(struct device *device)
|
|
{
|
|
switch (chip_type) {
|
|
case TMS_THN31:
|
|
TMS_INFO("TMS THN31 nfc start suspend\n");
|
|
nfc_device_suspend(device);
|
|
break;
|
|
|
|
case SAMPLE_DEV_1:
|
|
//TMS_INFO("XXX XXX nfc start suspend\n");
|
|
//sample_dev_1_suspend(device);
|
|
break;
|
|
|
|
case SAMPLE_DEV_2:
|
|
//TMS_INFO("XXX XXX nfc start suspend\n");
|
|
//sample_dev_2_suspend(device);
|
|
break;
|
|
|
|
default:
|
|
TMS_ERR("No chip to suspend %d\n", chip_type);
|
|
break;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
static int guide_resume(struct device *device)
|
|
{
|
|
switch (chip_type) {
|
|
case TMS_THN31:
|
|
TMS_INFO("TMS THN31 nfc start resume\n");
|
|
nfc_device_resume(device);
|
|
break;
|
|
|
|
case SAMPLE_DEV_1:
|
|
//TMS_INFO("XXX XXX nfc start resume\n");
|
|
//sample_dev_1_resume(device);
|
|
break;
|
|
|
|
case SAMPLE_DEV_2:
|
|
//TMS_INFO("XXX XXX nfc start resume\n");
|
|
//sample_dev_2_suspend(device);
|
|
break;
|
|
|
|
default:
|
|
TMS_ERR("No chip to resume %d\n", chip_type);
|
|
break;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
static const struct i2c_device_id guide_dev_id[] = {
|
|
{GUIDEDEV_NAME, 0 },
|
|
{ }
|
|
};
|
|
|
|
static struct of_device_id guide_match_table[] = {
|
|
{ .compatible = GUIDEDEV_NAME, },
|
|
{ }
|
|
};
|
|
|
|
static const struct dev_pm_ops guide_pm_ops = {
|
|
SET_SYSTEM_SLEEP_PM_OPS(guide_suspend, guide_resume)
|
|
};
|
|
|
|
static struct i2c_driver tms_guide_driver = {
|
|
.id_table = guide_dev_id,
|
|
.probe = guidev_dev_probe,
|
|
.remove = guidev_dev_remove,
|
|
.shutdown = guidev_dev_shutdown,
|
|
.driver = {
|
|
.name = GUIDEDEV_NAME,
|
|
.of_match_table = guide_match_table,
|
|
.pm = &guide_pm_ops,
|
|
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
|
},
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(of, guide_match_table);
|
|
|
|
static int __init tms_guide_init(void)
|
|
{
|
|
int ret = 0;
|
|
TMS_INFO("Loading guide driver\n");
|
|
ret = i2c_add_driver(&tms_guide_driver);
|
|
|
|
if (ret != 0) {
|
|
TMS_ERR("Add driver error ret = %d\n", ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void __exit tms_guide_exit(void)
|
|
{
|
|
switch (chip_type) {
|
|
case TMS_THN31:
|
|
#if defined(CONFIG_TMS_ESE_DEVICE) || defined(CONFIG_TMS_ESE_DEVICE_MODULE)
|
|
ese_driver_exit();
|
|
#endif
|
|
break;
|
|
|
|
case SAMPLE_DEV_1:
|
|
//sample_dev_1_driver_exit(device);
|
|
break;
|
|
|
|
case SAMPLE_DEV_2:
|
|
//sample_dev_2_driver_exit(device);
|
|
break;
|
|
|
|
default:
|
|
TMS_ERR("No chip to resume %d\n", chip_type);
|
|
break;
|
|
}
|
|
|
|
TMS_INFO("Unloading guide driver\n");
|
|
i2c_del_driver(&tms_guide_driver);
|
|
}
|
|
|
|
module_init(tms_guide_init);
|
|
module_exit(tms_guide_exit);
|
|
|
|
MODULE_DESCRIPTION("TMS Guide Driver");
|
|
MODULE_LICENSE("GPL v2");
|