Re: [PATCH 07/12] mmci: pass power_mode to the translate_vdd callback

2010-06-24 Thread Rabin VINCENT
On Wed, Jun 23, 2010 at 00:03:47 +0200, Linus Walleij wrote:
 2010/6/22 Rabin Vincent rabin.vinc...@stericsson.com:
  @@ -17,7 +17,8 @@
   * mmc/host.h
   * @translate_vdd: a callback function to translate a MMC_VDD_*
   * mask into a value to be binary or:ed and written into the
  - * MMCIPWR register of the block
  + * MMCIPWR register of the block.  May also control external power
  + * based on the power_mode.
 
 Actually this callback is named like that for a reason: it is to be used
 to translate the MMC_VDD_* into a u8:4 bitmask for the MMCIPWR
 register, 4 bits possibly routed out of the PL180 block on some
 designs (never seen in practice, but could be used in theory).
 
 So it translates a voltage into a 4-bit bitmask, hence the name.
 
 Now the semantics are altered to have other side-effects in
 the platform, so the function should be renamed, something like
 platform_vdd_handler() would be more appropriate.
 

This is already inside platform data, so how about just -vdd_handler()?
Or -set_power(), like some other drivers?

Note that we'd also like to use this to do the board-specific settings
for the *DIREN and FBCLK bits, which replace the Voltage bits on some ST
variants, like so:

+static u32 mop500_sdi0_translate_vdd(struct device *dev, unsigned int vdd,
+unsigned char power_mode)
+{
+   if (power_mode == MMC_POWER_UP)
+   gpio_set_value(gpio_sdmmc_en, 1);
+   else if (power_mode == MMC_POWER_OFF)
+   gpio_set_value(gpio_sdmmc_en, 0);
+
+   return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
+  MCI_DATA2DIREN | MCI_DATA31DIREN;
+}

Rabin
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 1/5] mmc: Add erase, secure erase, trim and secure trim operations

2010-06-24 Thread Adrian Hunter
From c7a9eb435367fd8ef16e79c053f0c5a630473830 Mon Sep 17 00:00:00 2001
From: Adrian Hunter adrian.hun...@nokia.com
Date: Tue, 1 Jun 2010 13:20:22 +0300
Subject: [PATCH 1/5] mmc: Add erase, secure erase, trim and secure trim 
operations

SD/MMC cards tend to support an erase operation.  In addition,
eMMC v4.4 cards can support secure erase, trim and secure trim
operations that are all variants of the basic erase command.

Signed-off-by: Adrian Hunter adrian.hun...@nokia.com
---
 drivers/mmc/core/core.c   |  346 +
 drivers/mmc/core/core.h   |2 +
 drivers/mmc/core/mmc.c|   47 ++-
 drivers/mmc/core/sd.c |   82 +++
 drivers/mmc/core/sd_ops.c |   48 ++
 drivers/mmc/core/sd_ops.h |1 +
 include/linux/mmc/card.h  |   19 +++
 include/linux/mmc/core.h  |   19 +++
 include/linux/mmc/host.h  |1 +
 include/linux/mmc/mmc.h   |   24 +++-
 include/linux/mmc/sd.h|5 +
 11 files changed, 587 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 569e94d..3b8b1b7 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1050,6 +1050,352 @@ void mmc_detect_change(struct mmc_host *host, unsigned 
long delay)
 
 EXPORT_SYMBOL(mmc_detect_change);
 
