Re: [PATCH 5/6] mmc: actions: add MMC driver for Actions OWL S700

2020-12-14 Thread André Przywara
On 14/12/2020 15:02, Amit Tomar wrote:
> Hi,
> 
> You could pass a pointer to owl_mmc_priv here, which can hold both those
> 
> values. See below for more more on this.
> 
> Did you mean for argument 3rd and 4th but then in that case how one
> could have differentiated
> between source and destination.
> 
> for instance 3rd and 4th arguments are different for read and write flag.

No, just the first two arguments (that's why I put the comment after
this line).

> 
> 
> > +             unsigned int src, unsigned int dst,
> > +             unsigned int len)
> > +{
> > +     unsigned int mode = drq;
> > +     u8 frame_cnt = 0x1;
> 
> Not needed, just use the 0x1 below directly.
> 
> 
> Ok.
> 
> 
> > +
> > +     /* Set Source and Destination adderess mode */
> > +     mode |= (DMA_MODE_ST_DEV | DMA_MODE_SAM_CONST |
> DMA_MODE_DT_DCU |
> > +                     DMA_MODE_DAM_INC);
> > +
> > +     writel(mode, dma_base + DMA_MODE);
> > +     writel(src, dma_base + DMA_SOURCE);
> > +     writel(dst, dma_base + DMA_DESTINATION);
> > +     writel(len, dma_base + DMA_FRAME_LEN);
> > +     writel(frame_cnt, dma_base + DMA_FRAME_CNT);
> > +}
> > +
> > +static void owl_mmc_prepare_data(struct owl_mmc_priv *priv,
> > +             struct mmc_data *data)
> > +{
> > +     unsigned int reg, total;
> > +     uint32_t buf = 0;
> > +
> > +     reg = readl(priv->reg_base + OWL_REG_SD_EN);
> > +     reg |= OWL_SD_EN_BSEL;
> > +     writel(reg, priv->reg_base + OWL_REG_SD_EN);
> > +
> > +     writel(data->blocks, priv->reg_base + OWL_REG_SD_BLK_NUM);
> > +     writel(data->blocksize, priv->reg_base + OWL_REG_SD_BLK_SIZE);
> > +     total = data->blocksize * data->blocks;
> > +
> > +     if (data->blocksize < 512)
> > +             writel(total, priv->reg_base + OWL_REG_SD_BUF_SIZE);
> > +     else
> > +             writel(512, priv->reg_base + OWL_REG_SD_BUF_SIZE);
> > +
> > +     /* DMA STOP */
> > +     writel(0x0, (DMA0_CHANNEL_BASE(2) + DMA_START));
> > +
> > +     if (data) {
> > +             if (data->flags == MMC_DATA_READ) {
> 
> Shouldn't that be used with '&', since it's one flag among others?
> 
> 
> ,Actually, I wasn't sure about some driver uses == and other one &, even
> here in Mainline
> U-boot.

Well, flags somewhat suggests it's a bitmap, but indeed mmc.c just
assigns a value, and "1" and "2" would work in both ways.

> > +                     buf = (ulong) (data->dest);
> > +                     owl_dma_config((void *) DMA0_CHANNEL_BASE(2),
> > +                                     priv->dma_drq,
> > +                                     (ulong) priv->reg_base +
> > +                                     OWL_REG_SD_DAT,
> > +                                     buf, total);
> > +                     invalidate_dcache_range(buf, buf + total);
> > +             } else if (data->flags == MMC_DATA_WRITE) {
> > +                     buf = (ulong) (data->src);
> > +                     owl_dma_config((void *) DMA0_CHANNEL_BASE(2),
> > +                                     priv->dma_drq,
> > +                                     buf,
> > +                                     (ulong) priv->reg_base +
> > +                                     OWL_REG_SD_DAT,
> > +                                     total);
> > +                     flush_dcache_range(buf, buf + total);
> > +             }
> > +             /* DMA START */
> > +             writel(0x1, (DMA0_CHANNEL_BASE(2) + DMA_START));
> > +     }
> > +}
> > +
> > +static int owl_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
> > +             struct mmc_data *data)
> > +{
> > +     struct owl_mmc_priv *priv = dev_get_priv(dev);
> > +     unsigned int cmd_rsp_mask, mode, reg;
> > +     int timeout = DATA_TRANSFER_TIMEOUT;
> > +
> > +     reg = readl(priv->reg_base + OWL_REG_SD_EN);
> > +     reg |= OWL_SD_ENABLE;
> > +     writel(reg, priv->reg_base + OWL_REG_SD_EN);
> > +
> > +     /* setup response */
> > +     switch (cmd->resp_type) {
> > +     case MMC_RSP_NONE:
> > +             break;
> > +     case MMC_RSP_R1:
> > +             if (data) {
> > +                     if (data->flags == MMC_DATA_READ)
> > +                             mode = OWL_SD_CTL_TM(4);
> > +                     else
> > +                             mode = OWL_SD_CTL_TM(5);
> > +             } else {
> > +                     mode = OWL_SD_CTL_TM(1);
> > +             }
> > +             cmd_rsp_mask = OWL_SD_STATE_CLNR | OWL_SD_STATE_CRC7ER;
> > +             break;
> > +     case MMC_RSP_R1b:
> > +             mode = OWL_SD_CTL_TM(3);
> > +             cmd_rsp_mask = OWL_SD_STATE_CLNR | 

Re: [PATCH 5/6] mmc: actions: add MMC driver for Actions OWL S700

2020-12-14 Thread Amit Tomar
Hi,

You could pass a pointer to owl_mmc_priv here, which can hold both those

> values. See below for more more on this.
>
> Did you mean for argument 3rd and 4th but then in that case how one could
have differentiated
between source and destination.

for instance 3rd and 4th arguments are different for read and write flag.


> + unsigned int src, unsigned int dst,
> > + unsigned int len)
> > +{
> > + unsigned int mode = drq;
> > + u8 frame_cnt = 0x1;
>
> Not needed, just use the 0x1 below directly.
>

Ok.

>
> > +
> > + /* Set Source and Destination adderess mode */
> > + mode |= (DMA_MODE_ST_DEV | DMA_MODE_SAM_CONST | DMA_MODE_DT_DCU |
> > + DMA_MODE_DAM_INC);
> > +
> > + writel(mode, dma_base + DMA_MODE);
> > + writel(src, dma_base + DMA_SOURCE);
> > + writel(dst, dma_base + DMA_DESTINATION);
> > + writel(len, dma_base + DMA_FRAME_LEN);
> > + writel(frame_cnt, dma_base + DMA_FRAME_CNT);
> > +}
> > +
> > +static void owl_mmc_prepare_data(struct owl_mmc_priv *priv,
> > + struct mmc_data *data)
> > +{
> > + unsigned int reg, total;
> > + uint32_t buf = 0;
> > +
> > + reg = readl(priv->reg_base + OWL_REG_SD_EN);
> > + reg |= OWL_SD_EN_BSEL;
> > + writel(reg, priv->reg_base + OWL_REG_SD_EN);
> > +
> > + writel(data->blocks, priv->reg_base + OWL_REG_SD_BLK_NUM);
> > + writel(data->blocksize, priv->reg_base + OWL_REG_SD_BLK_SIZE);
> > + total = data->blocksize * data->blocks;
> > +
> > + if (data->blocksize < 512)
> > + writel(total, priv->reg_base + OWL_REG_SD_BUF_SIZE);
> > + else
> > + writel(512, priv->reg_base + OWL_REG_SD_BUF_SIZE);
> > +
> > + /* DMA STOP */
> > + writel(0x0, (DMA0_CHANNEL_BASE(2) + DMA_START));
> > +
> > + if (data) {
> > + if (data->flags == MMC_DATA_READ) {
>
> Shouldn't that be used with '&', since it's one flag among others?
>

,Actually, I wasn't sure about some driver uses == and other one &, even
here in Mainline
U-boot.

>
> > + buf = (ulong) (data->dest);
> > + owl_dma_config((void *) DMA0_CHANNEL_BASE(2),
> > + priv->dma_drq,
> > + (ulong) priv->reg_base +
> > + OWL_REG_SD_DAT,
> > + buf, total);
> > + invalidate_dcache_range(buf, buf + total);
> > + } else if (data->flags == MMC_DATA_WRITE) {
> > + buf = (ulong) (data->src);
> > + owl_dma_config((void *) DMA0_CHANNEL_BASE(2),
> > + priv->dma_drq,
> > + buf,
> > + (ulong) priv->reg_base +
> > + OWL_REG_SD_DAT,
> > + total);
> > + flush_dcache_range(buf, buf + total);
> > + }
> > + /* DMA START */
> > + writel(0x1, (DMA0_CHANNEL_BASE(2) + DMA_START));
> > + }
> > +}
> > +
> > +static int owl_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
> > + struct mmc_data *data)
> > +{
> > + struct owl_mmc_priv *priv = dev_get_priv(dev);
> > + unsigned int cmd_rsp_mask, mode, reg;
> > + int timeout = DATA_TRANSFER_TIMEOUT;
> > +
> > + reg = readl(priv->reg_base + OWL_REG_SD_EN);
> > + reg |= OWL_SD_ENABLE;
> > + writel(reg, priv->reg_base + OWL_REG_SD_EN);
> > +
> > + /* setup response */
> > + switch (cmd->resp_type) {
> > + case MMC_RSP_NONE:
> > + break;
> > + case MMC_RSP_R1:
> > + if (data) {
> > + if (data->flags == MMC_DATA_READ)
> > + mode = OWL_SD_CTL_TM(4);
> > + else
> > + mode = OWL_SD_CTL_TM(5);
> > + } else {
> > + mode = OWL_SD_CTL_TM(1);
> > + }
> > + cmd_rsp_mask = OWL_SD_STATE_CLNR | OWL_SD_STATE_CRC7ER;
> > + break;
> > + case MMC_RSP_R1b:
> > + mode = OWL_SD_CTL_TM(3);
> > + cmd_rsp_mask = OWL_SD_STATE_CLNR | OWL_SD_STATE_CRC7ER;
> > + break;
> > + case MMC_RSP_R2:
> > + mode = OWL_SD_CTL_TM(2);
> > + cmd_rsp_mask = OWL_SD_STATE_CLNR | OWL_SD_STATE_CRC7ER;
> > + break;
> > + case MMC_RSP_R3:
> > + cmd->cmdarg = 0x40ff8000;
> > + mode = OWL_SD_CTL_TM(1);
> > + cmd_rsp_mask = OWL_SD_STATE_CLNR;
> > + break;
> > + default:
> > + printf("error: no math command RSP flag %x\n",
> cmd->cmdarg);
> > + return -1;
> > + }
> > +
> > + mode |= (readl(priv->reg_base + OWL_REG_SD_CTL) & (0xff << 16));
> > +
> > + /* setup command */
> > + 

Re: [PATCH 5/6] mmc: actions: add MMC driver for Actions OWL S700

2020-12-14 Thread Amit Tomar
Hi Jaehoon

Thanks for having a look and providing the comments

Order to the bit number.

Ok, Sure

>
> > +
> > +#define OWL_MMC_OCR (MMC_VDD_32_33 | MMC_VDD_33_34
> | \
> > +  MMC_VDD_165_195)
> > +
> > +#define DATA_TRANSFER_TIMEOUT(3 * (100 * 1000))
>
> Really need to set 30?
>

