On Tuesday, September 18, 2012, Thomas Abraham <thomas.abraham@xxxxxxxxxx> wrote: > +#ifdef CONFIG_OF > +/* given a slot id, find out the device node representing that slot */ > +static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) > +{ > + struct device_node *np; > + const __be32 *addr; > + int len; > + > + if (!dev || !dev->of_node) > + return NULL; > + > + for_each_child_of_node(dev->of_node, np) { > + addr = of_get_property(np, "reg", &len); > + if (!addr || (len < sizeof(int))) > + continue; > + if (be32_to_cpup(addr) == slot) > + return np; > + } > + return NULL; > +} > + > +/* find out bus-width for a given slot */ > +static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) > +{ > + struct device_node *np = dw_mci_of_find_slot_node(dev, slot); > + u32 bus_wd = 1; > + > + if (!np) > + return 1; > + > + if (of_property_read_u32(np, "bus-width", &bus_wd)) > + dev_err(dev, "bus-width property not found, assuming width" > + " as 1\n"); > + return bus_wd; > +} > +#else /* CONFIG_OF */ > +static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) > +{ > + return 1; > +} > +static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) > +{ > + return NULL; > +} > +#endif /* CONFIG_OF */ > + > static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) > { > struct mmc_host *mmc; > struct dw_mci_slot *slot; > + u8 bus_width; > > mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); > if (!mmc) > @@ -1782,6 +1830,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) > slot->id = id; > slot->mmc = mmc; > slot->host = host; > + host->slot[id] = slot; > > mmc->ops = &dw_mci_ops; > mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); > @@ -1806,8 +1855,18 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) > mmc->caps2 = host->pdata->caps2; > > if (host->pdata->get_bus_wd) > - if (host->pdata->get_bus_wd(slot->id) >= 4) > - mmc->caps |= MMC_CAP_4_BIT_DATA; > + bus_width = host->pdata->get_bus_wd(slot->id); > + else if (host->dev->of_node) > + bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id); > + else > + bus_width = 1; > + > + switch (bus_width) { > + case 8: > + mmc->caps |= MMC_CAP_8_BIT_DATA; > + case 4: > + mmc->caps |= MMC_CAP_4_BIT_DATA; > + } > > if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) > mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; > @@ -1852,7 +1911,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) > else > clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); > > - host->slot[id] = slot; > mmc_add_host(mmc); > > #if defined(CONFIG_DEBUG_FS) > @@ -1944,16 +2002,74 @@ static bool mci_wait_reset(struct device *dev, struct dw_mci *host) > return false; > } > The following CONFIG_OF block can be put together in upper CONFIG_OF . > +#ifdef CONFIG_OF > +static struct dw_mci_of_quirks { > + char *quirk; > + int id; > +} of_quirks[] = { > + { > + .quirk = "supports-highspeed", > + .id = DW_MCI_QUIRK_HIGHSPEED, > + }, { > + .quirk = "broken-cd", > + .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, > + }, > +}; > + > +static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) > +{ > + struct dw_mci_board *pdata; > + struct device *dev = host->dev; > + struct device_node *np = dev->of_node; > + int idx; > + > + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); > + if (!pdata) { > + dev_err(dev, "could not allocate memory for pdata\n"); > + return ERR_PTR(-ENOMEM); > + } > + > + /* find out number of slots supported */ > + if (of_property_read_u32(dev->of_node, "num-slots", > + &pdata->num_slots)) { > + dev_info(dev, "num-slots property not found, " > + "assuming 1 slot is available\n"); > + pdata->num_slots = 1; > + } > + > + /* get quirks */ > + for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++) > + if (of_get_property(np, of_quirks[idx].quirk, NULL)) > + pdata->quirks |= of_quirks[idx].id; > + > + if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) > + dev_info(dev, "fifo-depth property not found, using " > + "value of FIFOTH register as default\n"); > + > + of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); > + > + return pdata; > +} > + > +#else /* CONFIG_OF */ > +static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) > +{ > + return ERR_PTR(-EINVAL); > +} > +#endif /* CONFIG_OF */ > + > int dw_mci_probe(struct dw_mci *host) > { > int width, i, ret = 0; > u32 fifo_size; > int init_slots = 0; > > - if (!host->pdata || !host->pdata->init) { "!host->pdata->init" is removed. Please check it. Thanks, Seungwon Jeon > - dev_err(host->dev, > - "Platform data must supply init function\n"); > - return -ENODEV; > + if (!host->pdata) { > + host->pdata = dw_mci_parse_dt(host); > + if (IS_ERR(host->pdata)) { > + dev_err(host->dev, "platform data not available\n"); > + return -EINVAL; > + } > } > > if (!host->pdata->select_slot && host->pdata->num_slots > 1) { > -- > 1.6.6.rc2 > > -- > 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