示例#1
0
/* Enable/Disable IHF ext amplifier */
int spk_amp_event(struct snd_soc_dapm_widget *w,
			struct snd_kcontrol *k, int event)
{
	if (mc_dev_ctx->spk_pin <= 0)
		return 0;

	switch (event) {
	case SND_SOC_DAPM_POST_PMU:
		xgold_debug("%s: SND_SOC_DAPM_PRE_PMU\n", __func__);
		if (mc_dev_ctx->spk_pin > 0)
			gpiod_set_value(gpio_to_desc(mc_dev_ctx->spk_pin), 1);
		break;

	case SND_SOC_DAPM_PRE_PMD:
		xgold_debug("%s: SND_SOC_DAPM_PRE_PMD\n", __func__);
		if (mc_dev_ctx->spk_pin > 0)
			gpiod_set_value(gpio_to_desc(mc_dev_ctx->spk_pin), 0);
		break;

	default:
		break;
	}

	return 0;
}
int gpiodump_show(struct seq_file *s, void *unused)
{
	struct gpio_chip	*chip = NULL;
	unsigned		gpio;
	unsigned int ret = 0;

	if(s == NULL) {
		if (gpio_sleep_buffer == NULL)
			gpio_sleep_buffer = kmalloc(20000, GFP_ATOMIC);

		if (gpio_sleep_buffer == NULL) {
			pr_err("gpiodebug: gpiodump_show allocate memory fail\n");
			return 0;
		}
		memset(gpio_sleep_buffer, 0, sizeof(gpio_sleep_buffer));
		len = 0;
	}

	for (gpio = 0; gpio_is_valid(gpio); gpio++) {
		struct device *dev;

		if (chip == gpio_to_desc(gpio)->chip)
			continue;
		chip = gpio_to_desc(gpio)->chip;
		if (!chip)
			continue;

		if(s) {
			seq_printf(s, "%sGPIOs %d-%d", (char *)s->private,
					chip->base, chip->base + chip->ngpio - 1);
			dev = chip->dev;
			if (dev)
				seq_printf(s, ", %s/%s", dev->bus ? dev->bus->name : "no-bus",
					dev_name(dev));
			if (chip->label)
				seq_printf(s, ", %s", chip->label);
			if (chip->can_sleep)
				seq_printf(s, ", can sleep");
			seq_printf(s, ":\n");

			if (chip->dbg_show_sleep)
				chip->dbg_show_sleep(s, NULL, chip, 0);
		} else {
			len += sprintf(gpio_sleep_buffer + len, "GPIOs %d-%d",
					chip->base, chip->base + chip->ngpio - 1);
			dev = chip->dev;
			if (dev)
				len += sprintf(gpio_sleep_buffer + len, ", %s/%s", dev->bus ? dev->bus->name : "no-bus",
					dev_name(dev));
			if (chip->label)
				len += sprintf(gpio_sleep_buffer + len, ", %s", chip->label);
			if (chip->can_sleep)
				len += sprintf(gpio_sleep_buffer + len, ", can sleep");

			if (chip->dbg_show_sleep) {
				ret = chip->dbg_show_sleep(NULL, gpio_sleep_buffer,  chip, len);
				len = ret;
			}
		}
	}
示例#3
0
/**
 * mmc_gpio_request_cd - request a gpio for card-detection
 * @host: mmc host
 * @gpio: gpio number requested
 * @debounce: debounce time in microseconds
 *
 * As devm_* managed functions are used in mmc_gpio_request_cd(), client
 * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up,
 * if the requesting and freeing are only needed at probing and unbinding time
 * for once.  However, if client drivers do something special like runtime
 * switching for card-detection, they are responsible for calling
 * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own.
 *
 * If GPIO debouncing is desired, set the debounce parameter to a non-zero
 * value. The caller is responsible for ensuring that the GPIO driver associated
 * with the GPIO supports debouncing, otherwise an error will be returned.
 *
 * Returns zero on success, else an error.
 */
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
			unsigned int debounce)
{
	struct mmc_gpio *ctx;
	int ret;

	ret = mmc_gpio_alloc(host);
	if (ret < 0)
		return ret;

	ctx = host->slot.handler_priv;

	ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN,
				    ctx->cd_label);
	if (ret < 0)
		/*
		 * don't bother freeing memory. It might still get used by other
		 * slot functions, in any case it will be freed, when the device
		 * is destroyed.
		 */
		return ret;

	if (debounce) {
		ret = gpio_set_debounce(gpio, debounce);
		if (ret < 0)
			return ret;
	}

	ctx->override_cd_active_level = true;
	ctx->cd_gpio = gpio_to_desc(gpio);

	return 0;
}
示例#4
0
static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
	int ret = 0, i;

	clk_prepare_enable(skt->clk);

	if (skt->ops->hw_init) {
		ret = skt->ops->hw_init(skt);
		if (ret)
			return ret;
	}

	for (i = 0; i < ARRAY_SIZE(skt->stat); i++) {
		if (gpio_is_valid(skt->stat[i].gpio)) {
			unsigned long flags = GPIOF_IN;

			/* CD is active low by default */
			if (i == SOC_STAT_CD)
				flags |= GPIOF_ACTIVE_LOW;

			ret = devm_gpio_request_one(skt->socket.dev.parent,
						    skt->stat[i].gpio, flags,
						    skt->stat[i].name);
			if (ret) {
				__soc_pcmcia_hw_shutdown(skt, i);
				return ret;
			}

			skt->stat[i].desc = gpio_to_desc(skt->stat[i].gpio);
		}

		if (i < SOC_STAT_VS1 && skt->stat[i].desc) {
			int irq = gpiod_to_irq(skt->stat[i].desc);

			if (irq > 0) {
				if (i == SOC_STAT_RDY)
					skt->socket.pci_irq = irq;
				else
					skt->stat[i].irq = irq;
			}
		}

		if (skt->stat[i].irq) {
			ret = request_irq(skt->stat[i].irq,
					  soc_common_pcmcia_interrupt,
					  IRQF_TRIGGER_NONE,
					  skt->stat[i].name, skt);
			if (ret) {
				__soc_pcmcia_hw_shutdown(skt, i);
				return ret;
			}
		}
	}

	return ret;
}
示例#5
0
static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
{
    struct gpio_chip *chip;
    acpi_handle handle;
    acpi_status status;

    status = acpi_get_handle(NULL, path, &handle);
    if (ACPI_FAILURE(status))
        return ERR_PTR(-ENODEV);

    chip = gpiochip_find(handle, acpi_gpiochip_find);
    if (!chip)
        return ERR_PTR(-ENODEV);

    if (pin < 0 || pin > chip->ngpio)
        return ERR_PTR(-EINVAL);

    return gpio_to_desc(chip->base + pin);
}
示例#6
0
static int panel_dpi_probe_pdata(struct platform_device *pdev)
{
	const struct panel_dpi_platform_data *pdata;
	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
	struct omap_dss_device *dssdev, *in;
	struct videomode vm;
	int r;

	pdata = dev_get_platdata(&pdev->dev);

	in = omap_dss_find_output(pdata->source);
	if (in == NULL) {
		dev_err(&pdev->dev, "failed to find video source '%s'\n",
				pdata->source);
		return -EPROBE_DEFER;
	}

	ddata->in = in;

	ddata->data_lines = pdata->data_lines;

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

	dssdev = &ddata->dssdev;
	dssdev->name = pdata->name;

	r = devm_gpio_request_one(&pdev->dev, pdata->enable_gpio,
					GPIOF_OUT_INIT_LOW, "panel enable");
	if (r)
		goto err_gpio;

	ddata->enable_gpio = gpio_to_desc(pdata->enable_gpio);

	ddata->backlight_gpio = pdata->backlight_gpio;

	return 0;

err_gpio:
	omap_dss_put_device(ddata->in);
	return r;
}
/* Private function for resolving node pointer to gpio_chip */
static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
{
	struct gg_data *gg_data = data;
	int ret;

	if ((gc->of_node != gg_data->gpiospec.np) ||
	    (gc->of_gpio_n_cells != gg_data->gpiospec.args_count) ||
	    (!gc->of_xlate))
		return false;

	ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags);
	if (ret < 0) {
		/* We've found the gpio chip, but the translation failed.
		 * Return true to stop looking and return the translation
		 * error via out_gpio
		 */
		gg_data->out_gpio = ERR_PTR(ret);
		return true;
	 }

	gg_data->out_gpio = gpio_to_desc(ret + gc->base);
	return true;
}
示例#8
0
/**
 * mmc_gpio_request_ro - request a gpio for write-protection
 * @host: mmc host
 * @gpio: gpio number requested
 *
 * As devm_* managed functions are used in mmc_gpio_request_ro(), client
 * drivers do not need to explicitly call mmc_gpio_free_ro() for freeing up,
 * if the requesting and freeing are only needed at probing and unbinding time
 * for once.  However, if client drivers do something special like runtime
 * switching for write-protection, they are responsible for calling
 * mmc_gpio_request_ro() and mmc_gpio_free_ro() as a pair on their own.
 *
 * Returns zero on success, else an error.
 */