+void mmc_init_erase(struct mmc_card *card)
+{
+   unsigned int sz;
+
+   if (is_power_of_2(card-erase_size))
+   card-erase_shift = ffs(card-erase_size) - 1;
+   else
+   card-erase_shift = 0;
+
+   /*
+* It is possible to erase an arbitrarily large area of an SD or MMC
+* card.  That is not desirable because it can take a long time
+* (minutes) potentially delaying more important I/O, and also the
+* timeout calculations become increasingly hugely over-estimated.
+* Consequently, 'pref_erase' is defined as a guide to limit erases
+* to that size and alignment.
+*
+* For SD cards that define Allocation Unit size, limit erases to one
+* Allocation Unit at a time.  For MMC cards that define High Capacity
+* Erase Size, whether it is switched on or not, limit to that size.
+* Otherwise just have a stab at a good value.  For modern cards it
+* will end up being 4MiB.  Note that if the value is too small, it
+* can end up taking longer to erase.
+*/
+   if (mmc_card_sd(card)  card-ssr.au) {
+   card-pref_erase = card-ssr.au;
+   card-erase_shift = ffs(card-ssr.au) - 1;
+   } else if (card-ext_csd.hc_erase_size) {
+   card-pref_erase = card-ext_csd.hc_erase_size;
+   } else {
+   sz = (card-csd.capacity  (card-csd.read_blkbits - 9))  11;
+   if (sz  128)
+   card-pref_erase = 512 * 1024 / 512;
+   else if (sz  512)
+   card-pref_erase = 1024 * 1024 / 512;
+   else if (sz  1024)
+   card-pref_erase = 2 * 1024 * 1024 / 512;
+   else
+   card-pref_erase = 4 * 1024 * 1024 / 512;
+   if (card-pref_erase  card-erase_size)
+   card-pref_erase = card-erase_size;
+   else {
+   sz = card-pref_erase % card-erase_size;
+   if (sz)
+   card-pref_erase += card-erase_size - sz;
+   }
+   }
+}
+
+static void mmc_set_mmc_erase_timeout(struct mmc_card *card,
+ struct mmc_command *cmd,
+ unsigned int arg, unsigned int qty)
+{
+   unsigned int erase_timeout;
+
+   if (card-ext_csd.erase_group_def  1) {
+   /* High Capacity Erase Group Size uses HC timeouts */
+   if (arg == MMC_TRIM_ARG)
+   erase_timeout = card-ext_csd.trim_timeout;
+   else
+   erase_timeout = card-ext_csd.hc_erase_timeout;
+   } else {
+   /* CSD Erase Group Size uses write timeout */
+   unsigned int mult = (10  card-csd.r2w_factor);
+   unsigned int timeout_clks = card-csd.tacc_clks * mult;
+   unsigned int timeout_us;
+
+   /* Avoid overflow: e.g. tacc_ns=8000 mult=1280 */
+   if (card-csd.tacc_ns  100)
+   timeout_us = (card-csd.tacc_ns * mult) / 1000;
+   else
+   timeout_us = (card-csd.tacc_ns / 1000) * mult;
+
+   /*
+* ios.clock is only a target.  The real clock rate might be
+* less but not that much less, so fudge it by multiplying by 2.
+*/
+   timeout_clks = 1;
+   timeout_us += (timeout_clks * 1000) /
+ (card-host-ios.clock / 1000);
+
+   erase_timeout = timeout_us / 1000;
+
+   /*
+* 

[PATCH V3 3/5] omap_hsmmc: Add erase capability

2010-06-24 Thread Adrian Hunter
From 20b7223c8a3c021a31a7b8079990ec103d89007e Mon Sep 17 00:00:00 2001
From: Adrian Hunter adrian.hun...@nokia.com
Date: Tue, 18 May 2010 17:33:13 +0300
Subject: [PATCH 3/5] omap_hsmmc: Add erase capability

Disable the data (busy) timeout for erases and set the
MMC_CAP_ERASE capability.

Signed-off-by: Adrian Hunter adrian.hun...@nokia.com
---
 drivers/mmc/host/omap_hsmmc.c |   13 ++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index b032828..5cbbe09 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -28,6 +28,7 @@
 #include linux/clk.h
 #include linux/mmc/host.h
 #include linux/mmc/core.h
+#include linux/mmc/mmc.h
 #include linux/io.h
 #include linux/semaphore.h
 #include linux/gpio.h
@@ -78,6 +79,7 @@
 #define INT_EN_MASK0x307F0033
 #define BWR_ENABLE (1  4)
 #define BRR_ENABLE (1  5)
+#define DTO_ENABLE (1  20)
 #define INIT_STREAM(1  1)
 #define DP_SELECT  (1  21)
 #define DDIR   (1  4)
@@ -523,7 +525,8 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host 
*host)
dev_dbg(mmc_dev(host-mmc), MMC Clock is not stoped\n);
 }
 
-static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host)
+static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
+ struct mmc_command *cmd)
 {
unsigned int irq_mask;
 
@@ -532,6 +535,10 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host 
*host)
else
irq_mask = INT_EN_MASK;
 
+   /* Disable timeout for erases */
+   if (cmd-opcode == MMC_ERASE)
+   irq_mask = ~DTO_ENABLE;
+
OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR);
OMAP_HSMMC_WRITE(host-base, ISE, irq_mask);
OMAP_HSMMC_WRITE(host-base, IE, irq_mask);
@@ -782,7 +789,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, 
struct mmc_command *cmd,
mmc_hostname(host-mmc), cmd-opcode, cmd-arg);
host-cmd = cmd;
 
