diff mbox

[U-Boot,U-BOOT] mmc: enable switch partition function

Message ID 1296463665-26551-1-git-send-email-leiwen@marvell.com
State Superseded, archived
Delegated to: Andy Fleming
Headers show

Commit Message

Lei Wen Jan. 31, 2011, 8:47 a.m. UTC
For emmc, it may has upto 7 partitions: two boot partitions, one
user partition, one RPMB partition and four general purpose partitions.
(Refer to JESD84-A44.pdf/page 154)

As bootloader may need to read out or reflashing images on those

Comments

Wolfgang Denk Feb. 8, 2011, 2:26 p.m. UTC | #1
Dear Lei Wen,

In message <AANLkTimacphrMbu1RTGjWJKYU9FaC8+Xo2sgnjfW4LZQ@mail.gmail.com> you wrote:
>
> Does this patch could get the chance to be included in the 2011.03 release?

This is not a bug fix, and it was submitted after the merge window
was closed.

> I just see it haven't gotten any response after eight days...

Will reply ASAP.

Best regards,

Wolfgang Denk
Wolfgang Denk Feb. 8, 2011, 2:27 p.m. UTC | #2
Dear Lei Wen,

In message <1296463665-26551-1-git-send-email-leiwen@marvell.com> you wrote:
> For emmc, it may has upto 7 partitions: two boot partitions, one
> user partition, one RPMB partition and four general purpose partitions.
> (Refer to JESD84-A44.pdf/page 154)
> 
> As bootloader may need to read out or reflashing images on those
> different partitions, it is better to enable the partition switch with
> console command support.

Other devices - say, USB mass storage devices, IDE disks, etc. - have
partitions, too, and do not need any such special command.

> @@ -247,5 +268,6 @@ U_BOOT_CMD(
>  	"mmc write <device num> addr blk# cnt\n"
>  	"mmc rescan <device num>\n"
>  	"mmc part <device num> - lists available partition on mmc\n"
> +	"mmc sw_part <device num> <part_num> - switch part support for emmc\n"
>  	"mmc list - lists available devices");

Why would we need a separate command here?


Please rework this so it uses the same mechanism we use on all other
storage devices, without an extra command here.

Thanks.

Best regards,

Wolfgang Denk
Lei Wen Feb. 8, 2011, 3:03 p.m. UTC | #3
Hi Wolfgang,

On Tue, Feb 8, 2011 at 10:27 PM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Lei Wen,
>
> In message <1296463665-26551-1-git-send-email-leiwen@marvell.com> you wrote:
>> For emmc, it may has upto 7 partitions: two boot partitions, one
>> user partition, one RPMB partition and four general purpose partitions.
>> (Refer to JESD84-A44.pdf/page 154)
>>
>> As bootloader may need to read out or reflashing images on those
>> different partitions, it is better to enable the partition switch with
>> console command support.
>
> Other devices - say, USB mass storage devices, IDE disks, etc. - have
> partitions, too, and do not need any such special command.

EMMC is sightly different witht the other device with partition.
For IDE as example, we could copy file between part A and B without problem.
It is for the different partition start at different offset in the
physical media.
Just adding the offset with the read address would make this works, so it is
some kind of software implementation.

But for EMMC, the boot partition is different with the normal partition.
We need to send a special command to do the switch, not with the
different offset.
If we need to copy file between those two partition, we need to send
switch command
before copy operation.
It is a hardware one. IDE or usb masstorage has no such ability...

>
>> @@ -247,5 +268,6 @@ U_BOOT_CMD(
>>       "mmc write <device num> addr blk# cnt\n"
>>       "mmc rescan <device num>\n"
>>       "mmc part <device num> - lists available partition on mmc\n"
>> +     "mmc sw_part <device num> <part_num> - switch part support for emmc\n"
>>       "mmc list - lists available devices");
>
> Why would we need a separate command here?
>
>
> Please rework this so it uses the same mechanism we use on all other
> storage devices, without an extra command here.
>

The problem here is that the need to switch this hardware partition
only make sense
to the emmc. If make it generic to the other mmc command, it seems a
bit of weird for the
sd/mmc...

