On 28 September 2015 at 08:35, Yangbo Lu <yangbo.lu@xxxxxxxxxxxxx> 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 <yangbo.lu@xxxxxxxxxxxxx> > --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html