On 19 September 2012 19:09, Seungwon Jeon <tgih.jun@xxxxxxxxxxx> wrote: > 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 . The placement of device tree related code is considering the logical structure and flow of the code. So maybe we can just retain the below code here for now. > >> +#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. I have checked again in mmc-next branch and "init" is still there. Thanks, Thomas. > > 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