int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
{
	struct mmc_gpio *ctx;
	int ret;

	if (!gpio_is_valid(gpio))
		return -EINVAL;

	ret = mmc_gpio_alloc(host);
	if (ret < 0)
		return ret;

	ctx = host->slot.handler_priv;

	ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN,
				    ctx->ro_label);
	if (ret < 0)
		return ret;

	ctx->override_ro_active_level = true;
	ctx->ro_gpio = gpio_to_desc(gpio);

	return 0;
}
static int init_port(void)
{
	int i, nlow, nhigh, ret, irq;
	unsigned int base = gpio_calc_base();

	/* Translate our GPIO number into absolute number */
	gpio_out_pin = gpio_out_pin + base;
	gpio_in_pin = gpio_in_pin + base;

	if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
		printk(KERN_ALERT LIRC_DRIVER_NAME
		       ": cant claim gpio pin %d\n", gpio_out_pin);
		ret = -ENODEV;
		goto exit_init_port;
	}

	if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
		printk(KERN_ALERT LIRC_DRIVER_NAME
		       ": cant claim gpio pin %d\n", gpio_in_pin);
		ret = -ENODEV;
		goto exit_gpio_free_out_pin;
	}

	gpio_direction_input(gpio_in_pin);
	gpio_direction_output(gpio_out_pin, 1);
	gpio_set_value(gpio_out_pin, invert);

	irq = gpio_to_irq(gpio_in_pin);
	dprintk("to_irq %d\n", irq);
	irqdata = irq_get_irq_data(irq);

	if (irqdata && irqdata->chip) {
		irqchip = irqdata->chip;
	} else {
		ret = -ENODEV;
		goto exit_gpio_free_in_pin;
	}

	/* if pin is high, then this must be an active low receiver. */
	if (sense == -1) {
		/*
		 * probe 9 times every 0.04s, collect "votes" for
		 * active high/low
		 */
		nlow = 0;
		nhigh = 0;
		for (i = 0; i < 9; i++) {
			if (gpio_get_value(gpio_in_pin))
				nlow++;
			else
				nhigh++;
			msleep(40);
		}
		sense = (nlow >= nhigh ? 1 : 0);
		printk(KERN_INFO LIRC_DRIVER_NAME
		       ": auto-detected active %s receiver on GPIO pin %d\n",
		       sense ? "low" : "high", gpio_in_pin);
	} else {
		printk(KERN_INFO LIRC_DRIVER_NAME
		       ": manually using active %s receiver on GPIO pin %d\n",
		       sense ? "low" : "high", gpio_in_pin);
	}

	/* we have the gpio absolute number, translate into descriptor and 
	 * get the gpio chip it belongs to. In some devices there is more 
	 * than one gpio chip. "gco" can be equal to "gci" or not depending on
	 * the device and the choosed GPIOs */ 
	gco = gpiod_to_chip(gpio_to_desc(gpio_out_pin));
	gci = gpiod_to_chip(gpio_to_desc(gpio_in_pin));

	/* get the offset at the gpio chip 
	 * (we will use offsets for better performance) */
	gpio_out_pin = gpio_out_pin - gco->base;
	gpio_in_pin = gpio_in_pin - gci->base;

	printk(KERN_INFO LIRC_DRIVER_NAME
	       " IN: %s, base = %d, offset = %d\n", gci->label, gci->base, gpio_in_pin);
	printk(KERN_INFO LIRC_DRIVER_NAME
	       " OUT: %s, base = %d, offset = %d\n", gco->label, gco->base, gpio_out_pin);

	return 0;

	exit_gpio_free_in_pin:
	gpio_free(gpio_in_pin);

	exit_gpio_free_out_pin:
	gpio_free(gpio_out_pin);

	exit_init_port:
	return ret;
}
示例#10
0
static int gpio_charger_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct gpio_charger_platform_data *pdata = dev->platform_data;
	struct power_supply_config psy_cfg = {};
	struct gpio_charger *gpio_charger;
	struct power_supply_desc *charger_desc;
	unsigned long flags;
	int irq, ret;

	if (!pdata && !dev->of_node) {
		dev_err(dev, "No platform data\n");
		return -ENOENT;
	}

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

	/*
	 * This will fetch a GPIO descriptor from device tree, ACPI or
	 * boardfile descriptor tables. It's good to try this first.
	 */
	gpio_charger->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN);

	/*
	 * If this fails and we're not using device tree, try the
	 * legacy platform data method.
	 */
	if (IS_ERR(gpio_charger->gpiod) && !dev->of_node) {
		/* Non-DT: use legacy GPIO numbers */
		if (!gpio_is_valid(pdata->gpio)) {
			dev_err(dev, "Invalid gpio pin in pdata\n");
			return -EINVAL;
		}
		flags = GPIOF_IN;
		if (pdata->gpio_active_low)
			flags |= GPIOF_ACTIVE_LOW;
		ret = devm_gpio_request_one(dev, pdata->gpio, flags,
					    dev_name(dev));
		if (ret) {
			dev_err(dev, "Failed to request gpio pin: %d\n", ret);
			return ret;
		}
		/* Then convert this to gpiod for now */
		gpio_charger->gpiod = gpio_to_desc(pdata->gpio);
	} else if (IS_ERR(gpio_charger->gpiod)) {
		/* Just try again if this happens */
		if (PTR_ERR(gpio_charger->gpiod) == -EPROBE_DEFER)
			return -EPROBE_DEFER;
		dev_err(dev, "error getting GPIO descriptor\n");
		return PTR_ERR(gpio_charger->gpiod);
	}

	charger_desc = &gpio_charger->charger_desc;
	charger_desc->properties = gpio_charger_properties;
	charger_desc->num_properties = ARRAY_SIZE(gpio_charger_properties);
	charger_desc->get_property = gpio_charger_get_property;

	psy_cfg.of_node = dev->of_node;
	psy_cfg.drv_data = gpio_charger;

	if (pdata) {
		charger_desc->name = pdata->name;
		charger_desc->type = pdata->type;
		psy_cfg.supplied_to = pdata->supplied_to;
		psy_cfg.num_supplicants = pdata->num_supplicants;
	} else {
		charger_desc->name = dev->of_node->name;
		charger_desc->type = gpio_charger_get_type(dev);
	}

	if (!charger_desc->name)
		charger_desc->name = pdev->name;

	gpio_charger->charger = devm_power_supply_register(dev, charger_desc,
							   &psy_cfg);
	if (IS_ERR(gpio_charger->charger)) {
		ret = PTR_ERR(gpio_charger->charger);
		dev_err(dev, "Failed to register power supply: %d\n", ret);
		return ret;
	}

	irq = gpiod_to_irq(gpio_charger->gpiod);
	if (irq > 0) {
		ret = devm_request_any_context_irq(dev, irq, gpio_charger_irq,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				dev_name(dev), gpio_charger->charger);
		if (ret < 0)
			dev_warn(dev, "Failed to request irq: %d\n", ret);
		else
			gpio_charger->irq = irq;
	}

	platform_set_drvdata(pdev, gpio_charger);

	device_init_wakeup(dev, 1);

	return 0;
}
示例#11
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;
}
示例#12
0
int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
		struct usb_phy_generic_platform_data *pdata)
{
	enum usb_phy_type type = USB_PHY_TYPE_USB2;
	int err = 0;

	u32 clk_rate = 0;
	bool needs_vcc = false, needs_clk = false;

	if (dev->of_node) {
		struct device_node *node = dev->of_node;

		if (of_property_read_u32(node, "clock-frequency", &clk_rate))
			clk_rate = 0;

		needs_vcc = of_property_read_bool(node, "vcc-supply");
		needs_clk = of_property_read_bool(node, "clocks");
		nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
							   GPIOD_ASIS);
		err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
		if (!err) {
			nop->gpiod_vbus = devm_gpiod_get_optional(dev,
							 "vbus-detect",
							 GPIOD_ASIS);
			err = PTR_ERR_OR_ZERO(nop->gpiod_vbus);
		}
	} else if (pdata) {
		type = pdata->type;
		clk_rate = pdata->clk_rate;
		needs_vcc = pdata->needs_vcc;
		if (gpio_is_valid(pdata->gpio_reset)) {
			err = devm_gpio_request_one(dev, pdata->gpio_reset,
						    GPIOF_ACTIVE_LOW,
						    dev_name(dev));
			if (!err)
				nop->gpiod_reset =
					gpio_to_desc(pdata->gpio_reset);
		}
		nop->gpiod_vbus = pdata->gpiod_vbus;
	}

	if (err == -EPROBE_DEFER)
		return -EPROBE_DEFER;
	if (err) {
		dev_err(dev, "Error requesting RESET or VBUS GPIO\n");
		return err;
	}
	if (nop->gpiod_reset)
		gpiod_direction_output(nop->gpiod_reset, 1);

	nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
			GFP_KERNEL);
	if (!nop->phy.otg)
		return -ENOMEM;

	nop->clk = devm_clk_get(dev, "main_clk");
	if (IS_ERR(nop->clk)) {
		dev_dbg(dev, "Can't get phy clock: %ld\n",
					PTR_ERR(nop->clk));
		if (needs_clk)
			return PTR_ERR(nop->clk);
	}

	if (!IS_ERR(nop->clk) && clk_rate) {
		err = clk_set_rate(nop->clk, clk_rate);
		if (err) {
			dev_err(dev, "Error setting clock rate\n");
			return err;
		}
	}

	nop->vcc = devm_regulator_get(dev, "vcc");
	if (IS_ERR(nop->vcc)) {
		dev_dbg(dev, "Error getting vcc regulator: %ld\n",
					PTR_ERR(nop->vcc));
		if (needs_vcc)
			return -EPROBE_DEFER;
	}

	nop->dev		= dev;
	nop->phy.dev		= nop->dev;
	nop->phy.label		= "nop-xceiv";
	nop->phy.set_suspend	= nop_set_suspend;
	nop->phy.type		= type;

	nop->phy.otg->state		= OTG_STATE_UNDEFINED;
	nop->phy.otg->usb_phy		= &nop->phy;
	nop->phy.otg->set_host		= nop_set_host;
	nop->phy.otg->set_peripheral	= nop_set_peripheral;

	return 0;
}
示例#13
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 ret;

	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);
	i2c_set_clientdata(client, data);
	data->client = client;

	data->fw_name = SILEAD_FW_NAME;
	data->x_max = SILEAD_X_MAX;
	data->y_max = SILEAD_Y_MAX;
	data->max_fingers = SILEAD_MAX_FINGERS;
	data->pressure = SILEAD_PRESSURE;


	/* If the IRQ is not filled by DT or ACPI subsytem
	 * try using the named GPIO */
	if (client->irq <= 0) {
		data->gpio_irq = devm_gpiod_get(dev, SILEAD_IRQ_GPIO_NAME);
		if (IS_ERR(data->gpio_irq)) {
			dev_err(dev, "IRQ GPIO request failed\n");
			return -ENODEV;
		}

		ret = gpiod_direction_input(data->gpio_irq);
		if (ret) {
			dev_err(dev, "IRQ GPIO direction set failed\n");
			return ret;
		}

		client->irq = gpiod_to_irq(data->gpio_irq);
		if (client->irq <= 0) {
			dev_err(dev, "GPIO to IRQ translation failed %d\n",
				client->irq);
			return client->irq;
		}
	}

	/* Power GPIO pin */
	if (client->dev.of_node) {
		ret = of_get_named_gpio_flags(client->dev.of_node,
					      SILEAD_PWR_GPIO_NAME, 0, NULL);
		if (ret <= 0) {
			dev_err(&client->dev, "error getting gpio for %s\n",
				SILEAD_PWR_GPIO_NAME);
			return -ENODEV;
		}

		data->gpio_power = gpio_to_desc(ret);
		if (!data->gpio_power)
			return -ENODEV;
	}

	ret = gpiod_direction_output(data->gpio_power, 0);
	if (ret) {
		dev_err(dev, "Shutdown GPIO direction set failed\n");
		return ret;
	}

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

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

	ret = devm_request_threaded_irq(dev, client->irq, NULL,
					silead_ts_irq_handler,
					IRQF_ONESHOT | IRQ_TYPE_EDGE_RISING,
					client->name, data);
	if (ret) {
		dev_err(dev, "IRQ request failed %d\n", ret);
		return ret;
	}

	dev_dbg(dev, "Probing succeded\n");
	return 0;
}
示例#14
0
static struct clk *clk_register_gpio(struct device *dev, const char *name,
		const char * const *parent_names, u8 num_parents, unsigned gpio,
		bool active_low, unsigned long flags,
		const struct clk_ops *clk_gpio_ops)
{
	struct clk_gpio *clk_gpio;
	struct clk *clk;
	struct clk_init_data init = {};
	unsigned long gpio_flags;
	int err;

	if (dev)
		clk_gpio = devm_kzalloc(dev, sizeof(*clk_gpio),	GFP_KERNEL);
	else
		clk_gpio = kzalloc(sizeof(*clk_gpio), GFP_KERNEL);

	if (!clk_gpio)
		return ERR_PTR(-ENOMEM);

	if (active_low)
		gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
	else
		gpio_flags = GPIOF_OUT_INIT_LOW;

	if (dev)
		err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
	else
		err = gpio_request_one(gpio, gpio_flags, name);
	if (err) {
		if (err != -EPROBE_DEFER)
			pr_err("%s: %s: Error requesting clock control gpio %u\n",
					__func__, name, gpio);
		if (!dev)
			kfree(clk_gpio);

		return ERR_PTR(err);
	}

	init.name = name;
	init.ops = clk_gpio_ops;
	init.flags = flags | CLK_IS_BASIC;
	init.parent_names = parent_names;
	init.num_parents = num_parents;

	clk_gpio->gpiod = gpio_to_desc(gpio);
	clk_gpio->hw.init = &init;

	if (dev)
		clk = devm_clk_register(dev, &clk_gpio->hw);
	else
		clk = clk_register(NULL, &clk_gpio->hw);

	if (!IS_ERR(clk))
		return clk;

	if (!dev) {
		gpiod_put(clk_gpio->gpiod);
		kfree(clk_gpio);
	}

	return clk;
}
示例#15
0
文件: gpio_keys.c 项目: mkrufky/linux
static int gpio_keys_setup_key(struct platform_device *pdev,
				struct input_dev *input,
				struct gpio_keys_drvdata *ddata,
				const struct gpio_keys_button *button,
				int idx,
				struct fwnode_handle *child)
{
	const char *desc = button->desc ? button->desc : "gpio_keys";
	struct device *dev = &pdev->dev;
	struct gpio_button_data *bdata = &ddata->data[idx];
	irq_handler_t isr;
	unsigned long irqflags;
	int irq;
	int error;

