Re: [RFC PATCH 1/1 ]mmc: Support-FFU-for-eMMC-v5.0

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



argh...reposting my response as text only since linux-mmc doesn't like
html mail. :(

On Tue, Apr 1, 2014 at 1:26 PM, Grant Grundler <grundler@xxxxxxxxxxxx> wrote:
>
>
>
> On Mon, Mar 31, 2014 at 9:17 PM, Jaehoon Chung <jh80.chung@xxxxxxxxxxx>
> wrote:
>>
>> Hi, Seunguk.
>>
>> On 03/31/2014 07:51 PM, Seunguk Shin wrote:
>> > Some of Samsung eMMC does not show the argument for ffu in ext_csd.
>> > In case of this, eMMC shows 0x0 from ext_csd, Host has to modify the
>> > argument.
>> >
>> > Add "#define CID_MANFID_SAMSUNG               0x15"
>> If you need to add the Samsung eMMC specific code,
>> it would be better you would send the Samsung eMMC specific patch.
>> (based-on this patch.)
>
>
> I believe Seunguk Shin provided the information so someone else could add
> this code. I could be that person if no one from Samsung has have time for
> this.  I'm very grateful to Seungguk for posting these details.
>
> I hope we can see the same details for Samsung eMMC 4.5 also (but please use
> a different email Subject line so we aren't confused.)
>
>> This patch isn't patch for samsung eMMC.
>> I didn't see this patch fully, but i think this patch is general code.
>
>
> AFAICT, the MANFID_SAMSUNG is only a "quirk" for Samsung devices which
> specify the EXT_CSD_FFU_ARG as 0.
>
> The original patch from SanDisk is general code and most of Seunguk's
> comments are general too. SanDisk (ie Avi) should please ACK they've seen
> those comments since I believe Seunguk is correct.
>
> And Avi, please let us know if/when you plan on posting a V2. Or at least
> not be offended if I get impatient and hijack this patch series. :)
>
> cheers,
> grant
>
>> Best Regards,
>> Jaehoon Chung
>>
>> >
>> >> +int mmc_ffu_download(struct mmc_card *card, struct mmc_command *cmd,
>> >> +       u8 *data, int buf_bytes)
>> >> +{
>> >> +       u8 ext_csd[CARD_BLOCK_SIZE];
>> >> +       int err;
>> >> +       int ret;
>> >> +
>> >> +       /* Read the EXT_CSD */
>> >> +       err = mmc_send_ext_csd(card, ext_csd);
>> >> +       if (err) {
>> >> +               pr_err("FFU: %s: error %d sending ext_csd\n",
>> >> +                       mmc_hostname(card->host), err);
>> >> +               goto exit;
>> >> +       }
>> >> +
>> >> +       /* Check if FFU is supported by card */
>> >> +       if (!FFU_SUPPORTED_MODE(ext_csd[EXT_CSD_SUPPORTED_MODE])) {
>> >> +               err = -EINVAL;
>> >> +               pr_err("FFU: %s: error %d FFU is not supported\n",
>> >> +                       mmc_hostname(card->host), err);
>> >> +               goto exit;
>> >> +       }
>> >> +
>> >> +       err = mmc_host_set_ffu(card, ext_csd[EXT_CSD_FW_CONFIG]);
>> >> +       if (err) {
>> >> +               pr_err("FFU: %s: error %d FFU is not supported\n",
>> >> +                       mmc_hostname(card->host), err);
>> >> +               err = -EINVAL;
>> >> +               goto exit;
>> >> +       }
>> >> +
>> >> +       /* set device to FFU mode */
>> >> +       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> > EXT_CSD_MODE_CONFIG,
>> >> +               MMC_FFU_MODE_SET, card->ext_csd.generic_cmd6_time);
>> >> +       if (err) {
>> >> +               pr_err("FFU: %s: error %d FFU is not supported\n",
>> >> +                       mmc_hostname(card->host), err);
>> >> +               goto exit_normal;
>> >> +       }
>> >> +
>> >> +       /* set CMD ARG */
>> >> +       cmd->arg = ext_csd[EXT_CSD_FFU_ARG] |
>> >> +               ext_csd[EXT_CSD_FFU_ARG + 1] << 8 |
>> >> +               ext_csd[EXT_CSD_FFU_ARG + 2] << 16 |
>> >> +               ext_csd[EXT_CSD_FFU_ARG + 3] << 24;
>> >> +
>> >
>> > Add followings
>> > "
>> >        /* If arg is zero, should be set to a special value for samsung
>> > eMMC
>> > */
>> >        if ( card->cid.manfid == CID_MANFID_SAMSUNG && cmd->arg == 0x0 )
>> > {
>> >                cmd->arg = 0xc7810000;
>> >        }
>> > "
>> >
>> >> +       err = mmc_ffu_write(card, data, cmd->arg, buf_bytes);
>> >> +
>> >> +exit_normal:
>> >> +       /* host switch back to work in normal MMC Read/Write commands
>> >> */
>> >> +       ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> >> +               EXT_CSD_MODE_CONFIG, MMC_FFU_MODE_NORMAL,
>> >> +               card->ext_csd.generic_cmd6_time);
>> >> +       if (ret)
>> >> +               err = ret;
>> >> +
>> >> +exit:
>> >> +       return err;
>> >> +}
>> >> +EXPORT_SYMBOL(mmc_ffu_download);
>> >> +
>> >
>> >
>> >
>> > eMMC 5.0 Spec. says if device does not support MODE_OPERATION_CODES,
>> > device
>> > doesn't need to use NUMBER_OF_FW_SECTORS_CORRECTLY_PROGRAMMED.
>> > So, it's better to move the code for checking this value to
>> > FFU_FEATURES(ext_csd[EXT_CSD_FFU_FEATURES]
>> >
>> >> +int mmc_ffu_install(struct mmc_card *card) {
>> >> +       u8 ext_csd[CARD_BLOCK_SIZE];
>> >> +       int err;
>> >> +       u32 ffu_data_len;
>> >> +       u32 timeout;
>> >> +
>> >> +       err = mmc_send_ext_csd(card, ext_csd);
>> >> +       if (err) {
>> >> +               pr_err("FFU: %s: error %d sending ext_csd\n",
>> >> +                       mmc_hostname(card->host), err);
>> >> +               goto exit;
>> >> +       }
>> >> +
>> >> +       /* Check if FFU is supported */
>> >> +       if (!FFU_SUPPORTED_MODE(ext_csd[EXT_CSD_SUPPORTED_MODE]) ||
>> >> +               FFU_CONFIG(ext_csd[EXT_CSD_FW_CONFIG])) {
>> >> +               err = -EINVAL;
>> >> +               pr_err("FFU: %s: error %d FFU is not supported\n",
>> >> +                       mmc_hostname(card->host), err);
>> >> +               goto exit;
>> >> +       }
>> >
>> > Remove followings
>> > "
>> >        ffu_data_len = ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG]|
>> >                ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG + 1] << 8 |
>> >                ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG + 2] << 16 |
>> >                ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG + 3] << 24;
>> >
>> >        if (!ffu_data_len) {
>> >                err = -EPERM;
>> >                return err;
>> >        }
>> > "
>> >
>> >> +
>> >> +       /* check mode operation */
>> >> +       if (!FFU_FEATURES(ext_csd[EXT_CSD_FFU_FEATURES])) {
>> >> +               /* restart the eMMC */
>> >> +               err = mmc_ffu_restart(card);
>> >> +               if (err) {
>> >> +                       pr_err("FFU: %s: error %d FFU install:\n",
>> >> +                               mmc_hostname(card->host), err);
>> >> +               }
>> >> +       } else {
>> >
>> > Add followings
>> > "
>> >                         ffu_data_len =
>> > ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG]|
>> >                                 ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG + 1]
>> > << 8
>> > |
>> >                                 ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG + 2]
>> > <<
>> > 16 |
>> >                                 ext_csd[EXT_CSD_NUM_OF_FW_SEC_PROG + 3]
>> > <<
>> > 24;
>> >
>> >                         if (!ffu_data_len) {
>> >                                 err = -EPERM;
>> >                                 return err;
>> >                         }
>> > "
>> >
>> >> +                       /* set device to FFU mode */
>> >> +                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> >> +                               EXT_CSD_MODE_CONFIG, 0x1,
>> >> +                               card->ext_csd.generic_cmd6_time);
>> >> +                       if (err) {
>> >> +                               pr_err("FFU: %s: error %d FFU is not
>> > supported\n",
>> >> +                                       mmc_hostname(card->host), err);
>> >> +                               goto exit;
>> >> +                       }
>> >
>> >
>> >
>> > Checking ffu status in ext_csd should be done even if device does not
>> > support MODE_OPERATION_CODES So, it's better to move the code for
>> > checking
>> > this value to out of brace for
>> > FFU_FEATURES(ext_csd[EXT_CSD_FFU_FEATURES]
>> >
>> >> +                       /* set ext_csd to install mode */
>> >> +                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> >> +                               EXT_CSD_MODE_OPERATION_CODES,
>> >> +                               MMC_FFU_INSTALL_SET, timeout);
>> >> +
>> >> +                       if (err) {
>> >> +                               pr_err("FFU: %s: error %d setting
>> >> install
>> > mode\n",
>> >> +                                       mmc_hostname(card->host), err);
>> >> +                               goto exit;
>> >> +                       }
>> >> +
>> >
>> > Remove followings
>> > "
>> >                        /* read ext_csd */
>> >                        err = mmc_send_ext_csd(card, ext_csd);
>> >                        if (err) {
>> >                                pr_err("FFU: %s: error %d sending
>> > ext_csd\n",
>> >                                        mmc_hostname(card->host), err);
>> >                                goto exit;
>> >                        }
>> >                        /* return status */
>> >                        err = ext_csd[EXT_CSD_FFU_STATUS];
>> >                        if (err) {
>> >                                pr_err("FFU: %s: error %d FFU
>> > install:\n",
>> >                                        mmc_hostname(card->host), err);
>> >                                err = -EINVAL;
>> >                                goto exit;
>> >                        }
>> > "
>> >
>> >> +               }
>> >> +
>> >
>> > Add followings
>> > "
>> >            /* read ext_csd */
>> >            err = mmc_send_ext_csd(card, ext_csd);
>> >            if (err) {
>> >                    pr_err("FFU: %s: error %d sending ext_csd\n",
>> >                               mmc_hostname(card->host), err);
>> >                    goto exit;
>> >            }
>> >            /* return status */
>> >            err = ext_csd[EXT_CSD_FFU_STATUS];
>> >            if (err) {
>> >                    pr_err("FFU: %s: error %d FFU install:\n",
>> >                               mmc_hostname(card->host), err);
>> >                    err = -EINVAL;
>> >                    goto exit;
>> >            }
>> > "
>> >
>> >> +exit:
>> >> +       return err;
>> >> +}
>> >> +EXPORT_SYMBOL(mmc_ffu_install);
>> >> +
>> >
>> >
>> >
>> > And some device's fw should be transferred with one command.
>> > They does not support multiple commands for fw transfer.
>> > For these devices, MMC_IOC_MAX_BYTES should be greater.
>> >
>> > diff --git a/include/uapi/linux/mmc/ioctl.h
>> > b/include/uapi/linux/mmc/ioctl.h
>> > index 1f5e689..af9ea62 100644
>> > --- a/include/uapi/linux/mmc/ioctl.h
>> > +++ b/include/uapi/linux/mmc/ioctl.h
>> > @@ -53,5 +53,5 @@ struct mmc_ioc_cmd {
>> >   * is enforced per ioctl call.  For larger data transfers, use the
>> > normal
>> >   * block device operations.
>> >   */
>> > -#define MMC_IOC_MAX_BYTES  (512L * 256)
>> > +#define MMC_IOC_MAX_BYTES  (512L * 1024)
>> >  #endif /* LINUX_MMC_IOCTL_H */
>> >
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> > the body of a message to majordomo@xxxxxxxxxxxxxxx
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux