| 5 | |
| 6 | |
| 7 | [=#emmc] |
| 8 | == Embedded Multi-Media Controller (eMMC) == |
| 9 | Embedded Multi-Media Controller (eMMC) refers to a package consisting of both flash memory and a flash memory controller integrated into a single on-board chip. |
| 10 | |
| 11 | eMMC is very similar to a microSD but differs in the following ways: |
| 12 | * supports several hardware partitions |
| 13 | * 8-bit data bus |
| 14 | * device is on-board and thus non removable |
| 15 | |
| 16 | Gateworks uses eMMC on several of its products: |
| 17 | * Newport: |
| 18 | - GW630x / GW640x: 8GiB (16MB BOOT0, 16MB BOOT1, 4MB RPMB, 7.09GiB USER) |
| 19 | * Ventana: |
| 20 | - GW560x: 8GiB 8GiB (16MB BOOT0, 16MB BOOT1, 4MB RPMB, 7.09GiB USER) |
| 21 | |
| 22 | |
| 23 | [=#emmc-partitions] |
| 24 | === eMMC Partitions === |
| 25 | eMMC devices are partitioned into several hardware partitions but only one can be selected at a time: |
| 26 | - BOOT - one or more small partitions intended for boot firmware (eMMC 4.3 spec requires 2 boot and 1 user partition) |
| 27 | - RPMB - Replay Protected Memory Block - intended to store secure data (ie DRM content protection keys) (eMMC 4.4 spec adds the requirement of an RPMB partition) |
| 28 | - USER - a large partition intended for general storage |
| 29 | |
| 30 | Notes: |
| 31 | * BOOT and RPMB partitions are configured as SLC while USER can be SLC or MLC. |
| 32 | * Read / Write commands sent to an eMMC do not directly address the hardware partitions but instead a special command is used to select a partition. |
| 33 | * A Card Specific Data (CSD) register (EXT_CSD[179]) is used to configure what partition is selected at power-up. This can be configured within Linux via the {{{mmc-utils}}} application, or within U-Boot via the {{{mmc partconf}}} command (see below). |
| 34 | * It is up to the user to decide if and how to use each of the hardware partitions. |
| 35 | |
| 36 | Both Linux (see [#emmc-linux below]) and U-Boot (see [#emmc-uboot below]) support accessing the various partitions but in different ways. |
| 37 | |
| 38 | |
| 39 | [=#emmc-partconf] |
| 40 | === eMMC PARTITION_CONFIG (Boot partition selection) === |
| 41 | Because eMMC provides multiple hardware partitions but only one can be selected at a time. A non-volatile register in the eMMC device provides a PARTITION_CONFIG that is used to determine what partition is selected at power-up for boot devices. To access this data you need to read/write a 'Card Specific Data' or CSD register (EXT_CSD[179] - EXT_CSC_PART_CONFIG). This can be done both in Linux (see [#emmc-linux below]) or U-Boot (see [#emmc-uboot below]). |
| 42 | |
| 43 | |
| 44 | [=#emmc-uboot] |
| 45 | === U-Boot Support === |
| 46 | U-Boot provides access to eMMC devices through the {{{mmc}}} command and interface but adds an additional argument to the {{{mmc}}} interface to describe the hardware partition. The interface is therefore described as 'mmc <dev> <part>' where 'dev' is the mmc device (some boards have more than one) and 'part' is the hardware partition: 0=user, 1=boot0, 2=boot1. |
| 47 | |
| 48 | Use the {{{mmc dev}}} command to specify the device and partition: |
| 49 | {{{#!bash |
| 50 | mmc dev 0 0 # select user hw partition |
| 51 | mmc dev 0 1 # select boot0 hw partition |
| 52 | mmc dev 0 2 # select boot1 hw partition |
| 53 | }}} |
| 54 | |
| 55 | If U-Boot has been built with {{{CONFIG_SUPPORT_EMMC_BOOT}}} some additional mmc commands are available: |
| 56 | * mmc bootbus <dev> <boot_bus_width> <reset_boot_bus_width> <boot_mode> |
| 57 | * mmc bootpart-resize <dev> <boot-part-size-mb> <rpmb-part-size-mb> |
| 58 | * mmc partconf <dev> <boot_ack> <boot-partition> <partition-access> # set PARTITION_CONFIG field |
| 59 | * mmc rst-function <dev> <value> # change RST_n_FUNCTION field between 0|1|2 (write-once) |
| 60 | |
| 61 | The {{{mmc partconf}}} command can be used to configure the PARTITION_CONFIG specifying what hardware partition to boot from: |
| 62 | {{{#!bash |
| 63 | mmc partconf 0 0 0 0 # disable boot partition (default unset condition; boots from user partition) |
| 64 | mmc partconf 0 1 1 0 # set boot0 partition (with ack) |
| 65 | mmc partconf 0 1 2 0 # set boot1 partition (with ack) |
| 66 | mmc partconf 0 1 7 0 # set user partition (with ack) |
| 67 | }}} |
| 68 | |
| 69 | If U-Boot has been built with {{{CONFIG_SUPPORT_EMMC_RPMB}}} the {{{mmc rpmb}}} command is available for reading, writing and programming the key for the Replay Protection Memory Block (RPMB) partition in eMMC. |
| 70 | |
| 71 | |
| 72 | [=#emmc-linux] |
| 73 | === Linux Support === |
| 74 | Linux presents the various hardware partitions as separate devices: |
| 75 | - /dev/mmcblk0boot0 - BOOT0 partition |
| 76 | - /dev/mmcblk0boot1 - BOOT1 partition |
| 77 | - /dev/mmcblk0rpmb - RPMB partition |
| 78 | - /dev/mmcblk0 - USER partition |
| 79 | |
| 80 | Note that the BOOT partitions by default are read-only as they are typically used for sensitive boot firmware. To write to them you can disable {{{force_ro}}} in sysfs via: |
| 81 | {{{#!bash |
| 82 | echo 0 > /sys/class/block/mmcblk0boot0/force_ro |
| 83 | }}} |
| 84 | |
| 85 | The Linux {{{mmc}}} application provides access to eMMC configuration through CSD registers. This open-source application is available at http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git/. |
| 86 | * To build it: |
| 87 | {{{#!bash |
| 88 | git clone git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc-utils.git |
| 89 | cd mmc-utils |
| 90 | make |
| 91 | }}} |
| 92 | * Alternatively you can install this from a pre-built deb: |
| 93 | * Newport (arm64): |
| 94 | {{{#!bash |
| 95 | wget http://dev.gateworks.com/images/mmc-utils_0~gita3d3331-3~armbian5.35+1_arm64.deb |
| 96 | dpkg -i mmc-utils_0~gita3d3331-3~armbian5.35+1_arm64.deb |
| 97 | }}} |
| 98 | * Ventana (armhf): |
| 99 | {{{#!bash |
| 100 | wget http://dev.gateworks.com/images/mmc-utils_0~gita3d3331-3~armbian5.35+1_armhf.deb |
| 101 | dpkg -i mmc-utils_0~gita3d3331-3~armbian5.35+1_armhf.deb |
| 102 | }}} |
| 103 | |
| 104 | You can use the {{{mmc}}} utility to configure the eMMC PARTITION_CONFIG to specify the boot device on power-up via {{{mmc bootpart enable <boot_partition> <send_ack> <device>}}} where boot_partition specifies the hardware partition (1=boot0, 2=boot1, 7=user), send_ack specifies the device must send an awknoledgement (for fast boot), and device is the root mmc block device of the eMMC: |
| 105 | {{{#!bash |
| 106 | # set boot partition to boot0 |
| 107 | mmc bootpart enable 1 0 /dev/mmcblk0 |
| 108 | # set boot partition to boot1 |
| 109 | mmc bootpart enable 2 0 /dev/mmcblk0 |
| 110 | # set boot partition to user |
| 111 | mmc bootpart enable 7 0 /dev/mmcblk0 |
| 112 | }}} |
| 113 | |
| 114 | Some additional use cases: |
| 115 | {{{#!bash |
| 116 | # show PARTITION_CONFIG: |
| 117 | mmc extcsd read /dev/mmcblk0 | grep PARTITION_CONFIG |
| 118 | # show BUS CONFIG: |
| 119 | mmc extcsd read /dev/mmcblk0 | grep BOOT_BUS_CONDITIONS |
| 120 | # disable boot partition |
| 121 | mmc bootpart enable 0 0 /dev/mmcblk0 |
| 122 | }}} |
| 123 | |
| 124 | References: |
| 125 | * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/mmc/mmc-tools.txt |