ath79: add support for reset key on MikroTik RB912UAG-2HPnD
On MikroTik RB91x board series a reset key shares SoC gpio line #15 with NAND ALE and NAND IO7. So we need a custom gpio driver to manage this non-trivial connection schema. Also rb91x-nand needs to have an ability to disable a polling of the key while it works with NAND. While we've been integrating rb91x-key into a firmware, we've figured out that: * In the gpio-latch driver we need to add a "cansleep" suffix to several gpiolib calls, * When gpio-latch and rb91x-nand fail to get a gpio and an error is -EPROBE_DEFER, they shouldn't report about this, since this actually is not an error and occurs when the gpio-latch probe function is called before the rb91x-key probe. We fix these related things here too. Signed-off-by: Denis Kalashnikov <denis281089@gmail.com> Reviewed-by: Sergey Ryazanov <ryazanov.s.a@gmail.com> Tested-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
This commit is contained in:
		 Denis Kalashnikov
					Denis Kalashnikov
				
			
				
					committed by
					
						 Koen Vandeputte
						Koen Vandeputte
					
				
			
			
				
	
			
			
			 Koen Vandeputte
						Koen Vandeputte
					
				
			
						parent
						
							522e414dcb
						
					
				
				
					commit
					ec85e48a11
				
			| @@ -74,6 +74,7 @@ CONFIG_GPIO_74X164=y | |||||||