Also add additional command here is the minimual change. If insert
this into already existed
mmc command would make the fat command hard to work.
For mmc may change the hardware partition, but fat command cannot...
It is because
it need to be compatiable with other devices that have no hardware partition...

Best regards,
Lei
Wolfgang Denk Feb. 8, 2011, 3:13 p.m. UTC | #4
Dear Lei Wen,

In message <AANLkTikdUN37v6tvYpy0hyJrB9OJ4XK-LyNPSida7Dyf@mail.gmail.com> you wrote:
> 
> EMMC is sightly different witht the other device with partition. 

Maybe.  But does this really require a different iunterface in the
U-Boot context?   I doubt that.

> For IDE as example, we could copy file between part A and B without problem.

No, we cannot. U-Boot can only read _or_ write form mass storage
operations, so a copy operation would always require a "read from
device to RAM buffer", "write to device from RAM buffer" sequence.
The same can obviously be done with EMMC as well.

> But for EMMC, the boot partition is different with the normal partition.
> We need to send a special command to do the switch, not with the
> different offset.

Thisis an internal implementation detail.  As a user, I do not want to
know about it. I just want to read or write data to some partition.
The rest is driver internals.

> If we need to copy file between those two partition, we need to send
> switch command
> before copy operation.

So where is the problem?  See above. We always have TWO separate
operations, and each of them will select a device/partition.

> It is a hardware one. IDE or usb masstorage has no such ability...

I see no difference from the user point of view.  The internal
implementation may be different, but that doesn't matter.

> For mmc may change the hardware partition, but fat command cannot...
> It is because
> it need to be compatiable with other devices that have no hardware partition...

I don;t understand what you want to tell me here.  My complaint is
that your new code is _not_ compatible with other divices, and I see
no reason for such an incompatibility.

Best regards,

Wolfgang Denk
Lei Wen Feb. 8, 2011, 3:21 p.m. UTC | #5
Hi Wolfgang,

On Tue, Feb 8, 2011 at 11:13 PM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Lei Wen,
>
> In message <AANLkTikdUN37v6tvYpy0hyJrB9OJ4XK-LyNPSida7Dyf@mail.gmail.com> you wrote:
>>
>> EMMC is sightly different witht the other device with partition.
>
> Maybe.  But does this really require a different iunterface in the
> U-Boot context?   I doubt that.
>
>> For IDE as example, we could copy file between part A and B without problem.
>
> No, we cannot. U-Boot can only read _or_ write form mass storage
> operations, so a copy operation would always require a "read from
> device to RAM buffer", "write to device from RAM buffer" sequence.
> The same can obviously be done with EMMC as well.
>
>> But for EMMC, the boot partition is different with the normal partition.
>> We need to send a special command to do the switch, not with the
>> different offset.
>
> Thisis an internal implementation detail.  As a user, I do not want to
> know about it. I just want to read or write data to some partition.
> The rest is driver internals.
>
>> If we need to copy file between those two partition, we need to send
>> switch command
>> before copy operation.
>
> So where is the problem?  See above. We always have TWO separate
> operations, and each of them will select a device/partition.
>
>> It is a hardware one. IDE or usb masstorage has no such ability...
>
> I see no difference from the user point of view.  The internal
> implementation may be different, but that doesn't matter.
>
>> For mmc may change the hardware partition, but fat command cannot...
>> It is because
>> it need to be compatiable with other devices that have no hardware partition...
>
> I don;t understand what you want to tell me here.  My complaint is
> that your new code is _not_ compatible with other divices, and I see
> no reason for such an incompatibility.
>

I am thinking now approach for this.
How about adding addtitional member in the mmc structure, like part.
During mmc probe, the driver could know whether the device support partition
switch or not, if it support, we could register three other "faked" mmc device
corresponding to two boot partition, and RPMB partition.

Then we could use the current command to access the different hardware
partition in the emmc. Like if we are accessing one hardware partition, we need
to send switch command first. If the part member in the mmc is a invalid value,
we then don't send that switch partition command.

Could this approach be acceptable?

