static int dc_gpiochip_add(struct dc_pinmap *pmap, struct device_node *np)
{
	struct gpio_chip *chip = &pmap->chip;
	int ret;

	chip->label		= DRIVER_NAME;
	chip->parent		= pmap->dev;
	chip->request		= gpiochip_generic_request;
	chip->free		= gpiochip_generic_free;
	chip->direction_input	= dc_gpio_direction_input;
	chip->direction_output	= dc_gpio_direction_output;
	chip->get		= dc_gpio_get;
	chip->set		= dc_gpio_set;
	chip->base		= -1;
	chip->ngpio		= PINS_COUNT;
	chip->of_node		= np;
	chip->of_gpio_n_cells	= 2;

	spin_lock_init(&pmap->lock);

	ret = gpiochip_add_data(chip, pmap);
	if (ret < 0)
		return ret;

	ret = gpiochip_add_pin_range(chip, dev_name(pmap->dev), 0, 0,
				     PINS_COUNT);
	if (ret < 0) {
		gpiochip_remove(chip);
		return ret;
	}

	return 0;
}
Beispiel #2
0
static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
	struct device_node *np = chip->of_node;
	struct of_phandle_args pinspec;
	struct pinctrl_dev *pctldev;
	int index = 0, ret;

	if (!np)
		return;

	for (;; index++) {
		ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
				index, &pinspec);
		if (ret)
			break;

		pctldev = of_pinctrl_get(pinspec.np);
		if (!pctldev)
			break;

		ret = gpiochip_add_pin_range(chip,
					     pinctrl_dev_get_devname(pctldev),
					     pinspec.args[0],
					     pinspec.args[1],
					     pinspec.args[2]);

		if (ret)
			break;
	}
}
Beispiel #3
0
static int as3722_pinctrl_probe(struct platform_device *pdev)
{
	struct as3722_pctrl_info *as_pci;
	int ret;

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

	as_pci->dev = &pdev->dev;
	as_pci->dev->of_node = pdev->dev.parent->of_node;
	as_pci->as3722 = dev_get_drvdata(pdev->dev.parent);
	platform_set_drvdata(pdev, as_pci);

	as_pci->pins = as3722_pins_desc;
	as_pci->num_pins = ARRAY_SIZE(as3722_pins_desc);
	as_pci->functions = as3722_pin_function;
	as_pci->num_functions = ARRAY_SIZE(as3722_pin_function);
	as_pci->pin_groups = as3722_pingroups;
	as_pci->num_pin_groups = ARRAY_SIZE(as3722_pingroups);
	as3722_pinctrl_desc.name = dev_name(&pdev->dev);
	as3722_pinctrl_desc.pins = as3722_pins_desc;
	as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc);
	as_pci->pctl = pinctrl_register(&as3722_pinctrl_desc,
					&pdev->dev, as_pci);
	if (!as_pci->pctl) {
		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
		return -EINVAL;
	}

	as_pci->gpio_chip = as3722_gpio_chip;
	as_pci->gpio_chip.dev = &pdev->dev;
	as_pci->gpio_chip.of_node = pdev->dev.parent->of_node;
	ret = gpiochip_add(&as_pci->gpio_chip);
	if (ret < 0) {
		dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret);
		goto fail_chip_add;
	}

	ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev),
				0, 0, AS3722_PIN_NUM);
	if (ret < 0) {
		dev_err(&pdev->dev, "Couldn't add pin range, %d\n", ret);
		goto fail_range_add;
	}

	return 0;

fail_range_add:
	gpiochip_remove(&as_pci->gpio_chip);
fail_chip_add:
	pinctrl_unregister(as_pci->pctl);
	return ret;
}
int wmt_pinctrl_probe(struct platform_device *pdev,
		      struct wmt_pinctrl_data *data)
{
	int err;
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	data->base = devm_request_and_ioremap(&pdev->dev, res);
	if (!data->base) {
		dev_err(&pdev->dev, "failed to map memory resource\n");
		return -EBUSY;
	}

	wmt_desc.pins = data->pins;
	wmt_desc.npins = data->npins;

	data->gpio_chip = wmt_gpio_chip;
	data->gpio_chip.dev = &pdev->dev;
	data->gpio_chip.of_node = pdev->dev.of_node;
	data->gpio_chip.ngpio = data->nbanks * 32;

	platform_set_drvdata(pdev, data);

	data->dev = &pdev->dev;

