コード例 #1
0
ファイル: rfkill-gpio.c プロジェクト: a2hojsjsjs/linux
static int rfkill_gpio_probe(struct platform_device *pdev)
{
	struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
	struct rfkill_gpio_data *rfkill;
	struct gpio_desc *gpio;
	int ret;

	rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL);
	if (!rfkill)
		return -ENOMEM;

	if (ACPI_HANDLE(&pdev->dev)) {
		ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill);
		if (ret)
			return ret;
	} else if (pdata) {
		rfkill->name = pdata->name;
		rfkill->type = pdata->type;
	} else {
		return -ENODEV;
	}

	rfkill->clk = devm_clk_get(&pdev->dev, NULL);

	gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
	if (IS_ERR(gpio))
		return PTR_ERR(gpio);

	rfkill->reset_gpio = gpio;

	gpio = devm_gpiod_get_optional(&pdev->dev, "shutdown", GPIOD_OUT_LOW);
	if (IS_ERR(gpio))
		return PTR_ERR(gpio);

	rfkill->shutdown_gpio = gpio;

	/* Make sure at-least one of the GPIO is defined and that
	 * a name is specified for this instance
	 */
	if ((!rfkill->reset_gpio && !rfkill->shutdown_gpio) || !rfkill->name) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	rfkill->rfkill_dev = rfkill_alloc(rfkill->name, &pdev->dev,
					  rfkill->type, &rfkill_gpio_ops,
					  rfkill);
	if (!rfkill->rfkill_dev)
		return -ENOMEM;

	ret = rfkill_register(rfkill->rfkill_dev);
	if (ret < 0)
		return ret;

	platform_set_drvdata(pdev, rfkill);

	dev_info(&pdev->dev, "%s device registered.\n", rfkill->name);

	return 0;
}
コード例 #2
0
ファイル: sta350.c プロジェクト: Seagate/SMR_FS-EXT4
static int sta350_i2c_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	struct device *dev = &i2c->dev;
	struct sta350_priv *sta350;
	int ret, i;

	sta350 = devm_kzalloc(dev, sizeof(struct sta350_priv), GFP_KERNEL);
	if (!sta350)
		return -ENOMEM;

	mutex_init(&sta350->coeff_lock);
	sta350->pdata = dev_get_platdata(dev);

#ifdef CONFIG_OF
	if (dev->of_node) {
		ret = sta350_probe_dt(dev, sta350);
		if (ret < 0)
			return ret;
	}
#endif

	/* GPIOs */
	sta350->gpiod_nreset = devm_gpiod_get_optional(dev, "reset",
						       GPIOD_OUT_LOW);
	if (IS_ERR(sta350->gpiod_nreset))
		return PTR_ERR(sta350->gpiod_nreset);

	sta350->gpiod_power_down = devm_gpiod_get_optional(dev, "power-down",
							   GPIOD_OUT_LOW);
	if (IS_ERR(sta350->gpiod_power_down))
		return PTR_ERR(sta350->gpiod_power_down);

	/* regulators */
	for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++)
		sta350->supplies[i].supply = sta350_supply_names[i];

	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sta350->supplies),
				      sta350->supplies);
	if (ret < 0) {
		dev_err(dev, "Failed to request supplies: %d\n", ret);
		return ret;
	}

	sta350->regmap = devm_regmap_init_i2c(i2c, &sta350_regmap);
	if (IS_ERR(sta350->regmap)) {
		ret = PTR_ERR(sta350->regmap);
		dev_err(dev, "Failed to init regmap: %d\n", ret);
		return ret;
	}

	i2c_set_clientdata(i2c, sta350);

	ret = snd_soc_register_codec(dev, &sta350_codec, &sta350_dai, 1);
	if (ret < 0)
		dev_err(dev, "Failed to register codec (%d)\n", ret);

	return ret;
}
コード例 #3
0
ファイル: dwc3-pci.c プロジェクト: Lyude/linux
static int dwc3_pci_quirks(struct dwc3_pci *dwc)
{
	struct pci_dev			*pdev = dwc->pci;

	if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
		if (pdev->device == PCI_DEVICE_ID_INTEL_BXT ||
				pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) {
			guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid);
			dwc->has_dsm_for_pm = true;
		}

		if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
			struct gpio_desc *gpio;
			int ret;

			/* On BYT the FW does not always enable the refclock */
			ret = dwc3_byt_enable_ulpi_refclock(pdev);
			if (ret)
				return ret;

			ret = devm_acpi_dev_add_driver_gpios(&pdev->dev,
					acpi_dwc3_byt_gpios);
			if (ret)
				dev_dbg(&pdev->dev, "failed to add mapping table\n");

			/*
			 * A lot of BYT devices lack ACPI resource entries for
			 * the GPIOs, add a fallback mapping to the reference
			 * design GPIOs which all boards seem to use.
			 */
			gpiod_add_lookup_table(&platform_bytcr_gpios);

			/*
			 * These GPIOs will turn on the USB2 PHY. Note that we have to
			 * put the gpio descriptors again here because the phy driver
			 * might want to grab them, too.
			 */
			gpio = devm_gpiod_get_optional(&pdev->dev, "cs",
						       GPIOD_OUT_LOW);
			if (IS_ERR(gpio))
				return PTR_ERR(gpio);

			gpiod_set_value_cansleep(gpio, 1);

			gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
						       GPIOD_OUT_LOW);
			if (IS_ERR(gpio))
				return PTR_ERR(gpio);

			if (gpio) {
				gpiod_set_value_cansleep(gpio, 1);
				usleep_range(10000, 11000);
			}
		}
	}

	return 0;
}
コード例 #4
0
ファイル: phy-tusb1210.c プロジェクト: Lyude/linux
static int tusb1210_probe(struct ulpi *ulpi)
{
	struct tusb1210 *tusb;
	u8 val, reg;

	tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
	if (!tusb)
		return -ENOMEM;

	tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
						   GPIOD_OUT_LOW);
	if (IS_ERR(tusb->gpio_reset))
		return PTR_ERR(tusb->gpio_reset);

	gpiod_set_value_cansleep(tusb->gpio_reset, 1);

	tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
						GPIOD_OUT_LOW);
	if (IS_ERR(tusb->gpio_cs))
		return PTR_ERR(tusb->gpio_cs);

	gpiod_set_value_cansleep(tusb->gpio_cs, 1);

	/*
	 * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye
	 * diagram optimization and DP/DM swap.
	 */

	/* High speed output drive strength configuration */
	device_property_read_u8(&ulpi->dev, "ihstx", &val);
	reg = val << TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT;

	/* High speed output impedance configuration */
	device_property_read_u8(&ulpi->dev, "zhsdrv", &val);
	reg |= val << TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_SHIFT;

	/* DP/DM swap control */
	device_property_read_u8(&ulpi->dev, "datapolarity", &val);
	reg |= val << TUSB1210_VENDOR_SPECIFIC2_DP_SHIFT;

	if (reg) {
		ulpi_write(ulpi, TUSB1210_VENDOR_SPECIFIC2, reg);
		tusb->vendor_specific2 = reg;
	}

	tusb->phy = ulpi_phy_create(ulpi, &phy_ops);
	if (IS_ERR(tusb->phy))
		return PTR_ERR(tusb->phy);

	tusb->ulpi = ulpi;

	phy_set_drvdata(tusb->phy, tusb);
	ulpi_set_drvdata(ulpi, tusb);
	return 0;
}
コード例 #5
0
ファイル: panel-dpi.c プロジェクト: AK101111/linux
static int panel_dpi_probe_of(struct platform_device *pdev)
{
	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
	struct device_node *node = pdev->dev.of_node;
	struct omap_dss_device *in;
	int r;
	struct display_timing timing;
	struct videomode vm;
	struct gpio_desc *gpio;

	gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
	if (IS_ERR(gpio))
		return PTR_ERR(gpio);

	ddata->enable_gpio = gpio;

	/*
	 * Many different panels are supported by this driver and there are
	 * probably very different needs for their reset pins in regards to
	 * timing and order relative to the enable gpio. So for now it's just
	 * ensured that the reset line isn't active.
	 */
	gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
	if (IS_ERR(gpio))
		return PTR_ERR(gpio);

	ddata->vcc_supply = devm_regulator_get(&pdev->dev, "vcc");
	if (IS_ERR(ddata->vcc_supply))
		return PTR_ERR(ddata->vcc_supply);

	ddata->backlight_gpio = -ENOENT;

	r = of_get_display_timing(node, "panel-timing", &timing);
	if (r) {
		dev_err(&pdev->dev, "failed to get video timing\n");
		return r;
	}

	videomode_from_timing(&timing, &vm);
	videomode_to_omap_video_timings(&vm, &ddata->videomode);

	in = omapdss_of_find_source_for_first_ep(node);
	if (IS_ERR(in)) {
		dev_err(&pdev->dev, "failed to find video source\n");
		return PTR_ERR(in);
	}

	ddata->in = in;

	return 0;
}
コード例 #6
0
/* Return wake-up GPIO or NULL if sleep functionality should be disabled. */
static struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client)
{
	struct gpio_desc *gpio;

	if (!i2c_check_functionality(client->adapter,
						I2C_FUNC_SMBUS_WRITE_BYTE)) {
		dev_info(&client->dev,
			 "i2c adapter does not support SMBUS_WRITE_BYTE, sleep disabled");
		return NULL;
	}

	gpio = devm_gpiod_get_optional(&client->dev, "wakeup", GPIOD_IN);

	if (IS_ERR(gpio)) {
		dev_warn(&client->dev,
			 "gpio acquisition failed with error %ld, sleep disabled",
			 PTR_ERR(gpio));
		return NULL;
	} else if (!gpio) {
		dev_info(&client->dev,
			 "wakeup-gpio not found, sleep disabled");
	}

	return gpio;
}
コード例 #7
0
ファイル: pcm1789.c プロジェクト: the-snowwhite/linux-socfpga
int pcm1789_common_init(struct device *dev, struct regmap *regmap)
{
	struct pcm1789_private *pcm1789;

	pcm1789 = devm_kzalloc(dev, sizeof(struct pcm1789_private),
			       GFP_KERNEL);
	if (!pcm1789)
		return -ENOMEM;

	pcm1789->regmap = regmap;
	pcm1789->dev = dev;
	dev_set_drvdata(dev, pcm1789);

	pcm1789->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
	if (IS_ERR(pcm1789->reset))
		return PTR_ERR(pcm1789->reset);

	gpiod_set_value_cansleep(pcm1789->reset, 0);
	msleep(300);

	INIT_WORK(&pcm1789->work, pcm1789_work_queue);

	return devm_snd_soc_register_component(dev, &soc_component_dev_pcm1789,
					       &pcm1789_dai, 1);
}
コード例 #8
0
ファイル: ak5558.c プロジェクト: Lyude/linux
static int ak5558_i2c_probe(struct i2c_client *i2c)
{
	struct ak5558_priv *ak5558;
	int ret = 0;

	ak5558 = devm_kzalloc(&i2c->dev, sizeof(*ak5558), GFP_KERNEL);
	if (!ak5558)
		return -ENOMEM;

	ak5558->regmap = devm_regmap_init_i2c(i2c, &ak5558_regmap);
	if (IS_ERR(ak5558->regmap))
		return PTR_ERR(ak5558->regmap);

	i2c_set_clientdata(i2c, ak5558);
	ak5558->i2c = i2c;

	ak5558->reset_gpiod = devm_gpiod_get_optional(&i2c->dev, "reset",
						      GPIOD_OUT_LOW);
	if (IS_ERR(ak5558->reset_gpiod))
		return PTR_ERR(ak5558->reset_gpiod);

	ret = devm_snd_soc_register_component(&i2c->dev,
				     &soc_codec_dev_ak5558,
				     &ak5558_dai, 1);
	if (ret)
		return ret;

	pm_runtime_enable(&i2c->dev);

	return 0;
}
コード例 #9
0
ファイル: i2c-designware-master.c プロジェクト: avagin/linux
static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
{
	struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
	struct i2c_adapter *adap = &dev->adapter;
	struct gpio_desc *gpio;
	int r;

	gpio = devm_gpiod_get(dev->dev, "scl", GPIOD_OUT_HIGH);
	if (IS_ERR(gpio)) {
		r = PTR_ERR(gpio);
		if (r == -ENOENT || r == -ENOSYS)
			return 0;
		return r;
	}
	rinfo->scl_gpiod = gpio;

	gpio = devm_gpiod_get_optional(dev->dev, "sda", GPIOD_IN);
	if (IS_ERR(gpio))
		return PTR_ERR(gpio);
	rinfo->sda_gpiod = gpio;

	rinfo->recover_bus = i2c_generic_scl_recovery;
	rinfo->prepare_recovery = i2c_dw_prepare_recovery;
	rinfo->unprepare_recovery = i2c_dw_unprepare_recovery;
	adap->bus_recovery_info = rinfo;

	dev_info(dev->dev, "running with gpio recovery mode! scl%s",
		 rinfo->sda_gpiod ? ",sda" : "");

	return 0;
}
コード例 #10
0
static int silead_ts_probe(struct i2c_client *client,
			   const struct i2c_device_id *id)
{
	struct silead_ts_data *data;
	struct device *dev = &client->dev;
	int error;

	if (!i2c_check_functionality(client->adapter,
				     I2C_FUNC_I2C |
				     I2C_FUNC_SMBUS_READ_I2C_BLOCK |
				     I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
		dev_err(dev, "I2C functionality check failed\n");
		return -ENXIO;
	}

	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	i2c_set_clientdata(client, data);
	data->client = client;

	error = silead_ts_set_default_fw_name(data, id);
	if (error)
		return error;

	silead_ts_read_props(client);

	/* We must have the IRQ provided by DT or ACPI subsytem */
	if (client->irq <= 0)
		return -ENODEV;

	/* Power GPIO pin */
	data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
	if (IS_ERR(data->gpio_power)) {
		if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
			dev_err(dev, "Shutdown GPIO request failed\n");
		return PTR_ERR(data->gpio_power);
	}

	error = silead_ts_setup(client);
	if (error)
		return error;

	error = silead_ts_request_input_dev(data);
	if (error)
		return error;

	error = devm_request_threaded_irq(dev, client->irq,
					  NULL, silead_ts_threaded_irq_handler,
					  IRQF_ONESHOT, client->name, data);
	if (error) {
		if (error != -EPROBE_DEFER)
			dev_err(dev, "IRQ request failed %d\n", error);
		return error;
	}

	return 0;
}
コード例 #11
0
ファイル: isp1760-core.c プロジェクト: 020gzh/linux
int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
		     struct device *dev, unsigned int devflags)
{
	struct isp1760_device *isp;
	bool udc_disabled = !(devflags & ISP1760_FLAG_ISP1761);
	int ret;

	/*
	 * If neither the HCD not the UDC is enabled return an error, as no
	 * device would be registered.
	 */
	if ((!IS_ENABLED(CONFIG_USB_ISP1760_HCD) || usb_disabled()) &&
	    (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || udc_disabled))
		return -ENODEV;

	/* prevent usb-core allocating DMA pages */
	dev->dma_mask = NULL;

	isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL);
	if (!isp)
		return -ENOMEM;

	isp->dev = dev;
	isp->devflags = devflags;

	isp->rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH);
	if (IS_ERR(isp->rst_gpio))
		return PTR_ERR(isp->rst_gpio);

	isp->regs = devm_ioremap_resource(dev, mem);
	if (IS_ERR(isp->regs))
		return PTR_ERR(isp->regs);

	isp1760_init_core(isp);

	if (IS_ENABLED(CONFIG_USB_ISP1760_HCD) && !usb_disabled()) {
		ret = isp1760_hcd_register(&isp->hcd, isp->regs, mem, irq,
					   irqflags | IRQF_SHARED, dev);
		if (ret < 0)
			return ret;
	}

	if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && !udc_disabled) {
		ret = isp1760_udc_register(isp, irq, irqflags);
		if (ret < 0) {
			isp1760_hcd_unregister(&isp->hcd);
			return ret;
		}
	}

	dev_set_drvdata(dev, isp);

	return 0;
}
コード例 #12
0
ファイル: encoder-opa362.c プロジェクト: 020gzh/linux
static int opa362_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	struct panel_drv_data *ddata;
	struct omap_dss_device *dssdev, *in;
	struct gpio_desc *gpio;
	int r;

	dev_dbg(&pdev->dev, "probe\n");

	if (node == NULL) {
		dev_err(&pdev->dev, "Unable to find device tree\n");
		return -EINVAL;
	}

	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
	if (!ddata)
		return -ENOMEM;

	platform_set_drvdata(pdev, ddata);

	gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
	if (IS_ERR(gpio))
		return PTR_ERR(gpio);

	ddata->enable_gpio = gpio;

	in = omapdss_of_find_source_for_first_ep(node);
	if (IS_ERR(in)) {
		dev_err(&pdev->dev, "failed to find video source\n");
		return PTR_ERR(in);
	}

	ddata->in = in;

	dssdev = &ddata->dssdev;
	dssdev->ops.atv = &opa362_atv_ops;
	dssdev->dev = &pdev->dev;
	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
	dssdev->output_type = OMAP_DISPLAY_TYPE_VENC;
	dssdev->owner = THIS_MODULE;

	r = omapdss_register_output(dssdev);
	if (r) {
		dev_err(&pdev->dev, "Failed to register output\n");
		goto err_reg;
	}

	return 0;
err_reg:
	omap_dss_put_device(ddata->in);
	return r;
}
コード例 #13
0
ファイル: connector-hdmi.c プロジェクト: avagin/linux
static int hdmic_probe(struct platform_device *pdev)
{
	struct panel_drv_data *ddata;
	struct omap_dss_device *dssdev;
	struct gpio_desc *gpio;
	int r;

	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
	if (!ddata)
		return -ENOMEM;

	platform_set_drvdata(pdev, ddata);
	ddata->dev = &pdev->dev;

	mutex_init(&ddata->hpd_lock);

	/* HPD GPIO */
	gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
	if (IS_ERR(gpio)) {
		dev_err(&pdev->dev, "failed to parse HPD gpio\n");
		return PTR_ERR(gpio);
	}

	ddata->hpd_gpio = gpio;

	if (ddata->hpd_gpio) {
		r = devm_request_threaded_irq(&pdev->dev,
				gpiod_to_irq(ddata->hpd_gpio),
				NULL, hdmic_hpd_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
				IRQF_ONESHOT,
				"hdmic hpd", ddata);
		if (r)
			return r;
	}

	dssdev = &ddata->dssdev;
	dssdev->ops = &hdmic_ops;
	dssdev->dev = &pdev->dev;
	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
	dssdev->display = true;
	dssdev->owner = THIS_MODULE;
	dssdev->of_ports = BIT(0);
	dssdev->ops_flags = ddata->hpd_gpio
			  ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
			  : 0;

	omapdss_display_init(dssdev);
	omapdss_device_register(dssdev);

	return 0;
}
コード例 #14
0
ファイル: ak4104.c プロジェクト: AlexShiLucky/linux
static int ak4104_spi_probe(struct spi_device *spi)
{
	struct ak4104_private *ak4104;
	struct gpio_desc *reset_gpiod;
	unsigned int val;
	int ret;

	spi->bits_per_word = 8;
	spi->mode = SPI_MODE_0;
	ret = spi_setup(spi);
	if (ret < 0)
		return ret;

	ak4104 = devm_kzalloc(&spi->dev, sizeof(struct ak4104_private),
			      GFP_KERNEL);
	if (ak4104 == NULL)
		return -ENOMEM;

	ak4104->regulator = devm_regulator_get(&spi->dev, "vdd");
	if (IS_ERR(ak4104->regulator)) {
		ret = PTR_ERR(ak4104->regulator);
		dev_err(&spi->dev, "Unable to get Vdd regulator: %d\n", ret);
		return ret;
	}

	ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap);
	if (IS_ERR(ak4104->regmap)) {
		ret = PTR_ERR(ak4104->regmap);
		return ret;
	}

	reset_gpiod = devm_gpiod_get_optional(&spi->dev, "reset",
					      GPIOD_OUT_HIGH);
	if (IS_ERR(reset_gpiod) &&
	    PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
		return -EPROBE_DEFER;

	/* read the 'reserved' register - according to the datasheet, it
	 * should contain 0x5b. Not a good way to verify the presence of
	 * the device, but there is no hardware ID register. */
	ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
	if (ret != 0)
		return ret;
	if (val != AK4104_RESERVED_VAL)
		return -ENODEV;

	spi_set_drvdata(spi, ak4104);

	ret = devm_snd_soc_register_component(&spi->dev,
			&soc_component_device_ak4104, &ak4104_dai, 1);
	return ret;
}
コード例 #15
0
ファイル: etraxfs-uart.c プロジェクト: 19Dan01/linux
static int etraxfs_uart_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct uart_cris_port *up;
	int dev_id;

	if (!np)
		return -ENODEV;

	dev_id = of_alias_get_id(np, "serial");
	if (dev_id < 0)
		dev_id = 0;

	if (dev_id >= UART_NR)
		return -EINVAL;

	if (etraxfs_uart_ports[dev_id])
		return -EBUSY;

	up = devm_kzalloc(&pdev->dev, sizeof(struct uart_cris_port),
			  GFP_KERNEL);
	if (!up)
		return -ENOMEM;

	up->irq = irq_of_parse_and_map(np, 0);
	up->regi_ser = of_iomap(np, 0);
	up->dtr_pin = devm_gpiod_get_optional(&pdev->dev, "dtr");
	up->dsr_pin = devm_gpiod_get_optional(&pdev->dev, "dsr");
	up->ri_pin = devm_gpiod_get_optional(&pdev->dev, "ri");
	up->cd_pin = devm_gpiod_get_optional(&pdev->dev, "cd");
	up->port.dev = &pdev->dev;
	cris_serial_port_init(&up->port, dev_id);

	etraxfs_uart_ports[dev_id] = up;
	platform_set_drvdata(pdev, &up->port);
	uart_add_one_port(&etraxfs_uart_driver, &up->port);

	return 0;
}
コード例 #16
0
ファイル: emac_mdio.c プロジェクト: AshishNamdev/linux
/**
 * arc_mdio_probe - MDIO probe function.
 * @priv:	Pointer to ARC EMAC private data structure.
 *
 * returns:	0 on success, -ENOMEM when mdiobus_alloc
 * (to allocate memory for MII bus structure) fails.
 *
 * Sets up and registers the MDIO interface.
 */
int arc_mdio_probe(struct arc_emac_priv *priv)
{
	struct arc_emac_mdio_bus_data *data = &priv->bus_data;
	struct device_node *np = priv->dev->of_node;
	struct mii_bus *bus;
	int error;

	bus = mdiobus_alloc();
	if (!bus)
		return -ENOMEM;

	priv->bus = bus;
	bus->priv = priv;
	bus->parent = priv->dev;
	bus->name = "Synopsys MII Bus";
	bus->read = &arc_mdio_read;
	bus->write = &arc_mdio_write;
	bus->reset = &arc_mdio_reset;

	/* optional reset-related properties */
	data->reset_gpio = devm_gpiod_get_optional(priv->dev, "phy-reset",
						   GPIOD_OUT_LOW);
	if (IS_ERR(data->reset_gpio)) {
		error = PTR_ERR(data->reset_gpio);
		dev_err(priv->dev, "Failed to request gpio: %d\n", error);
		return error;
	}

	of_property_read_u32(np, "phy-reset-duration", &data->msec);
	/* A sane reset duration should not be longer than 1s */
	if (data->msec > 1000)
		data->msec = 1;

	snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name);

	error = of_mdiobus_register(bus, priv->dev->of_node);
	if (error) {
		dev_err(priv->dev, "cannot register MDIO bus %s\n", bus->name);
		mdiobus_free(bus);
		return error;
	}

	return 0;
}
コード例 #17
0
ファイル: at803x.c プロジェクト: shengwenhui/aufs4-linux
static int at803x_probe(struct phy_device *phydev)
{
	struct device *dev = &phydev->mdio.dev;
	struct at803x_priv *priv;
	struct gpio_desc *gpiod_reset;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
	if (IS_ERR(gpiod_reset))
		return PTR_ERR(gpiod_reset);

	priv->gpiod_reset = gpiod_reset;

	phydev->priv = priv;

	return 0;
}
コード例 #18
0
ファイル: at803x.c プロジェクト: mansr/linux-tangox
static int at803x_probe(struct phy_device *phydev)
{
	struct device *dev = &phydev->mdio.dev;
	struct at803x_priv *priv;
	struct gpio_desc *gpiod_reset;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	if (phydev->drv->phy_id != ATH8030_PHY_ID)
		goto does_not_require_reset_workaround;

	gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
	if (IS_ERR(gpiod_reset))
		return PTR_ERR(gpiod_reset);

	priv->gpiod_reset = gpiod_reset;

does_not_require_reset_workaround:
	phydev->priv = priv;

	return 0;
}
コード例 #19
0
ファイル: tsc200x-core.c プロジェクト: ChineseDr/linux
int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
                  struct regmap *regmap,
                  int (*tsc200x_cmd)(struct device *dev, u8 cmd))
{
    const struct tsc2005_platform_data *pdata = dev_get_platdata(dev);
    struct device_node *np = dev->of_node;

    struct tsc200x *ts;
    struct input_dev *input_dev;
    unsigned int max_x = MAX_12BIT;
    unsigned int max_y = MAX_12BIT;
    unsigned int max_p = MAX_12BIT;
    unsigned int fudge_x = TSC200X_DEF_X_FUZZ;
    unsigned int fudge_y = TSC200X_DEF_Y_FUZZ;
    unsigned int fudge_p = TSC200X_DEF_P_FUZZ;
    unsigned int x_plate_ohm = TSC200X_DEF_RESISTOR;
    unsigned int esd_timeout;
    int error;

    if (!np && !pdata) {
        dev_err(dev, "no platform data\n");
        return -ENODEV;
    }

    if (irq <= 0) {
        dev_err(dev, "no irq\n");
        return -ENODEV;
    }

    if (IS_ERR(regmap))
        return PTR_ERR(regmap);

    if (!tsc200x_cmd) {
        dev_err(dev, "no cmd function\n");
        return -ENODEV;
    }

    if (pdata) {
        fudge_x	= pdata->ts_x_fudge;
        fudge_y	= pdata->ts_y_fudge;
        fudge_p	= pdata->ts_pressure_fudge;
        max_x	= pdata->ts_x_max;
        max_y	= pdata->ts_y_max;
        max_p	= pdata->ts_pressure_max;
        x_plate_ohm = pdata->ts_x_plate_ohm;
        esd_timeout = pdata->esd_timeout_ms;
    } else {
        x_plate_ohm = TSC200X_DEF_RESISTOR;
        of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm);
        esd_timeout = 0;
        of_property_read_u32(np, "ti,esd-recovery-timeout-ms",
                             &esd_timeout);
    }

    ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
    if (!ts)
        return -ENOMEM;

    input_dev = devm_input_allocate_device(dev);
    if (!input_dev)
        return -ENOMEM;

    ts->irq = irq;
    ts->dev = dev;
    ts->idev = input_dev;
    ts->regmap = regmap;
    ts->tsc200x_cmd = tsc200x_cmd;
    ts->x_plate_ohm = x_plate_ohm;
    ts->esd_timeout = esd_timeout;

    ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
    if (IS_ERR(ts->reset_gpio)) {
        error = PTR_ERR(ts->reset_gpio);
        dev_err(dev, "error acquiring reset gpio: %d\n", error);
        return error;
    }

    ts->vio = devm_regulator_get_optional(dev, "vio");
    if (IS_ERR(ts->vio)) {
        error = PTR_ERR(ts->vio);
        dev_err(dev, "vio regulator missing (%d)", error);
        return error;
    }

    if (!ts->reset_gpio && pdata)
        ts->set_reset = pdata->set_reset;

    mutex_init(&ts->mutex);

    spin_lock_init(&ts->lock);
    setup_timer(&ts->penup_timer, tsc200x_penup_timer, (unsigned long)ts);

    INIT_DELAYED_WORK(&ts->esd_work, tsc200x_esd_work);

    snprintf(ts->phys, sizeof(ts->phys),
             "%s/input-ts", dev_name(dev));

    if (tsc_id->product == 2004) {
        input_dev->name = "TSC200X touchscreen";
    } else {
        input_dev->name = devm_kasprintf(dev, GFP_KERNEL,
                                         "TSC%04d touchscreen",
                                         tsc_id->product);
        if (!input_dev->name)
            return -ENOMEM;
    }

    input_dev->phys = ts->phys;
    input_dev->id = *tsc_id;
    input_dev->dev.parent = dev;
    input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
    input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);

    input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
    input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
    input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);

    if (np)
        touchscreen_parse_properties(input_dev, false, NULL);

    input_dev->open = tsc200x_open;
    input_dev->close = tsc200x_close;

    input_set_drvdata(input_dev, ts);

    /* Ensure the touchscreen is off */
    tsc200x_stop_scan(ts);

    error = devm_request_threaded_irq(dev, irq, NULL,
                                      tsc200x_irq_thread,
                                      IRQF_TRIGGER_RISING | IRQF_ONESHOT,
                                      "tsc200x", ts);
    if (error) {
        dev_err(dev, "Failed to request irq, err: %d\n", error);
        return error;
    }

    /* enable regulator for DT */
    if (ts->vio) {
        error = regulator_enable(ts->vio);
        if (error)
            return error;
    }

    dev_set_drvdata(dev, ts);
    error = sysfs_create_group(&dev->kobj, &tsc200x_attr_group);
    if (error) {
        dev_err(dev,
                "Failed to create sysfs attributes, err: %d\n", error);
        goto disable_regulator;
    }

    error = input_register_device(ts->idev);
    if (error) {
        dev_err(dev,
                "Failed to register input device, err: %d\n", error);
        goto err_remove_sysfs;
    }

    irq_set_irq_wake(irq, 1);
    return 0;

err_remove_sysfs:
    sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
disable_regulator:
    if (ts->vio)
        regulator_disable(ts->vio);
    return error;
}
コード例 #20
0
ファイル: adau1977.c プロジェクト: AshishNamdev/linux
int adau1977_probe(struct device *dev, struct regmap *regmap,
	enum adau1977_type type, void (*switch_mode)(struct device *dev))
{
	unsigned int power_off_mask;
	struct adau1977 *adau1977;
	int ret;

	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL);
	if (adau1977 == NULL)
		return -ENOMEM;

	adau1977->dev = dev;
	adau1977->type = type;
	adau1977->regmap = regmap;
	adau1977->switch_mode = switch_mode;
	adau1977->max_master_fs = 192000;

	adau1977->constraints.list = adau1977_rates;
	adau1977->constraints.count = ARRAY_SIZE(adau1977_rates);

	adau1977->avdd_reg = devm_regulator_get(dev, "AVDD");
	if (IS_ERR(adau1977->avdd_reg))
		return PTR_ERR(adau1977->avdd_reg);

	adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD");
	if (IS_ERR(adau1977->dvdd_reg)) {
		if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV)
			return PTR_ERR(adau1977->dvdd_reg);
		adau1977->dvdd_reg = NULL;
	}

	adau1977->reset_gpio = devm_gpiod_get_optional(dev, "reset",
						       GPIOD_OUT_LOW);
	if (IS_ERR(adau1977->reset_gpio))
		return PTR_ERR(adau1977->reset_gpio);

	dev_set_drvdata(dev, adau1977);

	if (adau1977->reset_gpio)
		ndelay(100);

	ret = adau1977_power_enable(adau1977);
	if (ret)
		return ret;

	if (type == ADAU1977) {
		ret = adau1977_setup_micbias(adau1977);
		if (ret)
			goto err_poweroff;
	}

	if (adau1977->dvdd_reg)
		power_off_mask = ~0;
	else
		power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN;

	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
				power_off_mask, 0x00);
	if (ret)
		goto err_poweroff;

	ret = adau1977_power_disable(adau1977);
	if (ret)
		return ret;

	return snd_soc_register_codec(dev, &adau1977_codec_driver,
			&adau1977_dai, 1);

err_poweroff:
	adau1977_power_disable(adau1977);
	return ret;

}
コード例 #21
0
ファイル: sun4i-codec.c プロジェクト: 020gzh/linux
static int sun4i_codec_probe(struct platform_device *pdev)
{
	struct snd_soc_card *card;
	struct sun4i_codec *scodec;
	struct resource *res;
	void __iomem *base;
	int ret;

	scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
	if (!scodec)
		return -ENOMEM;

	scodec->dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base)) {
		dev_err(&pdev->dev, "Failed to map the registers\n");
		return PTR_ERR(base);
	}

	scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
					     &sun4i_codec_regmap_config);
	if (IS_ERR(scodec->regmap)) {
		dev_err(&pdev->dev, "Failed to create our regmap\n");
		return PTR_ERR(scodec->regmap);
	}

	/* Get the clocks from the DT */
	scodec->clk_apb = devm_clk_get(&pdev->dev, "apb");
	if (IS_ERR(scodec->clk_apb)) {
		dev_err(&pdev->dev, "Failed to get the APB clock\n");
		return PTR_ERR(scodec->clk_apb);
	}

	scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
	if (IS_ERR(scodec->clk_module)) {
		dev_err(&pdev->dev, "Failed to get the module clock\n");
		return PTR_ERR(scodec->clk_module);
	}

	/* Enable the bus clock */
	if (clk_prepare_enable(scodec->clk_apb)) {
		dev_err(&pdev->dev, "Failed to enable the APB clock\n");
		return -EINVAL;
	}

	scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
						  GPIOD_OUT_LOW);
	if (IS_ERR(scodec->gpio_pa)) {
		ret = PTR_ERR(scodec->gpio_pa);
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev, "Failed to get pa gpio: %d\n", ret);
		return ret;
	}

	/* DMA configuration for TX FIFO */
	scodec->playback_dma_data.addr = res->start + SUN4I_CODEC_DAC_TXDATA;
	scodec->playback_dma_data.maxburst = 4;
	scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;

	/* DMA configuration for RX FIFO */
	scodec->capture_dma_data.addr = res->start + SUN4I_CODEC_ADC_RXDATA;
	scodec->capture_dma_data.maxburst = 4;
	scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;

	ret = snd_soc_register_codec(&pdev->dev, &sun4i_codec_codec,
				     &sun4i_codec_dai, 1);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register our codec\n");
		goto err_clk_disable;
	}

	ret = devm_snd_soc_register_component(&pdev->dev,
					      &sun4i_codec_component,
					      &dummy_cpu_dai, 1);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register our DAI\n");
		goto err_unregister_codec;
	}

	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register against DMAEngine\n");
		goto err_unregister_codec;
	}

	card = sun4i_codec_create_card(&pdev->dev);
	if (!card) {
		dev_err(&pdev->dev, "Failed to create our card\n");
		goto err_unregister_codec;
	}

	platform_set_drvdata(pdev, card);
	snd_soc_card_set_drvdata(card, scodec);

	ret = snd_soc_register_card(card);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register our card\n");
		goto err_unregister_codec;
	}

	return 0;