	bdata->input = input;
	bdata->button = button;
	spin_lock_init(&bdata->lock);

	if (child) {
		bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL,
								child,
								GPIOD_IN,
								desc);
		if (IS_ERR(bdata->gpiod)) {
			error = PTR_ERR(bdata->gpiod);
			if (error == -ENOENT) {
				/*
				 * GPIO is optional, we may be dealing with
				 * purely interrupt-driven setup.
				 */
				bdata->gpiod = NULL;
			} else {
				if (error != -EPROBE_DEFER)
					dev_err(dev, "failed to get gpio: %d\n",
						error);
				return error;
			}
		}
	} else if (gpio_is_valid(button->gpio)) {
		/*
		 * Legacy GPIO number, so request the GPIO here and
		 * convert it to descriptor.
		 */
		unsigned flags = GPIOF_IN;

		if (button->active_low)
			flags |= GPIOF_ACTIVE_LOW;

		error = devm_gpio_request_one(dev, button->gpio, flags, desc);
		if (error < 0) {
			dev_err(dev, "Failed to request GPIO %d, error %d\n",
				button->gpio, error);
			return error;
		}

		bdata->gpiod = gpio_to_desc(button->gpio);
		if (!bdata->gpiod)
			return -EINVAL;
	}

	if (bdata->gpiod) {
		if (button->debounce_interval) {
			error = gpiod_set_debounce(bdata->gpiod,
					button->debounce_interval * 1000);
			/* use timer if gpiolib doesn't provide debounce */
			if (error < 0)
				bdata->software_debounce =
						button->debounce_interval;
		}

		if (button->irq) {
			bdata->irq = button->irq;
		} else {
			irq = gpiod_to_irq(bdata->gpiod);
			if (irq < 0) {
				error = irq;
				dev_err(dev,
					"Unable to get irq number for GPIO %d, error %d\n",
					button->gpio, error);
				return error;
			}
			bdata->irq = irq;
		}

		INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func);

		isr = gpio_keys_gpio_isr;
		irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;

	} else {
		if (!button->irq) {
			dev_err(dev, "Found button without gpio or irq\n");
			return -EINVAL;
		}

		bdata->irq = button->irq;

		if (button->type && button->type != EV_KEY) {
			dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n");
			return -EINVAL;
		}

		bdata->release_delay = button->debounce_interval;
		setup_timer(&bdata->release_timer,
			    gpio_keys_irq_timer, (unsigned long)bdata);

		isr = gpio_keys_irq_isr;
		irqflags = 0;
	}

	bdata->code = &ddata->keymap[idx];
	*bdata->code = button->code;
	input_set_capability(input, button->type ?: EV_KEY, *bdata->code);

	/*
	 * Install custom action to cancel release timer and
	 * workqueue item.
	 */
	error = devm_add_action(dev, gpio_keys_quiesce_key, bdata);
	if (error) {
		dev_err(dev, "failed to register quiesce action, error: %d\n",
			error);
		return error;
	}

	/*
	 * If platform has specified that the button can be disabled,
	 * we don't want it to share the interrupt line.
	 */
	if (!button->can_disable)
		irqflags |= IRQF_SHARED;

	error = devm_request_any_context_irq(dev, bdata->irq, isr, irqflags,
					     desc, bdata);
	if (error < 0) {
		dev_err(dev, "Unable to claim irq %d; error %d\n",
			bdata->irq, error);
		return error;
	}

	return 0;
}
示例#16
0
static int xgold_mc_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *codec_of_node = NULL;
	struct device_node *jack_of_node = NULL;
	struct snd_soc_dai_link *dai_link;
	struct xgold_mc_private *mc_drv_ctx;
	const char *codec_dai_name = NULL;
	int ret = 0;
	int i;

	xgold_debug("%s:\n", __func__);

	xgold_snd_card.dev = &pdev->dev;
	snd_soc_card_set_drvdata(&xgold_snd_card, &audio_native_mode);