I should have used the timeout value used in the Mainline Linux driver
which is 3.
I would fix it to 3.


>
> > +
> > +/*
> > + * Simple DMA transfer operations defines for MMC/SD card
> > + */
> > +#define DMA0_CHANNEL_BASE(x) (0xe0230100 + 0x100 * (x))
>
> What is 0xe0230100?
>

This is the base address of external DMA channel 0 used for MMC/SD
controllers. Linux has
has separate full blown DMA driver for it but here we chose not to have
separate driver
instead use DMA bits only needed for MMC/SD.

>
> > +
> > +#define DMA_MODE 0x
> > +#define DMA_SOURCE   0x0004
> > +#define DMA_DESTINATION  0x0008
> > +#define DMA_FRAME_LEN0x000C
> > +#define DMA_FRAME_CNT0x0010
> > +#define DMA_START0x0024
> > +
> > +/* DMAx_MODE */
> > +#define DMA_MODE_ST(x)  (((x) & 0x3) << 8)
> > +#define DMA_MODE_ST_DEV DMA_MODE_ST(0)
> > +#define DMA_MODE_DT(x)  (((x) & 0x3) << 10)
> > +#define DMA_MODE_DT_DCU DMA_MODE_DT(2)
> > +#define DMA_MODE_SAM(x) (((x) & 0x3) << 16)
> > +#define DMA_MODE_SAM_CONST  DMA_MODE_SAM(0)
> > +#define DMA_MODE_DAM(x) (((x) & 0x3) << 18)
> > +#define DMA_MODE_DAM_INCDMA_MODE_DAM(1)
> > +
> > +
> > +struct owl_mmc_plat {
> > + struct mmc_config cfg;
> > + struct mmc mmc;
> > +};
> > +
> > +struct owl_mmc_priv {
> > + void *reg_base;
> > + struct clk clk;
> > + unsigned int clock;   /* Current clock */
> > + unsigned int dma_drq; /* Trigger Source */
> > +};
> > +
> > +static void owl_dma_config(void *dma_base, unsigned int drq,
> > + unsigned int src, unsigned int dst,
> > + unsigned int len)
> > +{
> > + unsigned int mode = drq;
> > + u8 frame_cnt = 0x1;
>
> Does it need to use frame_cnt variable?
>


> Ok, would remove it and use fixed value 0x1 for it.
> > +
> > + /* Set Source and Destination adderess mode */
> > + mode |= (DMA_MODE_ST_DEV | DMA_MODE_SAM_CONST | DMA_MODE_DT_DCU |
> > + DMA_MODE_DAM_INC);
> > +
> > + writel(mode, dma_base + DMA_MODE);
> > + writel(src, dma_base + DMA_SOURCE);
> > + writel(dst, dma_base + DMA_DESTINATION);
> > + writel(len, dma_base + DMA_FRAME_LEN);
> > + writel(frame_cnt, dma_base + DMA_FRAME_CNT);
> > +}
> > +
> > +static void owl_mmc_prepare_data(struct owl_mmc_priv *priv,
> > + struct mmc_data *data)
> > +{
> > + unsigned int reg, total;
> > + uint32_t buf = 0;
> > +
> > + reg = readl(priv->reg_base + OWL_REG_SD_EN);
> > + reg |= OWL_SD_EN_BSEL;
> > + writel(reg, priv->reg_base + OWL_REG_SD_EN);
> > +
> > + writel(data->blocks, priv->reg_base + OWL_REG_SD_BLK_NUM);
> > + writel(data->blocksize, priv->reg_base + OWL_REG_SD_BLK_SIZE);
> > + total = data->blocksize * data->blocks;
> > +
> > + if (data->blocksize < 512)
> > + writel(total, priv->reg_base + OWL_REG_SD_BUF_SIZE);
> > + else
> > + writel(512, priv->reg_base + OWL_REG_SD_BUF_SIZE);
>
> Is it right to set to 512?
>


> Actally, this is something picked from Linux driver as it.
>


> > +
> > + /* DMA STOP */
> > + writel(0x0, (DMA0_CHANNEL_BASE(2) + DMA_START));
> > +
> > + if (data) {
> > + if (data->flags == MMC_DATA_READ) {
> > + buf = (ulong) (data->dest);
> > + owl_dma_config((void *) DMA0_CHANNEL_BASE(2),
> > + priv->dma_drq,
> > + (ulong) priv->reg_base +
> > + OWL_REG_SD_DAT,
> > + buf, total);
> > + invalidate_dcache_range(buf, buf + total);
> > + } else if (data->flags == MMC_DATA_WRITE) {
>
> Not need to use "else if", because it shoud be MMC_DATA_WRITE.
>

Ok, I would remove this "else if" statement.

>
> > + buf = (ulong) (data->src);
> > + owl_dma_config((void *) DMA0_CHANNEL_BASE(2),
> > + priv->dma_drq,
> > + buf,
> > + (ulong) priv->reg_base +
> > + OWL_REG_SD_DAT,
> > + total);
> > + flush_dcache_range(buf, buf + total);
> > + }
> > + /* DMA START */
> > + writel(0x1, 

Re: [PATCH 5/6] mmc: actions: add MMC driver for Actions OWL S700

2020-12-14 Thread André Przywara
On 13/12/2020 10:08, Amit Singh Tomar wrote:
> From: Amit Singh Tomar 
> 
> This commit adds support for MMC controllers found on Actions OWL
> S700 SoC platform.
> 
> Signed-off-by: Amit Singh Tomar 
> ---
>  drivers/mmc/Kconfig   |   7 +
>  drivers/mmc/Makefile  |   1 +
>  drivers/mmc/owl_mmc.c | 404 
> ++
>  3 files changed, 412 insertions(+)
>  create mode 100644 drivers/mmc/owl_mmc.c
> 
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 14d7913..61f9c67 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -289,6 +289,13 @@ config MMC_MXC
>  
> If unsure, say N.
>  
> +config MMC_OWL
> + bool "Actions OWL Multimedia Card Interface support"
> + depends on ARCH_OWL && DM_MMC && BLK
> + help
> +   This selects the OWL SD/MMC host controller found on board
> +   based on Actions S700 SoC.
> +
>  config MMC_MXS
>   bool "Freescale MXS Multimedia Card Interface support"
>   depends on MX23 || MX28 || MX6 || MX7
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 1c849cb..f270f6c 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_MMC_OMAP_HS)   += omap_hsmmc.o
>  obj-$(CONFIG_MMC_MXC)+= mxcmmc.o
>  obj-$(CONFIG_MMC_MXS)+= mxsmmc.o
>  obj-$(CONFIG_MMC_OCTEONTX)   += octeontx_hsmmc.o
> +obj-$(CONFIG_MMC_OWL)+= owl_mmc.o
>  obj-$(CONFIG_MMC_PCI)+= pci_mmc.o
>  obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
>  obj-$(CONFIG_$(SPL_TPL_)SUPPORT_EMMC_RPMB) += rpmb.o
> diff --git a/drivers/mmc/owl_mmc.c b/drivers/mmc/owl_mmc.c
> new file mode 100644
> index 000..aa0ccb7
> --- /dev/null
> +++ b/drivers/mmc/owl_mmc.c
> @@ -0,0 +1,404 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2020 Amit Singh Tomar 
> + *
> + * Driver for SD/MMC controller present on Actions Semi S700 SoC, based
> + * on Linux Driver "drivers/mmc/host/owl-mmc.c".
> + *
> + * Though, there is a bit (BSEL, BUS or DMA Special Channel Selection) that
> + * controls the data transfer from SDx_DAT register either using CPU AHB Bus
> + * or DMA channel, but seems like, it only works correctly using external DMA
> + * channel, and those special bits used in this driver is picked from vendor
> + * source exclusively for MMC/SD.
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/*
> + * SDC registers
> + */
> +#define OWL_REG_SD_EN   0x
> +#define OWL_REG_SD_CTL  0x0004
> +#define OWL_REG_SD_STATE0x0008
> +#define OWL_REG_SD_CMD  0x000c
> +#define OWL_REG_SD_ARG  0x0010
> +#define OWL_REG_SD_RSPBUF0  0x0014
> +#define OWL_REG_SD_RSPBUF1  0x0018
> +#define OWL_REG_SD_RSPBUF2  0x001c
> +#define OWL_REG_SD_RSPBUF3  0x0020
> +#define OWL_REG_SD_RSPBUF4  0x0024
> +#define OWL_REG_SD_DAT  0x0028
> +#define OWL_REG_SD_BLK_SIZE 0x002c
> +#define OWL_REG_SD_BLK_NUM  0x0030
> +#define OWL_REG_SD_BUF_SIZE 0x0034
> +
> +/* SD_EN Bits */
> +#define OWL_SD_EN_RANE  BIT(31)
> +#define OWL_SD_EN_RESE  BIT(10)
> +#define OWL_SD_ENABLE   BIT(7)
> +#define OWL_SD_EN_BSEL  BIT(6)
> +#define OWL_SD_EN_DATAWID(x)(((x) & 0x3) << 0)
> +
> +/* SD_CTL Bits */
> +#define OWL_SD_CTL_TOUTEN   BIT(31)
> +#define OWL_SD_CTL_DELAY_MSKGENMASK(23, 16)
> +#define OWL_SD_CTL_RDELAY(x)(((x) & 0xf) << 20)
> +#define OWL_SD_CTL_WDELAY(x)(((x) & 0xf) << 16)
> +#define OWL_SD_CTL_TS   BIT(7)
> +#define OWL_SD_CTL_LBE  BIT(6)
> +#define OWL_SD_CTL_TM(x)(((x) & 0xf) << 0)
> +
> +#define OWL_SD_DELAY_LOW_CLK0x0f
> +#define OWL_SD_DELAY_MID_CLK0x0a
> +#define OWL_SD_RDELAY_HIGH   0x08
> +#define OWL_SD_WDELAY_HIGH   0x09
> +
> +/* SD_STATE Bits */
> +#define OWL_SD_STATE_CLNR   BIT(4)
> +#define OWL_SD_STATE_CRC7ER BIT(0)
> +#define OWL_SD_STATE_DAT0S  BIT(7)
> +
> +#define OWL_MMC_OCR (MMC_VDD_32_33 | MMC_VDD_33_34 | \
> +  MMC_VDD_165_195)
> +
> +#define DATA_TRANSFER_TIMEOUT(3 * (100 * 1000))
> +
> +/*
> + * Simple DMA transfer operations defines for MMC/SD card
> + */
> +#define DMA0_CHANNEL_BASE(x) (0xe0230100 + 0x100 * (x))
> +
> +#define DMA_MODE 0x
> +#define DMA_SOURCE   0x0004
> +#define DMA_DESTINATION  0x0008
> +#define DMA_FRAME_LEN0x000C
> +#define DMA_FRAME_CNT 

Re: [PATCH 5/6] mmc: actions: add MMC driver for Actions OWL S700

2020-12-13 Thread Jaehoon Chung
On 12/13/20 7:08 PM, Amit Singh Tomar wrote:
> From: Amit Singh Tomar 
> 
> This commit adds support for MMC controllers found on Actions OWL
> S700 SoC platform.
> 
> Signed-off-by: Amit Singh Tomar 
> ---
>  drivers/mmc/Kconfig   |   7 +
>  drivers/mmc/Makefile  |   1 +
>  drivers/mmc/owl_mmc.c | 404 
> ++
>  3 files changed, 412 insertions(+)
>  create mode 100644 drivers/mmc/owl_mmc.c
> 
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 14d7913..61f9c67 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -289,6 +289,13 @@ config MMC_MXC
>  
> If unsure, say N.
>  
> +config MMC_OWL
> + bool "Actions OWL Multimedia Card Interface support"
> + depends on ARCH_OWL && DM_MMC && BLK
> + help
> +   This selects the OWL SD/MMC host controller found on board
> +   based on Actions S700 SoC.
> +
>  config MMC_MXS
>   bool "Freescale MXS Multimedia Card Interface support"
>   depends on MX23 || MX28 || MX6 || MX7
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 1c849cb..f270f6c 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_MMC_OMAP_HS)   += omap_hsmmc.o
>  obj-$(CONFIG_MMC_MXC)+= mxcmmc.o
>  obj-$(CONFIG_MMC_MXS)+= mxsmmc.o
>  obj-$(CONFIG_MMC_OCTEONTX)   += octeontx_hsmmc.o
> +obj-$(CONFIG_MMC_OWL)+= owl_mmc.o
>  obj-$(CONFIG_MMC_PCI)+= pci_mmc.o
>  obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
>  obj-$(CONFIG_$(SPL_TPL_)SUPPORT_EMMC_RPMB) += rpmb.o
> diff --git a/drivers/mmc/owl_mmc.c b/drivers/mmc/owl_mmc.c
> new file mode 100644
> index 000..aa0ccb7
> --- /dev/null
> +++ b/drivers/mmc/owl_mmc.c
> @@ -0,0 +1,404 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2020 Amit Singh Tomar 
> + *
> + * Driver for SD/MMC controller present on Actions Semi S700 SoC, based
> + * on Linux Driver "drivers/mmc/host/owl-mmc.c".
> + *
> + * Though, there is a bit (BSEL, BUS or DMA Special Channel Selection) that
> + * controls the data transfer from SDx_DAT register either using CPU AHB Bus
> + * or DMA channel, but seems like, it only works correctly using external DMA
> + * channel, and those special bits used in this driver is picked from vendor
> + * source exclusively for MMC/SD.
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/*
> + * SDC registers
> + */
> +#define OWL_REG_SD_EN   0x
> +#define OWL_REG_SD_CTL  0x0004
> +#define OWL_REG_SD_STATE0x0008
> +#define OWL_REG_SD_CMD  0x000c
> +#define OWL_REG_SD_ARG  0x0010
> +#define OWL_REG_SD_RSPBUF0  0x0014
> +#define OWL_REG_SD_RSPBUF1  0x0018
> +#define OWL_REG_SD_RSPBUF2  0x001c
> +#define OWL_REG_SD_RSPBUF3  0x0020
> +#define OWL_REG_SD_RSPBUF4  0x0024
> +#define OWL_REG_SD_DAT  0x0028
> +#define OWL_REG_SD_BLK_SIZE 0x002c
> +#define OWL_REG_SD_BLK_NUM  0x0030
> +#define OWL_REG_SD_BUF_SIZE 0x0034
> +
> +/* SD_EN Bits */
> +#define OWL_SD_EN_RANE  BIT(31)
> +#define OWL_SD_EN_RESE  BIT(10)
> +#define OWL_SD_ENABLE   BIT(7)
> +#define OWL_SD_EN_BSEL  BIT(6)
> +#define OWL_SD_EN_DATAWID(x)(((x) & 0x3) << 0)
> +
> +/* SD_CTL Bits */
> +#define OWL_SD_CTL_TOUTEN   BIT(31)
> +#define OWL_SD_CTL_DELAY_MSKGENMASK(23, 16)
> +#define OWL_SD_CTL_RDELAY(x)(((x) & 0xf) << 20)
> +#define OWL_SD_CTL_WDELAY(x)(((x) & 0xf) << 16)
> +#define OWL_SD_CTL_TS   BIT(7)
> +#define OWL_SD_CTL_LBE  BIT(6)
> +#define OWL_SD_CTL_TM(x)(((x) & 0xf) << 0)
> +
> +#define OWL_SD_DELAY_LOW_CLK0x0f
> +#define OWL_SD_DELAY_MID_CLK0x0a
> +#define OWL_SD_RDELAY_HIGH   0x08
> +#define OWL_SD_WDELAY_HIGH   0x09
> +
> +/* SD_STATE Bits */
> +#define OWL_SD_STATE_CLNR   BIT(4)
> +#define OWL_SD_STATE_CRC7ER BIT(0)
> +#define OWL_SD_STATE_DAT0S  BIT(7)