Best regards,
Lei
Lei Wen Feb. 11, 2011, 3:05 p.m. UTC | #6
>
> I am thinking now approach for this.
> How about adding addtitional member in the mmc structure, like part.
> During mmc probe, the driver could know whether the device support partition
> switch or not, if it support, we could register three other "faked" mmc device
> corresponding to two boot partition, and RPMB partition.
>
> Then we could use the current command to access the different hardware
> partition in the emmc. Like if we are accessing one hardware partition, we need
> to send switch command first. If the part member in the mmc is a invalid value,
> we then don't send that switch partition command.
>
> Could this approach be acceptable?
>

Further refine this idea, don't need to call mmc_register multi-times.
For the purpose is to switch partition when needed, we really do want to one
real device. So I propose a new solution as:

Assume there is two sd/mmc controller on the board, named as mmc0&mmc1.
The mmc0 attach with a sd card, and mmc1 attach with a emmc that has partition
supported. Then we would have mmc(2, 3, 4, 5, 6, 7, 8) faked device map to mmc0
, mmc(9, 10, 11, 12, 13, 14, 15) map to mmc1.

Give the command as "mmc read 9 0x1000000 0 0x10", uboot would get the
real device
num by 9/7, while hardware part num is (9-1-7*real_dev_num) that is 1.
So we need
to make mmc1 send the switch part 1 command to the emmc, then perform the read
operation.

If we want to run "mmc read 5 0x10000 0x10 0x5", the sd attach on mmc0 has no
hardware partition suppport, it would simply refuse to execute that command.
Or if we want to be more gracefully handled, we could let the read 5
perform like the
read 0 command.

Best regards,
Lei
Lei Wen Feb. 12, 2011, 3:30 a.m. UTC | #7
Hi,

On Fri, Feb 11, 2011 at 11:05 PM, Lei Wen <adrian.wenl@gmail.com> wrote:
>>
>> I am thinking now approach for this.
>> How about adding addtitional member in the mmc structure, like part.
>> During mmc probe, the driver could know whether the device support partition
>> switch or not, if it support, we could register three other "faked" mmc device
>> corresponding to two boot partition, and RPMB partition.
>>
>> Then we could use the current command to access the different hardware
>> partition in the emmc. Like if we are accessing one hardware partition, we need
>> to send switch command first. If the part member in the mmc is a invalid value,
>> we then don't send that switch partition command.
>>
>> Could this approach be acceptable?
>>
>
> Further refine this idea, don't need to call mmc_register multi-times.
> For the purpose is to switch partition when needed, we really do want to one
> real device. So I propose a new solution as:
>
> Assume there is two sd/mmc controller on the board, named as mmc0&mmc1.
> The mmc0 attach with a sd card, and mmc1 attach with a emmc that has partition
> supported. Then we would have mmc(2, 3, 4, 5, 6, 7, 8) faked device map to mmc0
> , mmc(9, 10, 11, 12, 13, 14, 15) map to mmc1.
>
> Give the command as "mmc read 9 0x1000000 0 0x10", uboot would get the
> real device
> num by 9/7, while hardware part num is (9-1-7*real_dev_num) that is 1.
> So we need
> to make mmc1 send the switch part 1 command to the emmc, then perform the read
> operation.
>
> If we want to run "mmc read 5 0x10000 0x10 0x5", the sd attach on mmc0 has no
> hardware partition suppport, it would simply refuse to execute that command.
> Or if we want to be more gracefully handled, we could let the read 5
> perform like the
> read 0 command.
>

Any feedback for this?...

Thanks,
Lei
Wolfgang Denk April 12, 2011, 7:31 p.m. UTC | #8
Dear Lei Wen,

In message <AANLkTikH_5rXgFsWbNRnBQtB6WFjT=2K8pd8CBXaKcCQ@mail.gmail.com> you wrote:
>
> Further refine this idea, don't need to call mmc_register multi-times.
> For the purpose is to switch partition when needed, we really do want to one
> real device. So I propose a new solution as:
> 
> Assume there is two sd/mmc controller on the board, named as mmc0&mmc1.
> The mmc0 attach with a sd card, and mmc1 attach with a emmc that has partition
> supported. Then we would have mmc(2, 3, 4, 5, 6, 7, 8) faked device map to mmc0
> , mmc(9, 10, 11, 12, 13, 14, 15) map to mmc1.
> 
> Give the command as "mmc read 9 0x1000000 0 0x10", uboot would get the
> real device
> num by 9/7, while hardware part num is (9-1-7*real_dev_num) that is 1.
> So we need
> to make mmc1 send the switch part 1 command to the emmc, then perform the read
> operation.
> 
> If we want to run "mmc read 5 0x10000 0x10 0x5", the sd attach on mmc0 has no
> hardware partition suppport, it would simply refuse to execute that command.
> Or if we want to be more gracefully handled, we could let the read 5
> perform like the
> read 0 command.