err_unregister_codec:
	snd_soc_unregister_codec(&pdev->dev);
err_clk_disable:
	clk_disable_unprepare(scodec->clk_apb);
	return ret;
}
コード例 #22
0
ファイル: sis_i2c.c プロジェクト: AlexShiLucky/linux
static int sis_ts_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct sis_ts_data *ts;
	struct input_dev *input;
	int error;

	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
	if (!ts)
		return -ENOMEM;

	ts->client = client;

	ts->attn_gpio = devm_gpiod_get_optional(&client->dev,
						"attn", GPIOD_IN);
	if (IS_ERR(ts->attn_gpio)) {
		error = PTR_ERR(ts->attn_gpio);
		if (error != -EPROBE_DEFER)
			dev_err(&client->dev,
				"Failed to get attention GPIO: %d\n", error);
		return error;
	}

	ts->reset_gpio = devm_gpiod_get_optional(&client->dev,
						 "reset", GPIOD_OUT_LOW);
	if (IS_ERR(ts->reset_gpio)) {
		error = PTR_ERR(ts->reset_gpio);
		if (error != -EPROBE_DEFER)
			dev_err(&client->dev,
				"Failed to get reset GPIO: %d\n", error);
		return error;
	}

	sis_ts_reset(ts);

	ts->input = input = devm_input_allocate_device(&client->dev);
	if (!input) {
		dev_err(&client->dev, "Failed to allocate input device\n");
		return -ENOMEM;
	}

	input->name = "SiS Touchscreen";
	input->id.bustype = BUS_I2C;

	input_set_abs_params(input, ABS_MT_POSITION_X, 0, SIS_MAX_X, 0, 0);
	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, SIS_MAX_Y, 0, 0);
	input_set_abs_params(input, ABS_MT_PRESSURE, 0, SIS_MAX_PRESSURE, 0, 0);
	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
			     0, SIS_AREA_LENGTH_LONGER, 0, 0);
	input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
			     0, SIS_AREA_LENGTH_SHORT, 0, 0);

	error = input_mt_init_slots(input, SIS_MAX_FINGERS, INPUT_MT_DIRECT);
	if (error) {
		dev_err(&client->dev,
			"Failed to initialize MT slots: %d\n", error);
		return error;
	}

	error = devm_request_threaded_irq(&client->dev, client->irq,
					  NULL, sis_ts_irq_handler,
					  IRQF_ONESHOT,
					  client->name, ts);
	if (error) {
		dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
		return error;
	}

	error = input_register_device(ts->input);
	if (error) {
		dev_err(&client->dev,
			"Failed to register input device: %d\n", error);
		return error;
	}

	return 0;
}
コード例 #23
0
ファイル: tas571x.c プロジェクト: AlexShiLucky/linux
static int tas571x_i2c_probe(struct i2c_client *client,
			     const struct i2c_device_id *id)
{
	struct tas571x_private *priv;
	struct device *dev = &client->dev;
	const struct of_device_id *of_id;
	int i, ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
	i2c_set_clientdata(client, priv);

	of_id = of_match_device(tas571x_of_match, dev);
	if (of_id)
		priv->chip = of_id->data;
	else
		priv->chip = (void *) id->driver_data;

	priv->mclk = devm_clk_get(dev, "mclk");
	if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {
		dev_err(dev, "Failed to request mclk: %ld\n",
			PTR_ERR(priv->mclk));
		return PTR_ERR(priv->mclk);
	}

	if (WARN_ON(priv->chip->num_supply_names > TAS571X_MAX_SUPPLIES))
		return -EINVAL;
	for (i = 0; i < priv->chip->num_supply_names; i++)
		priv->supplies[i].supply = priv->chip->supply_names[i];

	ret = devm_regulator_bulk_get(dev, priv->chip->num_supply_names,
				      priv->supplies);
	if (ret) {
		dev_err(dev, "Failed to get supplies: %d\n", ret);
		return ret;
	}
	ret = regulator_bulk_enable(priv->chip->num_supply_names,
				    priv->supplies);
	if (ret) {
		dev_err(dev, "Failed to enable supplies: %d\n", ret);
		return ret;
	}

	priv->regmap = devm_regmap_init(dev, NULL, client,
					priv->chip->regmap_config);
	if (IS_ERR(priv->regmap))
		return PTR_ERR(priv->regmap);

	priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);
	if (IS_ERR(priv->pdn_gpio)) {
		dev_err(dev, "error requesting pdn_gpio: %ld\n",
			PTR_ERR(priv->pdn_gpio));
		return PTR_ERR(priv->pdn_gpio);
	}

	priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",
						   GPIOD_OUT_HIGH);
	if (IS_ERR(priv->reset_gpio)) {
		dev_err(dev, "error requesting reset_gpio: %ld\n",
			PTR_ERR(priv->reset_gpio));
		return PTR_ERR(priv->reset_gpio);
	} else if (priv->reset_gpio) {
		/* pulse the active low reset line for ~100us */
		usleep_range(100, 200);
		gpiod_set_value(priv->reset_gpio, 0);
		usleep_range(13500, 20000);
	}

	ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
	if (ret)
		return ret;

	usleep_range(50000, 60000);

	memcpy(&priv->component_driver, &tas571x_component, sizeof(priv->component_driver));
	priv->component_driver.controls = priv->chip->controls;
	priv->component_driver.num_controls = priv->chip->num_controls;

	if (priv->chip->vol_reg_size == 2) {
		/*
		 * The master volume defaults to 0x3ff (mute), but we ignore
		 * (zero) the LSB because the hardware step size is 0.125 dB
		 * and TLV_DB_SCALE_ITEM has a resolution of 0.01 dB.
		 */
		ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);
		if (ret)
			return ret;
	}

	return devm_snd_soc_register_component(&client->dev,
				      &priv->component_driver,
				      &tas571x_dai, 1);
}
コード例 #24
0
ファイル: cs35l33.c プロジェクト: Lyude/linux
static int cs35l33_i2c_probe(struct i2c_client *i2c_client,
				       const struct i2c_device_id *id)
{
	struct cs35l33_private *cs35l33;
	struct cs35l33_pdata *pdata = dev_get_platdata(&i2c_client->dev);
	int ret, devid, i;
	unsigned int reg;

	cs35l33 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs35l33_private),
			       GFP_KERNEL);
	if (!cs35l33)
		return -ENOMEM;

	i2c_set_clientdata(i2c_client, cs35l33);
	cs35l33->regmap = devm_regmap_init_i2c(i2c_client, &cs35l33_regmap);
	if (IS_ERR(cs35l33->regmap)) {
		ret = PTR_ERR(cs35l33->regmap);
		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
		return ret;
	}

	regcache_cache_only(cs35l33->regmap, true);

	for (i = 0; i < ARRAY_SIZE(cs35l33_core_supplies); i++)
		cs35l33->core_supplies[i].supply
			= cs35l33_core_supplies[i];
	cs35l33->num_core_supplies = ARRAY_SIZE(cs35l33_core_supplies);

	ret = devm_regulator_bulk_get(&i2c_client->dev,
			cs35l33->num_core_supplies,
			cs35l33->core_supplies);
	if (ret != 0) {
		dev_err(&i2c_client->dev,
			"Failed to request core supplies: %d\n",
			ret);
		return ret;
	}

	if (pdata) {
		cs35l33->pdata = *pdata;
	} else {
		cs35l33_of_get_pdata(&i2c_client->dev, cs35l33);
		pdata = &cs35l33->pdata;
	}

	ret = devm_request_threaded_irq(&i2c_client->dev, i2c_client->irq, NULL,
			cs35l33_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_LOW,
			"cs35l33", cs35l33);
	if (ret != 0)
		dev_warn(&i2c_client->dev, "Failed to request IRQ: %d\n", ret);

	/* We could issue !RST or skip it based on AMP topology */
	cs35l33->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
			"reset-gpios", GPIOD_OUT_HIGH);
	if (IS_ERR(cs35l33->reset_gpio)) {
		dev_err(&i2c_client->dev, "%s ERROR: Can't get reset GPIO\n",
			__func__);
		return PTR_ERR(cs35l33->reset_gpio);
	}

	ret = regulator_bulk_enable(cs35l33->num_core_supplies,
					cs35l33->core_supplies);
	if (ret != 0) {
		dev_err(&i2c_client->dev,
			"Failed to enable core supplies: %d\n",
			ret);
		return ret;
	}

	gpiod_set_value_cansleep(cs35l33->reset_gpio, 1);

	msleep(CS35L33_BOOT_DELAY);
	regcache_cache_only(cs35l33->regmap, false);

	/* initialize codec */
	ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_AB, &reg);
	devid = (reg & 0xFF) << 12;
	ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_CD, &reg);
	devid |= (reg & 0xFF) << 4;
	ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_E, &reg);
	devid |= (reg & 0xF0) >> 4;

	if (devid != CS35L33_CHIP_ID) {
		dev_err(&i2c_client->dev,
			"CS35L33 Device ID (%X). Expected ID %X\n",
			devid, CS35L33_CHIP_ID);
		goto err_enable;
	}

	ret = regmap_read(cs35l33->regmap, CS35L33_REV_ID, &reg);
	if (ret < 0) {
		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
		goto err_enable;
	}

	dev_info(&i2c_client->dev,
		 "Cirrus Logic CS35L33, Revision: %02X\n", reg & 0xFF);

	ret = regmap_register_patch(cs35l33->regmap,
			cs35l33_patch, ARRAY_SIZE(cs35l33_patch));
	if (ret < 0) {
		dev_err(&i2c_client->dev,
			"Error in applying regmap patch: %d\n", ret);
		goto err_enable;
	}

	/* disable mclk and tdm */
	regmap_update_bits(cs35l33->regmap, CS35L33_CLK_CTL,
		CS35L33_MCLKDIS | CS35L33_SDOUT_3ST_TDM,
		CS35L33_MCLKDIS | CS35L33_SDOUT_3ST_TDM);

	pm_runtime_set_autosuspend_delay(&i2c_client->dev, 100);
	pm_runtime_use_autosuspend(&i2c_client->dev);
	pm_runtime_set_active(&i2c_client->dev);
	pm_runtime_enable(&i2c_client->dev);

	ret = devm_snd_soc_register_component(&i2c_client->dev,
			&soc_component_dev_cs35l33, &cs35l33_dai, 1);
	if (ret < 0) {
		dev_err(&i2c_client->dev, "%s: Register component failed\n",
			__func__);
		goto err_enable;
	}

	return 0;

