diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2020-09-25 08:06:22 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-09-25 08:06:22 +0200 |
commit | 1ab2e649dc0ccef7ee990b999e1d8f8c32e7cd24 (patch) | |
tree | 66f02471e811228f4da2580109b7d26c68ebe90a | |
parent | 39bdcdfb814a22c8143c04938268378e9994b7dd (diff) | |
parent | 94c0b6c798f619bd45aa1411a2ffedba86cad063 (diff) | |
download | barebox-1ab2e649dc0ccef7ee990b999e1d8f8c32e7cd24.tar.gz barebox-1ab2e649dc0ccef7ee990b999e1d8f8c32e7cd24.tar.xz |
Merge branch 'for-next/mmc' into master
-rw-r--r-- | commands/mmc_extcsd.c | 25 | ||||
-rw-r--r-- | common/blspec.c | 11 | ||||
-rw-r--r-- | common/fastboot.c | 2 | ||||
-rw-r--r-- | common/globalvar.c | 5 | ||||
-rw-r--r-- | drivers/mci/Kconfig | 20 | ||||
-rw-r--r-- | drivers/mci/mci-core.c | 96 | ||||
-rw-r--r-- | include/globalvar.h | 1 | ||||
-rw-r--r-- | include/mci.h | 3 |
8 files changed, 136 insertions, 27 deletions
diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c index c9a28fb1fe..7ae068348d 100644 --- a/commands/mmc_extcsd.c +++ b/commands/mmc_extcsd.c @@ -11,6 +11,7 @@ #include <mci.h> #include <getopt.h> #include <fs.h> +#include <linux/sizes.h> #define EXT_CSD_BLOCKSIZE 512 @@ -1142,7 +1143,7 @@ static int print_field(u8 *reg, int index) return 1; case EXT_CSD_SEC_COUNT: - tmp64 = val * 512; + tmp64 *= 512; printf("\tDevice density: %llu B\n", tmp64); return 1; @@ -1232,7 +1233,7 @@ static int print_field(u8 *reg, int index) case EXT_CSD_HC_ERASE_GRP_SIZE: val = get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF); - val = val * 524288; + val = val * SZ_512K; if (val) str = basprintf("Erase-unit size: %u", val); else @@ -1342,7 +1343,8 @@ static int print_field(u8 *reg, int index) case EXT_CSD_ENH_SIZE_MULT: tmp = get_field_val(EXT_CSD_HC_WP_GRP_SIZE, 0, 0xFF); tmp = tmp + get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF); - tmp64 = val * tmp * 524288; + tmp64 *= tmp; + tmp64 *= SZ_512K; printf("\tEnhanced User Data Area %i Size: %llu B\n", index - EXT_CSD_ENH_SIZE_MULT, tmp64); return 1; @@ -1350,28 +1352,32 @@ static int print_field(u8 *reg, int index) case EXT_CSD_GP_SIZE_MULT3: tmp = get_field_val(EXT_CSD_HC_WP_GRP_SIZE, 0, 0xFF); tmp = tmp + get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF); - tmp64 = val * tmp * 524288; + tmp64 *= tmp; + tmp64 *= SZ_512K; printf("\tGeneral_Purpose_Partition_3 Size: %llu B\n", tmp64); return 1; case EXT_CSD_GP_SIZE_MULT2: tmp = get_field_val(EXT_CSD_HC_WP_GRP_SIZE, 0, 0xFF); tmp = tmp + get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF); - tmp64 = val * tmp * 524288; + tmp64 *= tmp; + tmp64 *= SZ_512K; printf("\tGeneral_Purpose_Partition_2 Size: %llu B\n", tmp64); return 1; case EXT_CSD_GP_SIZE_MULT1: tmp = get_field_val(EXT_CSD_HC_WP_GRP_SIZE, 0, 0xFF); tmp = tmp + get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF); - tmp64 = val * tmp * 524288; + tmp64 *= tmp; + tmp64 *= SZ_512K; printf("\tGeneral_Purpose_Partition_1 Size: %llu B\n", tmp64); return 1; case EXT_CSD_GP_SIZE_MULT0: tmp = get_field_val(EXT_CSD_HC_WP_GRP_SIZE, 0, 0xFF); tmp = tmp + get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF); - tmp64 = val * tmp * 524288; + tmp64 *= tmp; + tmp64 *= SZ_512K; printf("\tGeneral_Purpose_Partition_0 Size: %llu B\n", tmp64); return 1; @@ -1422,7 +1428,8 @@ static int print_field(u8 *reg, int index) case EXT_CSD_MAX_ENH_SIZE_MULT: tmp = get_field_val(EXT_CSD_HC_WP_GRP_SIZE, 0, 0xFF); tmp = tmp + get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF); - tmp64 = val * tmp * 524288; + tmp64 *= tmp; + tmp64 *= SZ_512K; printf("\tMax Enhanced Area: %llu B\n", tmp64); return 1; @@ -2156,7 +2163,7 @@ static int print_field(u8 *reg, int index) str = "FIFO policy for cache"; else str = "not provided"; - printf("\t[0] Device flushing: %s", str); + printf("\t[0] Device flushing: %s\n", str); return 1; case EXT_CSD_OPTIMAL_READ_SIZE: diff --git a/common/blspec.c b/common/blspec.c index ed66352d11..9499d32477 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -133,19 +133,18 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun) const char *overlays; const char *appendroot; struct bootm_data data = { - .initrd_address = UIMAGE_INVALID_ADDRESS, - .os_address = UIMAGE_SOME_ADDRESS, - .verbose = verbose, .dryrun = dryrun, }; globalvar_set_match("linux.bootargs.dyn.", ""); - globalvar_set_match("bootm.image", ""); - globalvar_set_match("bootm.oftree", ""); - globalvar_set_match("bootm.initrd", ""); + globalvar_set("bootm.image", ""); + globalvar_set("bootm.oftree", ""); + globalvar_set("bootm.initrd", ""); bootm_data_init_defaults(&data); + data.verbose = verbose || data.verbose; + devicetree = blspec_entry_var_get(entry, "devicetree"); initrd = blspec_entry_var_get(entry, "initrd"); options = blspec_entry_var_get(entry, "options"); diff --git a/common/fastboot.c b/common/fastboot.c index 302720c43d..86e7997a0b 100644 --- a/common/fastboot.c +++ b/common/fastboot.c @@ -383,7 +383,7 @@ static void __maybe_unused cb_boot(struct fastboot *fb, const char *opt) fastboot_tx_print(fb, FASTBOOT_MSG_INFO, "Booting kernel..\n"); globalvar_set_match("linux.bootargs.dyn.", ""); - globalvar_set_match("bootm.image", ""); + globalvar_set("bootm.image", ""); data.os_file = fb->tempname; diff --git a/common/globalvar.c b/common/globalvar.c index 6ab4c1f68e..eefee73e7a 100644 --- a/common/globalvar.c +++ b/common/globalvar.c @@ -399,6 +399,11 @@ void globalvar_set_match(const char *match, const char *val) } } +void globalvar_set(const char *name, const char *val) +{ + dev_set_param(&global_device, name, val); +} + static int globalvar_simple_set(struct device_d *dev, struct param_d *p, const char *val) { struct device_d *rdev; diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 09c0569286..b4c4072596 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -34,6 +34,26 @@ config MCI_WRITE config MCI_MMC_BOOT_PARTITIONS bool "support MMC boot partitions" + help + Provide access to the 'boot partitions' of devices of type 'MMC'. + These so called 'hardware partitions' act like an independent memory + device and thus, need special handling. + + Note: only 'MMC' have 'boot partitions'. So, if you don't use an + 'MMC' device, you don't need this support. + +config MCI_MMC_GPP_PARTITIONS + bool "support MMC general purpose partitions (GPP)" + help + Provide access to the 'general purpose partitions' of devices of type + 'MMC'. These so called 'hardware partitions' act like an independent + memory device and thus, need special handling. + + Note: only 'MMC' devices have 'general purpose partitions'. So, if + you don't use an 'MMC' device, you don't need this support. + + Note: by default, 'MMC' devices have no 'general purpose partitions', + it requires a special one-time configuration step to enable them. comment "--- MCI host drivers ---" diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index a58dedc1cd..2261fd1c1b 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -33,6 +33,7 @@ #include <disks.h> #include <of.h> #include <linux/err.h> +#include <linux/sizes.h> #define MAX_BUFFER_NUMBER 0xffffffff @@ -361,9 +362,9 @@ static int mmc_send_op_cond(struct mci *mci) } /** - * FIXME - * @param mci MCI instance - * @param ext_csd Buffer for a 512 byte sized extended CSD + * Read-in the card's whole extended CSD configuration area + * @param[in] mci MCI instance + * @param[out] ext_csd Buffer for an #EXT_CSD_BLOCKSIZE byte sized extended CSD * @return Transaction status (0 on success) * * Note: Only cards newer than Version 1.1 (Physical Layer Spec) support @@ -386,12 +387,16 @@ int mci_send_ext_csd(struct mci *mci, char *ext_csd) } /** - * FIXME - * @param mci MCI instance - * @param set FIXME - * @param index FIXME - * @param value FIXME + * Write a byte into the card's extended CSD configuration area + * @param[in] mci MCI instance + * @param[in] index Byte index in the extended CSD configuration area + * @param[in] value Byte to write at index into the extended CSD configuration area * @return Transaction status (0 on success) + * + * This sends a CMD6 (aka SWITCH) to the card and writes @b value at extended CSD @b index. + * + * @note It always writes a full byte, the alternatives 'bit set' and + * 'bit clear' aren't supported. */ int mci_switch(struct mci *mci, unsigned index, unsigned value) { @@ -441,6 +446,69 @@ static void mci_part_add(struct mci *mci, uint64_t size, } /** + * Read a value spread to three consecutive bytes in the ECSD information + * @param[in] ecsd_info Information from the eMMC + * @param[in] idx The index where to start to read + * @return The GPP size in units of 'write protect group' size + * + * The value in the ECSD information block is meant in little endian + */ +static __maybe_unused unsigned mmc_extract_gpp_units(const char *ecsd_info, unsigned idx) +{ + unsigned val; + + val = ecsd_info[idx]; + val |= ecsd_info[idx + 1] << 8; + val |= ecsd_info[idx + 2] << 16; + + return val; +} + +/** + * Create and enable access to 'general purpose hardware partitions' on demand + * @param mci[in,out] MCI instance + * + * General Purpose hardware Partitions (aka GPPs) aren't enabled by default. Its + * up to the application to (one-time) setup the eMMC to provide GPPs. Since + * they aren't wildly used, enable access to them on demand only. + */ +static __maybe_unused void mmc_extract_gpp_partitions(struct mci *mci) +{ + uint64_t wpgs, part_size; + size_t idx; + char *name, *partname; + static const unsigned gpp_offsets[MMC_NUM_GP_PARTITION] = { + EXT_CSD_GP_SIZE_MULT0, EXT_CSD_GP_SIZE_MULT1, + EXT_CSD_GP_SIZE_MULT2, EXT_CSD_GP_SIZE_MULT3, }; + + if (!(mci->ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & 0x01)) + return; /* no partitioning support */ + /* + * The size of GPPs is defined in units of 'write protect group' size. + * The 'write protect group' size is defined to: + * CSD_HC_ERASE_GRP_SIZE * CSD_HC_WP_GRP_SIZE * 512 kiB + */ + wpgs = mci->ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; + wpgs *= mci->ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + wpgs *= SZ_512K; + + /* up to four GPPs can be enabled. */ + for (idx = 0; idx < ARRAY_SIZE(gpp_offsets); idx++) { + part_size = mmc_extract_gpp_units(mci->ext_csd, gpp_offsets[idx]); + if (part_size == 0) + continue; + /* Convert to bytes */ + part_size *= wpgs; + + partname = xasprintf("gpp%zu", idx); + name = xasprintf("%s.%s", mci->cdevname, partname); + /* TODO read-only flag */ + mci_part_add(mci, part_size, EXT_CSD_PART_CONFIG_ACC_GPP0 + idx, + name, partname, idx, false, MMC_BLK_DATA_AREA_GP); + } +} + +/** * Change transfer frequency for an MMC card * @param mci MCI instance * @return Transaction status (0 on success) @@ -515,6 +583,9 @@ static int mmc_change_freq(struct mci *mci) mci->bootpart = (mci->ext_csd_part_config >> 3) & 0x7; } + if (IS_ENABLED(CONFIG_MCI_MMC_GPP_PARTITIONS)) + mmc_extract_gpp_partitions(mci); + return 0; } @@ -1239,13 +1310,16 @@ static int sd_send_if_cond(struct mci *mci) return 0; } +/** + * Switch between hardware MMC partitions on demand + */ static int mci_blk_part_switch(struct mci_part *part) { struct mci *mci = part->mci; int ret; - if (!IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS)) - return 0; + if (!IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && !IS_ENABLED(CONFIG_MCI_MMC_GPP_PARTITIONS)) + return 0; /* no need */ if (mci->part_curr == part) return 0; @@ -1637,6 +1711,8 @@ static int mci_register_partition(struct mci_part *part) break; case MMC_BLK_DATA_AREA_MAIN: break; + case MMC_BLK_DATA_AREA_GP: + break; default: return 0; } diff --git a/include/globalvar.h b/include/globalvar.h index 6f2c6db746..face53d33f 100644 --- a/include/globalvar.h +++ b/include/globalvar.h @@ -15,6 +15,7 @@ int globalvar_add_simple(const char *name, const char *value); void globalvar_remove(const char *name); char *globalvar_get_match(const char *match, const char *separator); void globalvar_set_match(const char *match, const char *val); +void globalvar_set(const char *name, const char *val); int globalvar_add_simple_string(const char *name, char **value); int globalvar_add_simple_int(const char *name, int *value, diff --git a/include/mci.h b/include/mci.h index 96547fb396..5e6805e8dc 100644 --- a/include/mci.h +++ b/include/mci.h @@ -277,6 +277,7 @@ */ #define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) #define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) +#define EXT_CSD_PART_CONFIG_ACC_GPP0 (0x4) #define EXT_CSD_CMD_SET_NORMAL (1<<0) #define EXT_CSD_CMD_SET_SECURE (1<<1) @@ -456,7 +457,7 @@ struct mci { uint64_t capacity; /**< Card's data capacity in bytes */ int ready_for_use; /** true if already probed */ int dsr_imp; /**< DSR implementation state from CSD */ - char *ext_csd; + u8 *ext_csd; int probe; struct param_d *param_boot; int bootpart; |