123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- /* drivers/mmc/cprmdrv_samsung.c
- *
- * Copyright 2010 Samsung Electronics Co.Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- */
- #include <linux/mmc/core.h>
- #include <linux/mmc/card.h>
- #include <linux/mmc/host.h>
- #include <linux/mmc/mmc.h>
- #include <linux/mmc/sd.h>
- #include <linux/scatterlist.h>
- #include <linux/uaccess.h>
- #include "cprmdrv_samsung.h"
- #include <linux/slab.h>
- static int mmc_wait_busy(struct mmc_card *card)
- {
- int ret, busy;
- struct mmc_command cmd;
- busy = 0;
- do {
- memset(&cmd, 0, sizeof(struct mmc_command));
- cmd.opcode = MMC_SEND_STATUS;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
- ret = mmc_wait_for_cmd(card->host, &cmd, 0);
- if (ret)
- break;
- if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
- busy = 1;
- printk(KERN_INFO "%s: Warning: Host did not "
- "wait for busy state to end.\n",
- mmc_hostname(card->host));
- }
- } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
- return ret;
- }
- static int CPRM_CMD_SecureRW(struct mmc_card *card,
- unsigned int command,
- unsigned int dir,
- unsigned long arg,
- unsigned char *buff,
- unsigned int length) {
- int err;
- int i = 0;
- struct mmc_request mrq;
- struct mmc_command cmd;
- struct mmc_command stop;
- struct mmc_data data;
- struct scatterlist sg;
- if (command == SD_ACMD25_SECURE_WRITE_MULTI_BLOCK ||
- command == SD_ACMD18_SECURE_READ_MULTI_BLOCK) {
- return -EINVAL;
- }
- memset(&cmd, 0, sizeof(struct mmc_command));
- cmd.opcode = MMC_APP_CMD;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
- //kishore
- mmc_rpm_hold(card->host, &card->dev);
- mmc_claim_host(card->host);
-
- err = mmc_wait_for_cmd(card->host, &cmd, 0);
- if (err)
- {
- printk("CPRM mmc_wait_for_cmd fail = %d ERROR\n", err);
- mmc_release_host(card->host);
- mmc_rpm_release(card->host, &card->dev);
- return (u32)-1;
- }
- if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
- {
- printk("CPRM mmc_host_is_spi fail ERROR\n");
- mmc_release_host(card->host);
- mmc_rpm_release(card->host, &card->dev);
- return (u32)-1;
- }
- printk("CPRM_CMD_SecureRW: 1, command : %d\n", command);
- memset(&cmd, 0, sizeof(struct mmc_command));
- cmd.opcode = command;
- if (command == SD_ACMD43_GET_MKB)
- cmd.arg = arg;
- else
- cmd.arg = 0;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- memset(&data, 0, sizeof(struct mmc_data));
- data.timeout_ns = 100000000;
- data.timeout_clks = 0;
- data.blksz = length;
- data.blocks = 1;
- data.flags = dir;
- data.sg = &sg;
- data.sg_len = 1;
- stop.opcode = MMC_STOP_TRANSMISSION;
- stop.arg = 0;
- stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
- memset(&mrq, 0, sizeof(struct mmc_request));
- mrq.cmd = &cmd;
- mrq.data = &data;
- if (data.blocks == 1)
- mrq.stop = NULL;
- else
- mrq.stop = &stop;
- printk(KERN_DEBUG"CPRM_CMD_SecureRW: 2\n");
- sg_init_one(&sg, buff, length);
- printk(KERN_DEBUG"CPRM_CMD_SecureRW: 3\n");
-
-
- mmc_wait_for_req(card->host, &mrq);
- //kishore
- mmc_release_host(card->host);
- mmc_rpm_release(card->host, &card->dev);
-
-
- printk(KERN_DEBUG"CPRM_CMD_SecureRW: 4\n");
- i = 0;
- do {
- printk(KERN_DEBUG"%x", buff[i++]);
- if (i > 10)
- break;
- } while (i < length);
- printk(KERN_DEBUG"\n");
- if (cmd.error) {
- printk(KERN_DEBUG "%s]cmd.error=%d\n ", __func__, cmd.error);
- return cmd.error;
- }
- if (data.error) {
- printk(KERN_DEBUG "%s]data.error=%d\n ", __func__, data.error);
- return data.error;
- }
- err = mmc_wait_busy(card);
- printk(KERN_DEBUG"CPRM_CMD_SecureRW: 5\n");
- if (err)
- return err;
- return 0;
- }
- static int CPRM_CMD_SecureMultiRW(struct mmc_card *card,
- unsigned int command,
- unsigned int dir,
- unsigned long arg,
- unsigned char *buff,
- unsigned int length) {
- int err;
- struct mmc_request mrq;
- struct mmc_command cmd;
- struct mmc_command stop;
- struct mmc_data data;
- unsigned long flags;
- struct scatterlist sg;
- memset(&cmd, 0, sizeof(struct mmc_command));
- memset(&stop, 0, sizeof(struct mmc_command));
- cmd.opcode = MMC_APP_CMD;
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
- err = mmc_wait_for_cmd(card->host, &cmd, 0);
- if (err)
- return (u32)-1;
- if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
- return (u32)-1;
- printk(KERN_DEBUG"CPRM_CMD_SecureRW: 1\n");
- memset(&cmd, 0, sizeof(struct mmc_command));
- cmd.opcode = command;
- if (command == SD_ACMD43_GET_MKB)
- cmd.arg = arg;
- else
- cmd.arg = 0;
- cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- memset(&data, 0, sizeof(struct mmc_data));
- data.timeout_ns = 100000000;
- data.timeout_clks = 0;
- data.blksz = 512;
- data.blocks = (length + 511) / 512;
- data.flags = dir;
- data.sg = &sg;
- data.sg_len = 1;
- stop.opcode = MMC_STOP_TRANSMISSION;
- stop.arg = 0;
- stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
- memset(&mrq, 0, sizeof(struct mmc_request));
- mrq.cmd = &cmd;
- mrq.data = &data;
- mrq.stop = &stop;
- printk(KERN_DEBUG "CPRM_CMD_SecureRW: 2\n");
- sg_init_one(&sg, buff, length);
- if (dir == MMC_DATA_WRITE) {
- local_irq_save(flags);
- sg_copy_from_buffer(&sg, data.sg_len, buff, length);
- local_irq_restore(flags);
- }
- printk(KERN_DEBUG "CPRM_CMD_SecureRW: 3\n");
- mmc_wait_for_req(card->host, &mrq);
- printk(KERN_DEBUG "CPRM_CMD_SecureRW: 4\n");
- if (cmd.error) {
- printk(KERN_DEBUG "%s]cmd.error=%d\n", __func__, cmd.error);
- return cmd.error;
- }
- if (data.error) {
- printk(KERN_DEBUG "%s]data.error=%d\n", __func__, data.error);
- return data.error;
- }
- err = mmc_wait_busy(card);
- printk(KERN_DEBUG "CPRM_CMD_SecureRW: 5\n");
- if (dir == MMC_DATA_READ) {
- local_irq_save(flags);
- sg_copy_to_buffer(&sg, data.sg_len, buff, length);
- local_irq_restore(flags);
- }
- if (err)
- return err;
- return 0;
- }
- int stub_sendcmd(struct mmc_card *card,
- unsigned int cmd,
- unsigned long arg,
- unsigned int len,
- unsigned char *buff) {
- int returnVal = -1;
- unsigned char *kbuffer = NULL;
- int direction = 0;
- int result = 0;
- if (card == NULL) {
- printk(KERN_DEBUG "stub_sendcmd: card is null error\n");
- return -ENXIO;
- }
- kbuffer = kmalloc(len, GFP_KERNEL);
- if (kbuffer == NULL) {
- printk(KERN_DEBUG "malloc failed\n");
- return -ENOMEM;
- }
- memset(kbuffer, 0x00, len);
- printk(KERN_DEBUG "%s]cmd=0x%x,len=%d\n ", __func__, cmd, len);
- mmc_claim_host(card->host);
- switch (cmd) {
- case ACMD43:
- direction = MMC_DATA_READ;
- returnVal = CPRM_CMD_SecureRW(card,
- SD_ACMD43_GET_MKB,
- direction,
- arg,
- kbuffer,
- len);
- printk(KERN_DEBUG "SD_ACMD43_GET_MKB:0x%x\n", returnVal);
- break;
- case ACMD44:
- direction = MMC_DATA_READ;
- returnVal = CPRM_CMD_SecureRW(card,
- SD_ACMD44_GET_MID,
- direction,
- 0,
- kbuffer,
- len);
- printk(KERN_DEBUG "SD_ACMD44_GET_MID:0x%x\n", returnVal);
- break;
- case ACMD45:
- direction = MMC_DATA_WRITE;
- result = copy_from_user((void *)kbuffer, (void *)buff, len);
- returnVal = CPRM_CMD_SecureRW(card,
- SD_ACMD45_SET_CER_RN1,
- direction,
- 0,
- kbuffer,
- len);
- printk(KERN_INFO"SD_ACMD45_SET_CER_RN1 [0x%x]\n ", returnVal);
- break;
- case ACMD46:
- direction = MMC_DATA_READ;
- returnVal = CPRM_CMD_SecureRW(card,
- SD_ACMD46_GET_CER_RN2,
- direction,
- 0,
- kbuffer,
- len);
- printk(KERN_DEBUG "SD_ACMD46_GET_CER_RN2:0x%x\n",
- returnVal);
- break;
- case ACMD47:
- direction = MMC_DATA_WRITE;
- result = copy_from_user((void *)kbuffer, (void *)buff, len);
- returnVal = CPRM_CMD_SecureRW(card,
- SD_ACMD47_SET_CER_RES2,
- direction,
- 0,
- kbuffer,
- len);
- printk(KERN_DEBUG "SD_ACMD47_SET_CER_RES2:0x%x\n",
- returnVal);
- break;
- case ACMD48:
- direction = MMC_DATA_READ;
- returnVal = CPRM_CMD_SecureRW(card,
- SD_ACMD48_GET_CER_RES1,
- direction,
- 0,
- kbuffer,
- len);
- printk(KERN_DEBUG "SD_ACMD48_GET_CER_RES1:0x%x\n",
- returnVal);
- break;
- case ACMD25:
- direction = MMC_DATA_WRITE;
- result = copy_from_user((void *)kbuffer, (void *)buff, len);
- returnVal = CPRM_CMD_SecureMultiRW(card,
- SD_ACMD25_SECURE_WRITE_MULTI_BLOCK,
- direction,
- 0,
- kbuffer,
- len);
- printk(KERN_DEBUG "SD_ACMD25_SECURE_WRITE_MULTI_BLOCK[%d]=%d\n",
- len, returnVal);
- break;
- case ACMD18:
- direction = MMC_DATA_READ;
- returnVal = CPRM_CMD_SecureMultiRW(card,
- SD_ACMD18_SECURE_READ_MULTI_BLOCK,
- direction,
- 0,
- kbuffer,
- len);
- printk(KERN_DEBUG "SD_ACMD18_SECURE_READ_MULTI_BLOCK [%d]=%d\n",
- len, returnVal);
- break;
- case ACMD13:
- break;
- default:
- printk(KERN_DEBUG " %s ] : CMD [ %x ] ERROR", __func__, cmd);
- break;
- }
- if (returnVal == 0) {
- if (direction == MMC_DATA_READ)
- result = copy_to_user((void *)buff,
- (void *)kbuffer,
- len);
- result = returnVal;
- printk(KERN_DEBUG "stub_sendcmd SDAS_E_SUCCESS\n");
- } else {
- printk(KERN_DEBUG "stub_sendcmd SDAS_E_FAIL\n");
- result = -EIO;
- }
- mmc_release_host(card->host);
- kfree(kbuffer);
- return result;
- }
|