#ifdef CONFIG_OF
	codec_of_node = of_parse_phandle(np,
			"intel,audio-codec", 0);

	if (codec_of_node == NULL) {
		xgold_err("Unable to get codec node\n");
		return -ENODEV;
	}

	ret = of_property_read_string(codec_of_node,
				PROP_CODEC_DAI_NAME,
				&codec_dai_name);

	if (ret) {
		xgold_err("Cannot get codec dai name ret %d\n", ret);
		return ret;
	}

	if (!audio_native_mode) {
		for (i = 0; i < xgold_snd_card.num_links; i++) {
			dai_link = &xgold_snd_card.dai_link[i];

			if (!strncmp(dai_link->stream_name, "PCM Audio",
				strlen("PCM Audio"))) {
				dai_link->cpu_of_node =
					dai_link->platform_of_node =
					of_parse_phandle(np, "intel,pcm-audio",
							0);
				dai_link->codec_dai_name = "snd-soc-dummy-dai";
				dai_link->codec_name = "snd-soc-dummy";

			} else if (!strcmp(dai_link->stream_name, "Voice")) {
				/* FIXME: for Voice stream, platform is
				 * snd-soc-dummy */
				dai_link->cpu_of_node = of_parse_phandle(np,
						"intel,pcm-voice", 0);

				dai_link->codec_of_node = codec_of_node;
				dai_link->codec_dai_name = codec_dai_name;

			} else if (!strncmp(dai_link->stream_name,
					"XGOLD_SPEECH_PROBE_",
					strlen("XGOLD_SPEECH_PROBE_"))) {
				dai_link->cpu_of_node =
					dai_link->platform_of_node =
					of_parse_phandle(np, "intel,speech", 0);
				dai_link->codec_dai_name = "snd-soc-dummy-dai";
				dai_link->codec_name = "snd-soc-dummy";
			} else if (!strncmp(dai_link->stream_name,
						"XGOLD_HW_PROBE_A",
						strlen("XGOLD_HW_PROBE_A"))) {
				dai_link->cpu_of_node =
				dai_link->platform_of_node =
				of_parse_phandle(np, "intel,pcm-audio", 0);
				dai_link->codec_dai_name = "snd-soc-dummy-dai";
				dai_link->codec_name = "snd-soc-dummy";
			} else if (!strncmp(dai_link->stream_name,
						"XGOLD_HW_PROBE_B",
						strlen("XGOLD_HW_PROBE_B"))) {
				dai_link->cpu_of_node =
				dai_link->platform_of_node =
				of_parse_phandle(np, "intel,pcm-audio", 0);
				dai_link->codec_dai_name = "snd-soc-dummy-dai";
				dai_link->codec_name = "snd-soc-dummy";
			}

			if (!dai_link->cpu_of_node)
				pr_err("error for %s DAI binding\n",
						dai_link->name);
		}
	} else {
		/* setup devices for native kernel support */
		for (i = 0; i < xgold_snd_card.num_links; i++) {
			dai_link = &xgold_snd_card.dai_link[i];
			dai_link->codec_of_node = codec_of_node;
			dai_link->codec_dai_name = codec_dai_name;

			if (!strncmp(dai_link->stream_name, "PCM Audio",
				strlen("PCM Audio")))
				dai_link->cpu_of_node =
					dai_link->platform_of_node =
					of_parse_phandle(np, "intel,pcm-audio",
							0);
			else if (!strcmp(dai_link->stream_name, "Voice"))
				/* FIXME: for Voice stream, platform is
				 * snd-soc-dummy */
				dai_link->cpu_of_node = of_parse_phandle(np,
						"intel,pcm-voice", 0);
			else if (!strncmp(dai_link->stream_name,
						"XGOLD_SPEECH_PROBE_",
						strlen("XGOLD_SPEECH_PROBE_")))
				dai_link->cpu_of_node =
					dai_link->platform_of_node =
					of_parse_phandle(np, "intel,speech", 0);
			else if (!strncmp(dai_link->stream_name,
							"XGOLD_HW_PROBE_A",
						strlen("XGOLD_HW_PROBE_A")))
				dai_link->cpu_of_node =
				dai_link->platform_of_node =
					of_parse_phandle(np, "intel,pcm-audio",
							0);
			else if (!strncmp(dai_link->stream_name,
						"XGOLD_HW_PROBE_B",
						strlen("XGOLD_HW_PROBE_B")))
				dai_link->cpu_of_node =
				dai_link->platform_of_node =
					of_parse_phandle(np, "intel,pcm-audio",
							0);
			if (!dai_link->cpu_of_node)
				pr_err("error for %s DAI binding\n",
						dai_link->name);
		}
	}
