static struct wl12xx_platform_data *get_platform_data(struct device *dev) { struct wl12xx_platform_data *pdata; struct device_node __maybe_unused *np; pdata = wl12xx_get_platform_data(); if (!IS_ERR(pdata)) return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL); #ifdef CONFIG_OF /* first, try looking for "upstream" dt */ pdata = wlcore_probe_of(dev); if (pdata) return pdata; /* if not found, look for our deprecated dt */ np = of_find_matching_node(NULL, wlcore_of_match); if (!np) { dev_err(dev, "No platform data set\n"); return NULL; } pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) { dev_err(dev, "Can't allocate platform data\n"); return NULL; } if (of_property_read_u32(np, "irq", &pdata->irq)) { u32 gpio; if (!of_property_read_u32(np, "gpio", &gpio) && !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) pdata->gpio = gpio; } /* Optional fields */ pdata->use_eeprom = of_property_read_bool(np, "use-eeprom"); of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock); of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock); of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks); #endif if (IS_ERR(pdata)) return NULL; return pdata; }
static int wl1271_probe(struct spi_device *spi) { struct wl12xx_spi_glue *glue; struct wlcore_platdev_data *pdev_data; struct resource res[1]; int ret; pdev_data = devm_kzalloc(&spi->dev, sizeof(*pdev_data), GFP_KERNEL); if (!pdev_data) return -ENOMEM; pdev_data->if_ops = &spi_ops; glue = devm_kzalloc(&spi->dev, sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(&spi->dev, "can't allocate glue\n"); return -ENOMEM; } glue->dev = &spi->dev; spi_set_drvdata(spi, glue); /* This is the only SPI value that we need to set here, the rest * comes from the board-peripherals file */ spi->bits_per_word = 32; glue->reg = devm_regulator_get(&spi->dev, "vwlan"); if (PTR_ERR(glue->reg) == -EPROBE_DEFER) return -EPROBE_DEFER; if (IS_ERR(glue->reg)) { dev_err(glue->dev, "can't get regulator\n"); return PTR_ERR(glue->reg); } ret = wlcore_probe_of(spi, glue, pdev_data); if (ret) { dev_err(glue->dev, "can't get device tree parameters (%d)\n", ret); return ret; } ret = spi_setup(spi); if (ret < 0) { dev_err(glue->dev, "spi_setup failed\n"); return ret; } glue->core = platform_device_alloc(pdev_data->family->name, PLATFORM_DEVID_AUTO); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device\n"); return -ENOMEM; } glue->core->dev.parent = &spi->dev; memset(res, 0x00, sizeof(res)); res[0].start = spi->irq; res[0].flags = IORESOURCE_IRQ | irq_get_trigger_type(spi->irq); res[0].name = "irq"; ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); if (ret) { dev_err(glue->dev, "can't add resources\n"); goto out_dev_put; } ret = platform_device_add_data(glue->core, pdev_data, sizeof(*pdev_data)); if (ret) { dev_err(glue->dev, "can't add platform data\n"); goto out_dev_put; } ret = platform_device_add(glue->core); if (ret) { dev_err(glue->dev, "can't register platform device\n"); goto out_dev_put; } return 0; out_dev_put: platform_device_put(glue->core); return ret; }
static int wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { struct wlcore_platdev_data *pdev_data; struct wl12xx_sdio_glue *glue; struct resource res[2]; mmc_pm_flag_t mmcflags; int ret = -ENOMEM; int irq, wakeirq, num_irqs; const char *chip_family; /* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV; pdev_data = devm_kzalloc(&func->dev, sizeof(*pdev_data), GFP_KERNEL); if (!pdev_data) return -ENOMEM; pdev_data->if_ops = &sdio_ops; glue = devm_kzalloc(&func->dev, sizeof(*glue), GFP_KERNEL); if (!glue) return -ENOMEM; glue->dev = &func->dev; /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; /* Use block mode for transferring over one block size of data */ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; ret = wlcore_probe_of(&func->dev, &irq, &wakeirq, pdev_data); if (ret) goto out; /* if sdio can keep power while host is suspended, enable wow */ mmcflags = sdio_get_host_pm_caps(func); dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags); if (mmcflags & MMC_PM_KEEP_POWER) pdev_data->pwr_in_suspend = true; sdio_set_drvdata(func, glue); /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); /* * Due to a hardware bug, we can't differentiate wl18xx from * wl12xx, because both report the same device ID. The only * way to differentiate is by checking the SDIO revision, * which is 3.00 on the wl18xx chips. */ if (func->card->cccr.sdio_vsn == SDIO_SDIO_REV_3_00) chip_family = "wl18xx"; else chip_family = "wl12xx"; glue->core = platform_device_alloc(chip_family, PLATFORM_DEVID_AUTO); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device"); ret = -ENOMEM; goto out; } glue->core->dev.parent = &func->dev; memset(res, 0x00, sizeof(res)); res[0].start = irq; res[0].flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq)); res[0].name = "irq"; if (wakeirq > 0) { res[1].start = wakeirq; res[1].flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(wakeirq)); res[1].name = "wakeirq"; num_irqs = 2; } else { num_irqs = 1; } ret = platform_device_add_resources(glue->core, res, num_irqs); if (ret) { dev_err(glue->dev, "can't add resources\n"); goto out_dev_put; } ret = platform_device_add_data(glue->core, pdev_data, sizeof(*pdev_data)); if (ret) { dev_err(glue->dev, "can't add platform data\n"); goto out_dev_put; } ret = platform_device_add(glue->core); if (ret) { dev_err(glue->dev, "can't add platform device\n"); goto out_dev_put; } return 0; out_dev_put: platform_device_put(glue->core); out: return ret; }