| CONFIG_GPIO_ATH79=y | CONFIG_GPIO_ATH79=y | ||||||
| CONFIG_GPIO_GENERIC=y | CONFIG_GPIO_GENERIC=y | ||||||
| # CONFIG_GPIO_LATCH is not set | # CONFIG_GPIO_LATCH is not set | ||||||
|  | # CONFIG_GPIO_RB91X_KEY is not set | ||||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | CONFIG_HANDLE_DOMAIN_IRQ=y | ||||||
| CONFIG_HARDWARE_WATCHPOINTS=y | CONFIG_HARDWARE_WATCHPOINTS=y | ||||||
| CONFIG_HAS_DMA=y | CONFIG_HAS_DMA=y | ||||||
|   | |||||||
| @@ -16,6 +16,13 @@ | |||||||
|                 led-upgrade = &led_power; |                 led-upgrade = &led_power; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  | 	gpio_key: gpio_key { | ||||||
|  | 		compatible = "mikrotik,gpio-rb91x-key"; | ||||||
|  | 		gpio-controller; | ||||||
|  | 		#gpio-cells = <2>; | ||||||
|  | 		gpio = <&gpio 15 GPIO_ACTIVE_HIGH>; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 	gpio_latch: gpio_latch { | 	gpio_latch: gpio_latch { | ||||||
| 		compatible = "gpio-latch"; | 		compatible = "gpio-latch"; | ||||||
| 		gpio-controller; | 		gpio-controller; | ||||||
| @@ -27,7 +34,7 @@ | |||||||
| 			<0>, /* Not connected */ | 			<0>, /* Not connected */ | ||||||
| 			<&gpio 13 GPIO_ACTIVE_HIGH>, | 			<&gpio 13 GPIO_ACTIVE_HIGH>, | ||||||
| 			<&gpio 14 GPIO_ACTIVE_HIGH>, | 			<&gpio 14 GPIO_ACTIVE_HIGH>, | ||||||
| 			<&gpio 15 GPIO_ACTIVE_HIGH>, | 			<&gpio_key 0 GPIO_ACTIVE_HIGH>, | ||||||
| 			<&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ | 			<&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| @@ -40,7 +47,8 @@ | |||||||
| 			<&gpio_latch 6 GPIO_ACTIVE_HIGH>, /* Command Latch Enable (CLE) */ | 			<&gpio_latch 6 GPIO_ACTIVE_HIGH>, /* Command Latch Enable (CLE) */ | ||||||
| 			<&gpio_latch 7 GPIO_ACTIVE_HIGH>, /* Address Latch Enable (ALE) */ | 			<&gpio_latch 7 GPIO_ACTIVE_HIGH>, /* Address Latch Enable (ALE) */ | ||||||
| 			<&gpio 12 GPIO_ACTIVE_LOW>,       /* Read/Write Enable (nRW) */ | 			<&gpio 12 GPIO_ACTIVE_LOW>,       /* Read/Write Enable (nRW) */ | ||||||
| 			<&gpio_latch 8 GPIO_ACTIVE_LOW>;  /* Latch Enable (nLE) */ | 			<&gpio_latch 8 GPIO_ACTIVE_LOW>,  /* Latch Enable (nLE) */ | ||||||
|  | 			<&gpio_key 2 GPIO_ACTIVE_HIGH>;   /* Key poll disable */ | ||||||
|  |  | ||||||
| 		partitions { | 		partitions { | ||||||
| 			compatible = "fixed-partitions"; | 			compatible = "fixed-partitions"; | ||||||
| @@ -64,6 +72,17 @@ | |||||||
| 		}; | 		}; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | 	keys { | ||||||
|  | 		compatible = "gpio-keys-polled"; | ||||||
|  | 		poll-interval = <20>; | ||||||
|  |  | ||||||
|  | 		button@0 { | ||||||
|  | 			label = "reset"; | ||||||
|  | 			linux,code = <KEY_RESTART>; | ||||||
|  | 			gpios = <&gpio_key 1 GPIO_ACTIVE_LOW>; | ||||||
|  | 		}; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 	leds { | 	leds { | ||||||
| 		compatible = "gpio-leds"; | 		compatible = "gpio-leds"; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ gpio_latch_get(struct gpio_chip *gc, unsigned offset) | |||||||
| 	int ret; | 	int ret; | ||||||
|  |  | ||||||
| 	gpio_latch_lock(glc, false); | 	gpio_latch_lock(glc, false); | ||||||
| 	ret = gpiod_get_value(glc->gpios[offset]); | 	ret = gpiod_get_raw_value_cansleep(glc->gpios[offset]); | ||||||
| 	gpio_latch_unlock(glc, false); | 	gpio_latch_unlock(glc, false); | ||||||
|  |  | ||||||
| 	return ret; | 	return ret; | ||||||
| @@ -81,7 +81,7 @@ gpio_latch_set(struct gpio_chip *gc, unsigned offset, int value) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	gpio_latch_lock(glc, enable_latch); | 	gpio_latch_lock(glc, enable_latch); | ||||||
| 	gpiod_set_raw_value(glc->gpios[offset], value); | 	gpiod_set_raw_value_cansleep(glc->gpios[offset], value); | ||||||
| 	gpio_latch_unlock(glc, disable_latch); | 	gpio_latch_unlock(glc, disable_latch); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -133,8 +133,10 @@ static int gpio_latch_probe(struct platform_device *pdev) | |||||||
| 		glc->gpios[i] = devm_gpiod_get_index_optional(dev, NULL, i, | 		glc->gpios[i] = devm_gpiod_get_index_optional(dev, NULL, i, | ||||||
| 			GPIOD_OUT_LOW); | 			GPIOD_OUT_LOW); | ||||||
| 		if (IS_ERR(glc->gpios[i])) { | 		if (IS_ERR(glc->gpios[i])) { | ||||||
|  | 			if (PTR_ERR(glc->gpios[i]) != -EPROBE_DEFER) { | ||||||
| 				dev_err(dev, "failed to get gpio %d: %d\n", i, | 				dev_err(dev, "failed to get gpio %d: %d\n", i, | ||||||
| 					PTR_ERR(glc->gpios[i])); | 					PTR_ERR(glc->gpios[i])); | ||||||
|  | 			} | ||||||
| 			return PTR_ERR(glc->gpios[i]); | 			return PTR_ERR(glc->gpios[i]); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										218
									
								
								target/linux/ath79/files/drivers/gpio/gpio-rb91x-key.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								target/linux/ath79/files/drivers/gpio/gpio-rb91x-key.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,218 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  | /* | ||||||
|  |  * Driver for reset key gpio line on MikroTik RB91x board series. | ||||||
|  |  * This line is shared between NAND ALE (goes through a latch), | ||||||
|  |  * NAND IO7 and reset key. We make 3 virtual gpio lines from the | ||||||
|  |  * single physical one: | ||||||
|  |  *   1) Capable output one for NAND, | ||||||
|  |  *   2) Capable input one for reset key, | ||||||
|  |  *   3) And capable output one, aka "key-poll-disable", | ||||||
|  |  *      for NAND -- to syncronise NAND operation and key polling. | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2021 Denis Kalashnikov <denis281089@gmail.com> | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/init.h> | ||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <linux/gpio/consumer.h> | ||||||
|  | #include <linux/gpio/driver.h> | ||||||
|  | #include <linux/platform_device.h> | ||||||
|  | #include <linux/of_platform.h> | ||||||
|  | #include <linux/of_gpio.h> | ||||||
|  | #include <linux/delay.h> | ||||||
|  |  | ||||||
|  | #define GPIO_RB91X_KEY_DRIVER_NAME  "gpio-rb91x-key" | ||||||
|  |  | ||||||
|  | enum gpio_rb91x_key_gpios { | ||||||
|  | 	GPIO_RB91X_KEY_NAND, | ||||||
|  | 	GPIO_RB91X_KEY_POLL, | ||||||
|  | 	GPIO_RB91X_KEY_PDIS, | ||||||
|  |  | ||||||
|  | 	GPIO_RB91X_KEY_NGPIOS, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | struct gpio_rb91x_key { | ||||||
|  | 	struct gpio_chip gc; | ||||||
|  | 	struct mutex mutex; | ||||||
|  | 	struct mutex poll_mutex; | ||||||
|  | 	int polling_disabled; | ||||||
|  | 	struct gpio_desc *gpio; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static inline struct gpio_rb91x_key *to_gpio_rb91x_key(struct gpio_chip *gc) | ||||||
|  | { | ||||||
|  | 	return container_of(gc, struct gpio_rb91x_key, gc); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int gpio_rb91x_key_get(struct gpio_chip *gc, unsigned offset) | ||||||
|  | { | ||||||
|  | 	struct gpio_rb91x_key *drvdata = to_gpio_rb91x_key(gc); | ||||||
|  | 	struct gpio_desc *gpio = drvdata->gpio; | ||||||
|  | 	int val, bak_val; | ||||||
|  |  | ||||||
|  | 	switch (offset) { | ||||||
|  | 	case GPIO_RB91X_KEY_NAND: | ||||||
|  | 		mutex_lock(&drvdata->mutex); | ||||||
|  | 		val = gpiod_get_value_cansleep(gpio); | ||||||
|  | 		mutex_unlock(&drvdata->mutex); | ||||||
|  | 		break; | ||||||
|  | 	case GPIO_RB91X_KEY_PDIS: | ||||||
|  | 		mutex_lock(&drvdata->mutex); | ||||||
|  | 		val = drvdata->polling_disabled; | ||||||
|  | 		mutex_unlock(&drvdata->mutex); | ||||||
|  | 		break; | ||||||
|  | 	case GPIO_RB91X_KEY_POLL: | ||||||
|  | 		mutex_lock(&drvdata->poll_mutex); | ||||||
|  | 		mutex_lock(&drvdata->mutex); | ||||||
|  | 		bak_val = gpiod_get_raw_value_cansleep(gpio); | ||||||
|  | 		gpiod_direction_input(gpio); | ||||||
|  | 		/* | ||||||
|  | 		 * Without this delay nothing works. Get it | ||||||
|  | 		 * from mikrotik RouterOS linux kernel patches. | ||||||
|  | 		 */ | ||||||
|  | 		udelay(200); | ||||||
|  | 		val = gpiod_get_raw_value_cansleep(gpio); | ||||||
|  | 		gpiod_direction_output_raw(gpio, bak_val); | ||||||
|  | 		mutex_unlock(&drvdata->mutex); | ||||||
|  | 		mutex_unlock(&drvdata->poll_mutex); | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int gpio_rb91x_key_direction_input(struct gpio_chip *gc, unsigned offset) | ||||||
|  | { | ||||||
|  | 	switch (offset) { | ||||||
|  | 	case GPIO_RB91X_KEY_POLL: | ||||||
|  | 		return 0; | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void gpio_rb91x_key_set(struct gpio_chip *gc, unsigned offset, int value) | ||||||
|  | { | ||||||
|  | 	struct gpio_rb91x_key *drvdata = to_gpio_rb91x_key(gc); | ||||||
|  | 	struct gpio_desc *gpio = drvdata->gpio; | ||||||
|  |  | ||||||
|  | 	mutex_lock(&drvdata->mutex); | ||||||
|  |  | ||||||
|  | 	switch (offset) { | ||||||
|  | 	case GPIO_RB91X_KEY_NAND: | ||||||
|  | 		gpiod_set_raw_value_cansleep(gpio, value); | ||||||
|  | 		break; | ||||||
|  | 	case GPIO_RB91X_KEY_PDIS: | ||||||
|  | 		if (value) { | ||||||
|  | 			if (!drvdata->polling_disabled) { | ||||||
|  | 				mutex_lock(&drvdata->poll_mutex); | ||||||
|  | 				drvdata->polling_disabled = 1; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if (drvdata->polling_disabled) { | ||||||
|  | 				mutex_unlock(&drvdata->poll_mutex); | ||||||
|  | 				drvdata->polling_disabled = 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mutex_unlock(&drvdata->mutex); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int gpio_rb91x_key_direction_output(struct gpio_chip *gc, unsigned offset, | ||||||
|  | 					   int value) | ||||||
|  | { | ||||||
|  | 	switch (offset) { | ||||||
|  | 	case GPIO_RB91X_KEY_NAND: | ||||||
|  | 	case GPIO_RB91X_KEY_PDIS: | ||||||
|  | 		gpio_rb91x_key_set(gc, offset, value); | ||||||
|  | 		return 0; | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int gpio_rb91x_key_probe(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	struct gpio_rb91x_key *drvdata; | ||||||
|  | 	struct gpio_chip *gc; | ||||||
|  | 	struct device *dev = &pdev->dev; | ||||||
|  | 	struct device_node *of_node = dev->of_node; | ||||||
|  | 	int r; | ||||||
|  |  | ||||||
|  | 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); | ||||||
|  | 	if (!drvdata) | ||||||
|  | 		return -ENOMEM; | ||||||
|  |  | ||||||
|  | 	mutex_init(&drvdata->mutex); | ||||||
|  | 	mutex_init(&drvdata->poll_mutex); | ||||||
|  |  | ||||||
|  | 	drvdata->gpio = devm_gpiod_get(dev, NULL, GPIOD_OUT_LOW); | ||||||
|  | 	if (IS_ERR(drvdata->gpio)) { | ||||||
|  | 		if (PTR_ERR(drvdata->gpio) != -EPROBE_DEFER) { | ||||||
|  | 			dev_err(dev, "failed to get gpio: %ld\n", | ||||||
|  | 				PTR_ERR(drvdata->gpio)); | ||||||
|  | 		} | ||||||
|  | 		return PTR_ERR(drvdata->gpio); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	gc = &drvdata->gc; | ||||||
|  | 	gc->label = GPIO_RB91X_KEY_DRIVER_NAME; | ||||||
|  | 	gc->can_sleep = 1; | ||||||
|  | 	gc->base = -1; | ||||||
|  | 	gc->ngpio = GPIO_RB91X_KEY_NGPIOS; | ||||||
|  | 	gc->get = gpio_rb91x_key_get; | ||||||
|  | 	gc->set = gpio_rb91x_key_set; | ||||||
|  | 	gc->direction_output = gpio_rb91x_key_direction_output; | ||||||
|  | 	gc->direction_input = gpio_rb91x_key_direction_input; | ||||||
|  | 	gc->of_node = of_node; | ||||||
|  |  | ||||||
|  | 	platform_set_drvdata(pdev, drvdata); | ||||||
|  |  | ||||||
|  | 	r = gpiochip_add(&drvdata->gc); | ||||||
|  | 	if (r) { | ||||||
|  | 		dev_err(dev, "gpiochip_add() failed: %d\n", r); | ||||||
|  | 		return r; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int gpio_rb91x_key_remove(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	struct gpio_rb91x_key *drvdata = platform_get_drvdata(pdev); | ||||||
|  |  | ||||||
|  | 	gpiochip_remove(&drvdata->gc); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const struct of_device_id gpio_rb91x_key_match[] = { | ||||||
|  | 	{ .compatible = "mikrotik,"GPIO_RB91X_KEY_DRIVER_NAME }, | ||||||
|  | 	{}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | MODULE_DEVICE_TABLE(of, gpio_rb91x_key_match); | ||||||
|  |  | ||||||
|  | static struct platform_driver gpio_rb91x_key_driver = { | ||||||
|  | 	.probe = gpio_rb91x_key_probe, | ||||||
|  | 	.remove = gpio_rb91x_key_remove, | ||||||
|  | 	.driver = { | ||||||
|  | 		.name = GPIO_RB91X_KEY_DRIVER_NAME, | ||||||
|  | 		.owner = THIS_MODULE, | ||||||
|  | 		.of_match_table = gpio_rb91x_key_match, | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | module_platform_driver(gpio_rb91x_key_driver); | ||||||
|  |  | ||||||
|  | MODULE_DESCRIPTION("Driver for reset key gpio line shared with NAND for MikroTik RB91x board series."); | ||||||
|  | MODULE_AUTHOR("Denis Kalashnikov <denis281089@gmail.com>"); | ||||||
|  | MODULE_LICENSE("GPL v2"); | ||||||
|  | MODULE_ALIAS("platform:" GPIO_RB91X_KEY_DRIVER_NAME); | ||||||
| @@ -40,6 +40,7 @@ enum rb91x_nand_gpios { | |||||||
| 	RB91X_NAND_ALE, /* Address Latch Enable */ | 	RB91X_NAND_ALE, /* Address Latch Enable */ | ||||||
| 	RB91X_NAND_NRW, /* Read/Write. Active low */ | 	RB91X_NAND_NRW, /* Read/Write. Active low */ | ||||||
| 	RB91X_NAND_NLE, /* Latch Enable. Active low */ | 	RB91X_NAND_NLE, /* Latch Enable. Active low */ | ||||||
|  | 	RB91X_NAND_PDIS, /* Reset Key Poll Disable. Active high */ | ||||||
|  |  | ||||||
| 	RB91X_NAND_GPIOS, | 	RB91X_NAND_GPIOS, | ||||||
| }; | }; | ||||||
| @@ -57,6 +58,12 @@ static inline void rb91x_nand_latch_lock(struct rb91x_nand_drvdata *drvdata, | |||||||
| 	gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_NLE], lock); | 	gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_NLE], lock); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static inline void rb91x_nand_rst_key_poll_disable(struct rb91x_nand_drvdata *drvdata, | ||||||
|  | 						   int disable) | ||||||
|  | { | ||||||
|  | 	gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_PDIS], disable); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int rb91x_ooblayout_ecc(struct mtd_info *mtd, int section, | static int rb91x_ooblayout_ecc(struct mtd_info *mtd, int section, | ||||||
| 			       struct mtd_oob_region *oobregion) | 			       struct mtd_oob_region *oobregion) | ||||||
| { | { | ||||||
| @@ -115,6 +122,7 @@ static void rb91x_nand_write(struct rb91x_nand_drvdata *drvdata, | |||||||
| 	unsigned i; | 	unsigned i; | ||||||
|  |  | ||||||
| 	rb91x_nand_latch_lock(drvdata, 1); | 	rb91x_nand_latch_lock(drvdata, 1); | ||||||
|  | 	rb91x_nand_rst_key_poll_disable(drvdata, 1); | ||||||
|  |  | ||||||
| 	oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); | 	oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); | ||||||
| 	out_reg = __raw_readl(base + AR71XX_GPIO_REG_OUT); | 	out_reg = __raw_readl(base + AR71XX_GPIO_REG_OUT); | ||||||
| @@ -146,6 +154,7 @@ static void rb91x_nand_write(struct rb91x_nand_drvdata *drvdata, | |||||||
| 	/* Flush write */ | 	/* Flush write */ | ||||||
| 	__raw_readl(base + AR71XX_GPIO_REG_OUT); | 	__raw_readl(base + AR71XX_GPIO_REG_OUT); | ||||||
|  |  | ||||||
|  | 	rb91x_nand_rst_key_poll_disable(drvdata, 0); | ||||||
| 	rb91x_nand_latch_lock(drvdata, 0); | 	rb91x_nand_latch_lock(drvdata, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -162,6 +171,7 @@ static void rb91x_nand_read(struct rb91x_nand_drvdata *drvdata, | |||||||
| 	gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_READ], 1); | 	gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_READ], 1); | ||||||
|  |  | ||||||
| 	rb91x_nand_latch_lock(drvdata, 1); | 	rb91x_nand_latch_lock(drvdata, 1); | ||||||
|  | 	rb91x_nand_rst_key_poll_disable(drvdata, 1); | ||||||
|  |  | ||||||
| 	/* Save registers */ | 	/* Save registers */ | ||||||
| 	oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); | 	oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); | ||||||
| @@ -199,6 +209,7 @@ static void rb91x_nand_read(struct rb91x_nand_drvdata *drvdata, | |||||||
| 	/* Flush write */ | 	/* Flush write */ | ||||||
| 	__raw_readl(base + AR71XX_GPIO_REG_OUT); | 	__raw_readl(base + AR71XX_GPIO_REG_OUT); | ||||||
|  |  | ||||||
|  | 	rb91x_nand_rst_key_poll_disable(drvdata, 0); | ||||||
| 	rb91x_nand_latch_lock(drvdata, 0); | 	rb91x_nand_latch_lock(drvdata, 0); | ||||||
|  |  | ||||||
| 	/* Disable read mode */ | 	/* Disable read mode */ | ||||||
| @@ -274,8 +285,11 @@ static int rb91x_nand_probe(struct platform_device *pdev) | |||||||
|  |  | ||||||
| 	gpios = gpiod_get_array(dev, NULL, GPIOD_OUT_LOW); | 	gpios = gpiod_get_array(dev, NULL, GPIOD_OUT_LOW); | ||||||
| 	if (IS_ERR(gpios)) { | 	if (IS_ERR(gpios)) { | ||||||
| 		dev_err(dev, "failed to get gpios: %d\n", (int)gpios); | 		if (PTR_ERR(gpios) != -EPROBE_DEFER) { | ||||||
| 		return -EINVAL; | 			dev_err(dev, "failed to get gpios: %d\n", | ||||||
|  | 				PTR_ERR(gpios)); | ||||||
|  | 		} | ||||||
|  | 		return PTR_ERR(gpios); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (gpios->ndescs != RB91X_NAND_GPIOS) { | 	if (gpios->ndescs != RB91X_NAND_GPIOS) { | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| CONFIG_CRC16=y | CONFIG_CRC16=y | ||||||
| CONFIG_CRYPTO_DEFLATE=y | CONFIG_CRYPTO_DEFLATE=y | ||||||
| CONFIG_GPIO_LATCH=y | CONFIG_GPIO_LATCH=y | ||||||
|  | CONFIG_GPIO_RB91X_KEY=y | ||||||
| CONFIG_GPIO_RB4XX=y | CONFIG_GPIO_RB4XX=y | ||||||
| CONFIG_GPIO_WATCHDOG=y | CONFIG_GPIO_WATCHDOG=y | ||||||
| CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y | CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y | ||||||
|   | |||||||
| @@ -14,6 +14,17 @@ | |||||||
|  config GPIO_LOGICVC |  config GPIO_LOGICVC | ||||||
|  	tristate "Xylon LogiCVC GPIO support" |  	tristate "Xylon LogiCVC GPIO support" | ||||||
|  	depends on MFD_SYSCON && OF |  	depends on MFD_SYSCON && OF | ||||||
|  | @@ -495,6 +502,10 @@ config GPIO_REG | ||||||
|  |  	  A 32-bit single register GPIO fixed in/out implementation.  This | ||||||
|  |  	  can be used to represent any register as a set of GPIO signals. | ||||||
|  |   | ||||||
|  | +config GPIO_RB91X_KEY | ||||||
|  | +	tristate "MikroTik RB91x board series reset key support" | ||||||
|  | +	depends on ATH79 | ||||||
|  | + | ||||||
|  |  config GPIO_SAMA5D2_PIOBU | ||||||
|  |  	tristate "SAMA5D2 PIOBU GPIO support" | ||||||
|  |  	depends on MFD_SYSCON | ||||||
| --- a/drivers/gpio/Makefile | --- a/drivers/gpio/Makefile | ||||||
| +++ b/drivers/gpio/Makefile | +++ b/drivers/gpio/Makefile | ||||||
| @@ -72,6 +72,7 @@ obj-$(CONFIG_GPIO_IT87)			+= gpio-it87.o | @@ -72,6 +72,7 @@ obj-$(CONFIG_GPIO_IT87)			+= gpio-it87.o | ||||||
| @@ -24,6 +35,14 @@ | |||||||
|  obj-$(CONFIG_GPIO_LOGICVC)		+= gpio-logicvc.o |  obj-$(CONFIG_GPIO_LOGICVC)		+= gpio-logicvc.o | ||||||
|  obj-$(CONFIG_GPIO_LOONGSON1)		+= gpio-loongson1.o |  obj-$(CONFIG_GPIO_LOONGSON1)		+= gpio-loongson1.o | ||||||
|  obj-$(CONFIG_GPIO_LOONGSON)		+= gpio-loongson.o |  obj-$(CONFIG_GPIO_LOONGSON)		+= gpio-loongson.o | ||||||
|  | @@ -121,6 +122,7 @@ obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)	+= gpio | ||||||
|  |  obj-$(CONFIG_GPIO_PXA)			+= gpio-pxa.o | ||||||
|  |  obj-$(CONFIG_GPIO_RASPBERRYPI_EXP)	+= gpio-raspberrypi-exp.o | ||||||
|  |  obj-$(CONFIG_GPIO_RB4XX)		+= gpio-rb4xx.o | ||||||
|  | +obj-$(CONFIG_GPIO_RB91X_KEY)		+= gpio-rb91x-key.o | ||||||
|  |  obj-$(CONFIG_GPIO_RC5T583)		+= gpio-rc5t583.o | ||||||
|  |  obj-$(CONFIG_GPIO_RCAR)			+= gpio-rcar.o | ||||||
|  |  obj-$(CONFIG_GPIO_RDA)			+= gpio-rda.o | ||||||
| --- a/drivers/mtd/nand/raw/Kconfig | --- a/drivers/mtd/nand/raw/Kconfig | ||||||
| +++ b/drivers/mtd/nand/raw/Kconfig | +++ b/drivers/mtd/nand/raw/Kconfig | ||||||
| @@ -571,4 +571,10 @@ config MTD_NAND_RB4XX | @@ -571,4 +571,10 @@ config MTD_NAND_RB4XX | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user