diff options
Diffstat (limited to 'drivers/gpio/gpio-samsung.c')
| -rw-r--r-- | drivers/gpio/gpio-samsung.c | 103 | 
1 files changed, 63 insertions, 40 deletions
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index ba126cc0407..8af4b06e80f 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -938,6 +938,67 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)  		s3c_gpiolib_track(chip);  } +#if defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) +static int s3c24xx_gpio_xlate(struct gpio_chip *gc, +			const struct of_phandle_args *gpiospec, u32 *flags) +{ +	unsigned int pin; + +	if (WARN_ON(gc->of_gpio_n_cells < 3)) +		return -EINVAL; + +	if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) +		return -EINVAL; + +	if (gpiospec->args[0] > gc->ngpio) +		return -EINVAL; + +	pin = gc->base + gpiospec->args[0]; + +	if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1]))) +		pr_warn("gpio_xlate: failed to set pin function\n"); +	if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff)) +		pr_warn("gpio_xlate: failed to set pin pull up/down\n"); + +	if (flags) +		*flags = gpiospec->args[2] >> 16; + +	return gpiospec->args[0]; +} + +static const struct of_device_id s3c24xx_gpio_dt_match[] __initdata = { +	{ .compatible = "samsung,s3c24xx-gpio", }, +	{} +}; + +static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, +						 u64 base, u64 offset) +{ +	struct gpio_chip *gc =  &chip->chip; +	u64 address; + +	if (!of_have_populated_dt()) +		return; + +	address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset; +	gc->of_node = of_find_matching_node_by_address(NULL, +			s3c24xx_gpio_dt_match, address); +	if (!gc->of_node) { +		pr_info("gpio: device tree node not found for gpio controller" +			" with base address %08llx\n", address); +		return; +	} +	gc->of_gpio_n_cells = 3; +	gc->of_xlate = s3c24xx_gpio_xlate; +} +#else +static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, +						 u64 base, u64 offset) +{ +	return; +} +#endif /* defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) */ +  static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,  					     int nr_chips, void __iomem *base)  { @@ -962,6 +1023,8 @@ static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,  			gc->direction_output = samsung_gpiolib_2bit_output;  		samsung_gpiolib_add(chip); + +		s3c24xx_gpiolib_attach_ofnode(chip, S3C24XX_PA_GPIO, i * 0x10);  	}  } @@ -3131,46 +3194,6 @@ samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)  }  EXPORT_SYMBOL(s3c_gpio_getpull); -/* gpiolib wrappers until these are totally eliminated */ - -void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) -{ -	int ret; - -	WARN_ON(to);	/* should be none of these left */ - -	if (!to) { -		/* if pull is enabled, try first with up, and if that -		 * fails, try using down */ - -		ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP); -		if (ret) -			s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN); -	} else { -		s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE); -	} -} -EXPORT_SYMBOL(s3c2410_gpio_pullup); - -void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) -{ -	/* do this via gpiolib until all users removed */ - -	gpio_request(pin, "temporary"); -	gpio_set_value(pin, to); -	gpio_free(pin); -} -EXPORT_SYMBOL(s3c2410_gpio_setpin); - -unsigned int s3c2410_gpio_getpin(unsigned int pin) -{ -	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); -	unsigned long offs = pin - chip->chip.base; - -	return __raw_readl(chip->base + 0x04) & (1 << offs); -} -EXPORT_SYMBOL(s3c2410_gpio_getpin); -  #ifdef CONFIG_S5P_GPIO_DRVSTR  s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)  {  |