	data->pctl_dev = pinctrl_register(&wmt_desc, &pdev->dev, data);
	if (!data->pctl_dev) {
		dev_err(&pdev->dev, "Failed to register pinctrl\n");
		return -EINVAL;
	}

	err = gpiochip_add(&data->gpio_chip);
	if (err) {
		dev_err(&pdev->dev, "could not add GPIO chip\n");
		goto fail_gpio;
	}

	err = gpiochip_add_pin_range(&data->gpio_chip, dev_name(data->dev),
				     0, 0, data->nbanks * 32);
	if (err)
		goto fail_range;

	dev_info(&pdev->dev, "Pin controller initialized\n");

	return 0;

fail_range:
	if (gpiochip_remove(&data->gpio_chip))
		dev_err(&pdev->dev, "failed to remove gpio chip\n");
fail_gpio:
	pinctrl_unregister(data->pctl_dev);
	return err;
}
static int meson_gpiolib_register(struct amlogic_pmx  *pc)
{
	struct meson_domain *domain;
	int i, ret;

	for (i = 0; i < pc->soc->num_domains; i++) {
		domain = &pc->domains[i];

		domain->chip.label = domain->data->name;
		domain->chip.dev = pc->dev;
		domain->chip.request = meson_gpio_request;
		domain->chip.free = meson_gpio_free;
		domain->chip.direction_input = meson_gpio_direction_input;
		domain->chip.direction_output = meson_gpio_direction_output;
		domain->chip.get = meson_gpio_get;
		domain->chip.set = meson_gpio_set;
		domain->chip.set_pullup_down = meson_gpio_set_pullup_down;
		domain->chip.set_gpio_to_irq = meson_gpio_to_irq;
		domain->chip.base = -1;
		domain->chip.ngpio = domain->data->num_pins;
		domain->chip.can_sleep = false;
		domain->chip.of_node = domain->of_node;
		domain->chip.of_gpio_n_cells = 2;

		ret = gpiochip_add(&domain->chip);
		if (ret) {
			dev_err(pc->dev, "can't add gpio chip %s\n",
				domain->data->name);
			goto fail;
		}

		ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev),
					     0, domain->data->pin_base,
					     domain->chip.ngpio);
		if (ret) {
			dev_err(pc->dev, "can't add pin range\n");
			goto fail;
		}
	}

	return 0;
