mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 09:12:39 +00:00
5deb3996e2
Copy and refresh patches and config from 5.4 to 5.10. Most patches require no more then automatic refresh. The only exception is the Ethernet driver patch, which requires some more work: * drop eth_change_mtu() usage since it was removed from the kernel, it anyway useless for drivers that utilizes alloc_etherdev(); * add the txqueue number argument to the .ndo_tx_timeout callback function; * replace ioremap_nocache() which was finally removed from the kernel by the ioremap() with the same behaviour. Switch target to the new kernel version. Signed-off-by: Daniel Golle <daniel@makrotopia.org> [use KERNEL_TESTING_PATCHVER for now] Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
364 lines
9.9 KiB
Diff
364 lines
9.9 KiB
Diff
--- a/arch/mips/ath25/Kconfig
|
|
+++ b/arch/mips/ath25/Kconfig
|
|
@@ -8,6 +8,7 @@ config SOC_AR5312
|
|
config SOC_AR2315
|
|
bool "Atheros AR2315+ SoC support"
|
|
depends on ATH25
|
|
+ select GPIO_AR2315
|
|
default y
|
|
|
|
config PCI_AR2315
|
|
--- a/arch/mips/ath25/ar2315.c
|
|
+++ b/arch/mips/ath25/ar2315.c
|
|
@@ -22,6 +22,8 @@
|
|
#include <linux/memblock.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/reboot.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/gpio.h>
|
|
#include <asm/bootinfo.h>
|
|
#include <asm/reboot.h>
|
|
#include <asm/time.h>
|
|
@@ -165,11 +167,42 @@ void __init ar2315_arch_init_irq(void)
|
|
ar2315_misc_irq_domain = domain;
|
|
}
|
|
|
|
+static struct resource ar2315_gpio_res[] = {
|
|
+ {
|
|
+ .name = "ar2315-gpio",
|
|
+ .flags = IORESOURCE_MEM,
|
|
+ .start = AR2315_RST_BASE + AR2315_GPIO,
|
|
+ .end = AR2315_RST_BASE + AR2315_GPIO + 0x10 - 1,
|
|
+ },
|
|
+ {
|
|
+ .name = "ar2315-gpio",
|
|
+ .flags = IORESOURCE_IRQ,
|
|
+ },
|
|
+ {
|
|
+ .name = "ar2315-gpio-irq-base",
|
|
+ .flags = IORESOURCE_IRQ,
|
|
+ .start = AR231X_GPIO_IRQ_BASE,
|
|
+ .end = AR231X_GPIO_IRQ_BASE,
|
|
+ }
|
|
+};
|
|
+
|
|
+static struct platform_device ar2315_gpio = {
|
|
+ .id = -1,
|
|
+ .name = "ar2315-gpio",
|
|
+ .resource = ar2315_gpio_res,
|
|
+ .num_resources = ARRAY_SIZE(ar2315_gpio_res)
|
|
+};
|
|
+
|
|
void __init ar2315_init_devices(void)
|
|
{
|
|
/* Find board configuration */
|
|
ath25_find_config(AR2315_SPI_READ_BASE, AR2315_SPI_READ_SIZE);
|
|
|
|
+ ar2315_gpio_res[1].start = irq_create_mapping(ar2315_misc_irq_domain,
|
|
+ AR2315_MISC_IRQ_GPIO);
|
|
+ ar2315_gpio_res[1].end = ar2315_gpio_res[1].start;
|
|
+ platform_device_register(&ar2315_gpio);
|
|
+
|
|
ath25_add_wmac(0, AR2315_WLAN0_BASE, AR2315_IRQ_WLAN0);
|
|
}
|
|
|
|
@@ -185,8 +218,8 @@ static void ar2315_restart(char *command
|
|
/* Cold reset does not work on the AR2315/6, use the GPIO reset bits
|
|
* a workaround. Give it some time to attempt a gpio based hardware
|
|
* reset (atheros reference design workaround) */
|
|
-
|
|
- /* TODO: implement the GPIO reset workaround */
|
|
+ gpio_request_one(AR2315_RESET_GPIO, GPIOF_OUT_INIT_LOW, "Reset");
|
|
+ mdelay(100);
|
|
|
|
/* Some boards (e.g. Senao EOC-2610) don't implement the reset logic
|
|
* workaround. Attempt to jump to the mips reset location -
|
|
--- a/drivers/gpio/Kconfig
|
|
+++ b/drivers/gpio/Kconfig
|
|
@@ -142,6 +142,13 @@ config GPIO_AMDPT
|
|
driver for GPIO functionality on Promontory IOHub
|
|
Require ACPI ASL code to enumerate as a platform device.
|
|
|
|
+config GPIO_AR2315
|
|
+ bool "AR2315 SoC GPIO support"
|
|
+ default y if SOC_AR2315
|
|
+ depends on SOC_AR2315
|
|
+ help
|
|
+ Say yes here to enable GPIO support for Atheros AR2315+ SoCs.
|
|
+
|
|
config GPIO_AR5312
|
|
bool "AR5312 SoC GPIO support"
|
|
default y if SOC_AR5312
|
|
--- a/drivers/gpio/Makefile
|
|
+++ b/drivers/gpio/Makefile
|
|
@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_ALTERA) += gpio-alt
|
|
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
|
|
obj-$(CONFIG_GPIO_AMD_FCH) += gpio-amd-fch.o
|
|
obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
|
|
+obj-$(CONFIG_GPIO_AR2315) += gpio-ar2315.o
|
|
obj-$(CONFIG_GPIO_AR5312) += gpio-ar5312.o
|
|
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
|
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
|
|
--- /dev/null
|
|
+++ b/drivers/gpio/gpio-ar2315.c
|
|
@@ -0,0 +1,233 @@
|
|
+/*
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
+ * License. See the file "COPYING" in the main directory of this archive
|
|
+ * for more details.
|
|
+ *
|
|
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
|
|
+ * Copyright (C) 2006 FON Technology, SL.
|
|
+ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
|
|
+ * Copyright (C) 2006 Felix Fietkau <nbd@nbd.name>
|
|
+ * Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com>
|
|
+ */
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/gpio.h>
|
|
+#include <linux/irq.h>
|
|
+
|
|
+#define DRIVER_NAME "ar2315-gpio"
|
|
+
|
|
+#define AR2315_GPIO_DI 0x0000
|
|
+#define AR2315_GPIO_DO 0x0008
|
|
+#define AR2315_GPIO_DIR 0x0010
|
|
+#define AR2315_GPIO_INT 0x0018
|
|
+
|
|
+#define AR2315_GPIO_DIR_M(x) (1 << (x)) /* mask for i/o */
|
|
+#define AR2315_GPIO_DIR_O(x) (1 << (x)) /* output */
|
|
+#define AR2315_GPIO_DIR_I(x) (0) /* input */
|
|
+
|
|
+#define AR2315_GPIO_INT_NUM_M 0x3F /* mask for GPIO num */
|
|
+#define AR2315_GPIO_INT_TRIG(x) ((x) << 6) /* interrupt trigger */
|
|
+#define AR2315_GPIO_INT_TRIG_M (0x3 << 6) /* mask for int trig */
|
|
+
|
|
+#define AR2315_GPIO_INT_TRIG_OFF 0 /* Triggerring off */
|
|
+#define AR2315_GPIO_INT_TRIG_LOW 1 /* Low Level Triggered */
|
|
+#define AR2315_GPIO_INT_TRIG_HIGH 2 /* High Level Triggered */
|
|
+#define AR2315_GPIO_INT_TRIG_EDGE 3 /* Edge Triggered */
|
|
+
|
|
+#define AR2315_GPIO_NUM 22
|
|
+
|
|
+static u32 ar2315_gpio_intmask;
|
|
+static u32 ar2315_gpio_intval;
|
|
+static unsigned ar2315_gpio_irq_base;
|
|
+static void __iomem *ar2315_mem;
|
|
+
|
|
+static inline u32 ar2315_gpio_reg_read(unsigned reg)
|
|
+{
|
|
+ return __raw_readl(ar2315_mem + reg);
|
|
+}
|
|
+
|
|
+static inline void ar2315_gpio_reg_write(unsigned reg, u32 val)
|
|
+{
|
|
+ __raw_writel(val, ar2315_mem + reg);
|
|
+}
|
|
+
|
|
+static inline void ar2315_gpio_reg_mask(unsigned reg, u32 mask, u32 val)
|
|
+{
|
|
+ ar2315_gpio_reg_write(reg, (ar2315_gpio_reg_read(reg) & ~mask) | val);
|
|
+}
|
|
+
|
|
+static void ar2315_gpio_irq_handler(struct irq_desc *desc)
|
|
+{
|
|
+ u32 pend;
|
|
+ int bit = -1;
|
|
+
|
|
+ /* only do one gpio interrupt at a time */
|
|
+ pend = ar2315_gpio_reg_read(AR2315_GPIO_DI);
|
|
+ pend ^= ar2315_gpio_intval;
|
|
+ pend &= ar2315_gpio_intmask;
|
|
+
|
|
+ if (pend) {
|
|
+ bit = fls(pend) - 1;
|
|
+ pend &= ~(1 << bit);
|
|
+ ar2315_gpio_intval ^= (1 << bit);
|
|
+ }
|
|
+
|
|
+ /* Enable interrupt with edge detection */
|
|
+ if ((ar2315_gpio_reg_read(AR2315_GPIO_DIR) & AR2315_GPIO_DIR_M(bit)) !=
|
|
+ AR2315_GPIO_DIR_I(bit))
|
|
+ return;
|
|
+
|
|
+ if (bit >= 0)
|
|
+ generic_handle_irq(ar2315_gpio_irq_base + bit);
|
|
+}
|
|
+
|
|
+static void ar2315_gpio_int_setup(unsigned gpio, int trig)
|
|
+{
|
|
+ u32 reg = ar2315_gpio_reg_read(AR2315_GPIO_INT);
|
|
+
|
|
+ reg &= ~(AR2315_GPIO_INT_NUM_M | AR2315_GPIO_INT_TRIG_M);
|
|
+ reg |= gpio | AR2315_GPIO_INT_TRIG(trig);
|
|
+ ar2315_gpio_reg_write(AR2315_GPIO_INT, reg);
|
|
+}
|
|
+
|
|
+static void ar2315_gpio_irq_unmask(struct irq_data *d)
|
|
+{
|
|
+ unsigned gpio = d->irq - ar2315_gpio_irq_base;
|
|
+ u32 dir = ar2315_gpio_reg_read(AR2315_GPIO_DIR);
|
|
+
|
|
+ /* Enable interrupt with edge detection */
|
|
+ if ((dir & AR2315_GPIO_DIR_M(gpio)) != AR2315_GPIO_DIR_I(gpio))
|
|
+ return;
|
|
+
|
|
+ ar2315_gpio_intmask |= (1 << gpio);
|
|
+ ar2315_gpio_int_setup(gpio, AR2315_GPIO_INT_TRIG_EDGE);
|
|
+}
|
|
+
|
|
+static void ar2315_gpio_irq_mask(struct irq_data *d)
|
|
+{
|
|
+ unsigned gpio = d->irq - ar2315_gpio_irq_base;
|
|
+
|
|
+ /* Disable interrupt */
|
|
+ ar2315_gpio_intmask &= ~(1 << gpio);
|
|
+ ar2315_gpio_int_setup(gpio, AR2315_GPIO_INT_TRIG_OFF);
|
|
+}
|
|
+
|
|
+static struct irq_chip ar2315_gpio_irq_chip = {
|
|
+ .name = DRIVER_NAME,
|
|
+ .irq_unmask = ar2315_gpio_irq_unmask,
|
|
+ .irq_mask = ar2315_gpio_irq_mask,
|
|
+};
|
|
+
|
|
+static void ar2315_gpio_irq_init(unsigned irq)
|
|
+{
|
|
+ unsigned i;
|
|
+
|
|
+ ar2315_gpio_intval = ar2315_gpio_reg_read(AR2315_GPIO_DI);
|
|
+ for (i = 0; i < AR2315_GPIO_NUM; i++) {
|
|
+ unsigned _irq = ar2315_gpio_irq_base + i;
|
|
+
|
|
+ irq_set_chip_and_handler(_irq, &ar2315_gpio_irq_chip,
|
|
+ handle_level_irq);
|
|
+ }
|
|
+ irq_set_chained_handler(irq, ar2315_gpio_irq_handler);
|
|
+}
|
|
+
|
|
+static int ar2315_gpio_get_val(struct gpio_chip *chip, unsigned gpio)
|
|
+{
|
|
+ return (ar2315_gpio_reg_read(AR2315_GPIO_DI) >> gpio) & 1;
|
|
+}
|
|
+
|
|
+static void ar2315_gpio_set_val(struct gpio_chip *chip, unsigned gpio, int val)
|
|
+{
|
|
+ u32 reg = ar2315_gpio_reg_read(AR2315_GPIO_DO);
|
|
+
|
|
+ reg = val ? reg | (1 << gpio) : reg & ~(1 << gpio);
|
|
+ ar2315_gpio_reg_write(AR2315_GPIO_DO, reg);
|
|
+}
|
|
+
|
|
+static int ar2315_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
|
|
+{
|
|
+ ar2315_gpio_reg_mask(AR2315_GPIO_DIR, 1 << gpio, 0);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int ar2315_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, int val)
|
|
+{
|
|
+ ar2315_gpio_reg_mask(AR2315_GPIO_DIR, 0, 1 << gpio);
|
|
+ ar2315_gpio_set_val(chip, gpio, val);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int ar2315_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
|
+{
|
|
+ return ar2315_gpio_irq_base + gpio;
|
|
+}
|
|
+
|
|
+static struct gpio_chip ar2315_gpio_chip = {
|
|
+ .label = DRIVER_NAME,
|
|
+ .direction_input = ar2315_gpio_dir_in,
|
|
+ .direction_output = ar2315_gpio_dir_out,
|
|
+ .set = ar2315_gpio_set_val,
|
|
+ .get = ar2315_gpio_get_val,
|
|
+ .to_irq = ar2315_gpio_to_irq,
|
|
+ .base = 0,
|
|
+ .ngpio = AR2315_GPIO_NUM,
|
|
+};
|
|
+
|
|
+static int ar2315_gpio_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct device *dev = &pdev->dev;
|
|
+ struct resource *res;
|
|
+ unsigned irq;
|
|
+ int ret;
|
|
+
|
|
+ if (ar2315_mem)
|
|
+ return -EBUSY;
|
|
+
|
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
|
|
+ "ar2315-gpio-irq-base");
|
|
+ if (!res) {
|
|
+ dev_err(dev, "not found GPIO IRQ base\n");
|
|
+ return -ENXIO;
|
|
+ }
|
|
+ ar2315_gpio_irq_base = res->start;
|
|
+
|
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, DRIVER_NAME);
|
|
+ if (!res) {
|
|
+ dev_err(dev, "not found IRQ number\n");
|
|
+ return -ENXIO;
|
|
+ }
|
|
+ irq = res->start;
|
|
+
|
|
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, DRIVER_NAME);
|
|
+ ar2315_mem = devm_ioremap_resource(dev, res);
|
|
+ if (IS_ERR(ar2315_mem))
|
|
+ return PTR_ERR(ar2315_mem);
|
|
+
|
|
+ ar2315_gpio_chip.parent = dev;
|
|
+ ret = gpiochip_add(&ar2315_gpio_chip);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "failed to add gpiochip\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ar2315_gpio_irq_init(irq);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct platform_driver ar2315_gpio_driver = {
|
|
+ .probe = ar2315_gpio_probe,
|
|
+ .driver = {
|
|
+ .name = DRIVER_NAME,
|
|
+ .owner = THIS_MODULE,
|
|
+ }
|
|
+};
|
|
+
|
|
+static int __init ar2315_gpio_init(void)
|
|
+{
|
|
+ return platform_driver_register(&ar2315_gpio_driver);
|
|
+}
|
|
+subsys_initcall(ar2315_gpio_init);
|
|
--- a/arch/mips/ath25/devices.h
|
|
+++ b/arch/mips/ath25/devices.h
|
|
@@ -4,6 +4,11 @@
|
|
|
|
#include <linux/cpu.h>
|
|
|
|
+#define AR231X_GPIO_IRQ_BASE 0x30
|
|
+
|
|
+/* GPIO number for AR2315/16 reset issue workaround */
|
|
+#define AR2315_RESET_GPIO 5
|
|
+
|
|
#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)
|
|
|
|
#define ATH25_IRQ_CPU_CLOCK (MIPS_CPU_IRQ_BASE + 7) /* C0_CAUSE: 0x8000 */
|
|
--- a/arch/mips/ath25/ar2315_regs.h
|
|
+++ b/arch/mips/ath25/ar2315_regs.h
|
|
@@ -315,6 +315,9 @@
|
|
#define AR2315_MEM_CFG_BANKADDR_BITS_M 0x00000018
|
|
#define AR2315_MEM_CFG_BANKADDR_BITS_S 3
|
|
|
|
+/* GPIO MMR base address */
|
|
+#define AR2315_GPIO 0x0088
|
|
+
|
|
/*
|
|
* Local Bus Interface Registers
|
|
*/
|