--- zzzz-none-000/linux-4.4.271/drivers/gpio/gpio-ath79.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/drivers/gpio/gpio-ath79.c 2023-04-19 10:22:28.000000000 +0000 @@ -15,8 +15,17 @@ #include #include #include +#include #include +#include + +#define AP147_V2_ID 17 +#define WMAC1_CALDATA_OFFSET 0x5000 +#define BOARDID_OFFSET 0x20 + +void __iomem *ath79_gpio_base; +EXPORT_SYMBOL_GPL(ath79_gpio_base); struct ath79_gpio_ctrl { struct gpio_chip chip; @@ -83,6 +92,124 @@ return 0; } +void ath79_gpio_input_select(struct gpio_chip *chip, unsigned gpio, + u8 shift, u8 reg_off) +{ + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); + unsigned long flags; + unsigned int reg; + u32 t; + + WARN_ON(!soc_is_ar934x() && !soc_is_qca953x() && !soc_is_qca956x() && + !soc_is_qcn550x()); + + if (gpio >= ctrl->chip.ngpio) + return; + + reg = AR934X_GPIO_REG_IN_ENABLE0 + (4 * reg_off); + + spin_lock_irqsave(&ctrl->lock, flags); + + t = __raw_readl(ctrl->base + reg); + t &= ~(0xff << shift); + t |= gpio << shift; + __raw_writel(t, (ctrl->base) + reg); + + /* flush write */ + (void) __raw_readl((ctrl->base) + reg); + + spin_unlock_irqrestore(&ctrl->lock, flags); +} + +void ath79_gpio_output_select(struct gpio_chip *chip, + unsigned gpio, u8 val) +{ + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); + unsigned long flags; + unsigned int reg; + u32 t, s; + + WARN_ON(!soc_is_ar934x() && !soc_is_qca953x() && !soc_is_qca956x() && + !soc_is_qcn550x()); + + if (gpio >= ctrl->chip.ngpio) + return; + + reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4); + s = 8 * (gpio % 4); + + spin_lock_irqsave(&ctrl->lock, flags); + + t = __raw_readl(ctrl->base + reg); + t &= ~(0xff << s); + t |= val << s; + __raw_writel(t, ctrl->base + reg); + + /* flush write */ + (void) __raw_readl(ctrl->base + reg); + + spin_unlock_irqrestore(&ctrl->lock, flags); +} + +int ath79_gpio_direction_select(struct gpio_chip *chip, + unsigned gpio, bool oe) +{ + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); + unsigned long flags; + bool oe_inverted = (soc_is_ar934x() || soc_is_qca953x()); + + spin_lock_irqsave(&ctrl->lock, flags); + + if ((oe_inverted && oe) || (!oe_inverted && !oe)) + __raw_writel( + __raw_readl( + ctrl->base + AR71XX_GPIO_REG_OE) & ~(1 << gpio), + ctrl->base + AR71XX_GPIO_REG_OE); + else + __raw_writel( + __raw_readl( + ctrl->base + AR71XX_GPIO_REG_OE) | (1 << gpio), + ctrl->base + AR71XX_GPIO_REG_OE); + + spin_unlock_irqrestore(&ctrl->lock, flags); + + return 0; +} + +static void __iomem *ath79_gpio_get_function_reg(struct gpio_chip *chip) +{ + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); + u32 reg = 0; + + if (soc_is_ar71xx() || + soc_is_ar724x() || + soc_is_ar913x() || + soc_is_ar933x()) + reg = AR71XX_GPIO_REG_FUNC; + else if (soc_is_ar934x() || soc_is_qca953x() || soc_is_qca956x() || + soc_is_qcn550x()) + reg = AR934X_GPIO_REG_FUNC; + else + WARN(1, "Unsupported SOC"); + + return ctrl->base + reg; +} + +void ath79_gpio_function_enable(struct gpio_chip *chip, u32 mask) +{ + struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); + void __iomem *reg = ath79_gpio_get_function_reg(chip); + unsigned long flags; + + spin_lock_irqsave(&ctrl->lock, flags); + + __raw_writel(__raw_readl(reg) | mask, reg); + /* flush write */ + __raw_readl(reg); + + spin_unlock_irqrestore(&ctrl->lock, flags); +} + static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip); @@ -145,6 +272,10 @@ u32 ath79_gpio_count; bool oe_inverted; int err; + const __be32 *paddr; + int len, i2c_sda, i2c_sck; + int i; + u8 *art = (u8*)KSEG1ADDR(0x1fff0000); ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) @@ -170,6 +301,9 @@ } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + ctrl->base = devm_ioremap_nocache( &pdev->dev, res->start, resource_size(res)); if (!ctrl->base) @@ -177,7 +311,7 @@ spin_lock_init(&ctrl->lock); memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip)); - ctrl->chip.dev = &pdev->dev; + ctrl->chip.parent = &pdev->dev; ctrl->chip.ngpio = ath79_gpio_count; if (oe_inverted) { ctrl->chip.direction_input = ar934x_gpio_direction_input; @@ -191,6 +325,40 @@ return err; } + if (strncmp(mips_get_machine_name(), "QCA AP147 Board", 15) == 0) { + u8 board_id = *(art + WMAC1_CALDATA_OFFSET + BOARDID_OFFSET); + + pr_info("AP147 Reference Board Id is %d\n", board_id); + if (board_id == AP147_V2_ID) + ath79_gpio_function_enable(&ctrl->chip, + AR934X_GPIO_FUNC_JTAG_DISABLE); + } + + if (strncmp(mips_get_machine_name(), "QCA AP152 Board", 15) == 0) { + of_property_read_u32(np, "i2c-sda", &i2c_sda); + of_property_read_u32(np, "i2c-sck", &i2c_sck); + ar934x_gpio_direction_output(&ctrl->chip, i2c_sda, 0); + ar934x_gpio_direction_output(&ctrl->chip, i2c_sck, 0); + ath79_gpio_input_select(&ctrl->chip, i2c_sda, + QCA956X_GPIO_IN_MUX_I2C_SDA, 4); + ath79_gpio_input_select(&ctrl->chip, i2c_sck, + QCA956X_GPIO_IN_MUX_I2C_SCK, 4); + } + + paddr = of_get_property(np, "val,gpio", &len); + + if (paddr && len >= (2 * sizeof(*paddr))) { + len /= sizeof(*paddr); + for (i = 0; i < len - 1; i += 2) { + u32 gpio; + u32 val; + + val = be32_to_cpup(paddr + i); + gpio = be32_to_cpup(paddr + i + 1); + ath79_gpio_output_select(&ctrl->chip, gpio, val); + } + } + return 0; }