-   omap_hsmmc_enable_irq(host);
+   omap_hsmmc_enable_irq(host, cmd);
 
host-response_busy = 0;
if (cmd-flags  MMC_RSP_PRESENT) {
@@ -2094,7 +2101,7 @@ static int __init omap_hsmmc_probe(struct platform_device 
*pdev)
mmc-max_seg_size = mmc-max_req_size;
 
mmc-caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-MMC_CAP_WAIT_WHILE_BUSY;
+MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
 
if (mmc_slot(host).wires = 8)
mmc-caps |= MMC_CAP_8_BIT_DATA;
-- 
1.6.3.3

--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 4/5] block: Add secure discard

2010-06-24 Thread Adrian Hunter
From b25b9a499f255ee5999c219525d82ef40382318c Mon Sep 17 00:00:00 2001
From: Adrian Hunter adrian.hun...@nokia.com
Date: Wed, 23 Jun 2010 15:41:38 +0300
Subject: [PATCH 4/5] block: Add secure discard

Secure discard is the same as discard except that all copies
of the discarded sectors (perhaps created by garbage collection)
must also be erased.

Signed-off-by: Adrian Hunter adrian.hun...@nokia.com
---
 block/blk-core.c|6 +-
 block/blk-lib.c |6 ++
 block/compat_ioctl.c|1 +
 block/elevator.c|4 
 block/ioctl.c   |   15 ++-
 include/linux/bio.h |7 ++-
 include/linux/blkdev.h  |   10 +-
 include/linux/fs.h  |2 ++
 kernel/trace/blktrace.c |8 
 9 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index f84cce4..6f9c6df 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1153,6 +1153,8 @@ void init_request_from_bio(struct request *req, struct 
bio *bio)
req-cmd_flags |= REQ_DISCARD;
if (bio_rw_flagged(bio, BIO_RW_BARRIER))
req-cmd_flags |= REQ_SOFTBARRIER;
+   if (bio_rw_flagged(bio, BIO_RW_SECURE))
+   req-cmd_flags |= REQ_SECURE;
} else if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER)))
req-cmd_flags |= REQ_HARDBARRIER;
 
@@ -1501,7 +1503,9 @@ static inline void __generic_make_request(struct bio *bio)
goto end_io;
 