This is ugly and error prone.

Why don't you follow the existing examples from other storage devices,
where we have a "dev" subcommand that allows to select one of the
existing devices as "active" device?  Similarly, you could here select
an active device/partition pair.

This makes the access commands easier, and the user has much less
problems to figure out which number he has to use to specify the -
wrong - partition.

Best regards,

Wolfgang Denk
Lei Wen April 13, 2011, 3:57 a.m. UTC | #9
Hi Wolfgang,

On Wed, Apr 13, 2011 at 3:31 AM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Lei Wen,
>
> In message <AANLkTikH_5rXgFsWbNRnBQtB6WFjT=2K8pd8CBXaKcCQ@mail.gmail.com> you wrote:
>>
>> Further refine this idea, don't need to call mmc_register multi-times.
>> For the purpose is to switch partition when needed, we really do want to one
>> real device. So I propose a new solution as:
>>
>> Assume there is two sd/mmc controller on the board, named as mmc0&mmc1.
>> The mmc0 attach with a sd card, and mmc1 attach with a emmc that has partition
>> supported. Then we would have mmc(2, 3, 4, 5, 6, 7, 8) faked device map to mmc0
>> , mmc(9, 10, 11, 12, 13, 14, 15) map to mmc1.
>>
>> Give the command as "mmc read 9 0x1000000 0 0x10", uboot would get the
>> real device
>> num by 9/7, while hardware part num is (9-1-7*real_dev_num) that is 1.
>> So we need
>> to make mmc1 send the switch part 1 command to the emmc, then perform the read
>> operation.
>>
>> If we want to run "mmc read 5 0x10000 0x10 0x5", the sd attach on mmc0 has no
>> hardware partition suppport, it would simply refuse to execute that command.
>> Or if we want to be more gracefully handled, we could let the read 5
>> perform like the
>> read 0 command.
>
> This is ugly and error prone.
>
> Why don't you follow the existing examples from other storage devices,
> where we have a "dev" subcommand that allows to select one of the
> existing devices as "active" device?  Similarly, you could here select
> an active device/partition pair.

dev subcommand to act as "sw_part" in my first patch?

>
> This makes the access commands easier, and the user has much less
> problems to figure out which number he has to use to specify the -
> wrong - partition.
>

How about this solution?
Like if want to access the dev 0 and hardware partition 1, we could use the
command as "mmc read 0:1 ***".
If not pass the :[part] parameter to the dev number, like "mmc read 0 ***",
that would means the partition is 0 by default. For this case, if that device
has no capabilty of multi hardware partition, it would act like normal, or
switch to the default 0 before any further action.

Best regads,
Lei
Wolfgang Denk April 13, 2011, 5:35 a.m. UTC | #10
Dear Lei Wen,

In message <BANLkTikWwbbuNyHppQQygZ3JDh4aXUg3NA@mail.gmail.com> you wrote:
> 
> > Why don't you follow the existing examples from other storage devices,
> > where we have a "dev" subcommand that allows to select one of the
> > existing devices as "active" device? =A0Similarly, you could here select
> > an active device/partition pair.
> 
> dev subcommand to act as "sw_part" in my first patch?

I'm not really sure I understand what this command was supposed to do.
What I want to see is consistency with other drivers, i. e. you should
be able to use "mmc dev" to select a device and optionally a partition
on it as current device, so the remaining "mmc" commands do not need
any device arguments any more.

> How about this solution?
> Like if want to access the dev 0 and hardware partition 1, we could use the
> command as "mmc read 0:1 ***".
> If not pass the :[part] parameter to the dev number, like "mmc read 0 ***",
> that would means the partition is 0 by default. For this case, if that device
> has no capabilty of multi hardware partition, it would act like normal, or
> switch to the default 0 before any further action.