err_enable:
	regulator_bulk_disable(cs35l33->num_core_supplies,
			       cs35l33->core_supplies);

	return ret;
}
コード例 #25
0
ファイル: si4713.c プロジェクト: forgivemyheart/linux
/* si4713_probe - probe for the device */
static int si4713_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	struct si4713_device *sdev;
	struct v4l2_ctrl_handler *hdl;
	struct si4713_platform_data *pdata = client->dev.platform_data;
	struct device_node *np = client->dev.of_node;
	struct radio_si4713_platform_data si4713_pdev_pdata;
	struct platform_device *si4713_pdev;
	int rval;

	sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL);
	if (!sdev) {
		dev_err(&client->dev, "Failed to alloc video device.\n");
		rval = -ENOMEM;
		goto exit;
	}

	sdev->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
						   GPIOD_OUT_LOW);
	if (IS_ERR(sdev->gpio_reset)) {
		rval = PTR_ERR(sdev->gpio_reset);
		dev_err(&client->dev, "Failed to request gpio: %d\n", rval);
		goto exit;
	}

	sdev->vdd = devm_regulator_get_optional(&client->dev, "vdd");
	if (IS_ERR(sdev->vdd)) {
		rval = PTR_ERR(sdev->vdd);
		if (rval == -EPROBE_DEFER)
			goto exit;

		dev_dbg(&client->dev, "no vdd regulator found: %d\n", rval);
		sdev->vdd = NULL;
	}

	sdev->vio = devm_regulator_get_optional(&client->dev, "vio");
	if (IS_ERR(sdev->vio)) {
		rval = PTR_ERR(sdev->vio);
		if (rval == -EPROBE_DEFER)
			goto exit;

		dev_dbg(&client->dev, "no vio regulator found: %d\n", rval);
		sdev->vio = NULL;
	}

	v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);

	init_completion(&sdev->work);

	hdl = &sdev->ctrl_handler;
	v4l2_ctrl_handler_init(hdl, 20);
	sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);

	sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
	sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
	sdev->rds_compressed = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
	sdev->rds_art_head = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
	sdev->rds_stereo = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
	sdev->rds_tp = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
	sdev->rds_ta = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
	sdev->rds_ms = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
	sdev->rds_dyn_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
	sdev->rds_alt_freqs_enable = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, 0, 1, 1, 0);
	sdev->rds_alt_freqs = v4l2_ctrl_new_custom(hdl, &si4713_alt_freqs_ctrl, NULL);
	sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
			10, DEFAULT_RDS_DEVIATION);
	/*
	 * Report step as 8. From RDS spec, psname
	 * should be 8. But there are receivers which scroll strings
	 * sized as 8xN.
	 */
	sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
	/*
	 * Report step as 32 (2A block). From RDS spec,
	 * radio text should be 32 for 2A block. But there are receivers
	 * which scroll strings sized as 32xN. Setting default to 32.
	 */
	sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);

	sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
	sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
			MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
	sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
			MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);

	sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
	sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
			DEFAULT_ACOMP_GAIN);
	sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_THRESHOLD,
			MIN_ACOMP_THRESHOLD, MAX_ACOMP_THRESHOLD, 1,
			DEFAULT_ACOMP_THRESHOLD);
	sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
			MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
	sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
			MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);

	sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
	sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
			10, DEFAULT_PILOT_DEVIATION);
	sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
			1, DEFAULT_PILOT_FREQUENCY);

	sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_PREEMPHASIS,
			V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
	sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_POWER_LEVEL, 0, SI4713_MAX_POWER,
			1, DEFAULT_POWER_LEVEL);
	sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
			V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, SI4713_MAX_ANTCAP,
			1, 0);

	if (hdl->error) {
		rval = hdl->error;
		goto free_ctrls;
	}
	v4l2_ctrl_cluster(29, &sdev->mute);
	sdev->sd.ctrl_handler = hdl;

	if (client->irq) {
		rval = devm_request_irq(&client->dev, client->irq,
			si4713_handler, IRQF_TRIGGER_FALLING,
			client->name, sdev);
		if (rval < 0) {
			v4l2_err(&sdev->sd, "Could not request IRQ\n");
			goto free_ctrls;
		}
		v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
	} else {
		v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
	}

	rval = si4713_initialize(sdev);
	if (rval < 0) {
		v4l2_err(&sdev->sd, "Failed to probe device information.\n");
		goto free_ctrls;
	}

	if (!np && (!pdata || !pdata->is_platform_device))
		return 0;

	si4713_pdev = platform_device_alloc("radio-si4713", -1);
	if (!si4713_pdev) {
		rval = -ENOMEM;
		goto put_main_pdev;
	}

	si4713_pdev_pdata.subdev = client;
	rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
					sizeof(si4713_pdev_pdata));
	if (rval)
		goto put_main_pdev;

	rval = platform_device_add(si4713_pdev);
	if (rval)
		goto put_main_pdev;

	sdev->pd = si4713_pdev;

	return 0;

put_main_pdev:
	platform_device_put(si4713_pdev);
	v4l2_device_unregister_subdev(&sdev->sd);
free_ctrls:
	v4l2_ctrl_handler_free(hdl);