fail:
	return ret;
}
Beispiel #6
0
static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
	struct device_node *np = chip->of_node;
	struct of_phandle_args pinspec;
	struct pinctrl_dev *pctldev;
	int index = 0, ret;

	if (!np)
		return;

	do {
		ret = of_parse_phandle_with_args(np, "gpio-ranges",
				"#gpio-range-cells", index, &pinspec);
		if (ret)
			break;

		pctldev = of_pinctrl_get(pinspec.np);
		if (!pctldev)
			break;

		/*
		 * This assumes that the n GPIO pins are consecutive in the
		 * GPIO number space, and that the pins are also consecutive
		 * in their local number space. Currently it is not possible
		 * to add different ranges for one and the same GPIO chip,
		 * as the code assumes that we have one consecutive range
		 * on both, mapping 1-to-1.
		 *
		 * TODO: make the OF bindings handle multiple sparse ranges
		 * on the same GPIO chip.
		 */
		ret = gpiochip_add_pin_range(chip,
					     pinctrl_dev_get_name(pctldev),
					     0, /* offset in gpiochip */
					     pinspec.args[0],
					     pinspec.args[1]);

		if (ret)
			break;

	} while (index++);
}
Beispiel #7
0
static int meson_gpiolib_register(struct meson_pinctrl *pc)
{
	int ret;

	pc->chip.label = pc->data->name;
	pc->chip.parent = pc->dev;
	pc->chip.request = meson_gpio_request;
	pc->chip.free = meson_gpio_free;
	pc->chip.direction_input = meson_gpio_direction_input;
	pc->chip.direction_output = meson_gpio_direction_output;
	pc->chip.get = meson_gpio_get;
	pc->chip.set = meson_gpio_set;
	pc->chip.base = pc->data->pin_base;
	pc->chip.ngpio = pc->data->num_pins;
	pc->chip.can_sleep = false;
	pc->chip.of_node = pc->of_node;
	pc->chip.of_gpio_n_cells = 2;

	ret = gpiochip_add_data(&pc->chip, pc);
	if (ret) {
		dev_err(pc->dev, "can't add gpio chip %s\n",
			pc->data->name);
		goto fail;
	}

	ret = gpiochip_add_pin_range(&pc->chip, dev_name(pc->dev),
				     0, pc->data->pin_base,
				     pc->chip.ngpio);
	if (ret) {
		dev_err(pc->dev, "can't add pin range\n");
		goto fail;
	}

	return 0;
fail:
	gpiochip_remove(&pc->chip);

	return ret;
}
Beispiel #8
0
static int em_gio_probe(struct platform_device *pdev)
{
	struct gpio_em_config pdata_dt;
	struct gpio_em_config *pdata = dev_get_platdata(&pdev->dev);
	struct em_gio_priv *p;
	struct resource *io[2], *irq[2];
	struct gpio_chip *gpio_chip;
	irq_chip_no_const *irq_chip;
	const char *name = dev_name(&pdev->dev);
	int ret;

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

	p->pdev = pdev;
	platform_set_drvdata(pdev, p);
	spin_lock_init(&p->sense_lock);

	io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);

	if (!io[0] || !io[1] || !irq[0] || !irq[1]) {
		dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
		ret = -EINVAL;
		goto err0;
	}

	p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start,
					resource_size(io[0]));
	if (!p->base0) {
		dev_err(&pdev->dev, "failed to remap low I/O memory\n");
		ret = -ENXIO;
		goto err0;
	}

	p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start,
				   resource_size(io[1]));
	if (!p->base1) {
		dev_err(&pdev->dev, "failed to remap high I/O memory\n");
		ret = -ENXIO;
		goto err0;
	}

	if (!pdata) {
		memset(&pdata_dt, 0, sizeof(pdata_dt));
		pdata = &pdata_dt;

		if (of_property_read_u32(pdev->dev.of_node, "ngpios",
					 &pdata->number_of_pins)) {
			dev_err(&pdev->dev, "Missing ngpios OF property\n");
			ret = -EINVAL;
			goto err0;
		}

		pdata->gpio_base = -1;
	}

	gpio_chip = &p->gpio_chip;
	gpio_chip->of_node = pdev->dev.of_node;
	gpio_chip->direction_input = em_gio_direction_input;
	gpio_chip->get = em_gio_get;
	gpio_chip->direction_output = em_gio_direction_output;
	gpio_chip->set = em_gio_set;
	gpio_chip->to_irq = em_gio_to_irq;
	gpio_chip->request = em_gio_request;
	gpio_chip->free = em_gio_free;
	gpio_chip->label = name;
	gpio_chip->dev = &pdev->dev;
	gpio_chip->owner = THIS_MODULE;
	gpio_chip->base = pdata->gpio_base;
	gpio_chip->ngpio = pdata->number_of_pins;

	irq_chip = &p->irq_chip;
	irq_chip->name = name;
	irq_chip->irq_mask = em_gio_irq_disable;
	irq_chip->irq_unmask = em_gio_irq_enable;
	irq_chip->irq_set_type = em_gio_irq_set_type;
	irq_chip->irq_request_resources = em_gio_irq_reqres;
	irq_chip->irq_release_resources = em_gio_irq_relres;
	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;

	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
					      pdata->number_of_pins,
					      pdata->irq_base,
					      &em_gio_irq_domain_ops, p);
	if (!p->irq_domain) {
		ret = -ENXIO;
		dev_err(&pdev->dev, "cannot initialize irq domain\n");
		goto err0;
	}

	if (devm_request_irq(&pdev->dev, irq[0]->start,
			     em_gio_irq_handler, 0, name, p)) {
		dev_err(&pdev->dev, "failed to request low IRQ\n");
		ret = -ENOENT;
		goto err1;
	}

	if (devm_request_irq(&pdev->dev, irq[1]->start,
			     em_gio_irq_handler, 0, name, p)) {
		dev_err(&pdev->dev, "failed to request high IRQ\n");
		ret = -ENOENT;
		goto err1;
	}

	ret = gpiochip_add(gpio_chip);
	if (ret) {
		dev_err(&pdev->dev, "failed to add GPIO controller\n");
		goto err1;
	}

	if (pdata->pctl_name) {
		ret = gpiochip_add_pin_range(gpio_chip, pdata->pctl_name, 0,
					     gpio_chip->base, gpio_chip->ngpio);
		if (ret < 0)
			dev_warn(&pdev->dev, "failed to add pin range\n");
	}
	return 0;

err1:
	irq_domain_remove(p->irq_domain);
