| | 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 |