| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- #include <generated/autoconf.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/init.h>
- #include <linux/spinlock.h>
- #include <linux/timer.h>
- #include <linux/ioport.h>
- #include <linux/device.h>
- #include <linux/miscdevice.h>
- #include <linux/platform_device.h>
- #include <linux/interrupt.h>
- #include <linux/delay.h>
- #include <linux/blkdev.h>
- #include <linux/mmc/host.h>
- #include <linux/mmc/card.h>
- #include <linux/mmc/core.h>
- #include <linux/mmc/mmc.h>
- #include <linux/mmc/sd.h>
- #include <linux/mmc/sdio.h>
- #include <linux/dma-mapping.h>
- #include <linux/proc_fs.h>
- #include <linux/fs.h>
- #include <asm/uaccess.h>
- #include "mt_sd.h"
- #include "emmc_otp.h"
- #include <mt-plat/partition.h>
- #define DRV_NAME_MISC "otp"
- #define PROCNAME "driver/otp"
- #ifndef CONFIG_MTK_EMMC_SUPPORT_OTP
- #define CONFIG_MTK_EMMC_SUPPORT_OTP
- #endif
- #define EMMC_OTP_DEBUG 1
- /* static spinlock_t g_emmc_otp_lock; */
- static struct emmc_otp_config g_emmc_otp_func;
- static unsigned int sg_wp_size; /* byte unit */
- static unsigned int g_otp_user_ccci = 2 * 1024 * 1024;
- struct msdc_host *emmc_otp_get_host(void)
- {
- return mtk_msdc_host[EMMC_HOST_NUM];
- }
- /******************************************************************************
- * EMMC OTP operations
- * ***************************************************************************/
- unsigned int emmc_get_wp_size(void)
- {
- unsigned char l_ext_csd[512];
- struct msdc_host *host_ctl;
- u32 *resp = NULL;
- unsigned int write_prot_grpsz = 0;
- /* not to change ERASE_GRP_DEF after card initialized */
- host_ctl = emmc_otp_get_host();
- BUG_ON(!host_ctl);
- BUG_ON(!host_ctl->mmc);
- BUG_ON(!host_ctl->mmc->card);
- if (0 != sg_wp_size) {
- pr_debug("msdc[%s:%d]mmc_host = 0x%p,sg_wp_size=%d\n", __func__,
- __LINE__, host_ctl->mmc, sg_wp_size);
- return sg_wp_size;
- }
- pr_debug("[%s:%d]mmc_host = 0x%p\n", __func__, __LINE__, host_ctl->mmc);
- mmc_claim_host(host_ctl->mmc);
- /* pr_debug("[%s:%d]claim host done!\n", __func__, __LINE__);
- * pr_debug("claim_status=%d, claim_cnt=%d, claimer=0x%x, current=0x%x\n",
- * host_ctl->mmc->claimed, host_ctl->mmc->claim_cnt, host_ctl->mmc->claimer
- * , current);
- */
- /*
- * As the ext_csd is so large and mostly unused, we don't store the
- * raw block in mmc_card, so re-get it here.
- */
- mmc_send_ext_csd(host_ctl->mmc->card, l_ext_csd);
- #if EMMC_OTP_DEBUG
- {
- int i;
- for (i = 0; i < 512; i++) {
- pr_debug("%x", l_ext_csd[i]);
- if (0 == ((i + 1) % 16))
- pr_debug("\n");
- }
- }
- #endif
- mmc_release_host(host_ctl->mmc);
- /* otp length equal to one write protect group size */
- if (l_ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x1) {
- /* use high-capacity erase uint size, hc erase timeout, hc wp size,
- * store in EXT_CSD */
- sg_wp_size =
- (512 * 1024 * l_ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
- l_ext_csd[EXT_CSD_HC_WP_GRP_SIZE]);
- } else {
- resp = host_ctl->mmc->card->raw_csd;
- write_prot_grpsz = UNSTUFF_BITS(resp, 32, 5);
- /* use old erase group size,write protect group size, store in CSD*/
- sg_wp_size = (512 * host_ctl->mmc->card->erase_size)*
- (write_prot_grpsz + 1);
- }
- pr_debug("write_protect_group_size = %d MByte %s:%d\n", sg_wp_size / 1048576);
- return sg_wp_size;
- }
- /* need subtract emmc reserved region for combo feature */
- unsigned int emmc_otp_start(void)
- {
- unsigned int l_addr;
- /* unsigned int l_offset;*/ /* for emmc combo reserved */
- /* unsigned int l_reserve;*/
- struct msdc_host *host_ctl;
- struct hd_struct *lp_hd_struct = NULL;
- if (0 == sg_wp_size)
- emmc_get_wp_size();
- host_ctl = emmc_otp_get_host();
- BUG_ON(!host_ctl);
- BUG_ON(!host_ctl->mmc);
- BUG_ON(!host_ctl->mmc->card);
- lp_hd_struct = get_part("otp");
- if (NULL == lp_hd_struct) {
- pr_debug("not find otp in scatter file error!\n");
- put_part(lp_hd_struct);
- return -EFAULT;
- }
- l_addr = lp_hd_struct->start_sect; /* block unit */
- /* find wp group start address in 43MB reserved region */
- if (l_addr % (sg_wp_size >> 9))
- l_addr += ((sg_wp_size >> 9) - l_addr % (sg_wp_size >> 9));
- if (NULL != lp_hd_struct)
- put_part(lp_hd_struct);
- pr_debug("find OTP start address is 0x%x\n", l_addr);
- return l_addr;
- }
- unsigned int emmc_otp_query_length(unsigned int *QLength)
- {
- /* otp length equal to one write protect group size */
- *QLength = emmc_get_wp_size() - g_otp_user_ccci;
- return 0;
- }
- unsigned int emmc_otp_read(unsigned int blk_offset, void *BufferPtr)
- {
- char l_buf[512];
- unsigned char *l_rcv_buf = (unsigned char *)BufferPtr;
- unsigned int l_addr;
- unsigned int l_otp_size;
- unsigned int l_ret;
- struct scatterlist msdc_sg;
- struct mmc_data msdc_data;
- struct mmc_command msdc_cmd;
- struct mmc_request msdc_mrq;
- struct msdc_host *host_ctl;
- /* check parameter */
- l_addr = emmc_otp_start();
- l_otp_size = emmc_get_wp_size();
- if (blk_offset > (l_otp_size >> 9))
- return OTP_ERROR_OVERSCOPE;
- l_addr += blk_offset;
- host_ctl = emmc_otp_get_host();
- BUG_ON(!host_ctl);
- BUG_ON(!host_ctl->mmc);
- pr_debug("[%s:%d]mmc_host is : 0x%p\n", __func__, __LINE__, host_ctl->mmc);
- mmc_claim_host(host_ctl->mmc);
- /* make sure access user data area */
- mmc_send_ext_csd(host_ctl->mmc->card, l_buf);
- if (l_buf[179] & 0x7) {
- l_buf[179] &= ~0x7;
- l_buf[179] |= 0x0;
- mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000);
- }
- #if EMMC_OTP_DEBUG
- pr_debug("EMMC_OTP: start MSDC_SINGLE_READ_WRITE!\n");
- #endif
- memset(&msdc_data, 0, sizeof(struct mmc_data));
- memset(&msdc_mrq, 0, sizeof(struct mmc_request));
- memset(&msdc_cmd, 0, sizeof(struct mmc_command));
- msdc_mrq.cmd = &msdc_cmd;
- msdc_mrq.data = &msdc_data;
- msdc_data.flags = MMC_DATA_READ;
- msdc_cmd.opcode = MMC_READ_SINGLE_BLOCK;
- msdc_data.blocks = 1; /* one block Request */
- memset(l_rcv_buf, 0, 512);
- msdc_cmd.arg = l_addr;
- BUG_ON(!host_ctl->mmc->card);
- if (!mmc_card_blockaddr(host_ctl->mmc->card)) {
- pr_debug("the device is used byte address!\n");
- msdc_cmd.arg <<= 9;
- }
- msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- msdc_data.stop = NULL;
- msdc_data.blksz = 512;
- msdc_data.sg = &msdc_sg;
- msdc_data.sg_len = 1;
- sg_init_one(&msdc_sg, l_rcv_buf, 512);
- mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card);
- mmc_wait_for_req(host_ctl->mmc, &msdc_mrq);
- mmc_release_host(host_ctl->mmc);
- if (msdc_cmd.error)
- l_ret = msdc_cmd.error;
- if (msdc_data.error)
- l_ret = msdc_data.error;
- else
- l_ret = OTP_SUCCESS;
- return l_ret;
- }
- unsigned int emmc_otp_write(unsigned int blk_offset, void *BufferPtr)
- {
- char l_buf[512];
- unsigned char *l_send_buf = (unsigned char *)BufferPtr;
- unsigned int l_ret;
- unsigned int l_addr;
- unsigned int l_otp_size;
- struct scatterlist msdc_sg;
- struct mmc_data msdc_data;
- struct mmc_command msdc_cmd;
- struct mmc_request msdc_mrq;
- struct msdc_host *host_ctl;
- #ifdef MTK_MSDC_USE_CACHE
- struct mmc_command msdc_sbc;
- #endif
- /* check parameter */
- l_addr = emmc_otp_start();
- l_otp_size = emmc_get_wp_size();
- if (blk_offset > (l_otp_size >> 9))
- return OTP_ERROR_OVERSCOPE;
- l_addr += blk_offset;
- host_ctl = emmc_otp_get_host();
- BUG_ON(!host_ctl);
- BUG_ON(!host_ctl->mmc);
- mmc_claim_host(host_ctl->mmc);
- /* make sure access user data area */
- mmc_send_ext_csd(host_ctl->mmc->card, l_buf);
- if (l_buf[179] & 0x7) {
- l_buf[179] &= ~0x7;
- l_buf[179] |= 0x0;
- mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000);
- }
- #if EMMC_OTP_DEBUG
- pr_debug("EMMC_OTP: start MSDC_SINGLE_READ_WRITE!\n");
- #endif
- memset(&msdc_data, 0, sizeof(struct mmc_data));
- memset(&msdc_mrq, 0, sizeof(struct mmc_request));
- memset(&msdc_cmd, 0, sizeof(struct mmc_command));
- #ifdef MTK_MSDC_USE_CACHE
- memset(&msdc_sbc, 0, sizeof(struct mmc_command));
- #endif
- msdc_mrq.cmd = &msdc_cmd;
- msdc_mrq.data = &msdc_data;
- msdc_data.flags = MMC_DATA_WRITE;
- #ifdef MTK_MSDC_USE_CACHE
- if (mmc_card_mmc(host_ctl->mmc->card) && (host_ctl->mmc->card->ext_csd.cache_ctrl & 0x1)) {
- msdc_cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
- msdc_mrq.sbc = &msdc_sbc;
- msdc_mrq.sbc->opcode = MMC_SET_BLOCK_COUNT;
- msdc_mrq.sbc->arg = msdc_data.blocks | (1 << 31);
- msdc_mrq.sbc->flags = MMC_RSP_R1 | MMC_CMD_AC;
- } else {
- msdc_cmd.opcode = MMC_WRITE_BLOCK;
- }
- #else
- msdc_cmd.opcode = MMC_WRITE_BLOCK;
- #endif
- msdc_data.blocks = 1;
- msdc_cmd.arg = l_addr;
- BUG_ON(!host_ctl->mmc->card);
- if (!mmc_card_blockaddr(host_ctl->mmc->card)) {
- pr_debug("the device is used byte address!\n");
- msdc_cmd.arg <<= 9;
- }
- msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- msdc_data.stop = NULL;
- msdc_data.blksz = 512;
- msdc_data.sg = &msdc_sg;
- msdc_data.sg_len = 1;
- sg_init_one(&msdc_sg, l_send_buf, 512);
- mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card);
- mmc_wait_for_req(host_ctl->mmc, &msdc_mrq);
- mmc_release_host(host_ctl->mmc);
- if (msdc_cmd.error)
- l_ret = msdc_cmd.error;
- if (msdc_data.error)
- l_ret = msdc_data.error;
- else
- l_ret = OTP_SUCCESS;
- return l_ret;
- }
- /*
- static int emmc_otp_proc_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
- {
- int len;
- if (off > 0)
- {
- return 0;
- }
- return len;
- }
- static int emmc_otp_proc_write(struct file* file, const char* buffer,
- unsigned long count, void *data)
- {
- char buf[16];
- int len = count;
- if (len >= sizeof(buf))
- {
- len = sizeof(buf) - 1;
- }
- if (copy_from_user(buf, buffer, len))
- {
- return -EFAULT;
- }
- return len;
- }
- */
- static int mt_otp_open(struct inode *inode, struct file *filp)
- {
- pr_debug("[%s]:(MAJOR)%d:(MINOR)%d\n",
- __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
- filp->private_data = (int *)OTP_MAGIC_NUM;
- return 0;
- }
- static int mt_otp_release(struct inode *inode, struct file *filp)
- {
- pr_debug("[%s]:(MAJOR)%d:(MINOR)%d\n",
- __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
- return 0;
- }
- static int mt_otp_access(unsigned int access_type, unsigned int offset, void *buff_ptr,
- unsigned int length, unsigned int *status)
- {
- unsigned int ret = 0;
- char *BufAddr = (char *)buff_ptr;
- unsigned int blkno, AccessLength = 0;
- unsigned int l_block_size = 512;
- int Status = 0;
- char *p_D_Buff;
- /* char S_Buff[64]; */
- p_D_Buff = kmalloc(l_block_size, GFP_KERNEL);
- if (!p_D_Buff) {
- ret = -ENOMEM;
- *status = OTP_ERROR_NOMEM;
- goto exit;
- }
- pr_debug("[%s]: %s (0x%x) length:(%d bytes) !\n",
- __func__, access_type ? "WRITE" : "READ", offset, length);
- do {
- blkno = offset / l_block_size;
- if (FS_EMMC_OTP_READ == access_type) {
- memset(p_D_Buff, 0xff, l_block_size);
- pr_debug("[%s]: Read Access of page (%d)\n", __func__, blkno);
- Status = g_emmc_otp_func.read(blkno, p_D_Buff);
- *status = Status;
- if (OTP_SUCCESS != Status) {
- pr_debug("[%s]: Read status (%d)\n", __func__, Status);
- break;
- }
- AccessLength = l_block_size - (offset % l_block_size);
- if (length >= AccessLength) {
- memcpy(BufAddr, (p_D_Buff + (offset % l_block_size)), AccessLength);
- } else {
- /* last time */
- memcpy(BufAddr, (p_D_Buff + (offset % l_block_size)), length);
- }
- } else if (FS_EMMC_OTP_WRITE == access_type) {
- AccessLength = l_block_size - (offset % l_block_size);
- memset(p_D_Buff, 0x0, l_block_size);
- Status = g_emmc_otp_func.read(blkno, p_D_Buff);
- *status = Status;
- if (OTP_SUCCESS != Status) {
- pr_debug("[%s]: read before write, Read status (%d) blkno (0x%x)\n",
- __func__, Status, blkno);
- break;
- }
- if (length >= AccessLength) {
- memcpy((p_D_Buff + (offset % l_block_size)), BufAddr, AccessLength);
- } else {
- /* last time */
- memcpy((p_D_Buff + (offset % l_block_size)), BufAddr, length);
- }
- Status = g_emmc_otp_func.write(blkno, p_D_Buff);
- *status = Status;
- if (OTP_SUCCESS != Status) {
- pr_debug("[%s]: Write status (%d)\n", __func__, Status);
- break;
- }
- } else {
- pr_err("[%s]: Error, not either read nor write operations !\n", __func__);
- break;
- }
- offset += AccessLength;
- BufAddr += AccessLength;
- if (length <= AccessLength) {
- length = 0;
- break;
- }
- length -= AccessLength;
- pr_debug("[%s]: Remaining %s (%d) !\n", __func__,
- access_type ? "WRITE" : "READ", length);
- } while (1);
- kfree(p_D_Buff);
- exit:
- return ret;
- }
- static long mt_otp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- {
- int ret = 0;
- char *pbuf;
- void __user *uarg = (void __user *)arg;
- struct otp_ctl otpctl;
- /* Lock */
- /* spin_lock(&g_emmc_otp_lock); */
- if (copy_from_user(&otpctl, uarg, sizeof(struct otp_ctl))) {
- ret = -EFAULT;
- goto exit;
- }
- /*
- if(false == g_bInitDone)
- {
- pr_err("ERROR: EMMC Flash Not initialized !!\n");
- ret = -EFAULT;
- goto exit;
- } */
- pbuf = kmalloc_array(otpctl.Length, sizeof(char), GFP_KERNEL);
- if (!pbuf) {
- ret = -ENOMEM;
- goto exit;
- }
- switch (cmd) {
- case EMMC_OTP_GET_LENGTH:
- pr_debug("OTP IOCTL: EMMC_OTP_GET_LENGTH\n");
- if (('c' == (otpctl.status & 0xff)) && ('c' == ((otpctl.status >> 8) & 0xff))
- && ('c' == ((otpctl.status >> 16) & 0xff))
- && ('i' == ((otpctl.status >> 24) & 0xff))) {
- otpctl.QLength = g_otp_user_ccci;
- } else {
- g_emmc_otp_func.query_length(&otpctl.QLength);
- }
- otpctl.status = OTP_SUCCESS;
- pr_debug("OTP IOCTL: The Length is %d\n", otpctl.QLength);
- break;
- case EMMC_OTP_READ:
- pr_debug("OTP IOCTL: EMMC_OTP_READ Offset(0x%x), Length(0x%x)\n", otpctl.Offset,
- otpctl.Length);
- memset(pbuf, 0xff, sizeof(char) * otpctl.Length);
- mt_otp_access(FS_EMMC_OTP_READ, otpctl.Offset, pbuf, otpctl.Length, &otpctl.status);
- if (copy_to_user(otpctl.BufferPtr, pbuf, (sizeof(char) * otpctl.Length))) {
- pr_err("EMMC_OTP IOCTL: Copy to user buffer Error !\n");
- goto error;
- }
- break;
- case EMMC_OTP_WRITE:
- pr_debug("OTP IOCTL: EMMC_OTP_WRITE Offset(0x%x), Length(0x%x)\n", otpctl.Offset,
- otpctl.Length);
- if (copy_from_user(pbuf, otpctl.BufferPtr, (sizeof(char) * otpctl.Length))) {
- pr_err("EMMC_OTP IOCTL: Copy from user buffer Error !\n");
- goto error;
- }
- mt_otp_access(FS_EMMC_OTP_WRITE, otpctl.Offset, pbuf, otpctl.Length,
- &otpctl.status);
- break;
- default:
- ret = -EINVAL;
- }
- ret = copy_to_user(uarg, &otpctl, sizeof(struct otp_ctl));
- error:
- kfree(pbuf);
- exit:
- /* spin_unlock(&g_emmc_otp_lock); */
- return ret;
- }
- #ifdef CONFIG_COMPAT
- static int compat_get_otp_ctl_allocation(struct compat_otp_ctl __user *arg32,
- struct otp_ctl __user *arg64)
- {
- compat_uint_t u;
- compat_uptr_t p;
- int err;
- err = get_user(u, &(arg32->QLength));
- err |= put_user(u, &(arg64->QLength));
- err |= get_user(u, &(arg32->Offset));
- err |= put_user(u, &(arg64->Offset));
- err |= get_user(u, &(arg32->Length));
- err |= put_user(u, &(arg64->Length));
- err |= get_user(p, &(arg32->BufferPtr));
- err |= put_user(compat_ptr(p), &(arg64->BufferPtr));
- err |= get_user(u, &(arg32->status));
- err |= put_user(u, &(arg64->status));
- return err;
- }
- static int compat_put_otp_ctl_allocation(struct compat_otp_ctl __user *arg32,
- struct otp_ctl __user *arg64)
- {
- compat_uint_t u;
- int err;
- err = get_user(u, &(arg64->QLength));
- err |= put_user(u, &(arg32->QLength));
- err |= get_user(u, &(arg64->Offset));
- err |= put_user(u, &(arg32->Offset));
- err |= get_user(u, &(arg64->Length));
- err |= put_user(u, &(arg32->Length));
- err |= get_user(u, &(arg64->status));
- err |= put_user(u, &(arg32->status));
- return err;
- }
- static long mt_otp_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
- {
- int ret = 0;
- int err = 0;
- struct compat_otp_ctl *arg32;
- struct otp_ctl *arg64;
- /* void __user *uarg = compat_ptr(arg); */
- if (!file->f_op || !file->f_op->unlocked_ioctl)
- return -ENOTTY;
- arg32 = compat_ptr(arg);
- arg64 = compat_alloc_user_space(sizeof(*arg64));
- if (arg64 == NULL)
- return -EFAULT;
- ret = compat_get_otp_ctl_allocation(arg32, arg64);
- if (ret)
- return ret;
- /* Lock */
- /* spin_lock(&g_emmc_otp_lock); */
- switch (cmd) {
- case COMPAT_EMMC_OTP_GET_LENGTH:
- ret = mt_otp_ioctl(file, EMMC_OTP_GET_LENGTH, (unsigned long)arg64);
- /* pr_err("OTP IOCTL: COMPAT_EMMC_OTP_GET_LENGTH\n"); */
- if (ret)
- pr_err("EMMC_OTP_GET_LENGTH unlocked_ioctl failed.");
- break;
- case COMPAT_EMMC_OTP_READ:
- /* pr_err("OTP IOCTL: COMPAT_EMMC_OTP_READ\n"); */
- ret = mt_otp_ioctl(file, EMMC_OTP_READ, (unsigned long)arg64);
- if (ret)
- pr_err("EMMC_OTP_READ unlocked_ioctl failed.");
- break;
- case COMPAT_EMMC_OTP_WRITE:
- /* pr_err("OTP IOCTL: COMPAT_EMMC_OTP_WRITE\n"); */
- ret = mt_otp_ioctl(file, EMMC_OTP_WRITE, (unsigned long)arg64);
- if (ret)
- pr_err("EMMC_OTP_WRITE unlocked_ioctl failed.");
- break;
- default:
- ret = -EINVAL;
- }
- err = compat_put_otp_ctl_allocation(arg32, arg64);
- return ret ? ret : err;
- }
- #endif
- static const struct file_operations emmc_otp_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = mt_otp_ioctl,
- .open = mt_otp_open,
- .release = mt_otp_release,
- #ifdef CONFIG_COMPAT
- .compat_ioctl = mt_otp_ioctl_compat,
- #endif
- };
- static struct miscdevice emmc_otp_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "otp",
- .fops = &emmc_otp_fops,
- };
- static int emmc_otp_probe(struct platform_device *pdev)
- {
- int ret = 0;
- pr_debug("in emmc otp probe function\n");
- return ret;
- }
- static int emmc_otp_remove(struct platform_device *pdev)
- {
- return 0;
- }
- static struct platform_driver emmc_otp_driver = {
- .probe = emmc_otp_probe,
- .remove = emmc_otp_remove,
- .driver = {
- .name = DRV_NAME_MISC,
- .owner = THIS_MODULE,
- },
- };
- static int __init emmc_otp_init(void)
- {
- int err = 0;
- pr_debug("MediaTek EMMC OTP misc driver init\n");
- /* spin_lock_init(&g_emmc_otp_lock); */
- g_emmc_otp_func.query_length = emmc_otp_query_length;
- g_emmc_otp_func.read = emmc_otp_read;
- g_emmc_otp_func.write = emmc_otp_write;
- #if 0
- #ifndef USER_BUILD_KERNEL
- entry = create_proc_entry(PROCNAME, 0660, NULL);
- #else
- entry = create_proc_entry(PROCNAME, 0440, NULL);
- #endif
- if (entry == NULL) {
- pr_err("emmc OTP: unable to create /proc entry\n");
- return -ENOMEM;
- }
- entry->read_proc = emmc_otp_proc_read;
- entry->write_proc = emmc_otp_proc_write;
- /* entry->owner = THIS_MODULE; */
- #endif
- platform_driver_register(&emmc_otp_driver);
- pr_debug("OTP: register EMMC OTP device ...\n");
- err = misc_register(&emmc_otp_dev);
- if (unlikely(err)) {
- pr_err("OTP: failed to register EMMC OTP device!\n");
- return err;
- }
- return 0;
- }
- static void __exit emmc_otp_exit(void)
- {
- pr_debug("MediaTek EMMC OTP misc driver exit\n");
- misc_deregister(&emmc_otp_dev);
- g_emmc_otp_func.query_length = NULL;
- g_emmc_otp_func.read = NULL;
- g_emmc_otp_func.write = NULL;
- platform_driver_unregister(&emmc_otp_driver);
- remove_proc_entry(PROCNAME, NULL);
- }
- module_init(emmc_otp_init);
- module_exit(emmc_otp_exit);
|