if (bio_rw_flagged(bio, BIO_RW_DISCARD) 
-   !blk_queue_discard(q)) {
+   (!blk_queue_discard(q) ||
+(bio_rw_flagged(bio, BIO_RW_SECURE) 
+ !blk_queue_secdiscard(q {
err = -EOPNOTSUPP;
goto end_io;
}
diff --git a/block/blk-lib.c b/block/blk-lib.c
index d0216b9..dc56682 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -52,6 +52,12 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t 
sector,
if (!blk_queue_discard(q))
return -EOPNOTSUPP;
 
+   if (flags  BLKDEV_IFL_SECURE) {
+   if (!blk_queue_secdiscard(q))
+   return -EOPNOTSUPP;
+   type |= DISCARD_SECURE;
+   }
+
while (nr_sects  !ret) {
unsigned int sector_size = q-limits.logical_block_size;
unsigned int max_discard_sectors =
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index f26051f..24a146d 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -753,6 +753,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, 
unsigned long arg)
case BLKFLSBUF:
case BLKROSET:
case BLKDISCARD:
+   case BLKSECDISCARD:
/*
 * the ones below are implemented in blkdev_locked_ioctl,
 * but we call blkdev_ioctl, which gets the lock for us
diff --git a/block/elevator.c b/block/elevator.c
index 923a913..23b5f3d 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -83,6 +83,10 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
bio_rw_flagged(rq-bio, BIO_RW_DISCARD))
return 0;
 
+   if (bio_rw_flagged(bio, BIO_RW_SECURE) !=
+   bio_rw_flagged(rq-bio, BIO_RW_SECURE))
+   return 0;
+
/*
 * different data direction or already started, don't merge
 */
diff --git a/block/ioctl.c b/block/ioctl.c
index e8eb679..1fba55f 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -114,8 +114,10 @@ static int blkdev_reread_part(struct block_device *bdev)
 }
 
 static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
-uint64_t len)
+uint64_t len, int secure)
 {
+   unsigned long flags = BLKDEV_IFL_WAIT;
+
if (start  511)
return -EINVAL;
if (len  511)
@@ -125,8 +127,9 @@ static int blk_ioctl_discard(struct block_device *bdev, 
uint64_t start,
 
if (start + len  (bdev-bd_inode-i_size  9))
return -EINVAL;
-   return blkdev_issue_discard(bdev, start, len, GFP_KERNEL,
-   BLKDEV_IFL_WAIT);
+   if (secure)
+   flags |= BLKDEV_IFL_SECURE;
+   return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags);
 }
 
 static int put_ushort(unsigned long arg, unsigned short val)
@@ -226,7 +229,8 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, 
unsigned cmd,
unlock_kernel();
return 0;
 
-   case BLKDISCARD: {
+   case BLKDISCARD:
+   case BLKSECDISCARD: {
uint64_t range[2];
 
if (!(mode  FMODE_WRITE))
@@ -235,7 +239,8 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, 
unsigned cmd,
if (copy_from_user(range, (void __user *)arg, sizeof(range)))
   

[PATCH V3 2/5] mmc_block: Add discard support

2010-06-24 Thread Adrian Hunter
From 1c859151d2d8c76e503a24c6d3d472cc01a68b3a Mon Sep 17 00:00:00 2001
From: Adrian Hunter adrian.hun...@nokia.com
Date: Thu, 3 Jun 2010 10:47:12 +0300
Subject: [PATCH 2/5] mmc_block: Add discard support

Enable MMC to service discard requests.  In the case of SD
and MMC cards that do not support trim, discards become
erases.  In the case of cards (MMC) that only allow erases
in multiples of erase group size, round to the nearest
completely discarded erase group.

Signed-off-by: Adrian Hunter adrian.hun...@nokia.com
---
 drivers/mmc/card/block.c |   42 +-
 drivers/mmc/card/queue.c |   16 ++--
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index cb9fbc8..af14ae1 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -242,7 +242,40 @@ static u32 get_card_status(struct mmc_card *card, struct 
request *req)
return cmd.resp[0];
 }
 
-static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
+static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
+{
+   struct mmc_blk_data *md = mq-data;
+   struct mmc_card *card = md-queue.card;
+   unsigned int from, nr, arg;
+   int err = 0;
+
+   mmc_claim_host(card-host);
+
+   if (!mmc_can_erase(card)) {
+   err = -EOPNOTSUPP;
+   goto out;
+   }
+
+   from = blk_rq_pos(req);
+   nr = blk_rq_sectors(req);
+
+   if (mmc_can_trim(card))
+   arg = MMC_TRIM_ARG;
+   else
+   arg = MMC_ERASE_ARG;
+
+   err = mmc_erase(card, from, nr, arg);
+out:
+   spin_lock_irq(md-lock);
+   __blk_end_request(req, err, blk_rq_bytes(req));
+   spin_unlock_irq(md-lock);
+
+   mmc_release_host(card-host);
+
+   return err ? 0 : 1;
+}
+
+static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 {
struct mmc_blk_data *md = mq-data;
struct mmc_card *card = md-queue.card;
@@ -470,6 +503,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct 
request *req)
return 0;
 }
 
+static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
+{
+   if (blk_discard_rq(req))
+   return mmc_blk_issue_discard_rq(mq, req);
+   else
+   return mmc_blk_issue_rw_rq(mq, req);
+}
 
 static inline int mmc_blk_readonly(struct mmc_card *card)
 {
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index d6ded24..37f648f 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -30,9 +30,9 @@
 static int mmc_prep_request(struct request_queue *q, struct request *req)
 {
/*
-* We only like normal block requests.
+* We only like normal block requests and discards.
 */
-   if (!blk_fs_request(req)) {
+   if (!blk_fs_request(req)  !blk_discard_rq(req)) {
blk_dump_rq_flags(req, MMC bad request);
return BLKPREP_KILL;
}
@@ -130,6 +130,18 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card, spinlock_t *lock
blk_queue_prep_rq(mq-queue, mmc_prep_request);
blk_queue_ordered(mq-queue, QUEUE_ORDERED_DRAIN, NULL);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq-queue);
+   if (mmc_can_erase(card)) {
+   queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq-queue);
+   mq-queue-limits.max_discard_sectors = UINT_MAX;
+   if (card-erased_byte == 0)
+   mq-queue-limits.discard_zeroes_data = 1;
+   if (!mmc_can_trim(card)  is_power_of_2(card-erase_size)) {
+   mq-queue-limits.discard_granularity =
+   card-erase_size  9;
+   mq-queue-limits.discard_alignment =
+   card-erase_size  9;
+   }
+   }
 
 #ifdef CONFIG_MMC_BLOCK_BOUNCE
if (host-max_hw_segs == 1) {
-- 
1.6.3.3

--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH 07/12] mmci: pass power_mode to the translate_vdd callback

2010-06-24 Thread Linus WALLEIJ
[Rabin]

 On Wed, Jun 23, 2010 at 00:03:47 +0200, Linus Walleij wrote:
  2010/6/22 Rabin Vincent rabin.vinc...@stericsson.com:
   @@ -17,7 +17,8 @@
    * mmc/host.h
    * @translate_vdd: a callback function to translate a MMC_VDD_*
    * mask into a value to be binary or:ed and written into the
   - * MMCIPWR register of the block
   + * MMCIPWR register of the block.  May also control external power
   + * based on the power_mode.
 
  Actually this callback is named like that for a reason: it is to be
 used
  to translate the MMC_VDD_* into a u8:4 bitmask for the MMCIPWR
  register, 4 bits possibly routed out of the PL180 block on some
  designs (never seen in practice, but could be used in theory).
 
  So it translates a voltage into a 4-bit bitmask, hence the name.
 
  Now the semantics are altered to have other side-effects in
  the platform, so the function should be renamed, something like
  platform_vdd_handler() would be more appropriate.
 
 
 This is already inside platform data, so how about just -
 vdd_handler()?
 Or -set_power(), like some other drivers?

Any of these look good to me atleast.

But now another thing I came to think of (the fun never
ends):

Since the ux500 also have a regulator for this and since
that mechanism is mutually exclusive in the code (since the
semantics implied that it was only a voltage translation
function) you should also remove the condition that this
only gets called in case there is no regulator.

 Note that we'd also like to use this to do the board-specific settings
 for the *DIREN and FBCLK bits, which replace the Voltage bits on some
 ST
 variants, like so:
 
 +static u32 mop500_sdi0_translate_vdd(struct device *dev, unsigned int
 vdd,
 +  unsigned char power_mode)
 +{
 + if (power_mode == MMC_POWER_UP)
 + gpio_set_value(gpio_sdmmc_en, 1);
 + else if (power_mode == MMC_POWER_OFF)
 + gpio_set_value(gpio_sdmmc_en, 0);
 +
 + return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
 +MCI_DATA2DIREN | MCI_DATA31DIREN;
 +}

OK just update the kerneldoc to reflect the fact that the platform
can OR on any *custom* bits it like to the PWR register in this
function.

Side notice: some of bits are for the ST version only, when you
patch in the latter, can you take this opportunity to also
rename MCI_FBCLKEN to MCI_ST_FBCLKEN and so on for all stuff
that is ST-specific? I think I am the sinner here, we had no
convention for how to do this naming when we first began
modifying this driver. It should be crystal clear that all
custom extensions are named MCI_VENDOR_FOO.

As a consequence, anything that is OR:ed into from the
vdd_handler() should typically be MCI_VENDOR_FOO, and
it will be clear why it's there.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Disable the non working eMMC on Zoom2/3

2010-06-24 Thread zhangfei gao
On Tue, Jun 22, 2010 at 7:43 PM, Ghorai, Sukumar s-gho...@ti.com wrote:


 -Original Message-
 From: zhangfei gao [mailto:zhangfei@gmail.com]
 Sent: Tuesday, June 22, 2010 4:51 PM
 To: Chikkature Rajashekar, Madhusudhan
 Cc: Tony Lindgren; Menon, Nishanth; Ghorai, Sukumar; linux-
 o...@vger.kernel.org; linux-mmc@vger.kernel.org
 Subject: Re: [PATCH] Disable the non working eMMC on Zoom2/3

 On Sat, May 8, 2010 at 5:25 AM, Madhusudhan madhu...@ti.com wrote:
 
 
  -Original Message-
  From: Tony Lindgren [mailto:t...@atomide.com]
  Sent: Thursday, May 06, 2010 10:31 AM
  To: Madhusudhan
  Cc: 'Nishanth Menon'; 'Ghorai, Sukumar'; linux-o...@vger.kernel.org;
  linux-mmc@vger.kernel.org
  Subject: Re: [PATCH] Disable the non working eMMC on Zoom2/3
 
  * Madhusudhan madhu...@ti.com [100505 18:31]:
  
  
-Original Message-
From: Tony Lindgren [mailto:t...@atomide.com]
  
And what about this Simulate multi mmc card as one big patch?
   
   Did not get you, what patch are you referring to?
 
  Oops sorry forgot the link:
 
  https://patchwork.kernel.org/patch/87944/
 
  This will not help. I don't know the history of the patch but what this
 is
  intended for is to support multiple MMC cards connected to a single
  controller. But on the Zoom the eMMC we are talking about is connected
 to
  MMC2.
 
  Regards,
  Madhu
 
  Tony
 
  --
  To unsubscribe from this list: send the line unsubscribe linux-mmc in
  the body of a message to majord...@vger.kernel.org
  More majordomo info at  http://vger.kernel.org/majordomo-info.html
 

 Hi, Guys

 Just wander whether 16G Micron eMMC works on your platform.
 I also have such issue, 16G Micron emmc can not work with read and
 write, with data timeout.
 While 8G Micron eMMC workable.
 Do you have the same issue?

 [Ghorai] we have 16G eMMC in ZOOM3 and 3630-SDP and its working fine. Let me 
 know what board you are using.
 mmc1: new high speed MMC card at address 0001
 PM: Adding info for mmc:mmc1:0001
 mmcblk0: mmc1:0001 STM16G 14.8 GiB
 PM: Adding info for No Bus:mmcblk0
  mmcblk0: p1 p2

 Thanks


Hi, Ghorai

Thanks for your valueable info.
We also enabled Micron 16G eMMC, two issues stuck us before.
1. The bus_width should be inited otherwise read ext_csd would be fail.
2. The emmc may stay in boot partition and kernel should switch to
user partition, where filesystem is located.

Thanks
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH] Disable the non working eMMC on Zoom2/3

2010-06-24 Thread Ghorai, Sukumar


 -Original Message-
 From: zhangfei gao [mailto:zhangfei@gmail.com]
 Sent: Thursday, June 24, 2010 4:26 PM
 To: Ghorai, Sukumar
 Cc: Chikkature Rajashekar, Madhusudhan; Tony Lindgren; Menon, Nishanth;
 linux-o...@vger.kernel.org; linux-mmc@vger.kernel.org
 Subject: Re: [PATCH] Disable the non working eMMC on Zoom2/3
 
 On Tue, Jun 22, 2010 at 7:43 PM, Ghorai, Sukumar s-gho...@ti.com wrote:
 
 
  -Original Message-
  From: zhangfei gao [mailto:zhangfei@gmail.com]
  Sent: Tuesday, June 22, 2010 4:51 PM
  To: Chikkature Rajashekar, Madhusudhan
  Cc: Tony Lindgren; Menon, Nishanth; Ghorai, Sukumar; linux-
  o...@vger.kernel.org; linux-mmc@vger.kernel.org
  Subject: Re: [PATCH] Disable the non working eMMC on Zoom2/3
 
  On Sat, May 8, 2010 at 5:25 AM, Madhusudhan madhu...@ti.com wrote:
  
  
   -Original Message-
   From: Tony Lindgren [mailto:t...@atomide.com]
   Sent: Thursday, May 06, 2010 10:31 AM
   To: Madhusudhan
   Cc: 'Nishanth Menon'; 'Ghorai, Sukumar'; linux-o...@vger.kernel.org;
   linux-mmc@vger.kernel.org
   Subject: Re: [PATCH] Disable the non working eMMC on Zoom2/3
  
   * Madhusudhan madhu...@ti.com [100505 18:31]:
   
   
 -Original Message-
 From: Tony Lindgren [mailto:t...@atomide.com]
   
 And what about this Simulate multi mmc card as one big patch?

Did not get you, what patch are you referring to?
  
   Oops sorry forgot the link:
  
   https://patchwork.kernel.org/patch/87944/
  
   This will not help. I don't know the history of the patch but what
 this
  is
   intended for is to support multiple MMC cards connected to a single
   controller. But on the Zoom the eMMC we are talking about is
 connected
  to
   MMC2.
  
   Regards,
   Madhu
  
   Tony
  
   --
   To unsubscribe from this list: send the line unsubscribe linux-mmc
 in
   the body of a message to majord...@vger.kernel.org
   More majordomo info at  http://vger.kernel.org/majordomo-info.html
  
 
  Hi, Guys
 
  Just wander whether 16G Micron eMMC works on your platform.
  I also have such issue, 16G Micron emmc can not work with read and
  write, with data timeout.
  While 8G Micron eMMC workable.
  Do you have the same issue?
 
  [Ghorai] we have 16G eMMC in ZOOM3 and 3630-SDP and its working fine.
 Let me know what board you are using.
  mmc1: new high speed MMC card at address 0001
  PM: Adding info for mmc:mmc1:0001
  mmcblk0: mmc1:0001 STM16G 14.8 GiB
  PM: Adding info for No Bus:mmcblk0
   mmcblk0: p1 p2
 
  Thanks
 
 
 Hi, Ghorai
 
 Thanks for your valueable info.
 We also enabled Micron 16G eMMC, two issues stuck us before.
 1. The bus_width should be inited otherwise read ext_csd would be fail.
 2. The emmc may stay in boot partition and kernel should switch to
 user partition, where filesystem is located.
[Ghorai] 
1. If my understanding is not wrong, then the same problem exists in external 
MMC card too. 
2. So, can you share your eMMC log, just to check if I have any clue! Or let me 
know how I can reproduce the issue.

 
 Thanks
--
To unsubscribe from this list: send the line unsubscribe linux-mmc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] MMC: remove regulator refcount fiddling in mmc core