err0:
	return ret;
}
Beispiel #9
0
int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
{
	struct sh_pfc_chip *chip;
	phys_addr_t address;
	unsigned int i;

	if (pfc->info->data_regs == NULL)
		return 0;

	/* Find the memory window that contain the GPIO registers. Boards that
	 * register a separate GPIO device will not supply a memory resource
	 * that covers the data registers. In that case don't try to handle
	 * GPIOs.
	 */
	address = pfc->info->data_regs[0].reg;
	for (i = 0; i < pfc->num_windows; ++i) {
		struct sh_pfc_window *window = &pfc->windows[i];

		if (address >= window->phys &&
		    address < window->phys + window->size)
			break;
	}

	if (i == pfc->num_windows)
		return 0;

	/* If we have IRQ resources make sure their number is correct. */
	if (pfc->num_irqs != pfc->info->gpio_irq_size) {
		dev_err(pfc->dev, "invalid number of IRQ resources\n");
		return -EINVAL;
	}

	/* Register the real GPIOs chip. */
	chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]);
	if (IS_ERR(chip))
		return PTR_ERR(chip);

	pfc->gpio = chip;

	if (IS_ENABLED(CONFIG_OF) && pfc->dev->of_node)
		return 0;

#ifdef CONFIG_SUPERH
	/*
	 * Register the GPIO to pin mappings. As pins with GPIO ports
	 * must come first in the ranges, skip the pins without GPIO
	 * ports by stopping at the first range that contains such a
	 * pin.
	 */
	for (i = 0; i < pfc->nr_ranges; ++i) {
		const struct sh_pfc_pin_range *range = &pfc->ranges[i];
		int ret;

		if (range->start >= pfc->nr_gpio_pins)
			break;

		ret = gpiochip_add_pin_range(&chip->gpio_chip,
			dev_name(pfc->dev), range->start, range->start,
			range->end - range->start + 1);
		if (ret < 0)
			return ret;
	}

	/* Register the function GPIOs chip. */
	if (pfc->info->nr_func_gpios == 0)
		return 0;

	chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup, NULL);
	if (IS_ERR(chip))
		return PTR_ERR(chip);
#endif /* CONFIG_SUPERH */

	return 0;
}
Beispiel #10
0
static int pmic_mpp_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct pinctrl_pin_desc *pindesc;
	struct pinctrl_desc *pctrldesc;
	struct pmic_mpp_pad *pad, *pads;
	struct pmic_mpp_state *state;
	int ret, npins, i;
	u32 reg;

	ret = of_property_read_u32(dev->of_node, "reg", &reg);
	if (ret < 0) {
		dev_err(dev, "missing base address");
		return ret;
	}

	npins = platform_irq_count(pdev);
	if (!npins)
		return -EINVAL;
	if (npins < 0)
		return npins;

	BUG_ON(npins > ARRAY_SIZE(pmic_mpp_groups));

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

	platform_set_drvdata(pdev, state);

	state->dev = &pdev->dev;
	state->map = dev_get_regmap(dev->parent, NULL);

	pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
	if (!pindesc)
		return -ENOMEM;

	pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
	if (!pads)
		return -ENOMEM;

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

	pctrldesc->pctlops = &pmic_mpp_pinctrl_ops;
	pctrldesc->pmxops = &pmic_mpp_pinmux_ops;
	pctrldesc->confops = &pmic_mpp_pinconf_ops;
	pctrldesc->owner = THIS_MODULE;
	pctrldesc->name = dev_name(dev);
	pctrldesc->pins = pindesc;
	pctrldesc->npins = npins;

	pctrldesc->num_custom_params = ARRAY_SIZE(pmic_mpp_bindings);
	pctrldesc->custom_params = pmic_mpp_bindings;
#ifdef CONFIG_DEBUG_FS
	pctrldesc->custom_conf_items = pmic_conf_items;
#endif

	for (i = 0; i < npins; i++, pindesc++) {
		pad = &pads[i];
		pindesc->drv_data = pad;
		pindesc->number = i;
		pindesc->name = pmic_mpp_groups[i];

		pad->irq = platform_get_irq(pdev, i);
		if (pad->irq < 0)
			return pad->irq;

		pad->base = reg + i * PMIC_MPP_ADDRESS_RANGE;

		ret = pmic_mpp_populate(state, pad);
		if (ret < 0)
			return ret;
	}

	state->chip = pmic_mpp_gpio_template;
	state->chip.parent = dev;
	state->chip.base = -1;
	state->chip.ngpio = npins;
	state->chip.label = dev_name(dev);
	state->chip.of_gpio_n_cells = 2;
	state->chip.can_sleep = false;

	state->ctrl = pinctrl_register(pctrldesc, dev, state);
	if (IS_ERR(state->ctrl))
		return PTR_ERR(state->ctrl);

	ret = gpiochip_add_data(&state->chip, state);
	if (ret) {
		dev_err(state->dev, "can't add gpio chip\n");
		goto err_chip;
	}

	ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
	if (ret) {
		dev_err(dev, "failed to add pin range\n");
		goto err_range;
	}

	return 0;