I want to get rid of the device argument in all these calls.

Best regards,

Wolfgang Denk
Lei Wen April 13, 2011, 5:38 a.m. UTC | #11
Hi Wolfgang,

On Wed, Apr 13, 2011 at 1:35 PM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Lei Wen,
>
> In message <BANLkTikWwbbuNyHppQQygZ3JDh4aXUg3NA@mail.gmail.com> you wrote:
>>
>> > Why don't you follow the existing examples from other storage devices,
>> > where we have a "dev" subcommand that allows to select one of the
>> > existing devices as "active" device? =A0Similarly, you could here select
>> > an active device/partition pair.
>>
>> dev subcommand to act as "sw_part" in my first patch?
>
> I'm not really sure I understand what this command was supposed to do.
> What I want to see is consistency with other drivers, i. e. you should
> be able to use "mmc dev" to select a device and optionally a partition
> on it as current device, so the remaining "mmc" commands do not need
> any device arguments any more.

Like this mmc dev[:part], could it be acceptable?

>
>> How about this solution?
>> Like if want to access the dev 0 and hardware partition 1, we could use the
>> command as "mmc read 0:1 ***".
>> If not pass the :[part] parameter to the dev number, like "mmc read 0 ***",
>> that would means the partition is 0 by default. For this case, if that device
>> has no capabilty of multi hardware partition, it would act like normal, or
>> switch to the default 0 before any further action.
>
> I want to get rid of the device argument in all these calls.
>

So the the mmc read would becomes "mmc read [ram address] [mmc sector
start] [sector num]"?

Best regards,
Lei
Wolfgang Denk April 13, 2011, 5:49 a.m. UTC | #12
Dear Lei Wen,

In message <BANLkTinFVYDiAt9D+EPadat2f_0qTQaS8w@mail.gmail.com> you wrote:
> 
> > I'm not really sure I understand what this command was supposed to do.
> > What I want to see is consistency with other drivers, i. e. you should
> > be able to use "mmc dev" to select a device and optionally a partition
> > on it as current device, so the remaining "mmc" commands do not need
> > any device arguments any more.
> 
> Like this mmc dev[:part], could it be acceptable?

The command should work similar to what we see with other storage
devices, i. e.

	mmc dev 3

will select device "3" as current device, so that 

	mmc dev

will print something like "mmc device 3: Model ... Type ... Capacity
..." etc., and that

	mmc read 80800000 0 100

would read the first 256 blocks of device 3 into RAM starting at
address 80800000.

Similar after

	mmc dev 2:3

but now for device 2, partition 3.

For example, here is how it works on IDE:

=> help ide
ide - IDE sub-system