2010-06-24 Thread Linus Walleij
Currently the mmc_regulator_set_ocr() fiddles with the regulator
refcount by selectively calling regulator_[enable|disable]
depending on the state of the regulator. This will confuse the
reference count if case the regulator is for example shared with
other MMC slots or user for other stuff than the MMC card.

Push regulator_[enable|disable] out into the MMC host drivers
and remove this from the MMC core so the reference count can be
trusted.

Cc: Andrew Morton a...@linux-foundation.org
Cc: Liam Girdwood l...@slimlogic.co.uk
Cc: Mark Brown broo...@opensource.wolfsonmicro.com
Cc: Tony Lindgren t...@atomide.com
Cc: Adrian Hunter adrian.hun...@nokia.com
Cc: Robert Jarzmik robert.jarz...@free.fr
Cc: Sundar Iyer sundar.i...@stericsson.com
Cc: Bengt Jonsson bengt.jons...@stericsson.com
Signed-off-by: Linus Walleij linus.wall...@stericsson.com
---
This has been regression compiled for U300, OMAP3, PXA3XX
defconfigs, tested on U300.

We're facing problems with our regulator reference counters if
this is not fixed.
---
 drivers/mmc/core/core.c   |   66 ++---
 drivers/mmc/host/mmci.c   |   10 --
 drivers/mmc/host/omap_hsmmc.c |   40 ++--
 drivers/mmc/host/pxamci.c |   17 --
 4 files changed, 78 insertions(+), 55 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 569e94d..904f245 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -784,47 +784,39 @@ int mmc_regulator_set_ocr(struct regulator *supply, 
unsigned short vdd_bit)
 {
int result = 0;
int min_uV, max_uV;
-   int enabled;
+   int tmp;
+   int voltage;
 
-   enabled = regulator_is_enabled(supply);
-   if (enabled  0)
-   return enabled;
-
-   if (vdd_bit) {
-   int tmp;
-   int voltage;
-
-   /* REVISIT mmc_vddrange_to_ocrmask() may have set some
-* bits this regulator doesn't quite support ... don't
-* be too picky, most cards and regulators are OK with
-* a 0.1V range goof (it's a small error percentage).
-*/
-   tmp = vdd_bit - ilog2(MMC_VDD_165_195);
-   if (tmp == 0) {
-   min_uV = 1650 * 1000;
-   max_uV = 1950 * 1000;
-   } else {
-   min_uV = 1900 * 1000 + tmp * 100 * 1000;
-   max_uV = min_uV + 100 * 1000;
-   }
-
-   /* avoid needless changes to this voltage; the regulator
-* might not allow this operation
-*/
-   voltage = regulator_get_voltage(supply);
-   if (voltage  0)
-   result = voltage;
-   else if (voltage  min_uV || voltage  max_uV)
-   result = regulator_set_voltage(supply, min_uV, max_uV);
-   else
-   result = 0;
+   if (!vdd_bit)
+   return 0;
 
-   if (result == 0  !enabled)
-   result = regulator_enable(supply);
-   } else if (enabled) {
-   result = regulator_disable(supply);
+   /*
+* REVISIT mmc_vddrange_to_ocrmask() may have set some
+* bits this regulator doesn't quite support ... don't
+* be too picky, most cards and regulators are OK with
+* a 0.1V range goof (it's a small error percentage).
+*/
+   tmp = vdd_bit - ilog2(MMC_VDD_165_195);
+   if (tmp == 0) {
+   min_uV = 1650 * 1000;
+   max_uV = 1950 * 1000;
+   } else {
+   min_uV = 1900 * 1000 + tmp * 100 * 1000;
+   max_uV = min_uV + 100 * 1000;
}
 
+   /*
+* Avoid needless changes to this voltage; the regulator
+* might not allow this operation
+*/
+   voltage = regulator_get_voltage(supply);
+   if (voltage  0)
+   result = voltage;
+   else if (voltage  min_uV || voltage  max_uV)
+   result = regulator_set_voltage(supply, min_uV, max_uV);
+   else
+   result = 0;
+
return result;
 }
 EXPORT_SYMBOL(mmc_regulator_set_ocr);
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 4917af9..5f530b1 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -467,15 +467,17 @@ static void mmci_set_ios(struct mmc_host *mmc, struct 
mmc_ios *ios)
 
switch (ios-power_mode) {
case MMC_POWER_OFF:
-   if(host-vcc 
-  regulator_is_enabled(host-vcc))
+   if (host-vcc)
regulator_disable(host-vcc);
break;
case MMC_POWER_UP:
 #ifdef CONFIG_REGULATOR
-   if (host-vcc)
-   /* This implicitly enables