2
0
forked from Ivasoft/openwrt

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
2022-01-19 13:25:05 +03:00
committed by Koen Vandeputte
parent 522e414dcb
commit ec85e48a11
7 changed files with 282 additions and 8 deletions

View File

@@ -40,6 +40,7 @@ enum rb91x_nand_gpios {
RB91X_NAND_ALE, /* Address Latch Enable */
RB91X_NAND_NRW, /* Read/Write. Active low */
RB91X_NAND_NLE, /* Latch Enable. Active low */
RB91X_NAND_PDIS, /* Reset Key Poll Disable. Active high */
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);
}
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,
struct mtd_oob_region *oobregion)
{
@@ -115,6 +122,7 @@ static void rb91x_nand_write(struct rb91x_nand_drvdata *drvdata,
unsigned i;
rb91x_nand_latch_lock(drvdata, 1);
rb91x_nand_rst_key_poll_disable(drvdata, 1);
oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE);
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 */
__raw_readl(base + AR71XX_GPIO_REG_OUT);
rb91x_nand_rst_key_poll_disable(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);
rb91x_nand_latch_lock(drvdata, 1);
rb91x_nand_rst_key_poll_disable(drvdata, 1);
/* Save registers */
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 */
__raw_readl(base + AR71XX_GPIO_REG_OUT);
rb91x_nand_rst_key_poll_disable(drvdata, 0);
rb91x_nand_latch_lock(drvdata, 0);
/* 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);
if (IS_ERR(gpios)) {
dev_err(dev, "failed to get gpios: %d\n", (int)gpios);
return -EINVAL;
if (PTR_ERR(gpios) != -EPROBE_DEFER) {
dev_err(dev, "failed to get gpios: %d\n",
PTR_ERR(gpios));
}
return PTR_ERR(gpios);
}
if (gpios->ndescs != RB91X_NAND_GPIOS) {