Order to the bit number.

> +
> +#define OWL_MMC_OCR (MMC_VDD_32_33 | MMC_VDD_33_34 | \
> +  MMC_VDD_165_195)
> +
> +#define DATA_TRANSFER_TIMEOUT(3 * (100 * 1000))

Really need to set 30?

> +
> +/*
> + * Simple DMA transfer operations defines for MMC/SD card
> + */
> +#define DMA0_CHANNEL_BASE(x) (0xe0230100 + 0x100 * (x))

What is 0xe0230100?

> +
> +#define DMA_MODE 0x
> +#define DMA_SOURCE   0x0004
> +#define DMA_DESTINATION  0x0008
> +#define 

[PATCH 5/6] mmc: actions: add MMC driver for Actions OWL S700

2020-12-13 Thread Amit Singh Tomar
From: Amit Singh Tomar 

This commit adds support for MMC controllers found on Actions OWL
S700 SoC platform.

Signed-off-by: Amit Singh Tomar 
---
 drivers/mmc/Kconfig   |   7 +
 drivers/mmc/Makefile  |   1 +
 drivers/mmc/owl_mmc.c | 404 ++
 3 files changed, 412 insertions(+)
 create mode 100644 drivers/mmc/owl_mmc.c

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 14d7913..61f9c67 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -289,6 +289,13 @@ config MMC_MXC
 
  If unsure, say N.
 
