static int microchip_sgpio_register_bank()

in pinctrl-microchip-sgpio.c [696:812]


static int microchip_sgpio_register_bank(struct device *dev,
					 struct sgpio_priv *priv,
					 struct fwnode_handle *fwnode,
					 int bankno)
{
	struct pinctrl_pin_desc *pins;
	struct pinctrl_desc *pctl_desc;
	struct pinctrl_dev *pctldev;
	struct sgpio_bank *bank;
	struct gpio_chip *gc;
	u32 ngpios;
	int i, ret;

	/* Get overall bank struct */
	bank = (bankno == 0) ? &priv->in : &priv->out;
	bank->priv = priv;

	if (fwnode_property_read_u32(fwnode, "ngpios", &ngpios)) {
		dev_info(dev, "failed to get number of gpios for bank%d\n",
			 bankno);
		ngpios = 64;
	}

	priv->bitcount = ngpios / SGPIO_BITS_PER_WORD;
	if (priv->bitcount > SGPIO_MAX_BITS) {
		dev_err(dev, "Bit width exceeds maximum (%d)\n",
			SGPIO_MAX_BITS);
		return -EINVAL;
	}

	pctl_desc = &bank->pctl_desc;
	pctl_desc->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%sput",
					 dev_name(dev),
					 bank->is_input ? "in" : "out");
	pctl_desc->pctlops = &sgpio_pctl_ops;
	pctl_desc->pmxops = &sgpio_pmx_ops;
	pctl_desc->confops = &sgpio_confops;
	pctl_desc->owner = THIS_MODULE;

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

	pctl_desc->npins = ngpios;
	pctl_desc->pins = pins;

	for (i = 0; i < ngpios; i++) {
		struct sgpio_port_addr addr;

		sgpio_pin_to_addr(priv, i, &addr);

		pins[i].number = i;
		pins[i].name = devm_kasprintf(dev, GFP_KERNEL,
					      "SGPIO_%c_p%db%d",
					      bank->is_input ? 'I' : 'O',
					      addr.port, addr.bit);
		if (!pins[i].name)
			return -ENOMEM;
	}

	pctldev = devm_pinctrl_register(dev, pctl_desc, bank);
	if (IS_ERR(pctldev))
		return dev_err_probe(dev, PTR_ERR(pctldev), "Failed to register pinctrl\n");

	gc			= &bank->gpio;
	gc->label		= pctl_desc->name;
	gc->parent		= dev;
	gc->of_node		= to_of_node(fwnode);
	gc->owner		= THIS_MODULE;
	gc->get_direction	= microchip_sgpio_get_direction;
	gc->direction_input	= microchip_sgpio_direction_input;
	gc->direction_output	= microchip_sgpio_direction_output;
	gc->get			= microchip_sgpio_get_value;
	gc->set			= microchip_sgpio_set_value;
	gc->request		= gpiochip_generic_request;
	gc->free		= gpiochip_generic_free;
	gc->of_xlate		= microchip_sgpio_of_xlate;
	gc->of_gpio_n_cells     = 3;
	gc->base		= -1;
	gc->ngpio		= ngpios;

	if (bank->is_input && priv->properties->flags & SGPIO_FLAGS_HAS_IRQ) {
		int irq = fwnode_irq_get(fwnode, 0);

		if (irq) {
			struct gpio_irq_chip *girq = &gc->irq;

			girq->chip = devm_kmemdup(dev, &microchip_sgpio_irqchip,
						  sizeof(microchip_sgpio_irqchip),
						  GFP_KERNEL);
			if (!girq->chip)
				return -ENOMEM;
			girq->parent_handler = sgpio_irq_handler;
			girq->num_parents = 1;
			girq->parents = devm_kcalloc(dev, 1,
						     sizeof(*girq->parents),
						     GFP_KERNEL);
			if (!girq->parents)
				return -ENOMEM;
			girq->parents[0] = irq;
			girq->default_type = IRQ_TYPE_NONE;
			girq->handler = handle_bad_irq;

			/* Disable all individual pins */
			for (i = 0; i < SGPIO_MAX_BITS; i++)
				sgpio_writel(priv, 0, REG_INT_ENABLE, i);
			/* Master enable */
			sgpio_clrsetbits(priv, REG_SIO_CONFIG, 0, 0, SGPIO_MASTER_INTR_ENA);
		}
	}

	ret = devm_gpiochip_add_data(dev, gc, bank);
	if (ret)
		dev_err(dev, "Failed to register: ret %d\n", ret);

	return ret;
}