err_range:
	gpiochip_remove(&state->chip);
err_chip:
	pinctrl_unregister(state->ctrl);
	return ret;
}
Beispiel #11
0
static int axp_pinctrl_probe(struct platform_device *pdev)
{
	struct device           *dev = &pdev->dev;
	struct axp_pinctrl      *pctl;
	struct pinctrl_pin_desc *pins;
	int    ret;
	int    i, rc;
	
	/* allocate and initialize axp-pinctrl */
	pctl = devm_kzalloc(dev, sizeof(*pctl), GFP_KERNEL);
	if (!pctl) {
		dev_err(dev, "allocate memory for axp-pinctrl structure failed\n");
		return -ENOMEM;
	}
	platform_set_drvdata(pdev, pctl);
	pctl->dev  = dev;
	pctl->desc = &axp_pinctrl_pins_desc;
	
	ret = axp_pinctrl_build_state(pdev);
	if (ret) {
		dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
		return ret;
	}
	/* register axp pinctrl */
	pins = devm_kzalloc(&pdev->dev,
			    pctl->desc->npins * sizeof(*pins),
			    GFP_KERNEL);
	if (!pins) {
		return -ENOMEM;
	}
	for (i = 0; i < pctl->desc->npins; i++) {
		pins[i] = pctl->desc->pins[i].pin;
	}
	axp_pinctrl_desc.name = dev_name(&pdev->dev);
	axp_pinctrl_desc.owner = THIS_MODULE;
	axp_pinctrl_desc.pins = pins;
	axp_pinctrl_desc.npins = pctl->desc->npins;
	pctl->pctl_dev = pinctrl_register(&axp_pinctrl_desc, dev, pctl);
	if (!pctl->pctl_dev) {
		rc = gpiochip_remove(pctl->gpio_chip);
		if (rc < 0)
			return rc;
		return -EINVAL;
	}
	/* initialize axp-gpio-chip */
	pctl->gpio_chip      = &axp_gpio_chip;
	pctl->gpio_chip->dev = dev;
	ret = gpiochip_add(pctl->gpio_chip);
	if (ret) {
		dev_err(dev, "could not add GPIO chip\n");
		return ret;
	}
	for (i = 0; i < pctl->desc->npins; i++) {
		const struct axp_desc_pin *pin = pctl->desc->pins + i;

		ret = gpiochip_add_pin_range(pctl->gpio_chip, dev_name(&pdev->dev),
					     pin->pin.number,
					     pin->pin.number, 1);
		if (ret) {
			dev_err(dev, "could not add GPIO pin range\n");
			rc = gpiochip_remove(pctl->gpio_chip);
			if (rc < 0)
				return rc;
			return ret;
		}
	}
	
	axp_pinctrl_parse_pin_cfg(pdev);
	
	return 0;
}
static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
	struct device_node *np = chip->of_node;
	struct of_phandle_args pinspec;
	struct pinctrl_dev *pctldev;
	int index = 0, ret;
	const char *name;
	static const char group_names_propname[] = "gpio-ranges-group-names";
	struct property *group_names;

	if (!np)
		return;

	group_names = of_find_property(np, group_names_propname, NULL);

	for (;; index++) {
		ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
				index, &pinspec);
		if (ret)
			break;

		pctldev = of_pinctrl_get(pinspec.np);
		if (!pctldev)
			break;

		if (pinspec.args[2]) {
			if (group_names) {
				ret = of_property_read_string_index(np,
						group_names_propname,
						index, &name);
				if (strlen(name)) {
					pr_err("%s: Group name of numeric GPIO ranges must be the empty string.\n",
						np->full_name);
					break;
				}
			}
			/* npins != 0: linear range */
			ret = gpiochip_add_pin_range(chip,
					pinctrl_dev_get_devname(pctldev),
					pinspec.args[0],
					pinspec.args[1],
					pinspec.args[2]);
			if (ret)
				break;
		} else {
			/* npins == 0: special range */
			if (pinspec.args[1]) {
				pr_err("%s: Illegal gpio-range format.\n",
					np->full_name);
				break;
			}

			if (!group_names) {
				pr_err("%s: GPIO group range requested but no %s property.\n",
					np->full_name, group_names_propname);
				break;
			}

			ret = of_property_read_string_index(np,
						group_names_propname,
						index, &name);
			if (ret)
				break;

			if (!strlen(name)) {
				pr_err("%s: Group name of GPIO group range cannot be the empty string.\n",
				np->full_name);
				break;
			}

			ret = gpiochip_add_pingroup_range(chip, pctldev,
						pinspec.args[0], name);
			if (ret)
				break;
		}
	}
}
Beispiel #13
0
static int gpio_rcar_probe(struct platform_device *pdev)
{
	struct gpio_rcar_priv *p;
	struct resource *io, *irq;
	struct gpio_chip *gpio_chip;
	struct irq_chip *irq_chip;
	const char *name = dev_name(&pdev->dev);
	int ret;

	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
	if (!p) {
		dev_err(&pdev->dev, "failed to allocate driver data\n");
		ret = -ENOMEM;
		goto err0;
	}

	p->pdev = pdev;
	spin_lock_init(&p->lock);

	/* Get device configuration from DT node or platform data. */
	gpio_rcar_parse_pdata(p);

	platform_set_drvdata(pdev, p);

	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

	if (!io || !irq) {
		dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
		ret = -EINVAL;
		goto err0;
	}

	p->base = devm_ioremap_nocache(&pdev->dev, io->start,
				       resource_size(io));
	if (!p->base) {
		dev_err(&pdev->dev, "failed to remap I/O memory\n");
		ret = -ENXIO;
		goto err0;
	}

	gpio_chip = &p->gpio_chip;
	gpio_chip->request = gpio_rcar_request;
	gpio_chip->free = gpio_rcar_free;
	gpio_chip->direction_input = gpio_rcar_direction_input;
	gpio_chip->get = gpio_rcar_get;
	gpio_chip->direction_output = gpio_rcar_direction_output;
	gpio_chip->set = gpio_rcar_set;
	gpio_chip->to_irq = gpio_rcar_to_irq;
	gpio_chip->label = name;
	gpio_chip->dev = &pdev->dev;
	gpio_chip->owner = THIS_MODULE;
	gpio_chip->base = p->config.gpio_base;
	gpio_chip->ngpio = p->config.number_of_pins;

	irq_chip = &p->irq_chip;
	irq_chip->name = name;
	irq_chip->irq_mask = gpio_rcar_irq_disable;
	irq_chip->irq_unmask = gpio_rcar_irq_enable;
	irq_chip->irq_enable = gpio_rcar_irq_enable;
	irq_chip->irq_disable = gpio_rcar_irq_disable;
	irq_chip->irq_set_type = gpio_rcar_irq_set_type;
	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED;

	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
					      p->config.number_of_pins,
					      p->config.irq_base,
					      &gpio_rcar_irq_domain_ops, p);
	if (!p->irq_domain) {
		ret = -ENXIO;
		dev_err(&pdev->dev, "cannot initialize irq domain\n");
		goto err1;
	}

	if (devm_request_irq(&pdev->dev, irq->start,
			     gpio_rcar_irq_handler, IRQF_SHARED, name, p)) {
		dev_err(&pdev->dev, "failed to request IRQ\n");
		ret = -ENOENT;
		goto err1;
	}

	ret = gpiochip_add(gpio_chip);
	if (ret) {
		dev_err(&pdev->dev, "failed to add GPIO controller\n");
		goto err1;
	}

	dev_info(&pdev->dev, "driving %d GPIOs\n", p->config.number_of_pins);

	/* warn in case of mismatch if irq base is specified */
	if (p->config.irq_base) {
		ret = irq_find_mapping(p->irq_domain, 0);
		if (p->config.irq_base != ret)
			dev_warn(&pdev->dev, "irq base mismatch (%u/%u)\n",
				 p->config.irq_base, ret);
	}

	if (p->config.pctl_name) {
		ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0,
					     gpio_chip->base, gpio_chip->ngpio);
		if (ret < 0)
			dev_warn(&pdev->dev, "failed to add pin range\n");
	}

	return 0;

err1:
	irq_domain_remove(p->irq_domain);
err0:
	return ret;
}