Usage:
ide reset - reset IDE controller
ide info  - show available IDE devices
ide device [dev] - show or set current device
ide part [dev] - print partition table of one or all IDE devices
ide read  addr blk# cnt
ide write addr blk# cnt - read/write `cnt' blocks starting at block `blk#'
    to/from memory address `addr'
=> ide dev

IDE device 0: Model: ST920813AM Firm: 3.02 Ser#: 5QA015N2
            Type: Hard Disk
            Capacity: 19077.1 MB = 18.6 GB (39070080 x 512)
=> ide dev 1

IDE device 1: not available


> > I want to get rid of the device argument in all these calls.
> 
> So the the mmc read would becomes "mmc read [ram address] [mmc sector
> start] [sector num]"?

Right.  That's what we use on other storage devices, too.

Best regards,

Wolfgang Denk
Lei Wen April 13, 2011, 5:54 a.m. UTC | #13
Hi Wolfgang,

On Wed, Apr 13, 2011 at 1:49 PM, Wolfgang Denk <wd@denx.de> wrote:
> Dear Lei Wen,
>
> In message <BANLkTinFVYDiAt9D+EPadat2f_0qTQaS8w@mail.gmail.com> you wrote:
>>
>> > I'm not really sure I understand what this command was supposed to do.
>> > What I want to see is consistency with other drivers, i. e. you should
>> > be able to use "mmc dev" to select a device and optionally a partition
>> > on it as current device, so the remaining "mmc" commands do not need
>> > any device arguments any more.
>>
>> Like this mmc dev[:part], could it be acceptable?
>
> The command should work similar to what we see with other storage
> devices, i. e.
>
>        mmc dev 3
>
> will select device "3" as current device, so that
>
>        mmc dev
>
> will print something like "mmc device 3: Model ... Type ... Capacity
> ..." etc., and that
>
>        mmc read 80800000 0 100
>
> would read the first 256 blocks of device 3 into RAM starting at
> address 80800000.
>
> Similar after
>
>        mmc dev 2:3
>
> but now for device 2, partition 3.
>
> For example, here is how it works on IDE:
>
> => help ide
> ide - IDE sub-system
>
> Usage:
> ide reset - reset IDE controller
> ide info  - show available IDE devices
> ide device [dev] - show or set current device
> ide part [dev] - print partition table of one or all IDE devices
> ide read  addr blk# cnt
> ide write addr blk# cnt - read/write `cnt' blocks starting at block `blk#'
>    to/from memory address `addr'
> => ide dev
>
> IDE device 0: Model: ST920813AM Firm: 3.02 Ser#: 5QA015N2
>            Type: Hard Disk
>            Capacity: 19077.1 MB = 18.6 GB (39070080 x 512)
> => ide dev 1
>
> IDE device 1: not available
>
>
>> > I want to get rid of the device argument in all these calls.
>>
>> So the the mmc read would becomes "mmc read [ram address] [mmc sector
>> start] [sector num]"?
>
> Right.  That's what we use on other storage devices, too.
>

Understand, I would reformat the original patch according to this change.

Thanks,
Lei
Andy Fleming April 13, 2011, 10:36 a.m. UTC | #14
>
>> > I want to get rid of the device argument in all these calls.
>>
>> So the the mmc read would becomes "mmc read [ram address] [mmc sector
>> start] [sector num]"?
>
> Right.  That's what we use on other storage devices, too.

Right now, getting rid of all of those is a bit of a chore.
Personally, I'd prefer if we did it in such a way that we still *can*
provide the argument on the command line. In my personal experience, I
far more often think verb, object, rather than the other way around.
The way I did the mdio command for phylib, one could do either one:

mii device foo
mdio read 0 0

or

mdio read foo 0 0

(and, as a side bonus, from then on, mdio read 0 0 will work, too).

Though I can't for the life of me remember why I left the device
identifier as a simple integer.

My 2 cents,
Andy
Lei Wen April 16, 2011, 2:17 a.m. UTC | #15
V2:
use the "mmc_cur_dev" to replace explicitly specify the dev num in mmc command.
change the switch parittion command per Wolfgang's suggestion

Lei Wen (2):
  cmd_mmc: eliminate device num in the mmc command
  mmc: enable partition switch fucntion for emmc

 common/cmd_mmc.c  |  198 +++++++++++++++++++++++++++++++----------------------
 drivers/mmc/mmc.c |   46 +++++++++++--
 include/mmc.h     |   11 +++
 3 files changed, 169 insertions(+), 86 deletions(-)
Lei Wen May 3, 2011, 2:26 a.m. UTC | #16
V2:
use the "mmc_cur_dev" to replace explicitly specify the dev num in mmc command.
change the switch parittion command per Wolfgang's suggestion

V3:
reuse "curr_device" in hte cmd_mmc.c
Modify notification message

Lei Wen (2):
  cmd_mmc: eliminate device num in the mmc command
  mmc: enable partition switch fucntion for emmc

 common/cmd_mmc.c  |  224 ++++++++++++++++++++++++++++++++--------------------
 drivers/mmc/mmc.c |   35 ++++++++-
 include/mmc.h     |    9 ++
 3 files changed, 181 insertions(+), 87 deletions(-)
diff mbox

Patch

different partitions, it is better to enable the partition switch with
console command support.

Signed-off-by: Lei Wen <leiwen@marvell.com>
---
 common/cmd_mmc.c  |   24 +++++++++++++++++++++++-
 drivers/mmc/mmc.c |   16 ++++++++++++++++
 include/mmc.h     |    5 +++++
 3 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 4323f76..2181e04 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -177,7 +177,6 @@  int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	case 0:
 	case 1:
-	case 4:
 		return cmd_usage(cmdtp);
 
 	case 2:
@@ -233,6 +232,28 @@  int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			printf("%d blocks written: %s\n",
 				n, (n == cnt) ? "OK" : "ERROR");
 			return (n == cnt) ? 0 : 1;
+		} else if (strcmp(argv[1], "sw_part") == 0) {
+			int dev = simple_strtoul(argv[2], NULL, 10);
+			struct mmc *mmc = find_mmc_device(dev);
+			int num = simple_strtoul(argv[3], NULL, 10);
+			int ret;
+
+			if (num > PART_ACCESS_MASK) {
+				printf("#part_num shouldn't be larger than %d\n",
+					PART_ACCESS_MASK);
+				return 1;
+			}
+
+			mmc_init(mmc);
+			if (mmc->part_config == MMCPART_NOAVAILABLE) {
+				printf("Card doesn't support part_switch\n");
+				return 1;
+			}
+
+			ret = mmc_switch_part(dev, num);
+			printf("switch to partions #%d, %s\n",
+					num, (!ret) ? "OK" : "ERROR");
+			return (!ret) ? 0 : 1;
 		} else
 			rc = cmd_usage(cmdtp);
 
@@ -247,5 +268,6 @@  U_BOOT_CMD(
 	"mmc write <device num> addr blk# cnt\n"
 	"mmc rescan <device num>\n"
 	"mmc part <device num> - lists available partition on mmc\n"
+	"mmc sw_part <device num> <part_num> - switch part support for emmc\n"
 	"mmc list - lists available devices");
 #endif
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 6805b33..f42b3fb 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -428,6 +428,18 @@  int mmc_change_freq(struct mmc *mmc)
 	return 0;
 }
 
+int mmc_switch_part(int dev_num, unsigned int part_num)
+{
+	struct mmc *mmc = find_mmc_device(dev_num);
+
+	if (!mmc)
+		return -1;
+
+	return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+			  (mmc->part_config & ~PART_ACCESS_MASK)
+			  | (part_num & PART_ACCESS_MASK));
+}
+
 int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
 {
 	struct mmc_cmd cmd;
@@ -725,6 +737,7 @@  int mmc_startup(struct mmc *mmc)
 	if (err)
 		return err;
 
+	mmc->part_config = MMCPART_NOAVAILABLE;
 	if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
 		/* check  ext_csd version and capacity */
 		err = mmc_send_ext_csd(mmc, ext_csd);
@@ -733,6 +746,9 @@  int mmc_startup(struct mmc *mmc)
 					ext_csd[214] << 16 | ext_csd[215] << 24;
 			mmc->capacity *= 512;
 		}
+		/* store the partition info of emmc */
+		if (ext_csd[160] & 0x1)
+			mmc->part_config = ext_csd[179];
 	}
 
 	if (IS_SD(mmc))
diff --git a/include/mmc.h b/include/mmc.h
index 74c0b1d..10dfafd 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -128,6 +128,7 @@ 
  * EXT_CSD fields
  */
 
+#define EXT_CSD_PART_CONF	179	/* R/W */
 #define EXT_CSD_BUS_WIDTH	183	/* R/W */
 #define EXT_CSD_HS_TIMING	185	/* R/W */
 #define EXT_CSD_CARD_TYPE	196	/* RO */
@@ -169,6 +170,8 @@ 
 #define MMC_RSP_R6      (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
 #define MMC_RSP_R7      (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
 
+#define MMCPART_NOAVAILABLE	(0xff)
+#define PART_ACCESS_MASK	(0x7)
 
 struct mmc_cid {
 	unsigned long psn;
@@ -265,6 +268,7 @@  struct mmc {
 	uint csd[4];
 	uint cid[4];
 	ushort rca;
+	char part_config;
 	uint tran_speed;
 	uint read_bl_len;
 	uint write_bl_len;
@@ -285,6 +289,7 @@  struct mmc *find_mmc_device(int dev_num);
 int mmc_set_dev(int dev_num);
 void print_mmc_devices(char separator);
 int board_mmc_getcd(u8 *cd, struct mmc *mmc);
+int mmc_switch_part(int dev_num, unsigned int part_num);
 
 #ifdef CONFIG_GENERIC_MMC
 int atmel_mci_init(void *regs);