exit:
	return rval;
}
コード例 #26
0
ファイル: silead.c プロジェクト: lumag/linux
static int silead_ts_probe(struct i2c_client *client,
			   const struct i2c_device_id *id)
{
	struct silead_ts_data *data;
	struct device *dev = &client->dev;
	int error;

	if (!i2c_check_functionality(client->adapter,
				     I2C_FUNC_I2C |
				     I2C_FUNC_SMBUS_READ_I2C_BLOCK |
				     I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
		dev_err(dev, "I2C functionality check failed\n");
		return -ENXIO;
	}

	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	i2c_set_clientdata(client, data);
	data->client = client;

	error = silead_ts_set_default_fw_name(data, id);
	if (error)
		return error;

	silead_ts_read_props(client);

	/* We must have the IRQ provided by DT or ACPI subsytem */
	if (client->irq <= 0)
		return -ENODEV;

	data->regulators[0].supply = "vddio";
	data->regulators[1].supply = "avdd";
	error = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators),
					data->regulators);
	if (error)
		return error;

	/*
	 * Enable regulators at probe and disable them at remove, we need
	 * to keep the chip powered otherwise it forgets its firmware.
	 */
	error = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
				      data->regulators);
	if (error)
		return error;

	error = devm_add_action_or_reset(dev, silead_disable_regulator, data);
	if (error)
		return error;

	/* Power GPIO pin */
	data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
	if (IS_ERR(data->gpio_power)) {
		if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
			dev_err(dev, "Shutdown GPIO request failed\n");
		return PTR_ERR(data->gpio_power);
	}

	error = silead_ts_setup(client);
	if (error)
		return error;

	error = silead_ts_request_input_dev(data);
	if (error)
		return error;

	error = devm_request_threaded_irq(dev, client->irq,
					  NULL, silead_ts_threaded_irq_handler,
					  IRQF_ONESHOT, client->name, data);
	if (error) {
		if (error != -EPROBE_DEFER)
			dev_err(dev, "IRQ request failed %d\n", error);
		return error;
	}

	return 0;
}
コード例 #27
0
ファイル: leds-lp8860.c プロジェクト: AlexShiLucky/linux
	for_each_available_child_of_node(np, child_node) {
		led->led_dev.default_trigger = of_get_property(child_node,
						    "linux,default-trigger",
						    NULL);

		ret = of_property_read_string(child_node, "label", &name);
		if (!ret)
			snprintf(led->label, sizeof(led->label), "%s:%s",
				 id->name, name);
		else
			snprintf(led->label, sizeof(led->label),
				"%s::display_cluster", id->name);
	}

	led->enable_gpio = devm_gpiod_get_optional(&client->dev,
						   "enable", GPIOD_OUT_LOW);
	if (IS_ERR(led->enable_gpio)) {
		ret = PTR_ERR(led->enable_gpio);
		dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret);
		return ret;
	}

	led->regulator = devm_regulator_get(&client->dev, "vled");
	if (IS_ERR(led->regulator))
		led->regulator = NULL;

	led->client = client;
	led->led_dev.name = led->label;
	led->led_dev.brightness_set_blocking = lp8860_brightness_set;

	mutex_init(&led->lock);
コード例 #28
0
ファイル: pwm_bl.c プロジェクト: Anjali05/linux
static int pwm_backlight_probe(struct platform_device *pdev)
{
	struct platform_pwm_backlight_data *data = dev_get_platdata(&pdev->dev);
	struct platform_pwm_backlight_data defdata;
	struct backlight_properties props;
	struct backlight_device *bl;
	struct device_node *node = pdev->dev.of_node;
	struct pwm_bl_data *pb;
	struct pwm_state state;
	unsigned int i;
	int ret;

	if (!data) {
		ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
		if (ret < 0) {
			dev_err(&pdev->dev, "failed to find platform data\n");
			return ret;
		}

		data = &defdata;
	}

	if (data->init) {
		ret = data->init(&pdev->dev);
		if (ret < 0)
			return ret;
	}

	pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
	if (!pb) {
		ret = -ENOMEM;
		goto err_alloc;
	}

	pb->notify = data->notify;
	pb->notify_after = data->notify_after;
	pb->check_fb = data->check_fb;
	pb->exit = data->exit;
	pb->dev = &pdev->dev;
	pb->enabled = false;
	pb->post_pwm_on_delay = data->post_pwm_on_delay;
	pb->pwm_off_delay = data->pwm_off_delay;

	pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
						  GPIOD_ASIS);
	if (IS_ERR(pb->enable_gpio)) {
		ret = PTR_ERR(pb->enable_gpio);
		goto err_alloc;
	}

	/*
	 * Compatibility fallback for drivers still using the integer GPIO
	 * platform data. Must go away soon.
	 */
	if (!pb->enable_gpio && gpio_is_valid(data->enable_gpio)) {
		ret = devm_gpio_request_one(&pdev->dev, data->enable_gpio,
					    GPIOF_OUT_INIT_HIGH, "enable");
		if (ret < 0) {
			dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n",
				data->enable_gpio, ret);
			goto err_alloc;
		}

		pb->enable_gpio = gpio_to_desc(data->enable_gpio);
	}

	/*
	 * If the GPIO is not known to be already configured as output, that
	 * is, if gpiod_get_direction returns either 1 or -EINVAL, change the
	 * direction to output and set the GPIO as active.
	 * Do not force the GPIO to active when it was already output as it
	 * could cause backlight flickering or we would enable the backlight too
	 * early. Leave the decision of the initial backlight state for later.
	 */
	if (pb->enable_gpio &&
	    gpiod_get_direction(pb->enable_gpio) != 0)
		gpiod_direction_output(pb->enable_gpio, 1);

	pb->power_supply = devm_regulator_get(&pdev->dev, "power");
	if (IS_ERR(pb->power_supply)) {
		ret = PTR_ERR(pb->power_supply);
		goto err_alloc;
	}

	pb->pwm = devm_pwm_get(&pdev->dev, NULL);
	if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER && !node) {
		dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
		pb->legacy = true;
		pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
	}

	if (IS_ERR(pb->pwm)) {
		ret = PTR_ERR(pb->pwm);
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev, "unable to request PWM\n");
		goto err_alloc;
	}

	dev_dbg(&pdev->dev, "got pwm for backlight\n");

	/* Sync up PWM state. */
	pwm_init_state(pb->pwm, &state);

	/*
	 * The DT case will set the pwm_period_ns field to 0 and store the
	 * period, parsed from the DT, in the PWM device. For the non-DT case,
	 * set the period from platform data if it has not already been set
	 * via the PWM lookup table.
	 */
	if (!state.period && (data->pwm_period_ns > 0))
		state.period = data->pwm_period_ns;

	ret = pwm_apply_state(pb->pwm, &state);
	if (ret) {
		dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
			ret);
		goto err_alloc;
	}

	if (data->levels) {
		/*
		 * For the DT case, only when brightness levels is defined
		 * data->levels is filled. For the non-DT case, data->levels
		 * can come from platform data, however is not usual.
		 */
		for (i = 0; i <= data->max_brightness; i++) {
			if (data->levels[i] > pb->scale)
				pb->scale = data->levels[i];

			pb->levels = data->levels;
		}
	} else if (!data->max_brightness) {
		/*
		 * If no brightness levels are provided and max_brightness is
		 * not set, use the default brightness table. For the DT case,
		 * max_brightness is set to 0 when brightness levels is not
		 * specified. For the non-DT case, max_brightness is usually
		 * set to some value.
		 */

		/* Get the PWM period (in nanoseconds) */
		pwm_get_state(pb->pwm, &state);

		ret = pwm_backlight_brightness_default(&pdev->dev, data,
						       state.period);
		if (ret < 0) {
			dev_err(&pdev->dev,
				"failed to setup default brightness table\n");
			goto err_alloc;
		}

		for (i = 0; i <= data->max_brightness; i++) {
			if (data->levels[i] > pb->scale)
				pb->scale = data->levels[i];

			pb->levels = data->levels;
		}
	} else {
		/*
		 * That only happens for the non-DT case, where platform data
		 * sets the max_brightness value.
		 */
		pb->scale = data->max_brightness;
	}

	pb->lth_brightness = data->lth_brightness * (state.period / pb->scale);

	memset(&props, 0, sizeof(struct backlight_properties));
	props.type = BACKLIGHT_RAW;
	props.max_brightness = data->max_brightness;
	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
				       &pwm_backlight_ops, &props);
	if (IS_ERR(bl)) {
		dev_err(&pdev->dev, "failed to register backlight\n");
		ret = PTR_ERR(bl);
		if (pb->legacy)
			pwm_free(pb->pwm);
		goto err_alloc;
	}

	if (data->dft_brightness > data->max_brightness) {
		dev_warn(&pdev->dev,
			 "invalid default brightness level: %u, using %u\n",
			 data->dft_brightness, data->max_brightness);
		data->dft_brightness = data->max_brightness;
	}

	bl->props.brightness = data->dft_brightness;
	bl->props.power = pwm_backlight_initial_power_state(pb);
	backlight_update_status(bl);

	platform_set_drvdata(pdev, bl);
	return 0;