#endif

	ret = snd_soc_register_card(&xgold_snd_card);
	if (ret < 0) {
		xgold_err("%s: unable to register sound card err %d\n",
			  __func__, ret);
		return ret;
	}

	mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC);
	if (!mc_drv_ctx) {
		xgold_err("Allocation failed!\n");
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, mc_drv_ctx);

	/* spk gpio */
	mc_drv_ctx->spk_pin = of_get_named_gpio_flags(np,
			PROP_SPK_AMP_NAME, 0, NULL);

	if (mc_drv_ctx->spk_pin <= 0) {
		xgold_debug("%s: unable to get speaker node %s\n",
			  __func__, PROP_SPK_AMP_NAME);
	} else {
		xgold_debug("%s: Get speaker node %s value: %d !!!\n",
			  __func__, PROP_SPK_AMP_NAME, mc_drv_ctx->spk_pin);
		ret = gpio_request(mc_drv_ctx->spk_pin, PROP_SPK_AMP_NAME);
		if (!ret) {
			xgold_debug("req gpio_request success!:%d\n", ret);
			gpiod_direction_output(
				gpio_to_desc(mc_drv_ctx->spk_pin), 0);
		} else {
			xgold_err("req gpio_request failed:%d\n", ret);
		}
	}

	jack_of_node = of_parse_phandle(np, "intel,jack", 0);
	if (!jack_of_node)
		return 0;

	mc_drv_ctx->jack = of_xgold_jack_probe(pdev, jack_of_node, &hs_jack);
	if (IS_ERR_OR_NULL(mc_drv_ctx->jack)) {
		xgold_err("Jack detection probe failed.\n");
		mc_drv_ctx->jack = NULL;
		/* Allow machine probe to succeed anyway */
	}

	mc_dev_ctx = mc_drv_ctx;

	return 0;
}