+config MMC_OWL
+   bool "Actions OWL Multimedia Card Interface support"
+   depends on ARCH_OWL && DM_MMC && BLK
+   help
+ This selects the OWL SD/MMC host controller found on board
+ based on Actions S700 SoC.
+
 config MMC_MXS
bool "Freescale MXS Multimedia Card Interface support"
depends on MX23 || MX28 || MX6 || MX7
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 1c849cb..f270f6c 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
 obj-$(CONFIG_MMC_MXC)  += mxcmmc.o
 obj-$(CONFIG_MMC_MXS)  += mxsmmc.o
 obj-$(CONFIG_MMC_OCTEONTX) += octeontx_hsmmc.o
+obj-$(CONFIG_MMC_OWL)  += owl_mmc.o
 obj-$(CONFIG_MMC_PCI)  += pci_mmc.o
 obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
 obj-$(CONFIG_$(SPL_TPL_)SUPPORT_EMMC_RPMB) += rpmb.o
diff --git a/drivers/mmc/owl_mmc.c b/drivers/mmc/owl_mmc.c
new file mode 100644
index 000..aa0ccb7
--- /dev/null
+++ b/drivers/mmc/owl_mmc.c
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Amit Singh Tomar 
+ *
+ * Driver for SD/MMC controller present on Actions Semi S700 SoC, based
+ * on Linux Driver "drivers/mmc/host/owl-mmc.c".
+ *
+ * Though, there is a bit (BSEL, BUS or DMA Special Channel Selection) that
+ * controls the data transfer from SDx_DAT register either using CPU AHB Bus
+ * or DMA channel, but seems like, it only works correctly using external DMA
+ * channel, and those special bits used in this driver is picked from vendor
+ * source exclusively for MMC/SD.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * SDC registers
+ */
+#define OWL_REG_SD_EN   0x
+#define OWL_REG_SD_CTL  0x0004
+#define OWL_REG_SD_STATE0x0008
+#define OWL_REG_SD_CMD  0x000c
+#define OWL_REG_SD_ARG  0x0010
+#define OWL_REG_SD_RSPBUF0  0x0014
+#define OWL_REG_SD_RSPBUF1  0x0018
+#define OWL_REG_SD_RSPBUF2  0x001c
+#define OWL_REG_SD_RSPBUF3  0x0020
+#define OWL_REG_SD_RSPBUF4  0x0024
+#define OWL_REG_SD_DAT  0x0028
+#define OWL_REG_SD_BLK_SIZE 0x002c
+#define OWL_REG_SD_BLK_NUM  0x0030
+#define OWL_REG_SD_BUF_SIZE 0x0034
+
+/* SD_EN Bits */
+#define OWL_SD_EN_RANE  BIT(31)
+#define OWL_SD_EN_RESE  BIT(10)
+#define OWL_SD_ENABLE   BIT(7)
+#define OWL_SD_EN_BSEL  BIT(6)
+#define OWL_SD_EN_DATAWID(x)(((x) & 0x3) << 0)
+
+/* SD_CTL Bits */
+#define OWL_SD_CTL_TOUTEN   BIT(31)
+#define OWL_SD_CTL_DELAY_MSKGENMASK(23, 16)
+#define OWL_SD_CTL_RDELAY(x)(((x) & 0xf) << 20)
+#define OWL_SD_CTL_WDELAY(x)(((x) & 0xf) << 16)
+#define OWL_SD_CTL_TS   BIT(7)
+#define OWL_SD_CTL_LBE  BIT(6)
+#define OWL_SD_CTL_TM(x)(((x) & 0xf) << 0)
+
+#define OWL_SD_DELAY_LOW_CLK0x0f
+#define OWL_SD_DELAY_MID_CLK0x0a
+#define OWL_SD_RDELAY_HIGH 0x08
+#define OWL_SD_WDELAY_HIGH 0x09
+
+/* SD_STATE Bits */
+#define OWL_SD_STATE_CLNR   BIT(4)
+#define OWL_SD_STATE_CRC7ER BIT(0)
+#define OWL_SD_STATE_DAT0S  BIT(7)
+
+#define OWL_MMC_OCR (MMC_VDD_32_33 | MMC_VDD_33_34 | \
+MMC_VDD_165_195)
+
+#define DATA_TRANSFER_TIMEOUT  (3 * (100 * 1000))
+
+/*
+ * Simple DMA transfer operations defines for MMC/SD card
+ */
+#define DMA0_CHANNEL_BASE(x)   (0xe0230100 + 0x100 * (x))
+
+#define DMA_MODE   0x
+#define DMA_SOURCE 0x0004
+#define DMA_DESTINATION0x0008
+#define DMA_FRAME_LEN  0x000C
+#define DMA_FRAME_CNT  0x0010
+#define DMA_START  0x0024
+
+/* DMAx_MODE */
+#define DMA_MODE_ST(x)  (((x) & 0x3) << 8)
+#define DMA_MODE_ST_DEV DMA_MODE_ST(0)
+#define DMA_MODE_DT(x)  (((x) & 0x3) << 10)
+#define DMA_MODE_DT_DCU DMA_MODE_DT(2)
+#define