On Wed, Jul 01, 2020 at 11:11:11AM +0200, Ahmad Fatoum wrote: > The BootROM resets both the SD/MMC host controller and the pin controller, > but the card itself remains in transfer mode. If we redo host-side > setup, we can directly read new blocks off the card. > > Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> > --- > drivers/mci/Kconfig | 4 + > drivers/mci/Makefile | 1 + > drivers/mci/atmel-sdhci-common.c | 3 + > drivers/mci/atmel-sdhci-pbl.c | 128 +++++++++++++++++++++++++++++++ > 4 files changed, 136 insertions(+) > create mode 100644 drivers/mci/atmel-sdhci-pbl.c > > diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig > index 6ae1e812528c..3026b25cadc9 100644 > --- a/drivers/mci/Kconfig > +++ b/drivers/mci/Kconfig > @@ -187,3 +187,7 @@ endif > config MCI_IMX_ESDHC_PBL > bool > select MCI_SDHCI > + > +config MCI_ATMEL_SDHCI_PBL > + bool > + select MCI_SDHCI > diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile > index 177483dcfba5..4a5363367476 100644 > --- a/drivers/mci/Makefile > +++ b/drivers/mci/Makefile > @@ -5,6 +5,7 @@ obj-$(CONFIG_MCI_ATMEL_SDHCI) += atmel-sdhci.o atmel-sdhci-common.o > obj-$(CONFIG_MCI_BCM283X) += mci-bcm2835.o > obj-$(CONFIG_MCI_BCM283X_SDHOST) += bcm2835-sdhost.o > obj-$(CONFIG_MCI_DOVE) += dove-sdhci.o > +pbl-$(CONFIG_MCI_ATMEL_SDHCI_PBL) += atmel-sdhci-pbl.o atmel-sdhci-common.o > obj-$(CONFIG_MCI_IMX) += imx.o > obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o imx-esdhc-common.o > pbl-$(CONFIG_MCI_IMX_ESDHC_PBL) += imx-esdhc-pbl.o imx-esdhc-common.o > diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c > index 1884f3836337..a83610c3d090 100644 > --- a/drivers/mci/atmel-sdhci-common.c > +++ b/drivers/mci/atmel-sdhci-common.c > @@ -12,7 +12,10 @@ > #include <common.h> > #include <mci.h> > > +#include <mach/early_udelay.h> > + > #ifdef __PBL__ > +#define udelay early_udelay > #undef dev_err > #define dev_err(d, ...) pr_err(__VA_ARGS__) > #undef dev_warn > diff --git a/drivers/mci/atmel-sdhci-pbl.c b/drivers/mci/atmel-sdhci-pbl.c > new file mode 100644 > index 000000000000..626e4008fe85 > --- /dev/null > +++ b/drivers/mci/atmel-sdhci-pbl.c > @@ -0,0 +1,128 @@ > +// SPDX-License-Identifier: BSD-1-Clause > +/* > + * Copyright (c) 2015, Atmel Corporation > + * Copyright (c) 2019, Ahmad Fatoum, Pengutronix > + * > + * Atmel's name may not be used to endorse or promote products derived from > + * this software without specific prior written permission. > + */ > + > +#include <common.h> > +#include <pbl.h> > +#include <mci.h> > +#include <debug_ll.h> > +#include <mach/xload.h> > +#include "atmel-sdhci.h" > + > +#include <mach/early_udelay.h> > + > +#ifdef __PBL__ > +#define udelay early_udelay > +#endif > + > +#define SECTOR_SIZE 512 > +#define SUPPORT_MAX_BLOCKS 16U > + > +struct at91_sdhci_priv { > + struct at91_sdhci host; > + bool highcapacity_card; > +}; > + > +static int sd_cmd_stop_transmission(struct at91_sdhci_priv *priv) > +{ > + struct mci_cmd cmd = { > + .cmdidx = MMC_CMD_STOP_TRANSMISSION, > + .resp_type = MMC_RSP_R1b, > + }; > + > + return at91_sdhci_send_command(&priv->host, &cmd, NULL); > +} > + > +static int sd_cmd_read_multiple_block(struct at91_sdhci_priv *priv, > + void *buf, > + unsigned int start, > + unsigned int block_count) > +{ > + u16 block_len = SECTOR_SIZE; > + struct mci_data data; > + struct mci_cmd cmd = { > + .cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK, > + .resp_type = MMC_RSP_R1, > + .cmdarg = start, > + }; > + > + if (!priv->highcapacity_card) > + cmd.cmdarg *= block_len; > + > + data.dest = buf; > + data.flags = MMC_DATA_READ; > + data.blocksize = block_len; > + data.blocks = block_count; > + > + return at91_sdhci_send_command(&priv->host, &cmd, &data); > +} > + > +static int at91_sdhci_bio_read(struct pbl_bio *bio, off_t start, > + void *buf, unsigned int nblocks) > +{ > + struct at91_sdhci_priv *priv = bio->priv; > + unsigned int blocks_done = 0; > + unsigned int blocks; > + unsigned int block_len = SECTOR_SIZE; > + unsigned int blocks_read; > + int ret; > + > + /* > + * Refer to the at91sam9g20 datasheet: > + * Figure 35-10. Read Function Flow Diagram > + */ > + > + while (blocks_done < nblocks) { > + blocks = min(nblocks - blocks_done, SUPPORT_MAX_BLOCKS); > + > + blocks_read = sd_cmd_read_multiple_block(priv, buf, > + start + blocks_done, > + blocks); > + > + ret = sd_cmd_stop_transmission(priv); > + if (ret) > + return ret; > + > + blocks_done += blocks_read; > + > + if (blocks_read != blocks) > + break; > + > + buf += blocks * block_len; > + } > + > + return blocks_done; > +} All this doesn't look at91 specific. It rather looks like it could be generic code. I know I have put similar code into the i.MX esdhc PBL driver, so I can't complain very much... Sascha -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox