示例#1
0
文件: sdio.c 项目: houlixin/BBB-TISDK
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;
}
示例#2
0
文件: spi.c 项目: AlexShiLucky/linux
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;
}
示例#3
0
文件: sdio.c 项目: AlexShiLucky/linux
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;
}