On 28 September 2015 at 08:35, Yangbo Lu <[email protected]> wrote:
> To support little endian eSDHC controller, we redefine both BE and
> LE IO accessors. In the new accessors, use ioread*/iowrite* instead
> of in_be32/out_be32 and will select accessors according to endian
> mode in probe function.
>
> Signed-off-by: Yangbo Lu <[email protected]>
> ---
It's good practice to provide the reviewers with some history of what
has been changed between each revision. Can you please add that future
wise.
> drivers/mmc/host/sdhci-esdhc.h | 2 +
> drivers/mmc/host/sdhci-of-esdhc.c | 436
> ++++++++++++++++++++++++++++----------
> 2 files changed, 324 insertions(+), 114 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
> index 163ac99..de132e2 100644
> --- a/drivers/mmc/host/sdhci-esdhc.h
> +++ b/drivers/mmc/host/sdhci-esdhc.h
> @@ -24,6 +24,8 @@
> SDHCI_QUIRK_PIO_NEEDS_DELAY | \
> SDHCI_QUIRK_NO_HISPD_BIT)
>
> +#define ESDHC_PROCTL 0x28
> +
> #define ESDHC_SYSTEM_CONTROL 0x2c
> #define ESDHC_CLOCK_MASK 0x0000fff0
> #define ESDHC_PREDIV_SHIFT 8
> diff --git a/drivers/mmc/host/sdhci-of-esdhc.c
> b/drivers/mmc/host/sdhci-of-esdhc.c
> index 2a54dbe..5315864 100644
> --- a/drivers/mmc/host/sdhci-of-esdhc.c
> +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> @@ -18,128 +18,326 @@
> #include <linux/of.h>
> #include <linux/delay.h>
> #include <linux/module.h>
> +#include <linux/slab.h>
> #include <linux/mmc/host.h>
> #include "sdhci-pltfm.h"
> #include "sdhci-esdhc.h"
>
> #define VENDOR_V_22 0x12
> #define VENDOR_V_23 0x13
> -static u32 esdhc_readl(struct sdhci_host *host, int reg)
> +
> +struct esdhc_host {
> + u8 vendor_ver;
> + u8 spec_ver;
> + u16 xfer_mode_shadow;
> + struct sdhci_host *host;
> +};
> +
> +static struct esdhc_host *esdhc;
This looks wrong, you shouldn't have a global variable for this.
Instead, I think you shall allocate one per device/host.
> +
> +/**
> + * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register
> + * to make it compatible with SD spec.
> + *
> + * @esdhc: pointer to esdhc_host
> + * @spec_reg: SD spec register address
> + * @value: 32bit eSDHC register value on spec_reg address
> + *
> + * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC
> + * registers are 32 bits. There are differences in register size, register
> + * address, register function, bit position and function between eSDHC spec
> + * and SD spec.
> + *
> + * Return a fixed up register value
> + */
> +static u32 esdhc_readl_fixup(struct esdhc_host *esdhc,
> + int spec_reg, u32 value)
> {
> u32 ret;
>
> - ret = in_be32(host->ioaddr + reg);
> /*
> * The bit of ADMA flag in eSDHC is not compatible with standard
> * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
> * supported by eSDHC.
> * And for many FSL eSDHC controller, the reset value of field
> - * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA,
> + * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA,
> * only these vendor version is greater than 2.2/0x12 support ADMA.
> - * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
> - * the verdor version number, oxFE is SDHCI_HOST_VERSION.
> */
> - if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) {
> - u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
> - tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
> - if (tmp > VENDOR_V_22)
> - ret |= SDHCI_CAN_DO_ADMA2;
> + if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1))
> {
> + if (esdhc->vendor_ver > VENDOR_V_22) {
> + ret = value | SDHCI_CAN_DO_ADMA2;
> + return ret;
> + }
> }
> -
> + ret = value;
> return ret;
> }
>
> -static u16 esdhc_readw(struct sdhci_host *host, int reg)
> +static u16 esdhc_readw_fixup(struct esdhc_host *esdhc,
> + int spec_reg, u32 value)
> {
> u16 ret;
> - int base = reg & ~0x3;
> - int shift = (reg & 0x2) * 8;
> + int shift = (spec_reg & 0x2) * 8;
>
> - if (unlikely(reg == SDHCI_HOST_VERSION))
> - ret = in_be32(host->ioaddr + base) & 0xffff;
> + if (spec_reg == SDHCI_HOST_VERSION)
> + ret = value & 0xffff;
> else
> - ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff;
> + ret = (value >> shift) & 0xffff;
> return ret;
> }
>
> -static u8 esdhc_readb(struct sdhci_host *host, int reg)
> +static u8 esdhc_readb_fixup(struct esdhc_host *esdhc,
> + int spec_reg, u32 value)
> {
> - int base = reg & ~0x3;
> - int shift = (reg & 0x3) * 8;
> - u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
> + u8 ret;
> + u8 dma_bits;
> + int shift = (spec_reg & 0x3) * 8;
> +
> + ret = (value >> shift) & 0xff;
>
> /*
> * "DMA select" locates at offset 0x28 in SD specification, but on
> * P5020 or P3041, it locates at 0x29.
> */
> - if (reg == SDHCI_HOST_CONTROL) {
> - u32 dma_bits;
> -
> - dma_bits = in_be32(host->ioaddr + reg);
> + if (spec_reg == SDHCI_HOST_CONTROL) {
> /* DMA select is 22,23 bits in Protocol Control Register */
> - dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK;
> -
> + dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK;
> /* fixup the result */
> ret &= ~SDHCI_CTRL_DMA_MASK;
> ret |= dma_bits;
> }
> -
> return ret;
> }
>
> -static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
> +/**
> + * esdhc_write*_fixup - Fixup the SD spec register value so that it could be
> + * written into eSDHC register.
> + *
> + * @esdhc: pointer to esdhc_host
> + * @spec_reg: SD spec register address
> + * @value: 8/16/32bit SD spec register value that would be written
> + * @old_value: 32bit eSDHC register value on spec_reg address
> + *
> + * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC
> + * registers are 32 bits. There are differences in register size, register
> + * address, register function, bit position and function between eSDHC spec
> + * and SD spec.
> + *
> + * Return a fixed up register value
> + */
> +static u32 esdhc_writel_fixup(struct esdhc_host *esdhc,
> + int spec_reg, u32 value, u32 old_value)
> {
> + u32 ret;
> +
> /*
> - * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
> - * when SYSCTL[RSTD]) is set for some special operations.
> - * No any impact other operation.
> + * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
> + * when SYSCTL[RSTD] is set for some special operations.
> + * No any impact on other operation.
> */
> - if (reg == SDHCI_INT_ENABLE)
> - val |= SDHCI_INT_BLK_GAP;
> - sdhci_be32bs_writel(host, val, reg);
> + if (spec_reg == SDHCI_INT_ENABLE)
> + ret = value | SDHCI_INT_BLK_GAP;
> + else
> + ret = value;
> +
> + return ret;
> }
>
> -static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
> +static u32 esdhc_writew_fixup(struct esdhc_host *esdhc,
> + int spec_reg, u16 value, u32 old_value)
> {
> - if (reg == SDHCI_BLOCK_SIZE) {
> + u32 ret;
> + int shift = (spec_reg & 0x2) * 8;
> +
> + switch (spec_reg) {
> + case SDHCI_TRANSFER_MODE:
> + /*
> + * Postpone this write, we must do it together with a
> + * command write that is down below. Return old value.
> + */
> + esdhc->xfer_mode_shadow = value;
> + return old_value;
> + case SDHCI_COMMAND:
> + ret = (value << 16) | esdhc->xfer_mode_shadow;
> + return ret;
> + }
> +
> + ret = old_value & (~(0xffff << shift));
> + ret |= (value << shift);
> +
> + if (spec_reg == SDHCI_BLOCK_SIZE) {
> /*
> * Two last DMA bits are reserved, and first one is used for
> * non-standard blksz of 4096 bytes that we don't support
> * yet. So clear the DMA boundary bits.
> */
> - val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
> + ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0));
> }
> - sdhci_be32bs_writew(host, val, reg);
> + return ret;
> }
>
> -static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
> +static u32 esdhc_writeb_fixup(struct esdhc_host *esdhc,
> + int spec_reg, u8 value, u32 old_value)
> {
> + u32 ret;
> + u32 dma_bits;
> + u8 tmp;
> + int shift = (spec_reg & 0x3) * 8;
> +
> /*
> * "DMA select" location is offset 0x28 in SD specification, but on
> * P5020 or P3041, it's located at 0x29.
> */
> - if (reg == SDHCI_HOST_CONTROL) {
> - u32 dma_bits;
> -
> + if (spec_reg == SDHCI_HOST_CONTROL) {
> /*
> * If host control register is not standard, exit
> * this function
> */
> - if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL)
> - return;
> + if (esdhc->host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL)
> + return old_value;
>
> /* DMA select is 22,23 bits in Protocol Control Register */
> - dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5;
> - clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5,
> - dma_bits);
> - val &= ~SDHCI_CTRL_DMA_MASK;
> - val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK;
> + dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5;
> + ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits;
> + tmp = (value & (~SDHCI_CTRL_DMA_MASK)) |
> + (old_value & SDHCI_CTRL_DMA_MASK);
> + ret = (ret & (~0xff)) | tmp;
> +
> + /* Prevent SDHCI core from writing reserved bits (e.g. HISPD)
> */
> + ret &= ~ESDHC_HOST_CONTROL_RES;
> + return ret;
> }
>
> - /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
> - if (reg == SDHCI_HOST_CONTROL)
> - val &= ~ESDHC_HOST_CONTROL_RES;
> - sdhci_be32bs_writeb(host, val, reg);
> + ret = (old_value & (~(0xff << shift))) | (value << shift);
> + return ret;
> +}
> +
> +static u32 esdhc_be_readl(struct sdhci_host *host, int reg)
> +{
> + u32 ret;
> + u32 value;
> +
> + value = ioread32be(host->ioaddr + reg);
> + ret = esdhc_readl_fixup(esdhc, reg, value);
> +
> + return ret;
> +}
> +
> +static u32 esdhc_le_readl(struct sdhci_host *host, int reg)
> +{
> + u32 ret;
> + u32 value;
> +
> + value = ioread32(host->ioaddr + reg);
> + ret = esdhc_readl_fixup(esdhc, reg, value);
> +
> + return ret;
> +}
> +
> +static u16 esdhc_be_readw(struct sdhci_host *host, int reg)
> +{
> + u16 ret;
> + u32 value;
> + int base = reg & ~0x3;
> +
> + value = ioread32be(host->ioaddr + base);
> + ret = esdhc_readw_fixup(esdhc, reg, value);
> + return ret;
> +}
> +
> +static u16 esdhc_le_readw(struct sdhci_host *host, int reg)
> +{
> + u16 ret;
> + u32 value;
> + int base = reg & ~0x3;
> +
> + value = ioread32(host->ioaddr + base);
> + ret = esdhc_readw_fixup(esdhc, reg, value);
> + return ret;
> +}
> +
> +static u8 esdhc_be_readb(struct sdhci_host *host, int reg)
> +{
> + u8 ret;
> + u32 value;
> + int base = reg & ~0x3;
> +
> + value = ioread32be(host->ioaddr + base);
> + ret = esdhc_readb_fixup(esdhc, reg, value);
> + return ret;
> +}
> +
> +static u8 esdhc_le_readb(struct sdhci_host *host, int reg)
> +{
> + u8 ret;
> + u32 value;
> + int base = reg & ~0x3;
> +
> + value = ioread32(host->ioaddr + base);
> + ret = esdhc_readb_fixup(esdhc, reg, value);
> + return ret;
> +}
> +
> +static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg)
> +{
> + u32 value;
> +
> + value = esdhc_writel_fixup(esdhc, reg, val, 0);
> + iowrite32be(value, host->ioaddr + reg);
> +}
> +
> +static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg)
> +{
> + u32 value;
> +
> + value = esdhc_writel_fixup(esdhc, reg, val, 0);
> + iowrite32(value, host->ioaddr + reg);
> +}
> +
> +static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg)
> +{
> + int base = reg & ~0x3;
> + u32 value;
> + u32 ret;
> +
> + value = ioread32be(host->ioaddr + base);
> + ret = esdhc_writew_fixup(esdhc, reg, val, value);
> + if (reg != SDHCI_TRANSFER_MODE)
> + iowrite32be(ret, host->ioaddr + base);
> +}
> +
> +static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg)
> +{
> + int base = reg & ~0x3;
> + u32 value;
> + u32 ret;
> +
> + value = ioread32(host->ioaddr + base);
> + ret = esdhc_writew_fixup(esdhc, reg, val, value);
> + if (reg != SDHCI_TRANSFER_MODE)
> + iowrite32(ret, host->ioaddr + base);
> +}
> +
> +static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg)
> +{
> + int base = reg & ~0x3;
> + u32 value;
> + u32 ret;
> +
> + value = ioread32be(host->ioaddr + base);
> + ret = esdhc_writeb_fixup(esdhc, reg, val, value);
> + iowrite32be(ret, host->ioaddr + base);
> +}
> +
> +static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg)
> +{
> + int base = reg & ~0x3;
> + u32 value;
> + u32 ret;
> +
> + value = ioread32(host->ioaddr + base);
> + ret = esdhc_writeb_fixup(esdhc, reg, val, value);
> + iowrite32(ret, host->ioaddr + base);
> }
>
> /*
> @@ -149,19 +347,15 @@ static void esdhc_writeb(struct sdhci_host *host, u8
> val, int reg)
> * For Continue, apply soft reset for data(SYSCTL[RSTD]);
> * and re-issue the entire read transaction from beginning.
> */
> -static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
> +static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask)
> {
> - u32 tmp;
> bool applicable;
> dma_addr_t dmastart;
> dma_addr_t dmanow;
>
> - tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
> - tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
> -
> applicable = (intmask & SDHCI_INT_DATA_END) &&
> - (intmask & SDHCI_INT_BLK_GAP) &&
> - (tmp == VENDOR_V_23);
> + (intmask & SDHCI_INT_BLK_GAP) &&
> + (esdhc->vendor_ver == VENDOR_V_23);
> if (!applicable)
> return;
>
> @@ -179,7 +373,11 @@ static void esdhci_of_adma_workaround(struct sdhci_host
> *host, u32 intmask)
>
> static int esdhc_of_enable_dma(struct sdhci_host *host)
> {
> - setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
> + u32 value;
> +
> + value = sdhci_readl(host, ESDHC_DMA_SYSCTL);
> + value |= ESDHC_DMA_SNOOP;
> + sdhci_writel(host, value, ESDHC_DMA_SYSCTL);
> return 0;
> }
>
> @@ -209,9 +407,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host,
> unsigned int clock)
> return;
>
> /* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */
> - temp = esdhc_readw(host, SDHCI_HOST_VERSION);
> - temp = (temp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
> - if (temp < VENDOR_V_23)
> + if (esdhc->vendor_ver < VENDOR_V_23)
> pre_div = 2;
>
> /* Workaround to reduce the clock frequency for p1010 esdhc */
> @@ -247,39 +443,26 @@ static void esdhc_of_set_clock(struct sdhci_host *host,
> unsigned int clock)
> mdelay(1);
> }
>
> -static void esdhc_of_platform_init(struct sdhci_host *host)
> -{
> - u32 vvn;
> -
> - vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
> - vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
> - if (vvn == VENDOR_V_22)
> - host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
> -
> - if (vvn > VENDOR_V_22)
> - host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
> -}
> -
> static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
> {
> u32 ctrl;
>
> + ctrl = sdhci_readl(host, ESDHC_PROCTL);
> + ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK);
> switch (width) {
> case MMC_BUS_WIDTH_8:
> - ctrl = ESDHC_CTRL_8BITBUS;
> + ctrl |= ESDHC_CTRL_8BITBUS;
> break;
>
> case MMC_BUS_WIDTH_4:
> - ctrl = ESDHC_CTRL_4BITBUS;
> + ctrl |= ESDHC_CTRL_4BITBUS;
> break;
>
> default:
> - ctrl = 0;
> break;
> }
>
> - clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
> - ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
> + sdhci_writel(host, ctrl, ESDHC_PROCTL);
> }
>
> static void esdhc_reset(struct sdhci_host *host, u8 mask)
> @@ -290,32 +473,13 @@ static void esdhc_reset(struct sdhci_host *host, u8
> mask)
> sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
> }
>
> -static const struct sdhci_ops sdhci_esdhc_ops = {
> - .read_l = esdhc_readl,
> - .read_w = esdhc_readw,
> - .read_b = esdhc_readb,
> - .write_l = esdhc_writel,
> - .write_w = esdhc_writew,
> - .write_b = esdhc_writeb,
> - .set_clock = esdhc_of_set_clock,
> - .enable_dma = esdhc_of_enable_dma,
> - .get_max_clock = esdhc_of_get_max_clock,
> - .get_min_clock = esdhc_of_get_min_clock,
> - .platform_init = esdhc_of_platform_init,
> - .adma_workaround = esdhci_of_adma_workaround,
> - .set_bus_width = esdhc_pltfm_set_bus_width,
> - .reset = esdhc_reset,
> - .set_uhs_signaling = sdhci_set_uhs_signaling,
> -};
> -
> #ifdef CONFIG_PM
> -
> static u32 esdhc_proctl;
> static int esdhc_of_suspend(struct device *dev)
> {
> struct sdhci_host *host = dev_get_drvdata(dev);
>
> - esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
> + esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL);
>
> return sdhci_suspend_host(host);
> }
> @@ -328,9 +492,8 @@ static int esdhc_of_resume(struct device *dev)
> if (ret == 0) {
> /* Isn't this already done by sdhci_resume_host() ? --rmk */
> esdhc_of_enable_dma(host);
> - sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
> + sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
> }
> -
> return ret;
> }
>
> @@ -343,16 +506,56 @@ static const struct dev_pm_ops esdhc_pmops = {
> #define ESDHC_PMOPS NULL
> #endif
>
> -static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
> - /*
> - * card detection could be handled via GPIO
> - * eSDHC cannot support End Attribute in NOP ADMA descriptor
> - */
> - .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
> - | SDHCI_QUIRK_NO_CARD_NO_RESET
> - | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
> - .ops = &sdhci_esdhc_ops,
> +static struct sdhci_ops sdhci_esdhc_ops = {
> + .set_clock = esdhc_of_set_clock,
> + .enable_dma = esdhc_of_enable_dma,
> + .get_max_clock = esdhc_of_get_max_clock,
> + .get_min_clock = esdhc_of_get_min_clock,
> + .adma_workaround = esdhc_of_adma_workaround,
> + .set_bus_width = esdhc_pltfm_set_bus_width,
> + .reset = esdhc_reset,
> + .set_uhs_signaling = sdhci_set_uhs_signaling,
> };
> +static struct sdhci_pltfm_data sdhci_esdhc_pdata;
> +
> +static void esdhc_setup_pltfm_data(struct platform_device *pdev)
> +{
> + struct device_node *np;
> +
> + np = pdev->dev.of_node;
> + if (of_get_property(np, "little-endian", NULL)) {
> + sdhci_esdhc_ops.read_l = esdhc_le_readl;
> + sdhci_esdhc_ops.read_w = esdhc_le_readw;
> + sdhci_esdhc_ops.read_b = esdhc_le_readb;
> + sdhci_esdhc_ops.write_l = esdhc_le_writel;
> + sdhci_esdhc_ops.write_w = esdhc_le_writew;
> + sdhci_esdhc_ops.write_b = esdhc_le_writeb;
> + } else {
> + sdhci_esdhc_ops.read_l = esdhc_be_readl;
> + sdhci_esdhc_ops.read_w = esdhc_be_readw;
> + sdhci_esdhc_ops.read_b = esdhc_be_readb;
> + sdhci_esdhc_ops.write_l = esdhc_be_writel;
> + sdhci_esdhc_ops.write_w = esdhc_be_writew;
> + sdhci_esdhc_ops.write_b = esdhc_be_writeb;
> + }
> +
> + sdhci_esdhc_pdata.quirks = ESDHC_DEFAULT_QUIRKS |
> + SDHCI_QUIRK_BROKEN_CARD_DETECTION |
> + SDHCI_QUIRK_NO_CARD_NO_RESET |
> + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
> + sdhci_esdhc_pdata.ops = &sdhci_esdhc_ops;
> +}
> +
> +static void esdhc_init(struct esdhc_host *esdhc, struct sdhci_host *host)
> +{
> + u16 host_ver;
> +
> + host_ver = sdhci_readw(host, SDHCI_HOST_VERSION);
> + esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
> + SDHCI_VENDOR_VER_SHIFT;
> + esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;
> + esdhc->host = host;
> +}
>
> static int sdhci_esdhc_probe(struct platform_device *pdev)
> {
> @@ -360,10 +563,15 @@ static int sdhci_esdhc_probe(struct platform_device
> *pdev)
> struct device_node *np;
> int ret;
>
> + esdhc_setup_pltfm_data(pdev);
> +
> host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
> if (IS_ERR(host))
> return PTR_ERR(host);
>
> + esdhc = kmalloc(sizeof(struct esdhc_host), GFP_KERNEL);
I think it's better to use devm_kzalloc(), thus you don't have to take
care of freeing data since that's handled automatically for the devm
APIs.
> + esdhc_init(esdhc, host);
> +
> sdhci_get_of_property(pdev);
>
> np = pdev->dev.of_node;
> --
> 2.1.0.27.g96db324
>
Kind regards
Uffe
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html