diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-sirf.c')
| -rw-r--r-- | drivers/pinctrl/pinctrl-sirf.c | 70 | 
1 files changed, 68 insertions, 2 deletions
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index a4f0c5e487d..d02498b30c6 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1246,7 +1246,23 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)  	return of_iomap(np, 0);  } -static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) +static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc, +       const struct of_phandle_args *gpiospec, +       u32 *flags) +{ +       if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE) +               return -EINVAL; + +       if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc) +               return -EINVAL; + +       if (flags) +               *flags = gpiospec->args[1]; + +       return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE; +} + +static int sirfsoc_pinmux_probe(struct platform_device *pdev)  {  	int ret;  	struct sirfsoc_pmx *spmx; @@ -1663,7 +1679,45 @@ const struct irq_domain_ops sirfsoc_gpio_irq_simple_ops = {  	.xlate = irq_domain_xlate_twocell,  }; -static int __devinit sirfsoc_gpio_probe(struct device_node *np) +static void sirfsoc_gpio_set_pullup(const u32 *pullups) +{ +	int i, n; +	const unsigned long *p = (const unsigned long *)pullups; + +	for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { +		n = find_first_bit(p + i, BITS_PER_LONG); +		while (n < BITS_PER_LONG) { +			u32 offset = SIRFSOC_GPIO_CTRL(i, n); +			u32 val = readl(sgpio_bank[i].chip.regs + offset); +			val |= SIRFSOC_GPIO_CTL_PULL_MASK; +			val |= SIRFSOC_GPIO_CTL_PULL_HIGH; +			writel(val, sgpio_bank[i].chip.regs + offset); + +			n = find_next_bit(p + i, BITS_PER_LONG, n + 1); +		} +	} +} + +static void sirfsoc_gpio_set_pulldown(const u32 *pulldowns) +{ +	int i, n; +	const unsigned long *p = (const unsigned long *)pulldowns; + +	for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { +		n = find_first_bit(p + i, BITS_PER_LONG); +		while (n < BITS_PER_LONG) { +			u32 offset = SIRFSOC_GPIO_CTRL(i, n); +			u32 val = readl(sgpio_bank[i].chip.regs + offset); +			val |= SIRFSOC_GPIO_CTL_PULL_MASK; +			val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH; +			writel(val, sgpio_bank[i].chip.regs + offset); + +			n = find_next_bit(p + i, BITS_PER_LONG, n + 1); +		} +	} +} + +static int sirfsoc_gpio_probe(struct device_node *np)  {  	int i, err = 0;  	struct sirfsoc_gpio_bank *bank; @@ -1671,6 +1725,8 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)  	struct platform_device *pdev;  	bool is_marco = false; +	u32 pullups[SIRFSOC_GPIO_NO_OF_BANKS], pulldowns[SIRFSOC_GPIO_NO_OF_BANKS]; +  	pdev = of_find_device_by_node(np);  	if (!pdev)  		return -ENODEV; @@ -1696,6 +1752,8 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)  		bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;  		bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);  		bank->chip.gc.of_node = np; +		bank->chip.gc.of_xlate = sirfsoc_gpio_of_xlate; +		bank->chip.gc.of_gpio_n_cells = 2;  		bank->chip.regs = regs;  		bank->id = i;  		bank->is_marco = is_marco; @@ -1726,6 +1784,14 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)  		irq_set_handler_data(bank->parent_irq, bank);  	} +	if (!of_property_read_u32_array(np, "sirf,pullups", pullups, +		SIRFSOC_GPIO_NO_OF_BANKS)) +		sirfsoc_gpio_set_pullup(pullups); + +	if (!of_property_read_u32_array(np, "sirf,pulldowns", pulldowns, +		SIRFSOC_GPIO_NO_OF_BANKS)) +		sirfsoc_gpio_set_pulldown(pulldowns); +  	return 0;  out:  |