err_alloc:
	if (data->exit)
		data->exit(&pdev->dev);
	return ret;
}
コード例 #29
0
ファイル: phy-msm-usb.c プロジェクト: guanhe0/kernel
static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
{
	struct msm_otg_platform_data *pdata;
	struct extcon_dev *ext_id, *ext_vbus;
	struct device_node *node = pdev->dev.of_node;
	struct property *prop;
	int len, ret, words;
	u32 val, tmp[3];

	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!pdata)
		return -ENOMEM;

	motg->pdata = pdata;

	pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev);
	if (!pdata->phy_type)
		return 1;

	motg->link_rst = devm_reset_control_get(&pdev->dev, "link");
	if (IS_ERR(motg->link_rst))
		return PTR_ERR(motg->link_rst);

	motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy");
	if (IS_ERR(motg->phy_rst))
		motg->phy_rst = NULL;

	pdata->mode = usb_get_dr_mode(&pdev->dev);
	if (pdata->mode == USB_DR_MODE_UNKNOWN)
		pdata->mode = USB_DR_MODE_OTG;

	pdata->otg_control = OTG_PHY_CONTROL;
	if (!of_property_read_u32(node, "qcom,otg-control", &val))
		if (val == OTG_PMIC_CONTROL)
			pdata->otg_control = val;

	if (!of_property_read_u32(node, "qcom,phy-num", &val) && val < 2)
		motg->phy_number = val;

	motg->vdd_levels[VDD_LEVEL_NONE] = USB_PHY_SUSP_DIG_VOL;
	motg->vdd_levels[VDD_LEVEL_MIN] = USB_PHY_VDD_DIG_VOL_MIN;
	motg->vdd_levels[VDD_LEVEL_MAX] = USB_PHY_VDD_DIG_VOL_MAX;

	if (of_get_property(node, "qcom,vdd-levels", &len) &&
	    len == sizeof(tmp)) {
		of_property_read_u32_array(node, "qcom,vdd-levels",
					   tmp, len / sizeof(*tmp));
		motg->vdd_levels[VDD_LEVEL_NONE] = tmp[VDD_LEVEL_NONE];
		motg->vdd_levels[VDD_LEVEL_MIN] = tmp[VDD_LEVEL_MIN];
		motg->vdd_levels[VDD_LEVEL_MAX] = tmp[VDD_LEVEL_MAX];
	}

	motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup");

	motg->switch_gpio = devm_gpiod_get_optional(&pdev->dev, "switch",
						    GPIOD_OUT_LOW);
	if (IS_ERR(motg->switch_gpio))
		return PTR_ERR(motg->switch_gpio);

	ext_id = ERR_PTR(-ENODEV);
	ext_vbus = ERR_PTR(-ENODEV);
	if (of_property_read_bool(node, "extcon")) {

		/* Each one of them is not mandatory */
		ext_vbus = extcon_get_edev_by_phandle(&pdev->dev, 0);
		if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
			return PTR_ERR(ext_vbus);

		ext_id = extcon_get_edev_by_phandle(&pdev->dev, 1);
		if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV)
			return PTR_ERR(ext_id);
	}

	if (!IS_ERR(ext_vbus)) {
		motg->vbus.extcon = ext_vbus;
		motg->vbus.nb.notifier_call = msm_otg_vbus_notifier;
		ret = extcon_register_notifier(ext_vbus, EXTCON_USB,
						&motg->vbus.nb);
		if (ret < 0) {
			dev_err(&pdev->dev, "register VBUS notifier failed\n");
			return ret;
		}

		ret = extcon_get_cable_state_(ext_vbus, EXTCON_USB);
		if (ret)
			set_bit(B_SESS_VLD, &motg->inputs);
		else
			clear_bit(B_SESS_VLD, &motg->inputs);
	}

	if (!IS_ERR(ext_id)) {
		motg->id.extcon = ext_id;
		motg->id.nb.notifier_call = msm_otg_id_notifier;
		ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST,
						&motg->id.nb);
		if (ret < 0) {
			dev_err(&pdev->dev, "register ID notifier failed\n");
			extcon_unregister_notifier(motg->vbus.extcon,
						   EXTCON_USB, &motg->vbus.nb);
			return ret;
		}

		ret = extcon_get_cable_state_(ext_id, EXTCON_USB_HOST);
		if (ret)
			clear_bit(ID, &motg->inputs);
		else
			set_bit(ID, &motg->inputs);
	}

	prop = of_find_property(node, "qcom,phy-init-sequence", &len);
	if (!prop || !len)
		return 0;

	words = len / sizeof(u32);

	if (words >= ULPI_EXT_VENDOR_SPECIFIC) {
		dev_warn(&pdev->dev, "Too big PHY init sequence %d\n", words);
		return 0;
	}

	pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
	if (!pdata->phy_init_seq)
		return 0;

	ret = of_property_read_u32_array(node, "qcom,phy-init-sequence",
					 pdata->phy_init_seq, words);
	if (!ret)
		pdata->phy_init_sz = words;

	return 0;
}
コード例 #30
0
ファイル: sirf.c プロジェクト: EMCAntimatter/linux
static int sirf_probe(struct serdev_device *serdev)
{
	struct device *dev = &serdev->dev;
	struct gnss_device *gdev;
	struct sirf_data *data;
	int ret;

	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	gdev = gnss_allocate_device(dev);
	if (!gdev)
		return -ENOMEM;

	gdev->type = GNSS_TYPE_SIRF;
	gdev->ops = &sirf_gnss_ops;
	gnss_set_drvdata(gdev, data);

	data->serdev = serdev;
	data->gdev = gdev;

	init_waitqueue_head(&data->power_wait);

	serdev_device_set_drvdata(serdev, data);
	serdev_device_set_client_ops(serdev, &sirf_serdev_ops);

	ret = sirf_parse_dt(serdev);
	if (ret)
		goto err_put_device;

	data->vcc = devm_regulator_get(dev, "vcc");
	if (IS_ERR(data->vcc)) {
		ret = PTR_ERR(data->vcc);
		goto err_put_device;
	}

	data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",
			GPIOD_OUT_LOW);
	if (IS_ERR(data->on_off))
		goto err_put_device;

	if (data->on_off) {
		data->wakeup = devm_gpiod_get_optional(dev, "sirf,wakeup",
				GPIOD_IN);
		if (IS_ERR(data->wakeup))
			goto err_put_device;

		/*
		 * Configurations where WAKEUP has been left not connected,
		 * are currently not supported.
		 */
		if (!data->wakeup) {
			dev_err(dev, "no wakeup gpio specified\n");
			ret = -ENODEV;
			goto err_put_device;
		}
	}

	if (data->wakeup) {
		ret = gpiod_to_irq(data->wakeup);
		if (ret < 0)
			goto err_put_device;

		data->irq = ret;

		ret = devm_request_threaded_irq(dev, data->irq, NULL,
				sirf_wakeup_handler,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
				"wakeup", data);
		if (ret)
			goto err_put_device;
	}

	if (data->on_off) {
		ret = regulator_enable(data->vcc);
		if (ret)
			goto err_put_device;

		/* Wait for chip to boot into hibernate mode */
		msleep(SIRF_BOOT_DELAY);
	}

	if (IS_ENABLED(CONFIG_PM)) {
		pm_runtime_set_suspended(dev);	/* clear runtime_error flag */
		pm_runtime_enable(dev);
	} else {
		ret = sirf_runtime_resume(dev);
		if (ret < 0)
			goto err_disable_vcc;
	}

	ret = gnss_register_device(gdev);
	if (ret)
		goto err_disable_rpm;

	return 0;

err_disable_rpm:
	if (IS_ENABLED(CONFIG_PM))
		pm_runtime_disable(dev);
	else
		sirf_runtime_suspend(dev);
err_disable_vcc:
	if (data->on_off)
		regulator_disable(data->vcc);
err_put_device:
	gnss_put_device(data->gdev);

	return ret;
}